mysql死鎖

知識儲備:

1、官方文檔上說mysql是支持非鎖定讀的;這個功能是這樣實現的,如果事務a 要對行的數據進行更新的話,那麼事務a要得到行的x鎖,並把這一行

之前的樣子記錄在undo log裏面,這樣一來如果a 事務rollback 了就可以通過undo log 來恢復到之前的樣子;說白了非鎖定的一致性讀就是讀的

行的undo log 中的內容,所以這貨根本就不用上鎖。

2、在mysql中事務與鎖的關係:

1、事務開始之後申請鎖。

2、得到鎖之後才進行相關的操作,事務提交或回滾之後纔會去釋放申請到的鎖。

3、如果想要select 語句也加上s鎖可以在select 後面加上lock in share mode 子句。

4、mysql支持意向鎖、意向鎖是在表級別上的;
  5、innodb 對鎖的分配方式:

1、innodb 的鎖是需要用到的時候纔會去分配,並是一次性要把事務要用到的鎖分配完成後纔去執行事務。

2、對鎖的申請請求是放在一個隊列當中的,請申請的先得到。
    例子:一個lock in share mode 引起的死鎖問題:
1、準備環境:

create database tempdb;
use tempdb;
create table t(x int);
insert into t(x) values(1);

2、事務一執行如下語句:

複製代碼

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t where x=1 lock in share mode;

+------+
| x    |
+------+
|    1 |
+------+
1 row in set (0.00 sec)

複製代碼
  3、事務二執行如下語句:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> delete from t where x=1;

4、接着事務一又執行如下語句:

mysql> delete from t where x=1;

5、最後mysql 監控到死鎖

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

原因分析:

1、事務一先是得到了x=1 這一行上的s 鎖;

  2、事務二要去申請x=1    這一行上的x鎖,由於事務一已經得到了s鎖,所以它要等待事務一釋放s鎖。

  3、事務一又想去申請x=1  這一行上的x鎖,由於事務二的申請在事務一的前面發起,所以它要等待事務二完成後才能得到。

由以上分析可知,事務一,事務二產生了相互等待;進而死鎖產生。
用戶A查詢一條紀錄,然後修改該條紀錄;這時用戶B修改該條紀錄,這時用戶A的事務裏鎖的性質由查詢的共享鎖企圖上升到獨佔鎖,而用戶B裏的獨佔鎖由於A 有共享鎖存在所以必須等A釋放掉共享鎖,而A由於B的獨佔鎖而無法上升的獨佔鎖也就不可能釋放共享鎖,於是出現了死鎖。這種死鎖比較隱蔽,但在稍大點的項 目中經常發生。如在某項目中,頁面上的按鈕點擊後,沒有使按鈕立刻失效,使得用戶會多次快速點擊同一按鈕,這樣同一段代碼對數據庫同一條記錄進行多次操 作,很容易就出現這種死鎖的情況。

解決方法:

1、對於按鈕等控件,點擊後使其立刻失效,不讓用戶重複點擊,避免對同時對同一條記錄操作。
2、使用樂觀鎖進行控制。樂觀鎖大多是基於數據版本(Version)記錄機制實現。即爲數據增加一個版本標識,在基於數據庫表的版本解決方案中,一般是 通過爲數據庫表增加一個“version”字段來實現。讀取出數據時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提交數據的版本數據與數 據庫表對應記錄的當前版本信息進行比對,如果提交的數據版本號大於數據庫表當前版本號,則予以更新,否則認爲是過期數據。樂觀鎖機制避免了長事務中的數據 庫加鎖開銷(用戶A和用戶B操作過程中,都沒有對數據庫數據加鎖),大大提升了大併發量下的系統整體性能表現。Hibernate 在其數據訪問引擎中內置了樂觀鎖實現。需要注意的是,由於樂觀鎖機制是在我們的系統中實現,來自外部系統的用戶更新操作不受我們系統的控制,因此可能會造 成髒數據被更新到數據庫中。
3、使用悲觀鎖進行控制。悲觀鎖大多數情況下依靠數據庫的鎖機制實現,如Oracle的Select … for update語句,以保證操作最大程度的獨佔性。但隨之而來的就是數據庫性能的大量開銷,特別是對長事務而言,這樣的開銷往往無法承受。如一個金融系統, 當某個操作員讀取用戶的數據,並在讀出的用戶數據的基礎上進行修改時(如更改用戶賬戶餘額),如果採用悲觀鎖機制,也就意味着整個操作過程中(從操作員讀 出數據、開始修改直至提交修改結果的全過程,甚至還包括操作員中途去煮咖啡的時間),數據庫記錄始終處於加鎖狀態,可以想見,如果面對成百上千個併發,這 樣的情況將導致災難性的後果。所以,採用悲觀鎖進行控制時一定要考慮清楚。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章