之前在面試中被問到此問題,在此做下筆記!
Mysql場景的存儲引擎爲MyISAM和InnoDB,我們以這兩種來分析。
MyISAM
總:MyISAM中不會出現死鎖。
在MyISAM中只用到表鎖,不會有死鎖的問題,鎖的開銷也很小,但是相應的併發能力很差。
解析:MyISAM不支持事務,即每次的讀寫都會隱性的加上讀寫鎖,而我們知道讀鎖是共享的,寫鎖是獨佔的,意味着當一個Session在寫時,另一個Session必須等待。
InnoDB
*總:InnoDB中會出現死鎖。
InnoDB中實用了行鎖和表鎖,當未命中索引時,會自動退化爲表鎖。
我們舉一個出現死鎖的例子。
假設我們有個賬戶金額表 user_balance,包括兩個字段,分別是 username 用戶名、balance 餘額。(例子來源極客時間“sql必知必會”)
某時刻用戶 A 和用戶 B 之間進行轉賬,同時數據庫管理員想要查詢 user_balance 表中的總金額:
SELECT SUM(balance) FROM user_balance
當我們讀取的時候用了加行鎖,可能會出現死鎖的情況,若 B 開始執行給 A 轉賬:
UPDATE user_balance SET balance=balance-100 WHERE username ='B'
UPDATE user_balance SET balance=balance+100 WHERE username =‘A’
UPDATE user_balance SET balance=balance+100 WHERE username ='A'
我們會發現此時 A 被鎖住了,而管理員事務還需要對 B 進行訪問,但 B 被用戶事務鎖住了,此時就發生了死鎖。
解決方法爲InnoDB中的MVCC機制,之後的博客再做介紹,或者讀者可以自行了解下這種機制。