1. 程式人生 > 其它 >MySQL 間隙鎖導致的死鎖場景分析

MySQL 間隙鎖導致的死鎖場景分析

實際業務場景

在我們使用mysql的時候,如果不注意間隙鎖容易引起死鎖,最近分析一個業務場景就是間隙鎖導致的死鎖,業務抽象如下:

系統有一個批量新增業務資源的功能,實現邏輯如下(businnessid為非唯一索引):

update 業務表 set isdeleted=1 where bussinessid=123;

insert into 業務表

在併發場景下,以上邏輯產生了死鎖。

以下為死鎖具體分析以及還原死鎖產生過程,最後給出解決方案。

建立一張表

CREATE TABLE `lock_demo` (

`id` INT NOT NULL AUTO_INCREMENT,

`index` INT NOT NULL,

`name` VARCHAR(50) NULL DEFAULT NULL,

PRIMARY KEY (`id`),

INDEX `index` (`index`)

)

COLLATE='utf8mb4_0900_ai_ci'

ENGINE=InnoDB

;

死鎖演示

事務一

事務二

update lock_demo set name='a' where index=1;

update lock_demo set name='a' where index=2; 未卡住,間隙鎖之間不衝突

insert into lock_demo(id,`index`,name)values(1,1,'1');

卡住,被事務二的間隙鎖鎖住

insert into lock_demo(id,`index`,name)values(2,2,'2');

檢測到死鎖

 具體步驟

步驟一

事務一

先更新一條記錄(不存在),不提交。

步驟二

事務二

更新一條記錄(不存在),不提交。

步驟三

事務一,執行一條新增語句,被事務二的間隙鎖鎖住

步驟四

事務二,執行一條新增語句,被事務一的間隙鎖鎖住,系統檢測到死鎖

解決方案

對於以上的業務,可以改寫sql避免死鎖

select id from 業務表  where bussinessid=123;

如果存在,

update 業務表 set isdeleted=1 where id in (xxx);

insert into 業務表