本篇文章主要介紹mysql資料庫死鎖的產生原因及解決辦法
資料庫和作業系統一樣,是一個多用戶使用的共享資源,當多個用戶并發地存取資料時,在資料庫中就會產生多個事務同時存取同一資料的情況,若對并發操作不加控制就可能會讀取和存盤不正確的資料,破壞資料庫的一致性,加鎖是實作資料庫并發控制的一個非常重要的技術,
在實際應用中經常會遇到的與鎖相關的例外情況,當兩個事務需要一組有沖突的鎖,而不能將事務繼續下去的話,就會出現死鎖,嚴重影回應用的正常執行,
在資料庫中有兩種基本的鎖型別:
- 排它鎖(Exclusive Locks,即X鎖)
- 共享鎖(Share Locks,即S鎖),
當資料物件被加上排它鎖時,其他的事務不能對它讀取和修改,加了共享鎖的資料物件可以被其他事務讀取,但不能修改,資料庫利用這兩種基本的鎖型別來對資料庫的事務進行并發控制,
MySQL小白也不用擔心,今天還準備了mysql的學習教程,動力節點老杜講的mysql,就是專門為小白量身打造,每一個知識點都講解得非常細膩,不光有基礎的知識,mysql高級的內容也有詳細講,由淺入深,戳下邊鏈接
MySQL在線學習:
https://www.bilibili.com/video/BV1fx411X7BD
MySQL資料下載:
http://www.bjpowernode.com/?bokeyuanchaimysql
死鎖的第一種情況:
一個用戶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陳述句,建立相應的索引進行優化,
小結
總體上來說,產生記憶體溢位與鎖表都是由于代碼寫的不好造成的,因此提高代碼的質量是最根本的解決辦法,有的人認為先把功能實作,有BUG時再在測驗階段進 行修正,這種想法是錯誤的,正如一件產品的質量是在生產制造的程序中決定的,而不是質量檢測時決定的,軟體的質量在設計與編碼階段就已經決定了,測驗只是 對軟體質量的一個驗證,因為測驗不可能找出軟體中所有的BUG,
你學會了嗎!!!
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/337558.html
標籤:MySQL
上一篇:標準國民經濟行業分類與代碼GB/T 4754-2011存入mysql資料庫
下一篇:asd asd
