MySQL MVCC专题

1,什么是MVCC?

MVCC-多版本并发控制。MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问。数据库使用锁来保证事务的隔离性,然而传统的锁在读和写的情况下都会锁住资源,效率很低。很多情况下是读多写少,很多数据的读取次数远大于修改的次数,而读取数据间互相排斥显得不是很必要。所以就使用了一种读写锁的方法,读锁和读锁之间不互斥,而写锁和写锁、读锁都互斥。这样就很大提升了系统的并发能力。之后人们发现并发读还是不够,又提出了能不能让读写之间也不冲突的方法,就是读取数据时通过一种类似快照的方式将数据保存下来,这样读锁就和写锁不冲突了,不同的事务session会看到自己特定版本的数据。

要点: 

  1. 数据版本

    • MVCC通过为每个数据对象(如行记录)保持不同的版本来工作。
    • 当用户开始一个事务时,他们看到的数据版本是该事务开始时数据库的状态。
  2. 读操作

    • 读取操作通常不会被阻塞,因为它们可以访问数据的旧版本。
    • 这意味着读取事务不会等待其他事务完成修改,实现了非锁定读。
  3. 写操作

    • 当写入操作发生时,系统会创建数据的新版本。
    • 对于更新和删除操作,MVCC通常会标记旧版本的数据为“不可见”,同时写入新的数据版本。
    • 其他事务如果没有提交更新操作,仍然可以看到旧版本的数据。
  4. 事务ID

    • 每个事务都分配有一个唯一的事务ID。
    • 数据版本会关联一个创建版本号和删除版本号,通常是事务ID。
    • 事务在访问数据时,只能看到创建版本号小于等于自身事务ID且删除版本号未定义或者大于自身事务ID的数据。
  5. 一致性视图

    • 在MVCC中,每个事务都有一个一致的数据库快照,这意味着在事务执行期间,无论其他事务如何修改数据,它都会看到事务开始时的数据状态。
  6. 提交与回滚

    • 事务提交时,其更改会变为永久性,并为其他事务创建一个新的数据版本。
    • 如果事务回滚,所有更改都会被丢弃,系统会删除这些临时版本的数据。
  7. 垃圾回收(清理旧版本)

    • 随着时间推移,旧的数据版本可能不再被任何事务所需要,这些数据版本需要通过垃圾回收机制来清理。
    • 这是为了避免无限制地增加存储需求并保持数据库性能。
  8. 并发冲突

    • 当两个事务尝试修改同一数据版本时,可能会出现冲突。
    • MVCC使用锁或乐观并发控制来处理这些冲突。
  9. 隔离级别

    • MVCC允许设置不同的事务隔离级别,以适应不同的一致性需求和性能权衡。
    • 较低的隔离级别(如读取未提交)可能会导致脏读,而较高的隔离级别(如可串行化)提供更强的数据一致性,但可能会牺牲并发性能。

2,MVCC在什么隔离级别下工作?

MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作。其他隔离级别与MVCC不兼容,因为在READ UNCOMMITTED 隔离级别下,总是读取最新数据行。而在SERIALIZABLE隔离级别下则会对任何读写行加锁,所以MVCC在这两个隔离级别下无效。

3,Undolog,redolog,binlog的详细介绍

binlog,是mysql服务层产生的日志,常用来进行数据恢复数据库复制,常见的mysql主从架构,就是采用slave同步master的binlog实现的, 另外通过解析binlog能够实现mysql到其他数据源(如ElasticSearch)的数据复制

redo log记录了数据操作在物理层面的修改,mysql中使用了大量缓存,缓存存在于内存中,修改操作时会直接修改内存,而不是立刻修改磁盘,当内存和磁盘的数据不一致时,称内存中的数据为脏页(dirty page)。为了保证数据的安全性,事务进行中时会不断的产生redo log,在事务提交时进行一次flush操作,保存到磁盘中, redo log是按照顺序写入的,磁盘的顺序读写的速度远大于随机读写。当数据库或主机失效重启时,会根据redo log进行数据的恢复,如果redo log中有事务提交,则进行事务提交修改数据。这样实现了事务的持久性。

undo log: 除了记录redo log外,当进行数据修改时还会记录undo log,undo log用于数据的撤回操作,它记录了修改的反向操作,比如,插入对应删除,修改对应修改为原来的数据,通过undo log可以实现事务回滚,并且可以根据undo log回溯到某个特定的版本的数据,实现MVCC。保证了事务的原子性

4,版本链

InnoDB行记录中除了刚才提到的行号外,还有trx_id和db_roll_ptr, trx_id表示最近修改的事务的id,db_roll_ptr指向undo segment中的undo log。

新增事务时trx_id会增加,trx_id表示事务执行的先后顺序

update undo log记录了数据之前的数据信息,通过这些信息可以还原到之前版本的状态。

当进行插入操作时,生成的Insert undo log在事务提交后即可删除,因为其他事务不需要这个undo log

进行删除修改操作时,会生成对应的undo log,并将当前数据记录中的db_roll_ptr指向新的undo log

5,readview

ReadView中主要就是有个列表来存储我们系统中当前活跃着的读写事务,也就是begin了还未提交的事务。通过这个列表来判断记录的某个版本是否对当前事务可见。

up_limit_id:活跃事务列表trx_ids中最小的事务ID,如果trx_ids为空,则up_limit_id 为 low_limit_id。当trx_id<up_limit_id时,对于当前Read View都是可见的。表示此事务在创建快照读事务时,事务已提交

low_limit_id:目前出现过的最大的事务ID+1,即下一个将被分配的事务ID,当事务号>=low_limit_id,对于当前Read View都不可见。表示在创建快照读时在此之后创建的事务是不可见的

trx_ids:Read View创建时其他未提交的活跃事务ID列表。所以当进行RR读的时候,trx_ids中的事务对于本事务是不可见的(除了自身事务,自身事务对于表的修改对于自己当然是可见的)。理解起来就是创建RV时,将当前活跃事务ID记录下来,后续即使他们提交对于本事务也是不可见的。

creator_trx_id:当前创建事务的ID,是一个递增的编号

总结:trx_id<up_limit_id 此事务已提交,事务可见

up_limit_id <trx_id<low_limit_id:分两种情况,如果此trx_id=自己,则可以访问此事务,否则不可访问

trx_id>low_limit_id:属于未来的事务,事务不可见

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nathaniel333

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值