[英]Why can not update a row that already updated by another transaction in MySQL
我試圖了解 MySQL InnoDB 的可重復讀取隔離級別。 但是當我嘗試這兩個事務時,它有一種我無法理解的行為。
這是我的測試初始化
mysql> SHOW CREATE TABLE `test`;
+-------+---------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+---------------------------------------------------------------------------------------+
| test | CREATE TABLE `test` (
`ID` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-------+---------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM `test`;
+----+
| ID |
+----+
| 1 |
+----+
1 row in set (0.00 sec)
mysql> SELECT @@TX_ISOLATION;
+-----------------+
| @@TX_ISOLATION |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
不 | TX1 | TX2 |
---|---|---|
1 | 開始交易 | 開始交易 |
2 | SELECT * FROM test ;# Return 1 |
SELECT * FROM test ;# Return 1 |
3 | SELECT * FROM test WHERE ID = 1 FOR UPDATE;# return 1 |
|
4 | 更新test 集 ID = 2 WHERE ID = 1; # 好的 |
更新test 集 ID = 3 WHERE ID = 1; # 鎖定等待 |
5 | SELECT * FROM test ;# Return 2 |
# 繼續等待 |
6 | 犯罪; # 好的 | # 查詢成功:匹配行:0,更改:0,警告:0 |
7 | SELECT * FROM test ;# Return 2 |
SELECT * FROM test WHERE ID = 1;# Return 1 |
8 | 更新test 集 ID = 3 WHERE ID = 1; #Query OK:匹配行:0,更改:0,警告:0 |
|
9 | SELECT * FROM test ;# Return 2 |
SELECT * FROM test ;# Return 1 <-- 即使行存在也不能更新1到3 |
10 | UPDATE test SET ID = 3 WHERE ID = 2;#Query OK: rows match:1, changed: 1, warnings: 0 |
|
11 | 犯罪; #好的 | |
12 | SELECT * FROM test # Return 3 |
SELECT * FROM test # Return 3 |
我想知道 MySQL 如何在第 8 行和第 10 行處理 Tx2 中的 ID=1 和 ID=2。如果我在 Tx2 的第 4 行使用UPDATE test SET ID = 3 WHERE ID = 2
,即使 Tx1 只持有ID = 1 的獨占鎖?
在第 8 步,不再有鎖定記錄,因為TX1
已完成 COMMIT,這將清除鎖定。
也不再有 ID=1 的記錄,因為它已被更新。
在步驟 9 和 10,由於可重復讀取, Tx2
無法更新記錄。 它看不到id=2 的記錄,也不再找到 id=1 的記錄(因為它已經消失/更改了)。
只有在 COMMIT 之后, Tx2
才能看到新的/更改的數據。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.