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下,
是读取最新一份快照,所以一个查询会看到不通的结果。
转载于:https://blog.51cto.com/lijiajun/1903974