14.2.2.2 Consistent Nonlocking Reads
一个一致读 意味着 InnoDB 使用多版本来提出一个查询数据库的快照 在一个时间点。
查询看到的事务的做出的改变,被提交了 在那个时间点之前,
之后没有改变或者没有提交的事务。 次规则的例外是 查询看到相同事务里早的语句的改变,
这个异常导致以下异常:如果你更新表的一些记录,一个SELECT 看到的最新的更新的记录的版本,
但是它也看到了任何记录老的版本。如果其他会话同时更新相同的表,你可能会看到 表从没在数据库中存在过的状态。
如果 事务隔离级别是 REPEATABLE READ(默认级别),所有的一致性读在相同的事务读取第一个读取建立的快照。
你可以得到一个新鲜的快照为你的查询通过提交当前的事务,然后执行新的查询。
READ COMMITTED 隔离级别,每个一致性读在一个事务内,读取它自己的新鲜的快照。
一致性读是默认的模式 InnoDB 处理SELECT 语句 在 READ COMMITTED and REPEATABLE READ 隔离级别。
一个一致读不在表上设置任何锁,因此其他的会话是自由的同时修改那些表 一个一致性读是在表上执行。
假设 你运行在默认的REPEATABLE READ隔离模式。 当你执行一致性读
(即,一个普通的SELECT 语句) InnoDB 给你的事务一个时间点根据你的查询看到的数据库。
如果另外的事务删除一条记录,提交在你分配的时间点之后,
你不会看到行已经被删掉了,insert和updates 也一样。
注意:
数据库状态的快照 应用于SELECT 语句在事务内,不是对于DML语句。如果插入或者修改一些记录
然后提交那个事务, 一个DELETE 或者UPDATE 语句被执行从另外一个并发的 REPEATABLE READ 事务
可能影响那些刚刚提交的行,尽管 session 不能查询它们。如果一个事务更新或者删除被不同的事务提交的记录,
那些改变变得对当前事务可见,比如,你可能遇到如下情况:
SELECT COUNT(c1) FROM t1 WHERE c1 = ‘xyz’; – Returns 0: no rows match.
DELETE FROM t1 WHERE c1 = ‘xyz’; – Deletes several rows recently committed by other transaction.
SELECT COUNT(c2) FROM t1 WHERE c2 = ‘abc’; – Returns 0: no rows match.
UPDATE t1 SET c2 = ‘cba’ WHERE c2 = ‘abc’; – Affects 10 rows: another txn just committed 10 rows with ‘abc’
values.
SELECT COUNT(c2) FROM t1 WHERE c2 = ‘cba’; – Returns 10: this txn can now see the rows it just updated.
你可以提高你的提交事务的时间点, 然后做另外的r SELECT or START TRANSACTION WITH CONSISTENT SNAPSHOT.
这个被称为多版本控制
在下面的例子中,SESSION A 看到 B插入的记录只有当B提交插入和 A也提交:
Session A Session B
SET autocommit=0; SET autocommit=0;
time
| SELECT * FROM t;
| empty set
| INSERT INTO t VALUES (1, 2);
|
v SELECT * FROM t;
empty set
COMMIT;
SELECT * FROM t;
empty set
COMMIT;
SELECT * FROM t;
---------------------
| 1 | 2 |
---------------------
如果你想看到最新鲜的数据库状态,
使用READ COMMITED 隔离机制或者锁定读:
SELECT * FROM t LOCK IN SHARE MODE;
READ COMMITED 隔离级别, 每个一致读在一个事务设置,读取它自己的新鲜的快照。
在LOCK IN SHARE MODE, 一个locking read 发生代替:一个SEELCT 堵塞指导事务包含最新的记录结束。
一致读在某些DDL语句不工作:
一致性读在DROP TABLE不工作,因为MySQL 不能使用一个已经被删除的表
一致性读在ALTER TABLE不工作,
读取不同的类型用于SELECT 自己像 INSERT INTO … SELECT, UPDATE … (SELECT), and CREATE TABLE … SELECT
不指定UPDATE 或者LOCK 在共享模式下:
默认情况下, InnoDB 使用更强的锁.SELECT 部分像READ COMMITTED,
每个一致性读,即使在相同的会话里,设置和读取它自己的最新的快照。
为了使用一致性读在这些情况下,启动innodb_locks_unsafe_for_binlog option 设置隔离级别为
READ UNCOMMITTED, READ COMMITTED, or REPEATABLE READ