思考:
首先,事务在可重复读的隔离级别下,同一事务读的值不会改变,那么在发生行锁竞争等待中,别的事务进行了数据修改,结果如何?
此处Q1读到的值是3,而Q2读到的值是1
原因:主要是因为mvcc(多版本并发控制)
mvcc基本概念:
undo log:记录数据库的操作
版本链:存储的记录中除了本身数据,还有两个字段trx_id(事务id,自增),roll_pointer(回滚指针),回滚指针形成版本链
readview: 快照,在版本链中找到合适的版本
这个主要说明了事务A读取到的值。
那么为什么事务B读到的值是3呢?
这里有两个概念:
当前读:每次都能读到最新的值,
例如,select lock in share mode (共享锁) select for update (排它锁) update(排它锁) insert(排它锁)delete(排它锁) 串行化事务隔离级别
快照读:读到的值是快照里的,例如,普通的select
也就是说每次更新,都要先读后更新,这个读就是当前读,因此值为3;
可重复读解决幻读问题:
快照读解决:
只生成一个readview,一个事务中,同一个版本链中查询结果一致
当前读解决:
使用间隙锁,范围加锁,不会出现两次读的数量不一致
RR和RC的readview有什么不同:
RR: 一个事务只会生成一个readview,查询是在同一个版本链上,结果一致
RC:每一个select都会生成一个readView ,一个事务中,第一次查询以后,进行了更新操作,第二次查询又会生成一个新的readview,导致两次查询出来的结果不一样,不支持可重复读
CREATE TABLE `t` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
insert into t(id, c) values(1,1),(2,2),(3,3),(4,4);
结果:
只要update 之前,另一个事务更新c的值,让id=c条件不成立即可,由于读一致性,读的值不会变