根據MySql文檔,MySql支持多粒度鎖定(MGL)。MySQL'select for update'行爲
殼體-1
開業終端-1:
//連接到mysql
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select id, status from tracking_number limit 5 for update;
+----+--------+
| id | status |
+----+--------+
| 1 | 0 |
| 2 | 0 |
| 3 | 0 |
| 4 | 0 |
| 5 | 0 |
+----+--------+
5 rows in set (0.00 sec)
mysql>
離開它打開和打開終端-2:
//連接到MySQL
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select id, status from tracking_number limit 5 for update;
<!-- Hangs here. and after some time it says-->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
雖然有很多行可供檢索,但T2會一直等到t1完成。
情形2
左終端-1作爲在is.Now終端-2:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
<!-- case 2.1 -->
mysql> select id, status from tracking_number where id=1;
+----+--------+
| id | status |
+----+--------+
| 1 | 0 |
+----+--------+
1 row in set (0.00 sec)
mysql> select id, status from tracking_number where id=2;
+----+--------+
| id | status |
+----+--------+
| 2 | 0 |
+----+--------+
1 row in set (0.00 sec)
<!-- case 2.2 -->
mysql> select * from tracking_number where id=2 for update;
<!-- Hangs here. and after some time -->
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
但爲什麼在情況1,T2等待相同的行集T1已鎖定?
這是否意味着無界選擇查詢(即使有limint參數,我也嘗試過不同的範圍)也會阻止整個表?
- 有什麼辦法讓事務獨立鎖定而不指定記錄的字段(即,不使用其中字段=值)?
- 通常(或按照Java併發鎖定),寫鎖定是獨佔的,讀取不是。在2.1情況下,雖然記錄處於寫鎖定模式,但T2如何讀取相同的記錄?由於這是允許的,鎖定它有什麼意義?
- 可以理解情況2.2。
打開一個終端和一個交易:
mysql> update tracking_number set status=4 where status=0 limit 5;
Query OK, 5 rows affected (0.00 sec)
Rows matched: 5 Changed: 5 Warnings: 0
離開那裏,打開另一個終端和交易:
mysql> update tracking_number set status=5 where status=0 limit 5;
T2沒有成功,直到我提交(或回滾)T1。
- 這是爲什麼?
感謝@ravnur。有沒有辦法讓事務獨立鎖定而不指定記錄的字段(即,不使用where field = value)? – 2012-07-28 19:09:20
獨立=同時?如果「是」,除了將隔離級別設置爲「髒讀」之外無法執行此操作(最好不要嘗試此選項)。如果你的答案是「否」,你可以嘗試'LOCK TABLE'或者設置隔離級別爲「SERIALIZABLE」(但我想你的答案應該是「是」)。 – ravnur 2012-07-29 21:09:09
我的回答是「是」。謝謝你的澄清。 – 2012-08-07 08:25:06