MySQL中有一個(gè)樂觀鎖的概念,稱為version。當(dāng)對于一條數(shù)據(jù)進(jìn)行更新時(shí),如果數(shù)據(jù)庫中的version與操作者傳過來的version不一致,則更新失敗,返回錯(cuò)誤信息。這種方式被稱為樂觀鎖,因?yàn)樗嘈挪l(fā)更新時(shí)數(shù)據(jù)間的沖突比較少。
然而,使用version實(shí)現(xiàn)樂觀鎖也帶來了一些問題。在使用InnoDB存儲引擎的情況下,使用了version的表將會被鎖定,這意味著更新時(shí)將會產(chǎn)生表級鎖。
mysql>create table test(id int primary key, version int, name varchar(20)) engine=innodb;
Query OK, 0 rows affected (0.29 sec)
mysql>insert into test values(1, 0, 'hello');
Query OK, 1 row affected (0.06 sec)
mysql>start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql>select * from test where id=1;
+----+---------+-------+
| id | version | name |
+----+---------+-------+
| 1 | 0 | hello |
+----+---------+-------+
1 row in set (0.00 sec)
mysql>update test set name='world', version=1 where id=1 and version=0;
Query OK, 1 row affected (0.06 sec)
mysql>select * from test where id=1;
+----+---------+-------+
| id | version | name |
+----+---------+-------+
| 1 | 1 | world |
+----+---------+-------+
1 row in set (0.00 sec)
mysql>update test set name='world', version=1 where id=1 and version=0;
Query OK, 0 rows affected (0.02 sec)
mysql>rollback;
Query OK, 0 rows affected (0.00 sec)
在上述例子中,我們可以看到當(dāng)更新的行被鎖定時(shí),事務(wù)將被掛起,直到鎖被釋放。這種行為同樣適用于其他DML語句。當(dāng)一條語句在執(zhí)行時(shí)被阻塞時(shí),數(shù)據(jù)庫將產(chǎn)生死鎖,并將等待直到死鎖解除。
因此,雖然使用version實(shí)現(xiàn)樂觀鎖可以減少沖突,但它也帶來了其他問題。為此,使用version應(yīng)該是謹(jǐn)慎的,并需要策略性地選擇。一般來說,如果一個(gè)表需要頻繁的修改和查詢請求,那么不應(yīng)該使用version。