MySQL 一致性读 深入研究(4)

语句级读一致性:Oracle强制实现语句级读一致性。一个查询语句只读取语句开始之前提交的数据。

事务级读一致性隔离级别为SERIALIZABLEread only的事务才支持事务级读一致性。事务中的所有查询语句只读取 事务开始之前提交的数据。

Oracle只实现了RC和serializable,没有实现Read uncommitted 和 RR。其实Oracle的serializable级别才实现了可重复读。

4. 当前读(current read) 和 一致性读

一致性读是指普通的select语句,不带 for update, in share mode 等等子句。使用的是undo中的提交的数据,不需要使用锁(MDL除外)。而当前读,是指update, delete, select for update, select in share mode等等语句进行的读,它们读取的是数据库中的最新的数据,并且会锁住读取的行和gap(RR隔离时)。如果不能获得锁,则会一直等待,直到获得或者超时。RC隔离级别的当前读没有gap lock,RC的update语句进行的是“半一致性读”,和RR的update语句的当前读不一样。

5. 一致性读与 mysqldump --single-transaction

我们知道 mysqldump --single-transaction的原理是:设置事务为RR模式,然后利用事务的特性,来获得一致性的数据,但是:

--single-transaction
                      Creates a consistent snapshot by dumping all tables in a
                      single transaction. Works ONLY for tables stored in
                      storage engines which support multiversioning (currently
                      only InnoDB does); the dump is NOT guaranteed to be
                      consistent for other storage engines. While a
                      --single-transaction dump is in process, to ensure a
                      valid dump file (correct table contents and binary log
                      position), no other connection should use the following
                      statements: ALTER TABLE, DROP TABLE, RENAME TABLE,
                      TRUNCATE TABLE, as consistent snapshot is not isolated
                      from them. Option automatically turns off --lock-tables.

在mysqldump运行期间,不能执行 alter table, drop table, rename table, truncate table 等等的DDL语句,因为一致性读和这些语句时无法隔离的。

那么在mysqldump --single-transaction 执行期间,执行了上面那些DDL,会发生什么呢?

mysqldump --single-transaction 的执行过程是:设置RR,然后开始事务,对应了一个LSN,然后对所有选中的表,一个一个的执行下面的过程:

save point sp; --> select * from t1 --> rollback to sp;

save point sp; --> select * from t2 --> rollback to sp;

... ...

1> 那么如果对t2表的DDL发生在 save point sp 之前,那么当mysqldump处理到 t2 表时,mysqldump 会立马报错:表结构已经改变......

2> 如果对t2表的DDL发生在 save point sp 之后,rollback to sp 之前,那么要么DDL被阻塞,要么mysqldump被阻塞,具体谁被阻塞,看谁先执行了。

被阻塞额原因是:DDL需要t2表的 MDL 的互斥锁,而select * from t1 需要MDL的共享锁,所以阻塞发生。

3> 如果对t2表的DDL发生在 rollback to sp 之后,那么因为对 t2 表的dump已经完成,不会发生错误或者阻塞。

那么为什么: 对t2表的DDL发生在 save point sp 之前,那么当mysqldump开始处理 t2 表时,mysqldump 立马报错呢?

其原因就是 一致性读的胳膊拗不过DDL的大腿:

Consistent read does not work over certain DDL statements:(一致性读的胳膊拗不过DDL的大腿)

原因:ALTER TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE 这些DDL语句的执行,会导致无法使用undo构造出正确的一致性读,一致性读和它们是无法隔离的。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/a2a97a94eb22cea7cf85fd428f5bd1ba.html