Innodb

InnoDB 引擎似乎在 Mysql5.7 中自動鎖定表

  • November 6, 2018

我有一個名為學生的表,例如:

mysql> select * from students;
+----+-------+---------+
| id | name  | classId |
+----+-------+---------+
| 1  | Kris  |       7 |
| 2  | Tom   |       7 |
| 3  | Mary  |       2 |
| 4  | Leon  |       2 |
| 5  | Mario |       3 |
+----+-------+---------+
5 rows in set (0.00 sec)

我執行下面的sql語句,但不給出commit語句:

set autocommit = 1; start transaction; update students set classId = 1 where id = 1; 

之後,我將打開另一個會話並執行以下 sql 語句:

set autocommit = 1; start transaction; update students set classId = 1 where id = 2;  

現在,整個外殼螢幕將阻塞並且沒有響應。過了一會兒它會給我一個錯誤,類似於這個:

1205 Lock wait timeout exceeded; try restarting transaction

所以,我很困惑為什麼 InnoDB 引擎會給我一個表上的行級鎖?在這種情況下,為什麼 MySQL 會阻止我對另一行的更新?

對於剛剛從手冊中複製和粘貼而與您的問題無關的其他答案,我深表歉意。

這是一個常見的誤解——Innodb 不做全表鎖來確保事務之間的隔離——但是,它預設應用行鎖和間隙鎖來確保不會發生幻讀。因為您的表沒有索引,所以進行間隙鎖定的唯一(低效)方法是在每一行和之間的每個間隙中設置單獨的鎖定(例如,如果您嘗試插入一個 id 為 0 的新行,它也應該被阻止。

您有兩個選擇:在 id 上創建一個索引(可能主鍵是正確的方法),因此由於新索引,實際上只有一行被鎖定,或者將您的預設隔離級別更改為讀取已送出SET SESSION transaction_isolation='READ-COMMITTED';)。

這是 dba.stackexchange 上的一個常見問題,所以在這裡你有一個更詳細的解釋,我在另一個類似的問題上寫過:MariaDB - “ERROR 1205 … Lock wait timeout exceeded; …” when doing multiple parallel UPDATEs against different rows

但是,在您的情況下,我強烈建議您走創建索引的路線。

引用自:https://dba.stackexchange.com/questions/221903