MySQL(七)关于MySQL不同版本下临键锁锁定范围不同
MySQL InnoDB底層的鎖實現算法分為三種 :
記錄鎖,間隙鎖,臨鍵鎖。
之前在驗證MySQL的臨鍵鎖的時候使用docker安裝的最新版本的MySQL鏡像,發現其臨鍵鎖在最新的MySQL的表現和低版本(5.7)不一致,后面又自己驗證了一下,并整理成博客
本文使用的高低版本MySQL分別為:
高版本MySQL: 8.0.18
低版本MySQL : 5.7.10
高版本下執行
使用臨鍵鎖:
在事務2里試驗一下插入和查詢操作
mysql> begin; Query OK, 0 rows affected (0.00 sec)mysql> insert into t2 values(8,'8'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> insert into t2 values (13,'13'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> insert into t2 values (15,'15'); Query OK, 1 row affected (0.01 sec) mysql> insert into t2 values (9,'9'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> insert into t2 values (14,'14'); ERROR 1062 (23000): Duplicate entry '14' for key 'PRIMARY'mysql> select * from t2 where id = 13 for update; Empty set (0.00 sec)mysql> select * from t2 where id = 14 for update; +----+------+ | id | name | +----+------+ | 14 | 14 | +----+------+ 1 row in set (0.00 sec) mysql> select * from t2 where id = 9 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 如果命中的剛好的查詢范圍內最大的記錄 #事務1 mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from t2 where id > 6 and id < = 9 for update; +----+------+ | id | name | +----+------+ | 9 | 9 | +----+------+ 1 row in set (0.00 sec)#事務2 mysql> begin; Query OK, 0 rows affected (0.00 sec)mysql> insert into t2 values(8,'8'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> insert into t2 values (10,'10'); Query OK, 1 row affected (0.00 sec)mysql> select * from t2 where id = 14 for update; +----+------+ | id | name | +----+------+ | 14 | 14 | +----+------+ 1 row in set (0.00 sec)通過SQL試驗結論:
1)select * from t2 where id > 6 and id < 10 for update;// 鎖住范圍是(5,9],(9,14)
在(5,9],(9,14)區間對于插入是阻塞的,但是對于查詢操作,只有查詢事務1中SQL命中的記錄id=9才會阻塞,查詢其他記錄均不會阻塞
2)select * from t2 where id > 6 and id <= 9 for update;// 鎖住范圍是(5,9]
在(5,9]區間對于插入是阻塞的,但是對于查詢操作,只有查詢事務1中SQL命中的記錄id=9才會阻塞,查詢其他記錄均不會阻塞
?
在低版下執行
#事務1 mysql> begin; Query OK, 0 rows affected (0.00 sec) mysql> select * from t2 where id > 6 and id < 10 for update; +----+------+ | id | name | +----+------+ | 9 | 9 | +----+------+ 1 row in set (0.00 sec) 如果在事務1執行select * from t2 where id > 6 and id < = 9 for update; 其鎖定范圍和上面的SQL是一致的#事務2 mysql> begin; Query OK, 0 rows affected (0.00 sec)mysql> insert into t2 values(8,'8'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> insert into t2 values (9,'9'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> insert into t2 values (13,'13'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> insert into t2 values (14,'14'); ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> insert into t2 values (15,'15'); Query OK, 1 row affected (0.01 sec)mysql> select * from t2 where id = 13 for update; Empty set (0.00 sec)mysql> select * from t2 where id = 14 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transactionmysql> select * from t2 where id = 9 for update; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction結論:在(5,9],(9,14]區間對于插入是阻塞的,但是對于查詢操作,只有在查詢區間(5,9],(9,14]中存在的記錄才會阻塞,查詢其他記錄均不會阻塞
比較高低版本下的SQL執行結果區別,發現其區別主要是在對id=14的操作上
低版本:
mysql> insert into t2 values (14,'14');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> select * from t2 where id = 14 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
高版本:
mysql> insert into t2 values (14,'14');
ERROR 1062 (23000): Duplicate entry '14' for key 'PRIMARY'
mysql> select * from t2 where id = 14 for update;
+----+------+
| id | name |
+----+------+
| 14 | 14 ? |
+----+------+
1 row in set (0.00 sec)
所以MySQL在8.0對臨鍵鎖算法進行了優化
1)對于在SQL執行時沒有命中的記錄,在同個事務中執行相同SQL的時候也不會查詢到,對于插入和查詢沒必要阻塞
2)對于臨鍵鎖的鎖定范圍做了優化,如果查詢的時候SQL可能查詢到的最大值剛好是Next-Key的右閉區間的值,那么也就不需要鎖住下一個臨鍵區間
簡單來說MySQL 8.0中臨鍵鎖的鎖定范圍是命中的Record和包含當前查詢范圍的最小Gap的并集,這樣其實跟我們理解的需要鎖定的范圍更加一致
?
?
?
?
總結
以上是生活随笔為你收集整理的MySQL(七)关于MySQL不同版本下临键锁锁定范围不同的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL(六)InnoDB锁详解
- 下一篇: MySQL(八)MySQL性能优化