在 mysql repeatable read 事务隔离级别下 其利用快照读 解决了 non-repeatable-read 的并发事务问题;
read view : https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_read_view
snapshot : https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_snapshot
快照读:
read view : 对于read view 在不同的事务隔离级别下其实现方式并不相同,read view 会在 read uncommitted /read committed / repeatable read 隔离级别下被创建
当前只针对 repeatable-read 隔离级别下 read view 生成策略 (以下使用 rr 表示 repeatable read )
对于启动快照读有两种方式
start transaction with consistent snapshot 会立即创建 read view
在事务启动后 第一次读取操作执行时才创建read view
对于read view 其基于 MVCC consistent read 要求, 在 rr级别下,创建的 read view 是基于整张表的, 里面存储的数据为 每一行的最新已提交事务id(低水位),当前事务开启时其他未提交的事务id(最大的事务id称为高水位);可以通过事务id查询 undo_log 日志来查询历史数据;
对于 rr 可见性控制实现, 主要是针对 同一时间未提交的事务判断,对于在 read view 正式创建前提交的事务是可见的,对于read view 创建后 已提交或未提交的事务都不会影响已创建的read view 数据
当前读:
对于当前读 的操作方式存在一下两种操作
https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
select ... for update : 锁的表现形式和 update 语句一样
select ... lock in share mode : 对于当前操作支持 再次读取操作(读锁之间并不互斥,支持重进入),但对于其他事务的更新操作会被阻塞(读锁/写锁之间会互斥),需要等待当前事务提交后才可以执行修改操作
对于以上两种读加锁情况,不能开启自动提交(通过 set autocommit = 0 来关闭自动提交,或设置 set autocommit = 1 ),需要手动开启事务 以及手动提交或回滚事务;
对于 set autcommit = 0 和 set autocommit = 1 的区别为
set autocommit = 0 模式下,执行任何语句(即使是select)都会开启一个事务,都需要手动 commit 或 rollback
set autocommit = 1 模式下, 必须使用 begin 或 start transaction 来开启事务
对于当前读的理解:
主要是针对更新操作(或具有更新操作特性的操作)而言,对于所有的更新操作(先读(当前读)后写)都需要先读取到当前行数据即时状态的持久化数据(事务已提交的数据),否则就有可能导致当前事务操作覆盖了之前事务的操作
读锁统一的特点为 读锁之间的不会互斥,读锁和写锁之间会互斥
区别点:
对于当前读和快照读的区别在于,当前读 读取当前行数据最新的已提交的事务数据,并不受read view 的影响