天天看點

RR 和RC 幻讀問題

<pre name="code" class="html">顯然 RR 支援 gap lock(next-key lock),而RC則沒有gap lock。因為MySQL的RR需要gap lock來解決幻讀問題。而RC隔離級别則是允許存在不可重複讀和幻讀的。是以RC的并發一般要好于RR;
RR 和RC 幻讀問題:

幻讀:同一個事務中多次執行同一個select, 讀取到的資料行發生改變。

也就是行數減少或者增加了(被其它事務delete/insert并且送出)。SERIALIZABLE要求解決幻讀問題; 

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)


Sessio 1:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)

mysql> use scan;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1 where id>100;
ERROR 1054 (42S22): Unknown column 'id' in 'where clause'
mysql> select * from t1 where c1>100;
+------+
| c1   |
+------+
|  119 |
|  200 |
|  300 |
|  400 |
| 8999 |
+------+
5 rows in set (0.00 sec)



Sessio 2:
mysql> insert into t1 values(9999);
Query OK, 1 row affected (0.01 sec)

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


Session 1 再次查詢:
mysql> select * from t1 where c1>100;
+------+
| c1   |
+------+
|  119 |
|  200 |
|  300 |
|  400 |
| 8999 |
+------+
5 rows in set (0.00 sec)


此時在RR模式下沒有幻讀



設定隔離級别為RC:
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)


Session 1:
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)

mysql> use scan;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1 where c1>100;
+------+
| c1   |
+------+
|  119 |
|  200 |
|  300 |
|  400 |
| 8999 |
| 9999 |
+------+
6 rows in set (0.00 sec)



Session 2:
mysql> select * from t1;
+------+
| c1   |
+------+
|   33 |
|   34 |
|   87 |
|   89 |
|  119 |
|  200 |
|  300 |
|  400 |
| 8999 |
| 9999 |
+------+
10 rows in set (0.00 sec)

mysql> insert into t1 values(7777777);
Query OK, 1 row affected (0.01 sec)

Session 1再次查詢:
mysql> select * from t1 where c1>100;
+---------+
| c1      |
+---------+
|     119 |
|     200 |
|     300 |
|     400 |
|    8999 |
|    9999 |
| 7777777 |
+---------+
7 rows in set (0.00 sec)

說明RC模式下,可以幻讀