資料庫死鎖分析與解決

2021-09-02 20:58:30 字數 2492 閱讀 8521

一、死鎖的表現

1、錯誤資訊是:事務(程序 id)與另乙個程序被死鎖在 鎖 資源上,並且已被選作死鎖犧牲品。請重新執行該事務。

2、錯誤資訊是:事務(程序 id )與另乙個程序被死鎖在 鎖 | 通訊緩衝區 資源上,並且已被選作死鎖犧牲品。請重新執行該事務。

二、死鎖的原因

1、由於多使用者、多工的併發性和事務的完整性要求,當多個事務處理對多個資源同時訪問時,若雙方已鎖定一部分資源但也都需要對方已鎖定的資源時,無法在有限的時間內完全獲得所需的資源,就會處於無限的等待狀態,從而造成其對資源需求的死鎖。

2、資料庫本身加鎖機制的實現方法不同,各資料庫系統也會產生其特殊的死鎖情況。如在sybase sql server 11 中,最小鎖為 2k

一頁的加鎖方法,而非行級鎖。如果某張表的記錄數少且記錄的長度較短(即記錄密度高,如應用系統中的系統配置表或系統參數列就屬於此類表),被訪問的頻率高,就容易在該頁上產生死鎖。

表現一:

乙個使用者 a 訪問表 a(鎖住了表 a),然後又訪問表 b。另乙個使用者 b 訪問表 b(鎖住了表 b),

然後企圖訪問表 a。這時使用者 a 由於使用者 b 已經鎖住表 b,它必須等待使用者 b 釋放表 b,

才能繼續,同樣使用者 b 要等使用者 a 釋放表 a 才能繼續操作,這樣就造成了死鎖。

解決方法:

這種死鎖是由於程式的 bug 產生的,需調整程式對資料庫層的實現邏輯。仔細分析程式的邏輯:

(1)盡量避免同時鎖定兩個資源。

(2)必須同時鎖定兩個資源時,要保證在任何時刻都應該按照相同的順序來鎖定資源。

表現二:

使用者 a 讀一條紀錄,然後修改該條紀錄,同時使用者 b 也修改該條紀錄。這裡使用者 a 的事務裡鎖的性質由共享鎖企圖上公升到獨佔鎖 (for update),而使用者 b 裡的獨佔鎖由於 a 有共享鎖存在所以必須等 a 釋放掉共享鎖,而 a 由於 b 的獨佔鎖而無法上公升的獨佔鎖也就不可能釋

放共享鎖,於是出現了死鎖。這種死鎖比較隱蔽,但其實在稍大點的專案中經常發生。

解決方法:

讓使用者 a 的事務(即先讀後寫型別的操作),在 select 時就是用 update lock。

語法如下:select * from table1 with(updlock) where ….

三、常見死鎖情況及解決方法

1、不同的儲存過程、觸發器、動態 sql 語句段按照不同的順序同時訪問多張表。

在系統實現時應規定所有儲存過程、觸發器、動態 sql 語句段中,對多張表的操作總是使用同一順序。如:有兩個儲存過程 procedure1、procedure2,都需要訪問三張表 table1、table2

和 table3,如果 procedure1 按照 table1、table2 和 table3 的順序進行訪問,那麼,procedure2也應該按照以上順序訪問這 3 張表。

2、在交換期間新增記錄頻繁的表,但在該錶上使用了非群集索引(non-clustered)。

對在交換期間新增記錄頻繁的表,使用群集索引(clustered),以減少多個使用者新增記錄到該錶的最後一頁上,在表尾產生熱點,造成死鎖。這類表多為往來賬的流水表,其特點是在交換期間需要在表尾追加大量的記錄,並且對已新增的記錄不做或較少做刪除操作。

3、表中的記錄少,且單條記錄較短,被訪問的頻率較高。

對單張表中記錄數不太多,且在交換期間 select 或 update 較頻繁的錶可使用設定每頁最大行的辦法,減少資料在表中存放的密度,模擬行級鎖,減少在該錶上死鎖情況的發生。這類表多為資訊繁雜且記錄條數少的表。

如:系統配置表或系統參數列。在定義該錶時新增如下語句: with max_rows_per_page=1

4、整張表被訪問的頻率高(如**對照表的查詢等)。

在儲存過程、觸發器、動態 sql 語句段中,若對某些整張表 select 操作較頻繁,則可能在

該錶上與其他訪問該錶的使用者產生死鎖。對於檢查賬號是否存在,但被檢查的字段在檢查期間不會被更新等非關鍵語句,可以採用在 select 命令中使用 at isolation read uncommitted 子句的方法解決。該方法實際上降低了 select 語句對整張表的鎖級別,提高了其他使用者對該錶

操作的併發性。在系統高負荷執行時,該方法的效果尤為顯著。

例如: select*from titles at isolation read uncommitted

5、對流水號一類的順序數生成器字段,可以先執行 update 流水號欄位+1,然後再執行 select

獲取流水號的方法進行操作。

備註:nolock(不加鎖):此選項被選中時,sql server 在讀取或修改資料時不加任何鎖。在這種情況下,使用者有可能讀取到未完成事務(uncommitted transaction)或回滾(roll back)中資料,即所謂的「髒資料」。

updlock(修改鎖):此選項被選中時,sql server 在讀取資料時使用修改鎖來代替共享鎖,並將此鎖保持至整個事務或命令結束。使用此選項能夠保證多個程序能同時讀取資料但只有該程序能修改資料。

oracle資料庫死鎖解決

進入oracle使用者 su oracle 進入dba模式 sqlplus as sysdba 1.查詢被鎖的情況 select object name,machine,s.sid,s.serial from v locked object l,dba objects o v session s w...

資料庫死鎖解決方案

一 活鎖 如果事務t1封鎖了資料r,事務t2又請求封鎖r,於是t2等待。t3也請求封鎖r,當t1釋放了r上的封鎖之後系統首先批准了t3的請求,t2仍然等待。然後t4又請求封鎖r,當t3釋放了r上的封鎖之後系統又批准了t4的請求,t2有可能永遠等待,這就是活鎖的情形。避免活鎖的簡單方法是採用先來先服務...

資料庫死鎖解決辦法

1.之前遇到過乙個場景 有乙個使用者登入一直失敗,但是其他使用者卻可以正常登入,後來測試藉口發現在登入時更新這個使用者的登入時間時,一直沒有反應然後超時了。因為innordb是行級鎖的所以就想到了是這條使用者的資訊被鎖住了。2.解決方案 執行語句 select from information sc...