【MySQL】mysql死鎖以及死鎖日誌分析

1.死鎖的概念

死鎖:死鎖通常是事務相互等待對方資源,最後造成環路形成的。
對於死鎖,數據庫處理方法:犧牲一個鏈接,保證另一個鏈接成功執行。
發生死鎖會返回ERROR:1213 錯誤提示,大部分的死鎖InnoDB存儲引擎自己能夠偵測到,不須要人爲進行干預。
注意:
InnoDB存儲引擎並不會回滾大部分的錯誤異常,像阻塞章節裏面的例子,可是死鎖例外,發現死鎖後,InnoDB存儲引擎會立刻回滾一個事務,會返回1213錯誤。數據庫

2.死鎖的情形舉例:

eg1:

步 驟 事務1 事務2
1 begin; begin;
2 delete from info_area where id=1;
3 update info_users set mobile='18514656666' where mobile='18514656620';
4 update info_users set mobile='18514656666' where mobile='18514656620';
5 delete from info_area where id=1;

clipboard.png

clipboard.png
分析死鎖日誌:
第一部分
從日誌裏咱們能夠看到事務1當前正在執行update info_users set mobile='18514656666' where mobile='18514656620',該條語句正在申請表info_users的索引IDX_MOBILE的X鎖,因此提示lock_mode X waiting
第二部分:
而後日誌的下半部分說明了事務2當前‘持有的鎖’以及‘等待的鎖’:
從日誌的HOLDS THE LOCKS(S)塊中咱們能夠看到事務2持有索引IDX_MOBILE的X鎖,而且是記錄鎖(Record Lock)。該鎖是經過事務2在步驟2執行的update語句申請的。
從日誌的WAITING FOR THIS LOCK TO BE GRANTED塊中咱們能夠看到事務2正在申請持有表info_area的索引GEN_CLUST_INDEX的X鎖,該鎖是delete from info_area where id=1;語句申請的。ui

eg2:

步驟 事務1 事務2
1 begin; begin;
2 update info_users set name=’aaa’ where id=1;
3 update info_users set name='bbb' where id=2;
4 update info_users set name='bbb' where id=2;
5 update info_users set name=’aaa’ where id=1;

eg3:

步驟 事務1 事務2
1 begin; begin;
2 DELETE from users where uid='bbb';執行成功
3 DELETE from users where uid='bbb';等待
4 ERROR 1213 (40001) insert INTO users VALUES(2,'bbb'); 成功

clipboard.png

clipboard.png

分析死鎖日誌:
第一部分
從日誌裏咱們能夠看到事務1當前正在執行DELETE from users where uid='bbb';,該條語句正在申請索引UID的X鎖,因此提示lock_mode X waiting
第二部分:
而後日誌的下半部分說明了事務2當前‘持有的鎖’以及‘等待的鎖’:
從日誌的HOLDS THE LOCKS(S)塊中咱們能夠看到事務2持有索引UID的X鎖,而且是記錄鎖(Record Lock)。該鎖是經過事務2在步驟2執行的delete語句申請的。
從日誌的WAITING FOR THIS LOCK TO BE GRANTED塊中咱們能夠看到事務2正在申請持有索引UID的S鎖,該鎖是insert INTO users VALUES(2,'bbb');語句申請的。insert語句在普通狀況下是會申請X鎖,可是這裏出現了S鎖。這是由於uid字段是一個惟一索引,因此insert語句會在插入前進行一次duplicate key的檢查,爲了使此次檢查成功,須要申請S鎖防止其餘事務對uid字段進行修改。spa

那麼爲何該S鎖會失敗呢?這是對同一個字段的鎖的申請是須要排隊的。S鎖前面還有一個未申請成功的X鎖,因此S鎖必須等待,因此造成了循環等待,死鎖出現了。日誌

經過閱讀死鎖日誌,咱們能夠清楚地知道兩個事務造成了怎樣的循環等待,再加以分析,就能夠逆向推斷出循環等待的成因,也就是死鎖造成的緣由。索引

相關文章
相關標籤/搜索