1. 程式人生 > >關於mysql鎖等待及等待超時的詳細案例( Lock wait timeout exceeded)

關於mysql鎖等待及等待超時的詳細案例( Lock wait timeout exceeded)

關於mysql鎖的一些基礎知識後期再更新一篇部落格,這裡先直接進入鎖等待的案例,不明白基礎知識的讀者請先去查詢其他相關的部落格學習以下。

簡單介紹下相關的sql:

  • show variables like "autocommit"  檢視當前會話是否自動提交事務;
  • set autocommit = 0  設定當前會話為非自動提交事務  0:非自動提交事務,對應 OFF   1:自動提交事務,對應為 ON
  • show variables like "Innodb_lock_wait_timeout"  檢視當前會話鎖等待超時時間限制,預設為50S;
  • set Innodb_lock_wait_timeout = 5; 設定當前會話鎖等待超時時間為5S
  • commit  提交當前會話的事務

案例1:兩個不同session同時對滿足條件的行資料進行update導致鎖等待超時,此時丟擲等待超時異常(即使使用的過濾條件不存在索引,也會陷入鎖等待)

  • 在sessionA開啟非自動提交事務,設定set autocommit = 0;
  • sessionA執行update:update user_info set age = 11 WHERE name = 'session A update 21';此時相當於sessionA擁有了name為“session A update 21”的行資料的排他鎖(X鎖);
  • sessionB同樣開始非自動提交事務:設定set autocommit = 0;
  • sessionB設定鎖等待超時時間為5S,方便觀察等待超時現象:set Innodb_lock_wait_timeout = 5;
  • sessionB同樣執行update操作:update user_info set age = 12 WHERE name = 'session A update 21';因為更新的資料行和sessionA更新的資料行一致,且sessionA的事務還沒提交,相當於排他鎖還沒釋放,所以sessionB進入鎖等待時間;
  • 超過5秒後,sessionB出現鎖等待超時i異常:Lock wait timeout exceeded; try restarting transaction
    ,如圖:

案例2:間隙鎖【排他鎖】導致的鎖等待——在非自動提交事務的前提下,sessionA試圖刪除一條不存在的資料,產生間隙鎖,此時sessionB試圖insert一條間隙範圍內的資料,處於鎖等待;

表結構:user_info (primary key id,name,age key);  分析:id為Record Lock ,age為 next-key lock

  • 已知存在age為12,20,30,35,50的資料;
  • session A 執行刪除語句:delete from user_info WHERE age = 15;此時因為不存在age=15的資料,所以產生間隙鎖,鎖範圍為[12,20];所以在sessionA事務未提交之前,不能對該為範圍內的資料加鎖,即不能進行update操作(包括 update,delete,insert);
  • session B執行insert操作:INSERT into user_info VALUES(REPLACE(UUID(),"-",""),"鎖",18),結果:Lock wait timeout exceeded; try restarting transaction
  • 分析:因為session A已經產生範圍為[12,20]的間隙鎖,此時插入的18在間隙鎖範圍內,必須等待sessionA提交事務或者等待鎖超時異常進行事務回滾;