MySQL InnoDB 鎖

鎖的類型 https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html

測試表

CREATE TABLE `dev` (
  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
  `x` int NOT NULL DEFAULT '0' COMMENT 'x',
  `y` int NOT NULL DEFAULT '0' COMMENT 't',
  `z` int NOT NULL DEFAULT '0' COMMENT 'z',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_z` (`z`),
  KEY `idx_y` (`y`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='table';

測試數(shù)據(jù)

INSERT INTO `dev` (`x`, `y`, `z`) VALUES (2, 22, 222),(4, 44, 444),(6, 66, 666);

版本
select version(); // 輸出:8.0.25
select @@SESSION.transaction_isolation; //輸出:REPEATABLE-READ

現(xiàn)象1(記錄存在的等值查詢):
session 1

begin;
select * from dev where y = 44 for update;

session 2

begin;
INSERT INTO `dev` (`x`, `y`, `z`) VALUES (1, 11, 111); // 成功寫入
INSERT INTO `dev` (`x`, `y`, `z`) VALUES (1, 22, 200); //  輸出: Lock wait timeout exceeded; try restarting transaction
INSERT INTO `dev` (`x`, `y`, `z`) VALUES (4, 44, 400);//  輸出: Lock wait timeout exceeded; try restarting transaction
INSERT INTO `dev` (`x`, `y`, `z`) VALUES (5, 55, 555);//  輸出: Lock wait timeout exceeded; try restarting transaction
INSERT INTO `dev` (`x`, `y`, `z`) VALUES (6, 66, 600); // 成功寫入 

結(jié)論1:
鎖是加在索引上,算法為next-key lock,是一個左閉右開的區(qū)間,因此y=22行不能新寫入。其中y=44不是唯一索引,InnoDB 會繼續(xù)查找到下一個y不等于44的記錄,因?yàn)槭亲箝]右開,因此數(shù)據(jù)y=44不能新寫入,而y=66可以新寫入。

現(xiàn)象2(記錄存在的唯一索引的等值查詢):
session 1

begin;
select * from dev where z = 444 for update;

session 2

begin;
INSERT INTO `dev` (`x`, `y`, `z`) VALUES (3, 33, 333); // 成功寫入

結(jié)論2:
記錄存在的唯一索引的等值查詢,next-key lock會優(yōu)化為 record lock

現(xiàn)象3(記錄不存在的等值查詢)
select * from dev where y = 40 for update; // 按照之前的結(jié)論:鎖的區(qū)間應(yīng)該為 [22, 44)(注意是左閉右開),也就是寫入y=22,33是失敗的,y=44是成功的

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容