返回顶部
首页 > 资讯 > 数据库 >MySQL如何实现事务的ACID
  • 657
分享到

MySQL如何实现事务的ACID

MySQL事务MySQL实现事务特性MySQL事务acid 2022-05-20 22:05:16 657人浏览 薄情痞子
摘要

前言 最近在面试,有被问到,Mysql的InnoDB引擎是如何实现事务的,又或者说是如何实现ACID这几个特性的,当时没有答好,所以自己总结出来,记录一下。 事务的四大特性ACID 事务的四大特性ACID分别是,A-

前言

最近在面试,有被问到,Mysql的InnoDB引擎是如何实现事务的,又或者说是如何实现ACID这几个特性的,当时没有答好,所以自己总结出来,记录一下。

事务的四大特性ACID

事务的四大特性ACID分别是,A-原子性(Atomicity),C-一致性(Consistency),I-隔离性(Isolation),D-持久性(Durability)。一致性是最终目的,原子性、隔离性、持久性是为了保证一致性所做的措施。所以我写的顺序并不是按照ACID来写的,将一致性放到了最后,顺序就变成了,ADIC。

原子性(A)

原子性是指一个事务就是一个不可分割的工作单位,要么全部都执行成功,要么全部都执行失败,没有中间状态或是只执行一部分。

mysql的InnoDB引擎是靠undo log(回滚日志)来实现的,undo log能够保证在事务回滚时,能够撤销所有已经执行成功的sql

undo log 属于逻辑日志,它记录的是SQL执行相关的信息。当事务对数据库进行修改时,InnoDB会生成与之对应的undo log。如果事务执行失败或者调用的rollback,导致事务需要回滚,InnoDB引擎会根据undo log中的记录,将数据回滚到之前的样子。
例如在执行insert语句时会生成相关的delete语句的undo log。反之执行delete语句也会生成相关的insert语句的undo log。执行update语句时也是如此,不过update语句在执行undo log回滚时有可能会涉及到mvcC。主要是为了保证在执行undo log的时候的select能看到哪个版本的数据。

持久性(D)

持久性是指事务一旦提交,对数据库的操作就是永久性的,接下来的其他操作和异常故障不应该对它有任何影响。
我们都知道MySQL的数据最终是存放在磁盘中的,所以才会有磁盘的容量大小决定数据容量的大小。但是如果对MySQL的操作都是通过读写磁盘来进行的话,那么光是磁盘的I/O就够把效率大大的拉低了。

所以InnoDB为MySQL提供了缓冲池(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射。
当从数据库读取数据时,会先从Buffer Pool中读取数据,如果Buffer Pool中没有,则从磁盘读取后放入到Buffer Pool中。
当向数据库写入数据时,会先写入到Buffer Pool中,Buffer Pool中更新的数据会定期刷新到磁盘中(此过程称为刷脏)。

虽然Buffer Pool为MySQL的读写提高了效率,但是却也带来了新的问题,那就是如果数据刚更新到Buffer Pool中还没来得及刷新到磁盘中时,MySQL突然宕机了,这就会导致数据丢失,造成事务的持久性无法保证了。
为了解决这个缓存的一致性问题,redo log就出现了。在对Buffer Pool中的数据进行修改的时候通过redo log记录这次操作,当事务提交时会通过fsync接口对redo log进行刷盘。

因为在事务提交时会把redo log是同步在磁盘中的,所以当MySQL出现宕机时,可以从磁盘中读取redo log进行数据的恢复,从而保证了事务的持久性。

redo log 采用的预写的方式记录日志,即先记录日志,再更新Buffer Pool,这样就强行的保证了,数据只要保存在了redo log中就一定会存储到磁盘中了。

这要解释一下,redo log 也是写磁盘,刷脏也是写磁盘,为啥要先记录redo log而不是直接刷脏?

主要原因就是redo log比刷脏快很多。

第一点是,redo log是追加操作日志,是顺序IO;而刷脏是随机IO,因为每次更新的数据不一定是挨着的,也就是随机的。

第二点是,刷脏是以数据页(Page)为单位的(即每次最少从磁盘中读取一页数据到内存,或者最少刷一页数据到磁盘),MySQL默认页大小是16KB,对一个页上的修改,都要整个页都刷到磁盘中;而redo log只包含真正的需要写入磁盘的操作日志。

MySQL还有一个记录操作的日志,叫binlog ,那么redo log和binlog又有什么区别呢?

  • 第一点作用上的区别:

redo log是用来记录更新缓存的,为了保证MySQL就算宕机也不会影响事务的持久性;binlog是用来记录什么时间操作了什么,主要有时间点,可以保证将数据恢复到某个时间点,也有用于主从同步数据的。

  • 第二点层次上的区别:

redo log是存储引擎InnoDB实现的(MyISAM就没有redo log),而binlog是在MySQL服务器层面存在的任何其他存储引擎也有binlog。
存储内容上,redo log是物理日志,基于磁盘的数据页,binlog是逻辑日志,存储的一条执行SQL。

  • 第三点写入时机的区别:

redo log 在默认情况下是在事务提交时,进行刷盘的;可以通过参数:innodb_flush_log_at_trx_commit 来改变策略,可以不用等到事务提交时才进行刷盘。
如:可以设置成每秒提交一次。
binlog是在事务提交时写入。

隔离性(I)

原子性和持久性都是基于单个事务内部的措施,而隔离性是只多个事务之间相互隔离,互不影响的特性。
我们都知道事务的隔离级别中最严谨的是串行化(Serializable),但是隔离性越高,性能就越低,所以一般不使用串行化这个隔离级别。
对于隔离性的,我们要分两种情况进行讨论:

  • 一个事务中的写操作对另一个事务中的写操作的影响;
  • 一个事务中的写操作对另一个事务中的读操作的影响;

首先,事务间的写操作其实是靠MySQL的机制来实现隔离的,而事务间的写和读操作是靠MVCC机制来实现的。

锁机制

MySQL中的锁主要有

按照功能分:读锁和写锁;按照作用范围分:表级锁和行级锁;
还有意向锁,间隙锁等。

读锁:又称“共享锁”,是指多个事务可以共享一把锁,都只能访问数据,并不能修改。

写锁:又称“排他锁”,是不能和其他事务共享数据的,如果一个事务获取到了一个数据的排他锁,那么其他事务就不能再获取该行的其他锁,包括共享锁和排他锁。

表级锁:是指会将整个表进行锁定,性能较差,不同存储引擎支持的锁的粒度不同,MyISAM引擎支持表级锁,InnoDB引擎支持表级锁也支持行级锁。

行级锁:会将需要操作的相应行进行锁定,性能好。

意向锁:意向锁是表级锁,如果在一个事务已经对一个表中的某个数据加上了排他锁或共享锁,那么就可以加上意向锁,这样当下一个事务来进行锁表的时候发现已经存在意向锁了,就会先被阻塞,如果不加意向锁的话,第二个事务来锁表的时候需要一行一行的遍历查看是否有数据已经被锁住了。

间隙锁:间隙锁是为了防止产生幻读而加的锁,加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间(但是并不包含当前记录)。这样就保证了在间隙锁执行的时候,新增的数据会阻塞,保证了一个事务中的两次查询获得的记录数都是一致的。

Next-Key Lock:Next-Key Lock是行级锁和间隙锁的结合产生的锁,因为间隙锁是不会锁住当前记录的而Next-Key Lock是会将当前记录也锁住的。

例如:如果一个表中有三条数据分别是:

id name number
1 小明 16
2 小红 17
3 小张 20
4 小王 20

那么在执行SQL:select * from table where number = 17 for update 时间隙锁会锁住,number的区间是(16,17),(17,20),但是Next-Key Lock的锁住的是:
16,17),(17,20)区间加间隙锁,同时number=17加记录锁。

锁机制保障了多个事务间的写操作的隔离,而多个事务间的读和写操作的保证是需要通过MVCC机制来保证的。

MVCC机制

MVCC全称是【Multi-Version ConCurrency Control】即多版本控制协议。

MVCC的主要是靠在每行记录上增加隐藏列和使用undo log来实现的,隐藏列主要包括,改行数据创建的版本号(递增的),删除时间,指向undo log的指针等。

那么MVCC是如何保证读写隔离的呢?主要是通过快照读和当前读两个操作。

  • 快照读:

MVCC为了保证并发的效率,在进行读取数据的时候是不加锁的,在执行select的时候(不带锁的普通select),会先读取当前数据的版本号,如果在select还没返回结果时,有事务将此行数据进行了修改,那么版本号就会比执行select的时候的大,所以为了保证select读取数据的一致性,就只会读取小于或等于当前版本的数据,这个历史版本的数据就是从undo log中获取到的。

  • 当前读:

当执行insert、update、delete的时候,是读取的当前最新的版本数据,并且会给当前记录加上锁,用来保证在操作的时候不会被别的事务将版本号进行修改。

像普通的select就是快照读即读取的有可能就是数据的历史版本。

insert、update、delete、select ... lock in share mode 和select ... for update 读取的就是当前读,即读取的都是数据的最新版本。

其实将隔离级别设置为Serializable也是可以实现读写隔离的,但是并发效率会比低很多,所以一般用的很少,但是MVCC是读不加锁的,只有在写的时候才会加锁,从而提高的并发的效率。

通过MVCC机制保证了多个事务间的读写隔离,从而实现了事务的隔离性。

一致性(C)

一致性是指在事务执行前后,数据的一致性,事务前后数据完整性没有破坏,并且都是合法的数据状态。

  • 其中一致性的指标有:

索引的完整(唯一索引,不重复等),数据列的完成(字段类型,长度,大小符合要求),外键约束等。

  • 实现一致性的措施:

保证原子性,持久性,隔离性,如果这些特性都无法保证,那么一致性就也无法保证了。从数据库层面来看,除了前面那几个特性的保证外,对字段的一致性是有保证措施的,例如整型的字符不能传入,字符串、时间等格式,字符串的长度不能超过列的限制。但是在应用层面也是需要开发者自己来保证的,
例如:从A转账给B一部分金额,那么就要保证,从A从将金额扣除多少就要去给B增加多少金额,如果只扣除A的金额,而没有增加B的金额,是无法保证一致性的。

另外,MySQL还通过两阶段提交事务,保证了redo log和binlog之间的数据一致性问题。

通过上面介绍持久性的时候解释了,redo log和binlog的区别了,在区别中的第三条有说到,在默认情况下,事务提交时,既写redo log 有写binlog那么他们是如何协调一致性的呢?事务提交成功以写入哪个日志为准呢?
MySQL通过两阶段提交来保证这两个日志的数据一致性。

  • 第一阶段提交,

将redo log提交到磁盘,并将状态改为prepare状态,binlog不做任何操作。

  • 第二阶段提交,

生成事务操作的binlog,并将binlog写入到磁盘中。

调用引擎的提交事务接口,将redo log的状态从prepare改为commit,事务提交完成。
通过上面这两阶段提交保证了事务数据的一致性。
当事务提交时redo log处于prepare阶段时,发生MySQL宕机或崩溃,则会执行事务回滚。
当事务提交redo log处于commit阶段时,发生了崩溃会执行事务恢复,本机事务通过redol og进行恢复,而如果是主从数据库的话,在commit阶段,会根据binlog对从库进行数据恢复。
这就是以写入binlog成功为提交事务成功的依据。因为一般在崩溃恢复的时候都是用binlong进行恢复的,如果还未生成binlog,只写入了redo log。在恢复的时候redo log恢复的是一个版本的数据,而通过bin log恢复的从库数据会是之前的一个时间点的binlog版本的数据,这样数据就导致不一致了。

总结

MySQL事务的ACID,一致性是最终目的。
保证一致性的措施有:

  • A原子性:靠undo log来保证(异常或执行失败后进行回滚)。
  • D持久性:靠redo log来保证(保证当MySQL宕机或停电后,可以通过redo log最终将数据保存至磁盘中)。
  • I隔离性:事务间的读写靠MySQL的锁机制来保证隔离,事务间的写操作靠MVCC机制(快照读、当前读)来保证隔离性。
  • C一致性:事务的最终目的,即需要数据库层面保证,又需要应用层面进行保证,并且MySQL底层通过两阶段提交事务保证了事务持久化时的一致性。

以上就是MySQL如何实现事务的ACID的详细内容,更多关于MySQL实现事务的ACID的资料请关注自学编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: MySQL如何实现事务的ACID

本文链接: https://lsjlt.com/news/9786.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • MySQL如何实现事务的ACID
    前言 最近在面试,有被问到,MySQL的InnoDB引擎是如何实现事务的,又或者说是如何实现ACID这几个特性的,当时没有答好,所以自己总结出来,记录一下。 事务的四大特性ACID 事务的四大特性ACID分别是,A-...
    99+
    2022-05-20
    MySQL 事务 MySQL 实现事务特性 MySQL 事务 acid
  • 如何在Mysql中实现事务ACID
    这期内容当中小编将会给大家带来有关如何在Mysql中实现事务ACID,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。原子性根据定义,原子性是指一个事务是一个不可分割的工作单...
    99+
    2024-04-02
  • MySql事务及ACID实现原理详解
    目录逻辑架构和存储引擎自动提交特殊操作ACID 特性原子性持久性隔离性脏读、不可重复读和幻读事务隔离级别MVCC一致性逻辑架构和存储引擎 自动提交 MySQL 中默认采用的是自动提...
    99+
    2024-04-02
  • [MySQL]事务ACID详解
    专栏简介 :MySql数据库从入门到进阶. 题目来源:leetcode,牛客,剑指offer. 创作目标:记录学习MySql学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现...
    99+
    2023-09-01
    mysql 数据库 java
  • mysql - innoDB、事务、ACID特性
    参考:https://www.bilibili.com/video/BV1ui4y1w7C6from=search&seid=9894164453600625754   InnoDB具有事务,支持4个事务隔离级别,回滚,崩溃修复能力和多版本...
    99+
    2018-05-21
    mysql - innoDB 事务 ACID特性 数据库入门 数据库基础教程 数据库 mysql
  • MySQL事务之ACID特性的实现原理是什么
    小编给大家分享一下MySQL事务之ACID特性的实现原理是什么,希望大家阅读完这篇文章后大所收获,下面让我们一起去探讨吧!事务是MySQL等关系型数据库区别于NoSQL的重要方面,是保证数据一致性的重要手段...
    99+
    2024-04-02
  • MySQL关系型数据库事务的ACID特性与实现
    目录1. 事务的 ACID 特性详2. MySQL 事务的实现3. Gorm 事务的使用4. Spring 事务的使用1. 事务的 ACID 特性详 ACID 是为保证事务(tran...
    99+
    2022-11-13
    MySQL关系型数据库事务 ACID特性
  • 一文快速搞懂MySQL InnoDB事务ACID实现原理
    【51CTO.com原创稿件】说到数据库事务,想到的就是要么都做修改,要么都不做,或者是 ACID 的概念。其实事务的本质就是锁、并发和重做日志的结合体。 这一篇主要讲一下 InnoDB 中的事务到底是如何...
    99+
    2024-04-02
  • SQL中的事务ACID
    概述: 事务是由一系列语句构成的逻辑工作单元。事务和存储过程等批处理有一定程度上的相似之处, 通常都是为了完成一定业务逻辑而将一条或者多条语句“封装”起来,使它们与其他语句之间出现一个逻辑上的边界,并形成相对独立的一个工作单元。 ...
    99+
    2017-12-30
    SQL中的事务ACID
  • MySQL事务中的ACID特性是什么
    MySQL事务中的ACID特性是什么?针对这个问题,这篇文章给出了相对应的分析和解答,希望能帮助更多想解决这个问题的朋友找到更加简单易行的办法。一、基础概念事务(Transaction)是指访问并可能更新数...
    99+
    2024-04-02
  • MySQL中怎么实现ACID
    本篇文章给大家分享的是有关MySQL中怎么实现ACID,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。  假设你执行了一条 sql 语句:  u...
    99+
    2024-04-02
  • MySQL事务ACID原理深度解析
    什么是MySQL事务? 事务是指对数据库的一组操作的集合,集合中的SQL语句要么全部执行成功,要么就全部失败,如果集合中任一操作出错,则此集合所有对数据库的操作全部回滚。 以常见的购物操作举例,用户下单后要执行订单创建、减库存等一系列操...
    99+
    2018-05-21
    MySQL事务ACID原理深度解析
  • MySQL事务控制流与ACID特性
    目录一、ACID 特性二、事务控制语法 三、事务并发异常 1、脏读 2、不可重复读 3、幻读 四、事务隔离级别 一、ACID 特性 事务处理是一种对必须整批执行的 MySQL 操作的...
    99+
    2024-04-02
  • MySQL中事务和ACID的作用是什么
    今天就跟大家聊聊有关MySQL中事务和ACID的作用是什么,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。所谓事务(Transaction),就是通过...
    99+
    2024-04-02
  • MySQL事务的ACID特性及并发问题实例分析
    本篇内容主要讲解“MySQL事务的ACID特性及并发问题实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL事务的ACID特性及并发问题实例分析”吧...
    99+
    2024-04-02
  • 【MySQL】MySQL实现ACID的原理(MySQL专栏启动)
    📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级...
    99+
    2023-10-18
    mysql 数据库 事务 隔离性 原子性 持久性 一致性 原力计划
  • 我们如何实现MySQL事务?
    我们知道,在事务中,语句是作为一个单元执行的。如果事务内的任何操作失败,则整个事务将失败并应回滚;否则,语句所做的任何更改都会保存到数据库中。为了实现事务,MySQL 提供了以下语句 -START TRANSACTION顾名思义,事务从此语...
    99+
    2023-10-22
  • 如何实现MySQL中的事务处理?
    如何实现MySQL中的事务处理?事务是数据库中重要的概念之一,能够保证数据的一致性和完整性,确保在并发操作中数据的正确性。MySQL作为一种常用的关系型数据库,也提供了事务处理的机制。一、事务的特点事务具有以下四个特点,通常用ACID来概括...
    99+
    2023-10-22
    MySQL 事务 处理
  • 数据库 事务的特性ACID
    事务(Transaction)是并发控制的基本单位。    所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。例如,银行转帐工作:从一个...
    99+
    2024-04-02
  • MySQL是如何实现事务隔离?
    前言   众所周知,MySQL的在RR隔离级别下查询数据,是可以保证数据不受其它事物影响,而在RC隔离级别下只要其它事物commit后,数据都会读到commit之后的数据,那么事物隔离的原理是什么?是通过什么实现的呢?那肯定是通过MVC...
    99+
    2017-02-21
    MySQL是如何实现事务隔离?
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作