个人MySQL的事务特性原理笔记总结

​ 事务Transaction是数据库区别于文件系统的重要特性之一,也是MySQL等关系型数据库区别于NoSQL数据库的重要方面。本文会先介绍事务的4个特性,然后讲解每个特性在MySQL中的实现原理。过程中有不对的地方,欢迎读者指出矫正与探讨。

一、基础概念

	### 1. 事务定义

​ 根据MySQL官网介绍:

​ 参考 https://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_acid

​ Transactions are atomic units of work that can be committed or rolled back. When a transaction makes multiple changes to the database, either all the changes succeed when the transaction is committed, or all the changes are undone when the transaction is rolled back.

​ 事务是可以提交回退的原子工作单元。当事务对数据库进行多次更改时,要么在提交事务后所有更改成功,要么在回滚事务后撤消所有更改。

2. 事务控制语句

  • START TRANSACTION | BEGIN:显示地开启一个事务。
  • COMMIT:也可以写成COMMIT WORK,会提交事务,修改数据会写入redo日志进行持久化。
  • ROLLBACK:回滚会结束用户的事务,并撤销在该事务中已经修改的数据。

3. 事务特性

​ 事务具体有四个特性ACID,严格来说,事务一定要同时满足这4个特性。但是不同的数据库厂商会在这个定义上有所调整。例如在MYSQL中,也只有InnoDB存储引擎完全满足ACID,像MyISAM存储引擎就完全不支持事务。ACID是以下4个词的缩写:

  • 原子性(atomicity)
  • 一致性(consistency)
  • 隔离性(isolation)
  • 持久性(durability)

​ 如无特殊说明,后文中描述的内容都是基于InnoDB存储引擎。

二、原子性

1. 原子性定义

​ 原子性指一个事务是数据库中不可分割的工作单位。只有事务中的所有操作CRUD都执行成功,才算整个事务成功。事务中的任何一个SQL语句执行失败,已经执行成功的SQL语句也必须撤销,数据库状态应该回到执行事务前的状态。

2. 实现

​ 在说明实现原理之前,先介绍一下MySQL的事务日志。MySQL的日志有很多种,比如:二进制日志、查询日志、慢查询日志、错误日志。此外InnoDB存储引擎还提供了两种事务日志:redo log(重做日志)和undo log(回滚日志)。其中redo log用于保证事务数据的持久化,undo log用于事务的回滚以及MVCC机制。

​ 说回undo log,实现原子性的保证,是当事务回滚时能够撤销该事务中已经执行成功的所有SQL语句。undo log 能够保证原子性在于:当事务对数据库进行数据修改、删除、增加操作时,会产生对应的undo log日志,这样如果事务或者语句由于某种原因失败了,又或者执行了ROLLBACK语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。

​ undo是逻辑日志,会记录事务中执行的SQL语句。当InnoDB存储引擎回滚时,它会根据undo log的中事务的语句,执行相反的SQL语句。对于每个INSERT,InnoDB存储引擎会完成一个DELETE;对于每个DELETE,InnoDB存储引擎会执行一个INSERT;对于每个UPDATE,InnoDB存储引擎会执行一个相反的UPDATE,将修改前的行修改回去。

​ MySQL在information_schema数据库下添加一张数据字典表为INNODB_TRX_UNDO,用来记录事务对应的undo log。该字典表会记录当前事务的这些信息:事务ID、回滚事务ID、插入类型、参与的表ID、发生变化的数据信息等.这样在需要会根据对应信息进行回滚。

三、持久性

1. 定义

​ 事务一旦提交,其结果就是永久性的。即使发生宕机等故障,数据库也能将数据恢复。

2. 实现

​ 持久性的实现依赖于上面提到的另一个事务日志:redo log日志,也叫重做日志。重做日志由两部分组成:一个是内存中的重做日志缓冲redo log buffer,它是易失的;二是重做日志文件,redo log file,它是持久的。

​ InnoDB是事务的存储引擎,其通过Force Log at Commit机制实现事务的持久性。当对数据库进行修改时,会将执行的语句先添加到redo log buffer中,当事务提交COMMIT时,InnoDB存储引擎会将redo log buffer的日志写入到redo log日志中进行持久化。同时还会进行一次fsync操作,可以确保重做日志写入磁盘。

3. redo log存在的背景

​ InnoDB作为MySQL的存储引擎,数据是存放在磁盘中的,但如果每次读写数据都需要磁盘IO,效率会很低。为此,InnoDB提供了缓存(Buffer Pool),Buffer Pool中包含了磁盘中部分数据页的映射,作为访问数据库的缓冲:当从数据库读取数据时,会首先从Buffer Pool中读取,如果Buffer Pool中没有,则从磁盘读取后放入Buffer Pool;当向数据库写入数据时,会首先写入Buffer Pool,Buffer Pool中修改的数据会定期刷新到磁盘中(这一过程称为脏页刷新)。

​ Buffer Pool的使用大大提高了读写数据的效率,但是也带了新的问题:如果MySQL宕机,而此时Buffer Pool中修改的数据还没有刷新到磁盘,就会导致数据的丢失,事务的持久性无法保证。

​ 于是,redo log被引入来解决这个问题:当数据修改时,除了修改Buffer Pool中的数据,还会在redo log记录这次操作;当事务提交时,会调用fsync接口对redo log进行刷盘。如果MySQL宕机,重启时可以读取redo log中的数据,对数据库进行恢复。redo log采用的是WAL(Write-ahead logging,预写式日志),所有修改先写入日志,再更新到Buffer Pool,保证了数据不会因MySQL宕机而丢失,从而满足了持久性要求。

​ 既然redo log也需要在事务提交时将日志写入磁盘,为什么它比直接将Buffer Pool中修改的数据写入磁盘(即刷脏)要快呢?主要有以下两方面的原因:

  1. 刷脏是随机IO,因为每次修改的数据位置随机,但写redo log是追加操作,属于顺序IO。
  2. 刷脏是以数据页(Page)为单位的,MySQL默认页大小是16KB,一个Page上一个小修改都要整页写入;而redo log中只包含真正需要写入的部分,无效IO大大减少。

附上一张InnoDB内存数据对象图

四、隔离性

1. 定义

​ 事务的隔离性是指__事务内的数据库操作与其他事务是隔离的,即该事务提交前对其他事务都不可见,事务间的操作是相互不影响的。__

2. 锁机制

​ 隔离性的原理主要依赖锁来完成。可以参考我的另一篇文章 https://www.cnblogs.com/process-h/p/14173838.html

五、一致性

1. 定义

​ 一致性是指__事务将数据库从一种状态转变为下一种一致的状态。__在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。比如说在表中有一个姓名字段,是唯一约束(即姓名不可重复),这时有个事务对姓名字段做了修改,但是事务提交或回滚后,姓名字段变得非唯一了,那这就破坏了事务的一致性要求。

2. 实现

​ 一致性也是事务追求的最终目的:__前面提到的原子性、持久性和隔离性,都是为了保证数据库状态的一致性。__不过,仅仅靠数据库来实现一致性还不够,也需要应用层面提供保障,比如在涉及转账业务时,A账户转出100,B账户入账100这2步需要一起完成,而不能只从A账户转出100.

参考文献

《深入浅出MySQL》

《MySQL技术内幕:InnoDB存储引擎》

https://dev.mysql.com/doc/refman/5.6/en/mysql-acid.html

https://dev.mysql.com/doc/refman/5.6/en/innodb-multi-versioning.html

https://www.cnblogs.com/kismetv/p/10331633.html#!comments

个人MySQL的事务特性原理学习笔记总结的更多相关文章

  1. MySQL事务控制语句(学习笔记)

    MySQL事务控制语句(学习笔记) MySQL事务控制语句         在mysql命令行的默认下,事务都是自动提交的,sql语句提交后马上会执行commit操作.因此开启一个事务必须使用begi ...

  2. 2018/09/13《涂抹MySQL》【MySQL复制特性】学习笔记(六)

    推荐一首歌 - <可不可以>张紫豪 好吧,随便从排行榜上找了一首 读 第十一章<MySQL的复制特性> 总结 1:复制(Replication) 应用场景? - 提高性能 (通 ...

  3. Unity3D 骨骼动画原理学习笔记

    最近研究了一下游戏中模型的骨骼动画的原理,做一个学习笔记,便于大家共同学习探讨. ps:最近改bug改的要死要活,博客写的吭哧吭哧的~ 首先列出学习参考的前人的文章,本文较多的参考了其中的表述: 1. ...

  4. MySql基本的语法(学习笔记)

    MySQL语法大全_自己整理的学习笔记 select * from emp;  #凝视 #--------------------------- #----命令行连接MySql--------- #启 ...

  5. mysql数据库事务隔离原理

    今天在学习JDBC的时候看到了关于MySQL的事务的隔离级别的问题,感觉内容挺高级的,所以记录一篇文章,以备后面使用. 数据库隔离级别有四种,应用<高性能mysql>一书中的说明: 然后说 ...

  6. 4 MySQL程序概述(包含mysql配置文件配置原理)-学习笔记

    以下参考MySQL5.5官方简体中文参考手册完美版--用于自学复习使用 4.1 程序概述 MySQL AB提供了几种类型的程序:一般放在/安装目录/bin下 1 MYSQL服务器和服务器启动脚本 my ...

  7. TCP/IP协议原理学习笔记

    昨天学习了杨宁老师的TCP/IP协议原理第一讲和第二讲,主要介绍了OSI模型,整理如下: OSI是open system innerconnection的简称,即开放式系统互联参考模型,它把网络协议从 ...

  8. Java并发之底层实现原理学习笔记

    本篇博文将介绍java并发底层的实现原理,我们知道java实现的并发操作最后肯定是由我们的CPU完成的,中间经历了将java源码编译成.class文件,然后进行加载,然后虚拟机执行引擎进行执行,解释为 ...

  9. MySQL之InnoDB索引面试学习笔记

    写在前面 想要做好后台开发,终究是绕不过索引这一关的.先问自己一个问题,InnoDB为什么选择B+树作为默认索引结构.本文主要参考MySQL索引背后的数据结构及算法原理和剖析Mysql的InnoDB索 ...

随机推荐

  1. python学习第五天 ----- 函数

    1. 内置函数 例如: print, round 2.自定义函数: 通过def来定义 def funcname(parameter_list): pass ⑴.参数parameter_list可以没有 ...

  2. JZOJ 2020.10.7 提高B组反思

    JZOJ 2020.10.7 提高B组反思 T1 比较简单的一道题 跑\(k\)遍\(SPFA\) 然后全排列顺序枚举求解 TLE 60 双向存边数组没开两倍-- T2 搞出分母 分子不会求 \(n^ ...

  3. 转:解析HTTP协议六种请求方法,get,head,put,delete,post有什么区别

    解析HTTP协议六种请求方法,get,head,put,delete,post有什么区别 标准Http协议支持六种请求方法,即: 1.GET 2.POST 3.PUT 4.Delete 5.HEAD ...

  4. pycharm执行报错: unprintable file name [Errno 2] No such file

    老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 老猿在pycharm执行一个工程文件testListView时,发现其工程文件对应的py文件没有后缀 ...

  5. PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的clicked信号参数QAbstractButton *解决办法

    一.引言 QDialogButtonBox本身只提供4种信号,分别是accepted.rejected.clicked和helpRequested,在<PyQt(Python+Qt)学习随笔:D ...

  6. buu学习记录(下)(做题是不可能做题的)

    目录: easy_calc 禁止套娃 EasyWeb Babysqli Easyweb easy_serialize_php 我有一个数据库 SSRFme 枯燥的抽奖 EasyPHP 题目解析: ea ...

  7. CSS基础-字体

    字体变化设置 改变字体颜色 color 改变字体大小 font-size 改变字体粗细 font-weight 改变字体样式 font-family 改变字间距 letter-spacing 改变字体 ...

  8. js中单引号和双引号区别

    总结: 1.无论单引号还是双引号都是成双成对出现的,否则报错!浏览器在读到第一个双引号开始,第二个双引号结束,同样浏览器读取单引号也是第一个开始,第二个单引号结束,在使用的时候必须遵循规则那就是一对双 ...

  9. POJ1422

    题目大意: 一个有向无环图,求最小路径覆盖 板子题... 把每个点拆成\(x\)和\(x^{'}\) \((u,v)\)有一条边则\(u\)向\(v^{'}\)连一条边,然后跑最大匹配,最小路径覆盖= ...

  10. ado.net使用sqlparameter的方式

    使用sqlparameter的方式,最终执行的sql语句 exec sp_executesql N'select top 1 ID,ZhangHu,MiMa,RID,ShiJian,EndTime,I ...