MySQL InnoDB鎖機制(一)

MySQL InnoDB一共有四種鎖:共享鎖(讀鎖,S鎖)、排他鎖(寫鎖,X鎖)、意向共享鎖(IS鎖)和意向排他鎖(IX鎖)。其中共享鎖與排他鎖屬於行級鎖,另外兩個意向鎖屬於表級鎖。

 

  • 共享鎖(讀鎖,S鎖):若事務T對數據對象A加上S鎖,則事務T可以讀A但不能修改A,其他事務只能再對A加S鎖,而不能加X鎖,直到T釋放S鎖。
  • 排他鎖(寫鎖,X鎖):若事務T對數據對象A加上X鎖,則只允許T讀取和修改A,其他事務不能再對A加作何類型的鎖,直到T釋放A上的X鎖。
  • 意向共享鎖(IS鎖):事務T在對錶中數據對象加S鎖前,首先需要對該表加IS(或更強的IX)鎖。
  • 意向排他鎖(IX鎖):事務T在對錶中的數據對象加X鎖前,首先需要對該表加IX鎖。

比如SELECT ... FROM T1 LOCK IN SHARE MODE語句,首先會對錶T1加IS鎖,成功加上IS鎖後纔會對數據加S鎖。

同樣,SELECT ... FROM T1 FOR UPDATE語句,首先會對錶T1加IX鎖,成功加上IX鎖後纔會對數據加X鎖。

MySQL InnoDB 鎖兼容陣列
  X IX S IS
X
IX
S
IS

 

 

MySQL官網上有個死鎖的例子,但分析得過於概括,這裏我們詳細分析一下。

首先,會話S1以SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE查詢,該語句首先會對t表加IS鎖,接着會對數據(i = 1)加S鎖。

 

mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)

mysql> INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+
| i    |
+------+
|    1 |
+------+
1 row in set (0.10 sec)
 接着,會話S2執行DELETE FROM t WHERE i = 1,該語句嘗試對t表加IX鎖,由於IX鎖與IS鎖是兼容的,所以成功對t表加IX鎖。接着繼續對數據(i = 1)加X鎖,但數據已經被會話S1事務加了S鎖了,所以會話S2等待。

 

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM t WHERE i = 1;
 接着,會話S1也執行DELETE FROM t WHERE i = 1,該語句首先對t表加IX鎖,雖然會話S2已經對t表加了IX鎖,但IX鎖與IX鎖之間是兼容的,所以成功對t表加上IX鎖。接着會話S1會對數據(i = 1)加X鎖,此時發現會話S2佔有的IX鎖與X鎖不兼容,所以會話S1也等待。就這樣,會話S1等S2釋放IX鎖,而會話S2等S1釋放S鎖,從而死鎖發生。
mysql> DELETE FROM t WHERE i = 1;
Query OK, 1 row affected (0.00 sec)

mysql>
 會話S2發生死鎖。
mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
mysql>
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章