MySQL事務+FOR UPDATE解決併發操作資料庫
注意 FOR UPDATE 僅適用於InnoDB,且必須在事務區塊(BEGIN/COMMIT)中才能生效。
由於InnoDB 預設是Row-Level Lock,所以只有「明確」的指定主鍵,MySQL 才會執行Row lock (只鎖住被選取的資料) ,否則MySQL 將會執行Table Lock (將整個資料表單給鎖住)。
例如下面幾種情況
A.假設有個表單products ,裡面有id 跟name 二個欄位,id 是主鍵。
(明確指定主鍵,並且有此資料,row lock也就是行鎖)
SELECT * FROM products WHERE id='3' FOR UPDATE;
B.(明確指定主鍵,若查無此資料,無lock)
SELECT * FROM products WHERE id='-1' FOR UPDATE;
C.(無主鍵,table lock)
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;
D .(主鍵不明確,table lock)
SELECT * FROM products WHERE id<>'3' FOR UPDATE;
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;
要測試鎖定的狀況,可以利用MySQL 的Command Mode ,開二個視窗來做測試
MySQL update && select
CREATE TABLE `testupdate` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`val` bigint(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
update testupdate
set val = val+1
where id = 1 and @value := val+1;
select @value;