隔離級別 | 髒讀 | 非重複讀 | 幻像讀 |
read uncommitted | 允許 | 允許 | 允許 |
read committed | 允許 | 允許 | |
repeatable read | 允許 | ||
serializable |
- 顯式指定獨佔鎖:select … for update
- 在數據庫增加表明狀態的LOCK字段
SESSION1 | SESSION2 | |
T1 | mysql> start transaction; Query OK, 0 rows affected (0.00 sec) |
mysql> start transaction; Query OK, 0 rows affected (0.00 sec) |
T2 | mysql> use icbc; Database changed mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 222.00 | card001 | +--------+----------+ 1 row in set (0.11 sec) |
mysql> use icbc; Database changed mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 222.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
T3 | mysql> update t_eventlog set amount=111 where fromcard='card001'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 |
|
T4 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 111.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】session1能夠讀取自己修改的最新數據 |
mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 222.00 | card001 | +--------+----------+ 1 row in set (0.12 sec) 【說明】amount不變,session1中修改數據事務未提交,並未出現髒讀 |
T5 | mysql> update t_eventlog set amount=333 where fromcard='card001'; 【說明】session2修改直接被掛起,因爲session1事務未提交 |
|
T6 | mysql> commit -> ; Query OK, 0 rows affected (0.00 sec) |
mysql> update t_eventlog set amount=333 where fromcard='card001'; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> start transaction; Query OK, 0 rows affected (0.00 sec) 【說明】session1提交事務,session2本應提交修改,但超時需要重啓事務,下面加快速度重複上述T2~T6操作 |
T2 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 111.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 111.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
T3 | mysql> update t_eventlog set amount=1 where fromcard='card001'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 |
|
T4 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 1.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】session1能夠讀取自己修改的最新數據 |
mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 111.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】amount不變,session1中修改數據事務未提交,並未出現髒讀 |
T5 | mysql> update t_eventlog set amount=2 where fromcard='card001'; 【說明】session2修改直接被掛起,因爲session1事務未提交 |
|
T6 | mysql> commit -> ; Query OK, 0 rows affected (0.00 sec) 【說明】提交session1事務 |
|
T7 | Query OK, 1 row affected (4.79 sec) Rows matched: 1 Changed: 1 Warnings: 0 【說明】session1事務提交,session2執行修改數據 |
|
T8 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 1.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】amount不變,session2中修改數據事務未提交,並未出現髒讀 |
mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 2.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
T9 | mysql> commit -> ; Query OK, 0 rows affected (0.00 sec) |
|
T10 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 2.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】讀取到最新的session2提交事務數據 |
mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 2.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
T11 | mysql> show variables like 'autocommit'\G *************************** 1. row *************************** Variable_name: autocommit Value: ON 1 row in set, 1 warning (0.00 sec) 【說明】在session1中T8、T10兩次的數據不一致,是否違背了重複讀呢,其實不然,由於我們設置的事務提交是自動。 |
mysql> show variables like 'autocommit'\G *************************** 1. row *************************** Variable_name: autocommit Value: ON 1 row in set, 1 warning (0.00 sec) |
A | 以上已經證明了不會出現髒讀,只有在更新事務提交後方可被其他事務讀取修改後數據;如果兩個事務同時對某一數據行進行更新操作,如A事務先更新,則B事務被掛起,待A更新操作事務提交後,B事務執行更新操作並等待事務提交(更新操作可能出現等待超時),提交後最終數據爲B事務提交數據。其實是加上了行共享鎖,此時數據行能夠被多個事務讀取卻不能被寫。 | |
T12 | mysql> set @@autocommit = 0 -> ; Query OK, 0 rows affected (0.00 sec) 【說明】設置事務提交手動 |
mysql> set @@autocommit = 0 -> ; Query OK, 0 rows affected (0.00 sec) 【說明】設置事務提交手動 |
T13 | mysql> start transaction; Query OK, 0 rows affected (0.00 sec) |
mysql> start transaction; Query OK, 0 rows affected (0.00 sec) |
T14 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 2.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 2.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
T15 | mysql> update t_eventlog set amount=3 where fromcard='card001'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 |
|
T16 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 2.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) |
|
T17 | mysql> commit -> ; Query OK, 0 rows affected (0.00 sec) mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 3.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】提交事務後查詢爲最新提交的事務數據 |
|
T18 | mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 2.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】數據依然沒有變化,目前爲手動提交事務,查詢也需要手動提交。此時說明在一個事務內重複讀,數據是一致的。 |
|
T19 | mysql> commit -> ; Query OK, 0 rows affected (0.00 sec) mysql> SELECT amount,fromcard FROM t_eventlog; +--------+----------+ | amount | fromcard | +--------+----------+ | 3.00 | card001 | +--------+----------+ 1 row in set (0.00 sec) 【說明】session1提交查看事務後重新查詢,可以看到session2提交的最新的數據 |
|
B | 通過手動提交事務驗證了,REPEATABLE-READ級別隔離下,在一個事務內,我們多次查詢結果是一樣的,能夠重複讀。 |