MVCC原理

MVCC是多版本并发控制,用于提高数据库并发性能。在MySQL的InnoDB中,它通过隐式字段、undo日志和Read View来实现。MVCC只在READ COMMITTED和REPEATABLE READ隔离级别下工作。当前读如SELECT FOR UPDATE等读取最新版本并加锁,而快照读的SELECT不加锁,基于MVCC读取历史版本。在不同的隔离级别下,MVCC的读取行为有所不同。
摘要由CSDN通过智能技术生成

什么是mvcc

mvcc即多版本并发控制。他主要在mysql innoDB中提高数据库并发性能,用更好的方式去处理读写冲突,做到即使有读写冲突,也可以做到不加锁,非阻塞并发读
MVCC模型在MySQL中的具体实现则是由 3个隐式字段(DB_TRX_ID,DB_ROLL_PTR,DB_ROW_ID),undo日志Read View 等去完成的
MVCC 只能在READ COMMITTEDREPEATABLE READ两个隔离级别下工作,因为READ UNCOMMITTED总是读取最新的数据行,而不是符合当前事务版本的数据行,而SERIALIZABLE则会对所有读取的行都加锁。

当前读

像select lock in share mode(共享锁), select for update ; update, insert ,delete(排他锁)这些操作都是一种当前读,为什么叫当前读?就是它读取的是记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁

快照读

像不加锁的select操作就是快照读,即不加锁的非阻塞读;快照读的前提是隔离级别不是未提交读和串行化级别,因为未提交读总是读取最新的数据⾏,⽽不是符合当前事务版本的数据行,而串行级别下的快照读会退化成当前读,会对所有读取的⾏都加锁;之所以出现快照读的情况,是基于提高并发性能的考虑,快照读的实现是基于多版本并发控制,即MVCC,可以认为MVCC是行锁的一个变种,但它在很多情况下,避免了加锁操作,降低了开销;既然是基于多版本,即快照读可能读到的并不一定是数据的最新版本,而有可能是之前的历史版本

Read Committed隔离级别:每次select都生成一个快照读。
Read Repeatable隔离级别:开启事务后第一个select语句才是快照读的地方,而不是一开启事务就快照读。
快照读的实现方式:undolog和多版本并发控制MVCC

mvcc的原理

隐式字段

DB_TRX_ID: 6字节DB_TRX_ID字段,表示最后更新的事务id(update,delete,insert)。此外,删除在内部被视为更新,其中行中的特殊位被设置为将其标记为已软删除。

DB_ROLL_PTR: 7字节回滚指针,指向前一个版本的undolog记录,组成undo链表。如果更新了行,则撤消日志记录包含在更新行之前重建行内容所需的信息。
  DB_ROW_ID: 6字节的DB_ROW_ID字段,隐含的自增ID(隐藏主键),如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引
  在这里插入图片描述
如上图,DB_ROW_ID是数据库默认为该行记录生成的唯一隐式主键,DB_TRX_ID是当前操作该记录的事务ID,而DB_ROLL_PTR是一个回滚指针,用于配合undo日志,指向上一个旧版本

undo log

undo log主要分为两种:

  • insert undo log
    代表事务在insert新记录时产生的undo log, 只在事务回滚时需要,并且在事务提交后可以被立即丢弃
  • update undo log
    事务在进行update或delete时产生的undo log; 不仅在事务回滚时需要,在快照读时也需要;所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除

Read View

Read View就是事务进行快照读操作的时候生产的读视图(Read View),在该事务执行的快照读的那一刻,会生成数据库系统当前的一个快照,记录并维护系统当前活跃事务的ID(当每个事务开启时,都会被分配一个ID, 这个ID是递增的,所以最新的事务,ID值越大)

所以我们知道 Read View主要是用来做可见性判断的, 即当我们某个事务执行快照读的时候,对该记录创建一个Read View读视图,把它比作条件用来判断当前事务能够看到哪个版本的数据,既可能是当前最新的数据,也有可能是该行记录的undo log里面的某个版本的数据。
通俗来讲就是我们select的时候,要从版本链中取哪一个
read view参数:
在这里插入图片描述
m_ids:没有commit的事务id
min_trx_id:m_ids中最小的id
max_trx_id:是应该赋给下一个的事务id,比如此时m_ids为1,2,3,min_trx_id就为1,max_trx_id为4
creator_trx_id:是谁生成了这个readview,他的id

当为读已提交(RC)隔离级别的时候

在每次执行快照读时生成readview
在这里插入图片描述
在这里插入图片描述
根据判断规则,最后算出他只能读到trx_id=1,name=张三的那一条,对照图就正好是读已提交。
在这里插入图片描述
这个得出最后可以读到trx_id=2,的那一条,这里根据上面的正好也体现出来了,一个事务中的两次select得出的结果不同,是不可重复读。

当为可重复读(RR)隔离级别的时候

仅在第一次执行快照读时生成readview,后续的快照读复用
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值