資料庫死鎖產生的原因及解決方案:1、程式的BUG產生,需要調整的程式的邏輯;2、頁面的按鈕沒有立即生效,需要使用樂觀鎖、悲觀鎖來控制;3 、執行多個不符合條件的update語句;需要對語句進行分析,建立對應的索引進行最佳化。
資料庫死鎖產生的原因及解決方案:
在資料庫中有兩種基本的鎖定類型:排它鎖定
(Exclusive Locks,即X鎖定)和共用鎖定
(Share Locks,即S鎖定)。當資料物件被加上排它鎖時,其他的事務不能對它讀取和修改。加了共享鎖的資料物件可以被其他事務讀取,但不能修改。資料庫利用這兩 種基本的鎖類型來對資料庫的事務進行並發控制。
相關圖文教學:mysql資料庫圖文教學
#死鎖的第一種情況
#一個用戶A 訪問表A(鎖定了表A),然後又訪問表B;另一個用戶B 訪問表B(鎖住了表B),然後企圖訪問表A;這時用戶A由於用戶B已經鎖住表B,它必須等待用戶B釋放表B才能繼續,同樣用戶B要等用戶A釋放表A才能繼續,這就死鎖就產生了。
解決方法:
這種死鎖比較常見,是由於程式的BUG產生的,除了調整的程式的邏輯沒有其它的辦法。仔細分析程序的邏輯,對於資料庫的多表操作時,盡量按照相同的順序進行處理,盡量避免同時鎖定兩個資源,如操作A和B兩張表時,總是按先A後B的順序處理, 必須同時鎖定兩個資源時,要確保在任何時刻都應該按照相同的順序來鎖定資源。
死鎖的第二種情況
用戶A查詢一筆紀錄,然後修改該條紀錄;這時用戶B修改該條紀錄,這時用戶A的事務裡鎖的性質由查詢的共享鎖企圖上升到獨佔鎖,而用戶B裡的獨佔鎖由於A 有共享鎖存在所以必須等A釋放掉共享鎖,而A由於B的獨佔鎖而無法上升的獨佔鎖也就不可能釋放共享鎖,於是出現了死鎖。這種死鎖比較隱蔽,但在稍大點的項 目中常發生。如在某項目中,頁面上的按鈕點擊後,沒有使按鈕立刻失效,使得用戶會多次快速點擊同一按鈕,這樣同一段程式碼對資料庫同一筆記錄進行多次操作,很容易就出現這種死鎖的情況。
解決方法:
1、對於按鈕等控件,點擊後使其立刻失效,不讓使用者重複點擊,避免對同時對同一記錄操作。
2、使用樂觀鎖定進行控制。樂觀鎖大多是基於資料版本(Version)記錄機制實作。即為資料增加一個版本標識,在基於資料庫表的版本解決方案中,一般是 透過為資料庫表增加一個「version」字段來實現。讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交資料的版本資料與數 據庫表對應記錄的當前版本資訊進行比對,如果提交的資料版本號大於資料庫表目前版本號,則予以更新,否則認為是過期資料。樂觀鎖機制避免了長事務中的資料 庫加鎖開銷(用戶A和用戶B操作過程中,都沒有對資料庫資料加鎖),大大提升了大並發量下的系統整體效能表現。 Hibernate 在其資料存取引擎中內建了樂觀鎖實作。需要注意的是,由於樂觀鎖定機制是在我們的系統中實現,來自外部系統的使用者更新操作不受我們系統的控制,因此可能會造 成臟資料被更新到資料庫中。
3、使用悲觀鎖定進行控制。悲觀鎖大多數情況下依靠資料庫的鎖定機制實現,例如Oracle的Select … for update語句,以確保操作最大程度的獨佔性。但隨之而來的就是資料庫效能的大量開銷,特別是對長事務而言,這樣的開銷往往無法負擔。如一個金融系統, 當某個操作員讀取用戶的數據,並在讀出的用戶數據的基礎上進行修改時(如更改用戶帳戶餘額),如果採用悲觀鎖機制,也就意味著整個操作過程中(從操作員讀出資料、開始修改直至提交修改結果的全過程,甚至還包括操作員中途去煮咖啡的時間),資料庫記錄始終處於加鎖狀態,可以想見,如果面對成百上千個並發,這樣的情況將導致災難性的後果。所以,採用悲觀鎖來控制時一定要考慮清楚。
死鎖的第三種情況
如果在事務中執行了一條不滿足條件的update語句,則執行全表掃描,把行級鎖定上升為表級鎖,多個這樣的事務執行後,就很容易產生死鎖和阻塞。類似的情 況還有當表中的資料量非常龐大而索引建的過少或不合適的時候,使得經常發生全表掃描,最終應用系統會越來越慢,最終發生阻塞或死鎖。
解決方法:
SQL語句中不要使用太複雜的關聯多表的查詢;使用「執行計劃」對SQL語句進行分析,對於有全表掃描的SQL語句,建立對應的索引進行最佳化。
相關學習推薦:mysql影片教學
以上是資料庫死鎖產生的原因及解決方案的詳細內容。更多資訊請關注PHP中文網其他相關文章!