日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

1-2 【包子mysql系列】, 对mysql的innoDB加锁分析

發布時間:2025/5/22 数据库 57 如意码农
生活随笔 收集整理的這篇文章主要介紹了 1-2 【包子mysql系列】, 对mysql的innoDB加锁分析 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

innoDB的事務,是基于鎖來實現的,用到事務不自然就會用到鎖,而如果對鎖理解的不通透,很容易造成線上問題。

數據庫加鎖的分析,和事務的引擎,隔離級別,索引,主鍵索引都有關系,

如果去考慮引擎和各種隔離級別的話,就會很復雜了,所以下面都是基于innoDB和RR的隔離級別進行分析:

表結構:

內容:

1 , 根據主鍵更新

如果根據主鍵來行數

事務A

事務B

 

update user set name='ce1' where id='1';

update user set name='ce3' where Id='3';

同時執行,都成功

update user set name='ce1' where id='1';

update user set name='ce3' where userId='10003';

B更新失敗,直至:Lock wait timeout

結論,如果根據非主鍵來更新,會把整個表進行鎖定,無法 進行更新操作。

注:只要是根據主鍵索引來更新,哪怕事務A沒命中主鍵,也不會鎖定整個表

2,根據非索引非主鍵更新

事務A

事務B

 

update user set name='ce1' where userId='10001';

update user set name='ce3' where Id='3';

或者

update user set name='ce3' where userId='10003'

都會失敗,如果非索引,直接鎖表

3, 如果在userId 列上加入普通唯一索引

修改成

再更新

事務A

事務B

 

update user set name='ce1' where userId='10001';

update user set name='ce3' where Id='3';

或者

update user set name='ce3' where userId='10003'

都會成功,如果有唯一索引,也是能成功行數,互相不影響

4, 如果在userId 列上加入普通非唯一索引 (重點探討)

把userId改成非唯一索引:

記錄內容如下:

+----+--------+------+

| id | userId | name |

+----+--------+------+

| 1 | 10001 | ce1 |

| 2 | 10002 | ce2 |

| 3 | 10001 | ce3 |

| 4 | 10004 | ce4 |

+----+--------+------+

再相同操作

事務A

事務B

 

update user set name='ce1' where userId='10001';

update user set name='ce3' where Id='3';

B失誤執行失敗,顯然id=3的這行也被鎖住了

其實最終還是按主鍵鎖住的記錄 id=1和id=3的記錄

非唯一索引與普通索引,更一步的區別是GAP鎖

gap鎖是用于解決幻讀的存在,演示

把記錄修改成,如:

id為pk. userId為Normal key

A事務

B事務

結果

begin;

update user set name='ce22' where userId='100020';

   
 

insert into user (userId,name) values('100021','tttt');

直至事務失敗超時

1, 首先GAP鎖針對的是insert操作

2, 當更新userId='100020'時,會鎖住兩邊的記錄區間,防止幻讀的存在。

3, 鎖是作用在普通索引上,但由于索引是由B+樹存儲,那么鎖住的是兩邊的區間,防止insert

GAP鎖為什么不是鎖住一條記錄,而是鎖住一個區間呢? 

附上疑問: https://www.oschina.net/question/867417_2289606

其實:

GAP鎖是解決幻讀存在的,如當 delete時就必須鎖住區間了

A事務

B事務

 

begin;

delete from user where userId='888888';

   
 

insert into user (userId,name) values('100021','tttt');

OK, 可以插入

 

insert into user (userId,name) values('100041','tttt');

插入超時

可見,這個GAP鎖,鎖住的是100040~無窮大 的記錄

死鎖的產生分析

1, 兩條語句產生的死鎖

id = pk, userId= key

最簡單的。兩條語句互相更新等待

begin;

update user set name='ce1' where userId='100010';

begin;

update user set name='ce2' where userId='100020';

update user set name='ce2' where userId='100020';

update user set name='ce1' where userId='100010';

 

最簡單的死鎖

2, 由于gap鎖,刪除一臺不存在的記錄

如,先刪除一條記錄,然后插入一條記錄, 如果記錄GAP鎖沖突,兩個事務容易互為死鎖。如:

A事務

B事務

begin;

delete from user where userId='100020';

(Query OK, 1 row affected)

begin;

delete from user where userId='565656';

insert into user (userId,name) values('100041','tttt');

 

insert into user (userId,name) values('100019','tttt');

結果直接拋出:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

分析:

A事務 delete 加入gap鎖【100010,100020】, 第二段【100020,100030】

B事務 delete加入gap 鎖【100040,無窮大】

然后A事務插入,獲取插入意向鎖時B事務的GAP鎖被阻塞

B事務插入,獲取插入意向鎖時時被A事務的GAP鎖阻塞

結果死鎖

總結

以上是生活随笔為你收集整理的1-2 【包子mysql系列】, 对mysql的innoDB加锁分析的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。