場景描述
在update表的時候出現deadlockloserdataacces***ception異常 (deadlock found when trying to get lock; try restarting transaction...)。
問題分析
這個異常並不會影響使用者使用,因為資料庫遇到死鎖會自動回滾並重試。使用者的感覺就是操作稍有卡頓。但是監控老是報異常,所以需要解決一下。
延伸:資料庫死鎖
資料庫死鎖是事務性資料庫 (如sql server, mysql等)經常遇到的問題。除非資料庫死鎖問題頻繁出現導致使用者無法操作,一般情況下資料庫死鎖問題不嚴重。在應用程式中進行try-catch就可以。那麼資料死鎖是如何產生的呢?
innodb實現的是行鎖 (row level lock),分為共享鎖 (s) 和 互斥鎖 (x)。
共享鎖用於事務read一行。
互斥鎖用於事務update或delete一行。
當客戶a持有共享鎖s,並請求互斥鎖x;同時客戶b持有互斥鎖x,並請求共享鎖s。以上情況,會發生資料庫死鎖。如果還不夠清楚,請看下面的例子。
資料庫死鎖例子
首先,客戶a建立乙個表t,並向t中插入一條資料,客戶a開始乙個select事務,所以拿著共享鎖s。
mysql> create table t (i int) engine = innodb;
query ok, 0 rows affected (1.07 sec)
mysql> insert into t (i) values(1);
query ok, 1 row affected (0.09 sec)
mysql> start transaction;
query ok, 0 rows affected (0.00 sec)
mysql> select * from t where i = 1 lockin share mode;
| i |
| 1 |
然後,客戶b開始乙個新事務,新事務是delete表t中的唯一一條資料。
mysql> start transaction;
query ok, 0 rows affected (0.00 sec)
mysql> delete from t where i = 1;
刪除操作需要互斥鎖 (x),但是互斥鎖x和共享鎖s是不能相容的。所以刪除事務被放到鎖請求佇列中,客戶b阻塞。
最後,客戶a也想刪除表t中的那條資料:
mysql> delete from t where i = 1;
error 1213 (40001): deadlock found when trying to get lock;
try restarting transaction
死鎖產生了!因為客戶a需要鎖x來刪除行,而客戶b拿著鎖x並正在等待客戶a釋放鎖s。看看客戶a,b的狀態:
客戶a: 拿著鎖s,等待著客戶b釋放鎖x。
客戶b: 拿著鎖x,等待著客戶a釋放鎖s。
發生死鎖後,innodb會為對乙個客戶產生錯誤資訊並釋放鎖。返回給客戶的資訊:
error 1213 (40001): deadlock found when trying to get lock;
try restarting transaction
所以,另乙個客戶可以正常執行任務。死鎖結束。
C 模擬死鎖問題
模擬學生作筆記,假設乙個學生只有同時擁有筆記本和筆才能學習,這裡模擬2個學生,但只有1個筆記本和乙隻筆 如果想進行學習,需同時獲得筆記本和筆,當a同學獲得筆記本時,b也已獲得筆,此時,a試圖獲得b的筆,而b試圖獲得a的筆記本,此時便發生死鎖 using system using system.col...
使用java執行緒模擬死鎖
原文 當兩個或多個執行緒之間同時等待對方釋放資源的時候就會形成執行緒之間的死鎖 當兩個執行緒被阻塞,每個執行緒在等待另乙個執行緒時就發生死鎖 當多個執行緒等待乙個物件鎖時,沒有獲取到鎖的執行緒將發生阻塞。執行緒的阻塞 1.sleep 方法 sleep 允許指定以毫秒為單位的一段時間作為引數,它使得執...
乙個模擬死鎖的多執行緒
package org.kevinlifeng public class testdeadlock implements runnable catch interruptedexception e t1嘗試鎖o2 可o2 已經被t2 給鎖住了還沒釋放,一直等待 synchronized o2 到了這...