數(shù)據(jù)庫的死鎖: 和 JAVA的 死鎖類似 ,條件 ,兩個事務(線程) ,事務1 和事務2 ,事務1 要拿到 了 鎖a ,等待 鎖 b ,事務2 拿到了 鎖b ,等待鎖a。 這時候就死鎖了。
備注: java 我們很明顯的 知道什么時候加的鎖什么時候釋放鎖,比如 synch 方法( 進入方法前獲取鎖,方法執(zhí)行完畢釋放鎖 ), synch 語句塊( 進入語句塊 和退出 語句塊 ) ,lock 接口( lock 和 unlock 的時候 )。
數(shù)據(jù)庫加鎖在什么時候呢?
MySQL 為例, mysql 的寫是加的 寫鎖,也就是獨占鎖, mysql innodb 的讀 因為有個非鎖定讀的機制,所以 讀的時候不需要加鎖,并且讀的時候別的事務 也能改這份數(shù)據(jù),但是 讀線程讀到的依舊是 事務啟動的時候的數(shù)據(jù)( RR 事務隔離級別 描述的 可重復讀)。
也就是 innodb 讀不加鎖。但是寫加了鎖,在什么時候加鎖呢? 在我們執(zhí)行一條 update 語句的時候。 在什么時候釋放鎖呢? 在事務提交的時候。
時間 事務a 開始 事務b 開始
t1 1 隨便 讀點啥..... 1 隨便 搞點啥
t2 2 update 資源 1 鎖 資源1,如果拿不到就等待 2 update 資源2 鎖定資源2 ,鎖不到就等待
t3 3 隨便搞搞點 啥 3 隨便搞點啥
t4 4 update 資源 2 鎖資源2,如果拿不到就等待 4 update 資源1 鎖定資源1 ,鎖不到就等待
上面說過 鎖會在事務提交的時候釋放,所以 兩個事務就鎖死了。
做實驗的時候可以 關閉mysql 的自動提交 ,然后2 個窗口敲 ?;蛘?java代碼里面通過 java的 CyclicBarrier 讓兩個事務 在 t3 的時間點對齊 。
然后說說數(shù)據(jù)庫死鎖的解決辦法。
1 編碼規(guī)范有計劃的順序更新數(shù)據(jù)避免出現(xiàn) 相互抱鎖的 問題。
2 數(shù)據(jù)庫線程有超時 機制,一個事務超時,鎖被釋放,另一個線程就會向下執(zhí)行了。
3 數(shù)據(jù)庫有死鎖檢查 機制,發(fā)現(xiàn)死鎖的時候 會讓 更新少的 一個 事務回滾。
innodb_deadlock_detect=on 之歌參數(shù)默認是打開的,也就是mysql 默認就會處理死鎖問題。處理方式就是回滾 跟新少的事務。
4 mysql 如果關閉了 死鎖回滾 可以配置 等鎖超時 時間 innodb_lock_wait_timeout 。 默認是 5 0 秒。