- 图中表示的是,一行数据的三个不同版本,其中字段1为a的是第一个版本,b为第二个版本,c为第三个版本,即当前版本
- 因为是同一行数据,所以主键和row_id在不同版本里是一样的,
- roll_ptr为回滚指针,它指向的是上一个版本的数据位置
- trx_id表明了是哪一个事务修改的本行数据。
MySQL笔记五-MVCC
什么是MVCC
MVCC即为多版本并发控制,是一种用于提高并发量的方法,其可以有效的提高innodb引擎数据库的并发性能,做到即使有读写冲突,也能不加锁并发读。
什么是当前读和快照读
当前读:select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,即读取当前的最新数据,为了保证数据是最新的,需要对读的数据加锁,不让其他事务在读的期间修改
快照读:不加锁的select就是快照读,从字面理解,就是将数据取一份当前的快照,然后select这个快照上的数据,也不会加锁。当select数据时,此数据可能已经不是最新的了(被其他事务修改),显然此时的隔离级别不能是串行化,否则不会有其他事务并行修改。
为什么需要快照读
为了提高并发度,降低锁等待的时间
如何实现快照度
利用MVCC,MVCC避免了加锁操作,降低了开销,实现了读写冲突时不加锁(仅限快照读)
MVCC涉及的部分
一,MVCC的实现利用了每行记录的三个隐藏字段,分别时DB_TRX_ID(最近修改本行数据的事务id),DB_ROLL_PTR(undo log带来的回滚指针,指向本行数据的上个版本),DB_ROW_ID(本行数据的隐藏主键,如果没有主键,会以此主键生成表)
ps,还有第四个隐藏字段 flag_delete,删除标记,实际删除由purge线程完成,与本文无关
二,MVCC的实现还利用了Read VIew,Read View就是在进行快照读时生成一个事务快照,他会记录当前数据库内begin但未commit的事务id。这个View包含三部分,1,维护当前begin未commit的事务id的list ,记为trx_list ;2,list事务里的最小事务id,记为trx_min_id;3,View生成时刻,最大事务id+1的值,记为trx_max_id_plus ,也可以认为是下一个将要分配的事务id,需要注意的是这个最大事务是全局的,不是list里的事务,这与第二点不太相同。
Read View遵循可见性算法,具体规则如下
1,事务id小于trx_min_id,那么此事务对此Read View不可见,
2,事务id大于trx_max_id_plus,此事务不可见
3,事务id是否在trx_list中,在则不可见,不在则可见。
三条规则依次判断
三,MVCC的实现还利用了undo log,确切的说的update undo log。当update某行数据时,先加行锁,修改本行数据,然后将相应的undo log保存,同时回滚指针将指向undo log的位置,最后释放锁。如果希望获得update之前的数据,只需要将回滚指针指向的undo log应用到本行数据上即可。如果有多个版本的数据,那么会形成链表结构,链表最后端为最新数据,最前端为最老数据,不同版本之间也是通过回滚指针相连接。如果要获得最老的数据,就拿最新数据按照链表的顺序,一个一个的应用undo log即可。
MVCC的具体实现
结合图说