InnoDB一致性非锁定读(Consistent Nonlocking Reads)

一致性读(consistend read)

一致性读(consistend read)指的是InnoDB使用多版本查询数据库在某个时间点的快照。此查询可以看到该时间点之前提交的事务所做的更改并且不会被之后的修改或者未提交事务所影响。但是对于同一事务中的较早语句的修改则不适用此规则,这种情况会产生以下异常:如果你更新表中的某些行,一次SELECT可能看到更新行的最新版本也可能看到任一行的旧版本;如果其它会话同时更新到同一个表,则可能会看到该表处于数据库中从未存在过的状态。

多版本并发控制

  • 当事务隔离级别为REPEATABLE READ时,同一个事务中的一致性读都是读取的是该事务下第一次查询所建立的快照。

我们可以通过

  • 当事务隔离级别为READ COMMITTED时,同一事务下的一致性读都会建立和读取此查询自己的最新的快照

一致性读是InnoDB在REPEATABLE READ和READ COMMITTED事务隔离中处理SELECT语句的默认模式。一致性读不会在表上设置任何锁,所以其它会话可以对表进行读写操作。

数据库状态的快照适用于事务中的SELECT语句,而不一定适用于DML语句。如果执行INSERT或者UPDATE某些行然后提交该事务,则从另一个并发REPEATABLE READ事务发出的DELETE或UPDATE语句则会影响那些刚刚提交的数据行。下面这个示例展示了这种场景:

             Session A                              Session B

           begin;                                   begin;
-------------------------------------------------------------------------------------
           SELECT * FROM t;                        SELECT * FROM t;
           > empty set                             > empty set
          
-------------------------------------------------------------------------------------
                                                   INSERT INTO t (id) VALUES (1);
                                                    > 1 row affected
          
                                                    SELECT * FROM t;
                                                    -----------
                                                    |   id    |
                                                    -----------
                                                    |    1    |
                                                    -----------
-------------------------------------------------------------------------------------            
           SELECT * FROM t;         
           > empty set
-------------------------------------------------------------------------------------                                                    
                                                    COMMIT;
-------------------------------------------------------------------------------------
           SELECT * FROM t;
           > empty set
-------------------------------------------------------------------------------------

           DELETE FROM t WAERE id = 1;
           > 1 row affected
-------------------------------------------------------------------------------------
                                                    SELECT * FROM t;
                                                    -----------
                                                    |   id    |
                                                    -----------
                                                    |    1    |
                                                    -----------
-------------------------------------------------------------------------------------
           COMMIT;
-------------------------------------------------------------------------------------
                                                    SELECT * FROM t;
                                                    > empty set
-------------------------------------------------------------------------------------
           SELECT * FROM t;
           -----------
           |   id    |
           -----------
           |    1    |
           -----------
-------------------------------------------------------------------------------------
复制代码

一致的读取不适用于某些DDL语句

  • 一致性读不适用于DROP TABLE,因为表已经被InnoDB销毁了
  • 一致性读不适用于ALTER TABLE,因为ALTER TABLE实际是生成一张原始表的临时表,并在构建完成后删除原始表。在事务中进行一致的读取时,新表中的行不可见,这种情况下事务会返回 ER_TABLE_DEF_CHANGED错误(表定义已更改,请重试事务)

在没有指定FOR UPDATE或者LOCK IN SHARE MODE的情况下INSERT INTO ... SELECT,UPDATE ...(SELECT)和CREATE TABLE ...等语句中的的读取会有以下差异:

  • 默认情况下,就像READ COMMITTED一样,即使在同一事务中,每个一致性读都会建立和读取自己的快照
  • 如果将innodb_locks_unsafe_for_binlog设置为了enable并且事务隔离级别不是SERIALIZABLE,则读操作不会再行上加锁
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值