read commited 和 REPEATABLE read
關於一致性讀的問題。 參考 mysql 技術內幕--innodb 存儲引擎
session 1
:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t2;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
同時到session2:
mysql>
mysql>
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t2;
+------+
| id |
+------+
| 1 |
+------+
1 row in set (0.00 sec)
mysql> update t2 set id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql>
mysql> select * from t2;
+------+
| id |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
再回到session1:
如果是
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)
mysql> select * from t2;
+------+
| id |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
在session1 的同一個事物中,兩次查詢t2,會看到不通的結果,
如果是:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
在session 1 中,看到
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t2;
+------+
| id |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
mysql> select * from t2;
+------+
| id |
+------+
| 2 |
+------+
1 row in set (0.00 sec)
是同一個結果。
這是由於mysql的一致性非鎖定讀 造成的。
如果讀取的行正在備其他事物執行update或delete操作,這時讀取操作不會因此去等待行上鎖
的釋放,innodb回去讀一個快照數據。因爲不需要等待訪問的行上x鎖的釋放,所以稱之爲非鎖定讀。
快照數據是指該行 的之前版本的數據(可能有多個版本)。是通過undo斷來實現的,undo是用
來在事物中回滾數據,因此快照數據沒有額外開銷。
在REPEATABLE read 下,快照讀總是讀取事物開始時的行版本數據;而在read commited下,
是讀取最新一份快照,所以一個查詢會看到不通的結果。