產生原因:
- 兩個線程
- 不同方向
- 相同資源
只要上面3個碰在一起一定會出現死鎖問題!
舉個例子:轉賬
兩個事務單元
事務單元一
第一步操作:Lock Bob
第二部操作:Lock Simth
事務單元二
第一步操作:Lock Simth
第二部操作:Lock Bob
他們倆都持有一把鎖;
事務單元2想要Lock Bob的時候,他是進不到Bob那個鎖上面的,於是事務單元2就等待了;
而事務單元1想要Lock Smith的時候,他也是進不到Smith的那個鎖上面的,他也會在外面等待;
相互之間等待,而相互之間又維持了一個鎖,這就是死鎖產生的原因
死鎖解決辦法:
- 儘可能不死鎖
如:儘可能降低隔離級別,因爲死鎖的核心主要就是事務之間相互等待產生的;
不加讀鎖自然而然就能減少死鎖的可能;
這個一般對用戶要求較高,所以一般數據庫會提供兩個主要的死鎖檢測的方法:第一種交碰撞檢測;第二種叫等鎖超時 - 碰撞檢測
把事務單元和事務單元所維持的鎖都記錄下來,比如把事務單元1所有等待的鎖,去申請鎖之前先記錄到內存裏,當他鎖住Bob的時候,再去鎖住Smith的時候需要去申請另外一把鎖,然後利用Smith在查看看這把鎖申請的事務單元有哪些鎖,發現事務單元2,然後去看事務單元2又是在申請哪些鎖,會發現又回來了,於是在這種情況下,就認爲在事務單元1中Lock Smith的時候發生了一個碰撞;於是解決了這個死鎖問題,只要終止一邊就可以了!
這種方式的效率一般來說是最高的;等鎖超時效率稍微會低一點 - 等鎖超時
也是一種比較常見的作法,我等待持有鎖的時間,比如持有超過一分鐘,我就認爲這個鎖可能有問題,超時了直接給你報錯,但這種方式會帶來一個問題;比如超長事務,這種死鎖檢測的方式會導致每一個死鎖被發現都需要非常長的時間,有些時候是不能接受的,所以在主流的數據庫中主要是使用碰撞檢測;