mysql悲观锁 更新_MySQL学习笔记(四)悲观锁 for update
惱騷
最近在搞并發的問題,訂單的異步通知和主動查詢會存在并發的問題,用到了Mysql數據庫的?for update 鎖
在TP5直接通過lock(true),用于數據庫的鎖機制
Db::name(‘pay_order‘)->where(‘order_no‘,‘S1807081342018949’)->lock(true)->find();
打印生成的SQL語句
SELECT * FROM `pay_order` WHERE `order_no` = ‘S1807081342018949‘ LIMIT 1 FOR UPDATE
for update?是什么?
在oracle中,利用 select * for update 可以鎖表。假設有個表單products ,里面有id跟name二個欄位,id是主鍵。
例1: (明確指定主鍵,并且有此筆資料,row lock)
SELECT * FROM products WHERE id=‘3‘ FOR UPDATE;
例2: (明確指定主鍵,若查無此筆資料,無lock)
SELECT * FROM products WHERE id=‘-1‘ FOR UPDATE;
例3: (無主鍵,table lock)
SELECT * FROM products WHERE name=‘Mouse‘ FOR UPDATE;
例4: (主鍵不明確,table lock)
SELECT * FROM products WHERE id<>‘3‘ FOR UPDATE;
例5: (主鍵不明確,table lock)
SELECT * FROM products WHERE id LIKE ‘3‘ FOR UPDATE;
注1: FOR UPDATE僅適用于InnoDB,且必須在交易區塊(BEGIN/COMMIT)中才能生效。
先開始一把
使用悲觀鎖的原理就是,當我們在查詢出?pay_order 信息后就把當前的數據鎖定,直到我們修改完畢后再解鎖。那么在這個過程中,因為 pay_order?被鎖定了,就不會出現其他操作者來對其進行修改了。
第一次,開啟事務,但是不提交事務
異步通知
-- 開啟事務
START TRANSACTION;
-- 查詢訂單
SELECT id,order_no,`status` FROM `pay_order` WHERE `order_no` = ‘S1807081342018949‘ LIMIT 1 FOR UPDATE;
-- 修改訂單
UPDATE `pay_order` SET `status` = 11 WHERE id = 347;
COMMIT;
-- 查詢數據是否修改成功
SELECT id,order_no,`status` FROM `pay_order` WHERE `order_no` = ‘S1807081342018949‘ LIMIT 1 FOR UPDATE;
執行結果:很快就執行完畢了,但是數據并沒有修改成功(注意:但是重復執行一次,則數據又修改成功了)
主動查詢
1、加鎖
SELECT id,order_no,`status` FROM `pay_order` WHERE `order_no` = ‘S1807081342018949‘ LIMIT 1 FOR UPDATE;
執行結果,一直在阻塞中
過一會,會自動取消鎖機制
[Err] 1205 - Lock wait timeout exceeded; try restarting transaction
2、不加鎖
SELECT id,order_no,`status` FROM `pay_order` WHERE `order_no` = ‘S1807081342018949‘;
執行結果,沒有阻塞,則能正常查詢出數據,不會受第一個事務的影響
第二次,開啟事務,提交事務
異步查詢開啟事務,提交事務
主動查詢加鎖則不受影響
總結:鎖如果是回滾或者提交事務,會自動釋放掉鎖的。
下面研究以下行鎖和表鎖
例1: 明確指定主鍵,并且有此數據,row lock
show variables like ‘%storage_engine%‘;
原文:https://www.cnblogs.com/tinywan/p/9655664.html
總結
以上是生活随笔為你收集整理的mysql悲观锁 更新_MySQL学习笔记(四)悲观锁 for update的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java dexclassloader_
- 下一篇: pdo_mysql 必须 ×未安装_ph