1.什么是MVCC
? MVCC即多版本并发控制,主要是为了提高数据库的并发性能。
? 同一行数据平时发生读写请求时,会上锁阻塞住,这是其他事务就无法访问这行数据。但MVCC用更好的方式去处理—写请求,做到在发生读–写请求冲突时不用加锁。
? 这个读指的是快照读,而不是当前读,当前读是一种加锁操作,是悲观锁。
2.当前读
? 它读取的数据记录,都是当前最新的版本,会对当前读取的数据进行加锁,防止其他的事务对其进行修改,是悲观锁的一种操作,以下操作都是当前读:
- select lock in share mode(共享锁)
- select for update(排他锁)
- update(排他锁)
- insert(排他锁)
- delete(排他锁)
- 串行化事务隔离级别
3.快照读
? 快照读的实现是基于多版本并发控制,即MVCC,这个多版本指的是数据的多版本,那么快照读读到的数据不一定是当前的最新数据,有可能是之前的历史版本的数据,以下是快照读操作:
- 不加锁的select操作(注:事务级别不是串行化)
4.MVCC常见日志
4.1 undo日志
? undo log中存入的是最新版本之前旧版本的数据,如下图理解:
4.2 ReadView
? ReadView中会存入当前未提交事务的id号和已创建事务(包括未提交和已提交)的最大事务id号,然后进行比对,有以下参数:
- m_ids:表示生成"ReadView"时当前系统中活跃的读写事务的"事务id"列表,活跃的读写事务指的是没有commit的事务id号
- min_trx_id:表示当前系统中活跃的读写事务中的最小的"事务id",也就是"m_ids"中的最小值
- max_trx_id:表示生成ReadView时系统应该分配给下一个事务的id值,比如现在ReadView中有1、2、3三个id值,那么系统下一个要分配的id值就应该是4,这个"max_trx_id"就是4
- creator_trx_id:表示生成该"ReadView"的事务的"事务id"
4.3 ReadView判断版本链的哪个版本可用,比较规则
- trx_id==creator_trx_id:可以访问这个版本
- trx_id<min_trx_id:可以访问这个版本
- trx_id>max_trx_id:不可以访问这个版本
- min_trx_id<=trx_id<=max_trx_id:如果trx_id在m_ids是不可以访问这个版本的,反之可以
4.4 读已提交
? 在读已提交的隔离级别下,每一次select都会产生一个ReadView,当第一个select产生ReadView时,查询到的语句可能是一个;当第二个select产生另外一个ReadView,查询到的语句可能就是另外一个;两次查询的数据不一致,所以就会产生不可重复读的问题。
4.5 可重复读
? 在可重复读的隔离级别下,一个事务只会产生一份ReadView,一个事务共用一个ReadView,版本链就不会变,所以在"可重复读"的隔离级别下,就会解决不可重复读的问题。
4.6 可重复读的隔离级别下解决幻读
? 在可重复读的隔离级别下,只会产生一份ReadView,那么在这个事务中进行多次select就不会产生幻读,但这只是表面上解决了幻读,实际上其他事务还是会插入数据,只不过在快照读下读不到插入的数据。
? 真正解决幻读是当前读使用临键锁解决的幻读问题,当有以下查询语句时:
select * from user where id>3 for update
5.比较规则举例
第一个select
第二个select
|