MySQL REPEATABLE-READ && 幻讀

MySQL REPEATABLE-READ && 幻讀mysql

關於mysql命令行中事務控制的語句見該文章sql

http://my.oschina.net/xinxingegeya/blog/296459session

關於MVCC多版本控制spa

http://my.oschina.net/xinxingegeya/blog/208821.net

表結構命令行

create table t1(
    a int primary key,
    b int not null    
)

 

REPEATABLE-READ可重複讀(一)

這裏打開兩個mysql的命令行窗口,窗口A,即session1,窗口B,即session2。版本控制

session1code

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

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
+----+------+
4 rows in set (0.00 sec)

以上sql只是顯示的開啓了事務,執行了sql查詢。下面看session2的操做。blog

要注意這裏的select操做是通常的快照讀。根據MVCC多版本控制規則讀取的數據行。事務

session2

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

mysql> insert into t1 values (55, 3000);
Query OK, 1 row affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.03 sec)

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
| 55 | 3000 |
+----+------+
5 rows in set (0.00 sec)

session2插入了一條數據,並顯式的提交了事務。

session1

此時返回session1進行如下操做

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
+----+------+
4 rows in set (0.00 sec)

此時,雖然在session2中插入了一條數據,而且提交了事務,但在session1中的查詢和session1的上次查詢仍是同一個結果,這就是重複讀。(也能夠說是根據MVCC規則讀取的數據行)。若是是在"READ-COMMITTED"級別下是能夠讀到a=55這條記錄的(由於session2在剛纔已經提交了事務)。

 

REPEATABLE-READ可重複讀(二)

session1

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

mysql> select * from t1 where a = 56;
+----+------+
| a  | b    |
+----+------+
| 56 | 7000 |
+----+------+
1 row in set (0.00 sec)

session1,開啓了一個事務,查詢a = 56 的記錄。

session2 

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

mysql> update t1 set b = 8000 where a = 56;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from t1 where a = 56;
+----+------+
| a  | b    |
+----+------+
| 56 | 8000 |
+----+------+
1 row in set (0.00 sec)

mysql> commit
    -> ;
Query OK, 0 rows affected (0.04 sec)

session2開啓了事務,更新a = 56 的記錄,同時查詢a = 56 的記錄,能夠看到在同一事務內重複讀的效果。

session1

mysql> select * from t1 where a = 56;
+----+------+
| a  | b    |
+----+------+
| 56 | 7000 |
+----+------+
1 row in set (0.00 sec)

和上次查詢結果一致,驗證了重複讀。仍是要注意這裏的select操做只是通常的快照讀。其實無論session2 作什麼操做,這裏的快照讀都是重複讀的。

此時,若是session1提交該事務,從新開啓事務,查詢能查到session2中修改的結果

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

mysql> select * from t1 where a = 56;
+----+------+
| a  | b    |
+----+------+
| 56 | 8000 |
+----+------+
1 row in set (0.00 sec)

注:以上的重複讀,雖然在當前事務中真的是重複讀的現象,但到底來講是經過MVCC多版本控制實現的可重複讀。

 

REPEATABLE-READ與幻讀

session1 

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

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
| 55 | 4000 |
| 56 | 8000 |
+----+------+
6 rows in set (0.00 sec)

開啓事務,select操做爲快照讀。

session2

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

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
| 55 | 4000 |
| 56 | 8000 |
+----+------+
6 rows in set (0.00 sec)

mysql> insert into t1 values (57, 1000);
Query OK, 1 row affected (0.00 sec)

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
| 55 | 4000 |
| 56 | 8000 |
| 57 | 1000 |
+----+------+
7 rows in set (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.11 sec)

在session2 中作了一系列的操做,插入insert,這裏實際上是當前讀(寫入)。而後提交事務。

session1 

mysql> update t1 set b = b+1000;
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7  Changed: 7  Warnings: 0

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 4000 |
| 52 | 4000 |
| 53 | 4000 |
| 54 | 4000 |
| 55 | 5000 |
| 56 | 9000 |
| 57 | 2000 |
+----+------+
7 rows in set (0.00 sec)

session1作更新操做,這裏更新成功。若是session2 插入記錄後,沒有提交事務,這裏更新是要阻塞的,由於session2 插入記錄持有那條記錄的X鎖。

session1整個會話的sql

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

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
| 55 | 4000 |
| 56 | 8000 |
+----+------+
6 rows in set (0.00 sec)

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 3000 |
| 52 | 3000 |
| 53 | 3000 |
| 54 | 3000 |
| 55 | 4000 |
| 56 | 8000 |
+----+------+
6 rows in set (0.00 sec)

mysql> update t1 set b = b+1000;
Query OK, 7 rows affected (0.00 sec)
Rows matched: 7  Changed: 7  Warnings: 0

mysql> select * from t1;
+----+------+
| a  | b    |
+----+------+
| 51 | 4000 |
| 52 | 4000 |
| 53 | 4000 |
| 54 | 4000 |
| 55 | 5000 |
| 56 | 9000 |
| 57 | 2000 |
+----+------+
7 rows in set (0.00 sec)

mysql>

能夠看到多出了一行,這算是幻讀嗎?其實不是。這是根據MVCC的select規則讀出來的數據

請詳見http://my.oschina.net/xinxingegeya/blog/505675

 

總結:

REPEATABLE READ:在mysql中,不會出現幻讀。mysql的實現和標準定義的RR隔離級別有差異。

==========END==========

相關文章
相關標籤/搜索