MySQL的MVCC机制

介绍

        MVCC是指多版本并发控制,MVCC是在并发访问数据库时,通过对数据进行多版本控制,避免因写锁而导致读操作的堵塞,从而很好的优化并发堵塞问题,为了用来处理读写冲突的手段和解决数据库的事务操作中的多线程并发安全问题的无锁并发控制技术。

作用

  1. MVCC通过数据行的多个版本管理来实现数据库的并发控制,使得在InnoDB事务隔离级别下执行一致性读操作有了保障。
  2. mysql中的InnoDB中实现了MVCC主要是为了提高数据库的并发性能,在无锁的情况下也能处理读写并发,大大提高数据库的并发度。
  3.  MySQl中只有InnoDB支持MVCC,其他存储引擎不支持
  4. 为了查询一些正在被其他事务更新的值的时候,能够查到它们被更新之前的值,这样做就能在查询的时候不必等待更新事务的提交。

在InnoDB中,会对增删改操作自动添加排它锁,因此两个事务不会出现脏写的情况,也就是不会出现两个事务交叉着对同一条记录进行修改,必须等待第一个事务提交才能进行第二个事务。

解决的问题

  1.  读写之间的堵塞问题,提高事务的并发读写能力
  2.  降低了死锁的概率,MVCC采用了乐观锁的方式,读取数据的时候不需要加锁,对于写操作,也只要锁定必要的行
  3.  解决快照读问题,当查询数据库某个时间节点的快照的时候,只能查看到在这个节点之前提交的事务的结果而看不到时间点之后事务提交的更新结果

MVCC来源

在数据库中,通常有以下四种并发读写情况
    
    读读(Read-Read):在读读情况下,即两个事务同时进行读取操作时
    读写(Read-Write):在读写情况下,一个事务进行读取操作,另一个事务进行写入操作
    写读(Write-Read):在写读情况下,一个事务进行写入操作,而另一个事务进行读取操作
    写写(Write-Write):在写写情况下,两个事务同时进行写入操作
    
总的来说数据并发情况有三种:
   1. 读读并发:不存在问题,不需要并发控制
   2. 读写并发:有线程安全问题,可能会造成事务隔离性问题,遇到脏读,幻读,不可重复读
   3. 写写并发:有线程安全问题,可能会有更新丢失


在读读情况下,不需要并发控制,但是为了在读写情况下也能实现并发,所以引入了MVCC机制

MVCC解决的就是读写并发的问题,是一种无锁并发控制。
也就是为事务分配单向增长的时间戳,为每个修改保存一个版本,版本与事务时间戳关联,读操作只读该事务开始前的数据库快照,这样就解决了两个问题:
       1. 在并发读写操作数据库时,可以做到读操作和写操作互不阻塞,提高数据库并发性能
       2. 解决读写并发时可能会出现的脏读,幻读,不可重复读等事务隔离问题

事务基本特性ACID

原子性 指的是一个事务中的操作要么全部成功,要么全部失败。

一致性 指的是数据库总是从一个一致性的状态转换到另外一个一致性的状态。比如A转账给B100块钱,假设中间sql执行过程中系统崩溃A也不会损失100块,因为事务没有提交,修改也就不会保存到数据库。

隔离性 指的是一个事务的修改在最终提交前,对其他事务是不可见的。

持久性 指的是一旦事务提交,所做的修改就会永久保存到数据库中。

ACID靠什么保证 

A原子性 由undo log日志保证,它记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql

C一致性 一般由代码层面来保证

I隔离性 由MVCC来保证

D持久性 由内存+redo log来保证,mysql修改数据同时在内存和redo log记录这次操作,事务提交的时候通过redo log刷盘,宕机的时候可以从redo log恢复

 隔离性下有四种级别

read uncommit 读未提交

        可能会读到其他事务未提交的数据,也叫做脏读。

        用户本来应该读取到id=1的用户age应该是10,结果读取到了其他事务还没有提交的事务,结果读取结果age=20,这就是脏读。

read commit 读已提交

        两次读取结果不一致,叫做不可重复读。不可重复读解决了脏读的问题,他只会读取已经提交的事务。

        用户开启事务读取id=1用户,查询到age=10,再次读取发现结果=20,在同一个事务里同一个查询读取到不同的结果叫做不可重复读。

repeatable read 可重复复读

        这是mysql的默认级别,就是每次读取结果都一样,无论其他事务是否修改并提交了数据,在这个事务中看到的数据值始终不受其他事务影响,但是有可能产生幻读。

serializable 串行

        一个事务一个事务的执行, 一般是不会使用的,他会给每一行读取的数据加锁,会导致大量超时和锁竞争的问题。

实现原理

        MVCC的两个实现核心是undo log和一致性视图,以及三个隐藏字段,通过undo log来保存多版本的数据,通过一致性视图来保存当前活跃的事务列表,将两者结合和制定一定的规则来判断当前可读数据,

隐藏字段

        RowId: 隐藏主键,如果表中没有指定主键,会自动生成一个id作为主键

        TrxId: 最近修改事务Id,记录了创建这条记录或是最后一次修改这条记录的事务Id

        RollPtr: 回滚指针,用于配合undoLog这条记录的上一个版本

undoLog(回滚日志)

        在进行增删改操作时记录的方便回滚的日志

        在进行insert操作的时候,记录的undoLog只在回滚的时候需要,并且在事务提交后删除

        在进行delete,update操作的时候,记录的undoLog不仅在事务回滚的时候需要,在快照读的时候也需要。只有 在快照读和事务回滚都不涉及该日志时,才会被线程统一清除。

        也就是delete_bit为true且表中事务Id相对于purge线程的read view可见时,才删除

Read View

        ReadView即一致性视图,用来判断版本链中的哪个版本是当前事务可见的。

        RC和RR隔离级别之间一个非常大的区别就是——它们生成ReadView的时机不同!!

        RC——在一个事务中,每次读取数据前都生成一个ReadView。

        RR——在一个事务中,只在第一次读取数据时生成一个ReadView。

 具体实现原理:Mysql MVCC机制原理详解_Mysql_脚本之家

  • 24
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值