概述

事务(Transaction)是访问和更新数据库的程序执行单元;事务中可能包含一个或多个语句,这些语句要么都执行,要么都不执行,事务是保证数据一致性的重要手段。事务具有4个属性,就是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),简称ACID属性。MySQL的事务是由存储引擎实现的,支持事务的数据库引擎包括InnoDB、NDB Cluster等,其中InnoDB的使用最为广泛。下面以InnoDB为基础进行描述,剖析InnoDB实现事务特性的原理。

事务提交与回滚

首先,回顾以下在MySQL中显式使用事务的方式

-- 开启事务start transaction;...-- 一条或多条DML或DDL语句select | insert | update | delete...-- 提交或回滚commit | rollback;

MySQL的InnoDB存储引擎默认是自动提交事务,可以通过下面的设置和查看

-- 关闭自动提交set autocommit = 0;-- 开启自动提交set autocommit = 1;-- 查看自动提交变量状态show variables like 'autocommit';

在自动提交模式下,如果没有start transaction显式地开始一个事务,那么每个sql语句都会被当做一个事务执行提交操作。

在MySQL中,存在一些特殊的命令,如果在事务中执行了这些命令,会马上强制执行commit提交事务务,比如如DDL语句create table、drop table、alter table、lock tables语句等。对于常用的select、insert、update和delete命令,则不会强制提交事务。

原子性实现原理

原子性是指一个事务是一个不可分割的工作单位,其中的操作要么都做,要么都不做;如果事务中一个语句执行失败,则已执行的语句也必须回滚,数据库退回到事务前的状态。InnoDB主要基于回滚日志实现事务的原子性。

  • 隐藏字段

在InnoDB中,每一行数据除了包括我们设计的字段之外,还包含了一些内部字段,也叫隐藏字段。比如在InnoDB的聚簇索引记录中会包含3个隐藏列row_id、trx_id、roll_pointer等

row_id

数据行id,用于标识一行数据。row_id并不是必要的,如果创建的表中有主键或者非NULL唯一键时都不会包含row_id列

trx_id

事务id,每次对某数据记录进行修改时,都会把对应的事务id赋值给trx_id列。每次事务操作都会分配一个事务id,它是一个自增id。

roll_pointer

当前数据记录的上一个版本的指针。每次对某条数据记录进行改动时,都会把旧版本数据记录按照一定格式写入到回滚日志(undo log) 中,而roll_pointer列则保存了该旧版本数据记录在回滚日志中的位置,相当于一个指针。

比如一个user表,目前只有一个id和name字段,id为主键。则InnoDB中表示一行数据的结构如下

表示一行数据的数据结构

回滚日志(undo log)与版本链

MySQL架构设计当中,其有一个完整的日志体系,包括二进制日志、通用查询日志、慢查询日志等,为排查问题、性能优化、实现事务控制等提供了强大的支撑。在这些日志当中,和事务直接相关的日志有两个,一个是重做日志(redo log),一个是回滚日志(undo log)。其中的回滚日志,是事务原子性和隔离性实现的基础。

回滚日志分为两类,一类是插入回滚日志(insert undo log),一类是更新回滚日志(update undo log)。插入回滚日志由insert操作产生的,在事务提交后可以被立即丢弃;更新回滚日志则是由update和delete操作产生的,更新回滚日志不仅在事务回滚时使用,在InnoDB实现事务隔离性时也需要用到,所以不能随便删除,只有在快速读或事务回滚不涉及该日志时,对应的日志才会被purge线程统一清除。

比如以下三条语句

insert into user (id,name) values (1,'蕃豆咖啡');start transaction;update user set name = 'coffee' where id = 1;update user set name = '最新的名字' where id = 1;commit;

其产生的回滚日志内容如下图所示

回滚日志和版本链

每次对数据记录进行修改时(事务操作),都会产生一条回滚日志 ,每条回滚日志也都有一个roll_pointer属性(insert操作对应的回滚日志没有该属性,因为该记录并没有更早的版本),随着更新次数的增多,所有的版本都会被roll_pointer属性连接成一个链表,这个链表称之为版本链。版本链的头节点就是当前记录最新的值。注意,每个版本中还包含生成该版本时对应的事务id,这个信息很重要,是InnoDB实现事务隔离性的关键部分。

  • 实现原理

实现原子性的关键,是当事务回滚时能够撤销所有已经成功执行的sql语句。当开启一个事务对数据进行增删改时,InnoDB会生成一条对应的回滚日志(修改前的数据信息)到回滚日志缓冲中。如果事务执行失败或调用了rollback命令,导致事务需要回滚时,InnoDB就会根据回滚日志中的信息,执行与当前事务相反的工作,将数据回滚到增删改之前的状态。

InnoDB的回滚实现原理,简单理解,就是在需要回滚事务时,InnoDB根据回滚日志的信息,对于每个insert语句,执行一条对应的delete语句;对于每个update语句,会执行一条更新为原值的update语句;对于每条delete语句,会执行一条对应的insert语句。

这样,通过回滚日志,InnoDB可以在任何需要回滚的地方将相关数据回滚到事务前的状态。

  • 回滚日志示例

比如创建一条新的用户记录

insert into user (id,name) values (1,'蕃豆咖啡');

当需要回滚时,InnoDB将根据回滚日志会生成一条删除语句并执行

delete from user where id = 1;

再比如更新该用户名字

update user set name = 'coffee' where id = 1;

当需要回滚时,InnoDB将根据回滚日志会生成一条更新语句并执行

-- InnoDB根据update语句所更新的主键id、更新列name、列更新前内容(蕃豆咖啡)-- 生成对应的回滚日志update user set name = '蕃豆咖啡' where id = 1;

如要删除该用户记录时

delete from user where id = 1;

当需要回滚时,InnoDB将根据回滚日志会生成一条插入语句并执行

insert into user (id,name) values (1,'蕃豆咖啡');

总结

InnoDB实现回滚的关键是回滚日志。回滚的过程比上面描述的会复杂一些,比如在并发情况下,多个事务之间,回滚时需要区分当前事务可见的回滚日志,然后再根据回滚日志进行回滚,这实际上已经属于事务隔离性的范畴了,这里暂不深入探讨。

innodb 删除隐藏列_MySQL进阶之InnoDB事务原子性实现原理相关推荐

  1. mysql引擎innodb与ndb比较_mysql存储引擎InnoDB 1.1、NDB 7.5对比

    mysql存储引擎InnoDB 1.1.NDB 7.5对比 官网针对NDB和InnoDB进行了多方位的对比: TheNDBstorage engine is implemented using a d ...

  2. mysql删除多列_MySQL删除单列重复或多列同时重复值并保留一条

    在生产环境中,我们有的列是不允许出现重复值的,亦或是某两列不允许同时重复,但由于前端未做限制,或者没限制住,出现了单列重复值,或者两列本应组成唯一组合却也出现重复,这两种情况都是不允许的.现在由于前端 ...

  3. mysql 释放空间_Mysql InnoDB删除数据后释放磁盘空间的步骤详解

    Mysql InnoDB删除数据后释放磁盘空间的方法 Innodb数据库对于已经删除的数据只是标记为删除,并不真正释放所占用的磁盘空间,这就导致InnoDB数据库文件不断增长. 如果在创建数据库的时候 ...

  4. bootstrap-table真实交互数据_mysql存储引擎InnoDB详解,从底层看清InnoDB数据结构

    InnoDB一个支持事务安全的存储引擎,同时也是mysql的默认存储引擎.本文主要从数据结构的角度,详细介绍InnoDB行记录格式和数据页的实现原理,从底层看清InnoDB存储引擎. InnoDB简介 ...

  5. mysql 开启引擎命令_MySql中启用InnoDB数据引擎的方法

    1.存储引擎是什么? Mysql中的数据用各种不同的技术存储在文件(或者内存)中.这些技术中的每一种技术都使用不同的存储机制.索引技巧.锁定水平并且最终提供广泛的不同的功能和能力.通过选择不同的技术, ...

  6. mysql innodb和myisam区别_MySQL?存储引擎简介

    ​大家好,我是anyux.本文介绍MySQL存储引擎. 简介 相当于Linux文件系统,只不过比文件系统强大 功能 数据读写 数据安全和一致性 提高性能 热备份 自动故障恢复 高可用方面支持 引擎类别 ...

  7. mysql中engine是什么意思_mysql中engine=innodb和engine=myisam的区别

    最开始用MySQL Administrator建数据库的时候,表缺省是InnoDB类型,也就没有在意.后来用Access2MySQL导数据的时候发现只能导成 MyISAM类型的表,不知道这两种类型有什 ...

  8. mysql系统特性_MySQL · 引擎特性 · InnoDB 事务系统

    前言 关系型数据库的事务机制因其有原子性,一致性等优秀特性深受开发者喜爱,类似的思想已经被应用到很多其他系统上,例如文件系统等.本文主要介绍InnoDB事务子系统,主要包括,事务的启动,事务的提交,事 ...

  9. 3种mysql的储存机制_MySQL三种InnoDB、MyISAM和MEMORY存储引擎对比

    三种引擎的区别: 事务:InnoDB支持事务,MyISAM和MEMORY两个不支持. 存储限制:InnoDB有64TB的存储限制,MyISAM和MEMORY要跟具体情况而定. 空间使用:InnoDB对 ...

  10. MySQL内核月报 2015.01-MySQL · 捉虫动态· InnoDB自增列重复值问题

    问题重现 先从问题入手,重现下这个bug 这里我们关闭mysql,再启动mysql,然后再插入一条数据 我们看到插入了(2,2),而如果我没有重启,插入同样数据我们得到的应该是(4,2). 上面的测试 ...

最新文章

  1. C#学习笔记—了解C#
  2. java todo error_java基础-异常
  3. Java.lang.IllegalStateException Activity has been destroyed
  4. mysql行锁同索引键问题_mysql 锁问题 (相同索引键值或同一行或间隙锁的冲突)
  5. canvas反向裁剪技巧
  6. RuoYi-Cloud 部署篇_03(windows环境 mysql版本)
  7. Mybatis异常--java.lang.IllegalArgumentException: NO ENUM const class org.apache.ibatis.type.JdbcType.i
  8. leetCode:reverseInteger 反向整数 【JAVA实现】
  9. 《通信技术导论(原书第5版)》——2.5 内部使用的IP专用交换系统
  10. ubantu 系统安装apache 和mysql
  11. 【原创】查找原始MySQL死锁ID
  12. 音频格式G711转PCM的代码
  13. Maya---之viewcube的寻找
  14. Matlab:成功解决In an assignment A(I)=B,the number of elements in B and I must be the same
  15. Office 2010 安装过程中出错
  16. PLC可编程控制实验装置及单片机综合实验台
  17. silverlight mysql_Silverlight中衔接MySQL数据库实例详解
  18. Python OpenCV 图片滑块验证码 滑块图片验证码 快速自动识别方案 代码简单 模板匹配识别 识别成功率达90%+
  19. Android 如何OTG 鼠标,otg键盘和鼠标映射软件v5.2.0 Android版
  20. labview问题集锦

热门文章

  1. 20190929每日一句
  2. 190113每日一句
  3. Atitit redis使用场合总结 使用场景 目录 1.1. 3. Session 存储 1 1、 配置数据查询 1 2. 排行榜应用,取TOP N操作 1 1.2.     1、查找最
  4. Atitit 互联网2018风口与趋势大盘点 目录 1.1. 短视频 1 1.2. 互联网金融 1 1.3. 区块链 1 1.4. 新零售 1 2. 2018热度榜丨你能抓住的风口有几个?.html
  5. Atitti 文本分类  以及 垃圾邮件 判断原理 以及贝叶斯算法的应用解决方案
  6. Atitit.软件开发概念(11)--网络子系统--url编码 空格问题URLEncoder java js php
  7. paip.java gui swt/jface 最佳实践
  8. paip.提升用户体验-----c++ 实现360浏览器收藏动作星星动画效果
  9. PAIP.AHK调试以及同于脚本的调试法
  10. paip.提升安全性-----动态KEY