作用
for update不僅可以鎖行,也可以鎖表。
僅適用於InnoDB。通常使用該語句對數據進行手工加鎖,避免其他線程對該數據進行修改,造成數據不一致性。
鎖的範圍
行鎖:明確指定Id,且數據存在
select * from customer where id = 1124 for UPDATE
表鎖:未指定Id或Id不明確
-- 未指定Id列 SELECT * from customer where name = 1112 for update -- Id不明確 SELECT * from customer where id <> 11 for update
以上可通過變量innodb_row_lock進行觀察
模擬表鎖
線程A,未指定Id列,會造成表鎖
線程B,對id=1的數據加鎖,此時因爲線程A表鎖了,需要等待線程A釋放纔可以加鎖
鎖的場景
for update 悲觀鎖,當前線程在處理時,希望別的線程對當前數據無法進行操作。
線程A
BEGIN; -- 將ID=1的數據鎖住 SELECT * FROM work_order WHERE id = 1 FOR UPDATE;
-- 模擬事物未提交 -- COMMIT;
執行結果,對id=1 的數據進行加鎖,但是未提交事物,此時別的線程只可讀卻無法更改
線程B
BEGIN; -- 查詢出id=1的數據 SELECT * FROM work_order WHERE id = 1 ; -- 修改id=1的狀態爲V UPDATE work_order set `status` = 'V' WHERE id = 1 ; COMMIT;
執行結果,可以查詢出id=1的數據,修改時會等待線程A釋放鎖,否則會進行等待
innodb_row_lock
Innodb_row_lock_current_waits : 當前等待的鎖的數量
Innodb_row_lock_time:鎖的總時長
Innodb_row_lock_time_avg:每次等待鎖花時間的平均數
Innodb_row_lock_time_max:最大的一次等待鎖花的時間
Innodb_row_lock_waits:一共等待鎖的次數