聊聊MySQL中的事务,MVCC

事务


  • 我们知道,事务具有四大特性——ACID

  • A atomicity 指的是原子性

  • C consistency 指的是一致性

  • I isolation 指的是隔离性

  • D durability 指的是持久性

四大特性的实现原理


原子性

  • 原子性在这指的是整个事务操作,要么同时成功要么同时失败。让它变成一个整体。

  • 同时成功这好办,难办的是同时失败。

  • 想要实现同时失败,就需要恢复之前的数据,如何恢复旧版本数据呢? undolog回滚日志

  • undolog回滚日志是实现事务原子性的关键。它保存了数据修改之前的历史数据。当我们的事务中有insert操作时,他会反向的记录一个delete,反之亦然。

隔离性


  • 隔离性指的是当由多个活动事务的时候,每一个事务应该是相互独立的整体。也就是说它们互不干扰。

  • 隔离性实现是基于MVCC多版本数据并发控制实现的。

持久性


  • 持久性指的是,当我的事务提交,事务里面涉及修改的数据都会得到持久性。而不会因为某些特殊原因导致我的修改数据没有更新到磁盘里面去。

  • 持久性的实现是由redolog重做日志完成的。

  • 当我们对数据做增删改的时候,会经历这样的过程:

  • 修改缓冲池里面的数据

  • 写入缓冲池的redolog

  • 提交事务

  • 同步更新磁盘中的redolog

  • 等待后台线程刷新脏数据,完成持久化。

一致性


  • 一致性指的是发生增删改操作时,数据库从一个一致性的状态进入另一个一致性状态。

  • 其实上面三个特性就是为了实现一致性。

  • 举例说:

  • 我的钱包里有1000块钱,买了一包烟花掉100块钱。

  • 那么此时的一致性应该是这样:

  • 我的钱包从1000变成了900.

  • 烟店老板的钱包从N 变成了N+100

redolog


redolog是innodb存储引擎提供的一个日志机制,它可以保证事务的持久性特性。

redolog解决什么问题


  • 首先要知道,mysql的存储结构是包含内存结构和硬盘结构。

  • 内存结构中主要的结构就是缓冲池,当我们增删改一条数据的时候,会从缓冲池里面寻找这条数据,如果没有则从硬盘读取。在对数据做修改的时候,如果不是唯一索引条件的修改,那么会先把缓存池里的数据先修改,为了保证性能,修改完之后并不会马上同步到硬盘里。此时存在缓冲池里面这条不一致的数据就是脏数据。

  • 脏数据会等待一段时间由后台线程刷新到磁盘中。

  • 假如没有redolog,在刷新到磁盘的过程中出现问题了,那么就会出现一致性问题。

  • redolog就是为了解决这个问题。

redolog啥时候用


  • 当我们对数据做修改时,此时就会记录这条修改数据的redolog,此时事务尚未提交,记录的是redolog的内存部分。

  • 当事务提交的时候,便会将内存中的redolog同步到磁盘中去。

  • 搞得这么麻烦,为啥不直接在事务提交的时候将脏页刷新过去?

  • 这是因为数据的修改,写入磁盘顺序是随机的。而写入日志文件,则是顺序写入磁盘,在性能上要远强于直接写入数据。在写入数据之前先写入日志,这个叫做WAL(Write Ahead Logging)

  • 当脏页成功刷盘之后,redolog就可以被销毁了。

redolog会不会有一致性问题


  • 不会

  • 从上面也知道,redolog 是在事务提交的时候,同步写入硬盘。如果此时提交事务这条线程宕机了,那么原事务也会撤销掉。也就是说由于持久化redolog这个动作是同步的,所以不会有一致性问题。

redolog如何保证持久性


  • 如果真的发生宕机,redolog如何保证事务提交之后仍然可以将脏页持久到磁盘。

  • 这个部分,则是由redolog的两阶段提交做保证。

  • redolog在写入磁盘的时候,并不是写进去就完事的。

  • 它是有两个状态,跟Binlog做配合。

  • 刚刚写入磁盘,此时是repare准备阶段,当Binlog接收到时,此时才是真正的commit状态。

  • 只有commit状态的redolog才会被看作事务真正完成了,如果是prepare状态则代表这条日志还没有被处理完。

undolog


undolog跟redolog不同,它是逻辑日志。当有修改操作发生时,它记录的时与它相反的动作。undolog保证了事务的原子性特性。

undolog解决什么问题


  • 作为回滚日志,它主要解决的就是如何实现事务的同时失败。

  • undolog用于记录数据被修改前的信息。

  • 当insert的时候,他会记录相反的操作delete;反之亦然。当Update的时候则会记录一条相反的数据。

undolog啥时候用


  • undolog是在修改数据的时候生成的。

  • undolog在事务提交之后不会马上删除,因为它还可以用于MVCC。

undolog版本链


  • insert产生的undolog 只在回滚需要,在事务提交后可被立即删除。

  • update,delete的时候产生的undolog不仅在回滚是需要,在快照读的时候也需要,不会立即删除。因为它记录了数据之前的版本是什么样子。

  • 当有活动事务的时候,undolog版本链就不能被删除。

  • 不同的事务或者相同事务对同一条记录进行修改,会导致这条记录的undolog生成一条记录版本链表,链表的头部都是最新的旧纪录,链表尾部是最早的旧纪录.

MVCC


基本概念


全称 Multi-Version Concurrency Control,多版本并发控制。指维护一个数据的多个版本,使得读写操作没有冲突。数据库隔离级别读已提交、可重复读 都是基于MVCC实现的,事务的隔离性也是基于MVCC实现。相对于加锁简单粗暴的方式,它用更好的方式去处理读写冲突,能有效提高数据库并发性能。MVCC的具体实现,还需要依赖于数据库记录中的三个隐式字段、undo log日志、readView。

当前读

  • 当前读读的是最新的数据,在读取的时候给这一行数据加上共享锁,增删改加的是排他锁,它们也是当前读。

  • 例如select ... for share mode, delete ,insert ,update

快照读

  • 简单的select 就是快照读,快照读读取的是记录数据的可见版本。有可能是历史版本,也可能是最新版本。

  • 读取的时候不加锁,非阻塞读。

  • 在RR(可重复读)的隔离级别下,事务中的第一次读是快照读,后续读到的数据都是第一次快照读的版本。所以它可以解决不可重复读。

  • 而RC(读已提交)的隔离级别下,事务中每一次读取数据都是快照读,所以不可以解决不可重复读,可以解决读已提交。

三个隐藏字段

  • MVCC的实现原理依赖于三个隐藏字段,undolog,readView

  • 三个隐藏字段分别为,事务ID,回滚指针,行ID(有可能不需要)

隐藏字段

含义

DB_TRXID

最近修改事务D,记录插入这条记录或最后一次修改该记录的事务D。

DB ROLL PTR

回滚指针,指向这条记录的上一个版本,用于配合undo log,指向上一个版本。

DB ROW ID

隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段。

ReadView


  • readView(读视图)是快照读SQL执行的时候MVCC提取数据的依据,记录并且维护系统当前活跃的事务id

  • readView包含四个核心字段

字段

含义

m_ ids

当前活跃的事务D集合

min_ trx id

最小活跃事务ID

max_ trx id

预分配事务D 当前最大事务ID+1(因为事务D是自增的)

creator trx_ id

ReadView创建者的事务D

MVCC的实现原理


  • 前面提到,MVCC的实现依赖于三个隐藏字段+undolog+ReadView

  • 那么具体是怎么利用他们完成多版本并发控制的呢?

  • RreadView版本链数据的访问规则 + 不同隔离级别下快照读的时机

  • readView规定了版本链数据的访问规则,这套规则就是实现MVCC的关键。

条件

是否可以访问

说明

trx_id == creator_trx_id

可以访问该版本

成立,说明数据是当前这个事 务更改的。

trx_id< min_trx_id

可以访问该版本

成立,说明数据已经提交了。

trx_id> max_trx_id

不可以访问该版本

成立,说明该事务是在 ReadView生成后才开启。

min_trx_id<= trx_id <= max_trx_id

如果trx_id不在m_ids中, 是可以访问该版本的

成立,说明数据已经提交。

  • 简单来说,这套规则会让那些可以被访问的数据是别的事务已经提交的数据。

  • 同时,不同的隔离级别,生成readView的时机也是不同的

  • READ COMMITTED :在事务中每一次执行快照读时生成ReadView。

  • REPEATABLE READ:仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值