一、事务基本概念

  • 与 锁 一样,事务也是数据库区别于文件系统的重要特性之一。

  • 事务会把数据库从一种状态转换为另一种一致的状态。<假如整个世界是一个数据库系统,我们的任意行为都是在把世界从一个状态转换为另一个状态,区别是我们只管做,却没有回滚按钮。>

  • 也可以说:事务是访问并更新数据库中各种数据的一个程序的基本单元。

事务的特性:ACID

A-(atomicity) 原子性:

  • 事务内的多个SQL,可以把它们看成一个整体,要么全部成功,要么全不执行,如果某个SQL报错无法执行,那么必须回滚所有已经执行的部分。它代表整个数据库事务是不可分割的工作单元。

C-(consistency) 一致性:

  • 任意事务让数据库从一个状态转换为另一个一致的状态,所谓的一致性,可以看成是所有必须遵循的约束,任意事务的提交都不能未被这些约束;例如:主键约束、外键约束等等。举个例子,任意表的主键是不可重复的,如果某个事务提交后导致主键不唯一了,那么就违背了一致性的约束,事务是一致性的单位。

I-(isolation) 隔离性:

  • 它也被称为:并发控制、可串行化、锁 。
  • 多个事务之间必须是隔离的,未提交事务对任意事务不可见。每个事务读写的对象,与其他事务操作的对象隔离。

D-(durability) 持久性:

  • 一旦事务提交,那么事务修改的内容必须是永久的,必须保存到磁盘中固化。
  • 当然,保存数据的设备可能因为认为原因损坏,比如:*** rm -rf / *** ,持久性保证的是高可靠性而不是高可用性。

事务类型

1.扁平事务

扁平事务的所有操作的都是在同一层次的,扁平事务是原子的,它是最基本的事务,同样就意味着它是使用最广泛的事务。

2.带保存点的扁平事务

当单个扁平事务太长时,如果为了部分错误回滚整个事务那么成本将难以接受。对此,诞生了带保存点的扁平事务,当错误发生时它允许事务退回到预先设置的某个保存点,而不是将整个事务回滚。

3.链式事务

带保存点的扁平事务在系统发生崩溃时所有的保存点都会丢失,同样带来了上述问题:系统崩溃时,带保存点的 扁平事务,依然被全部回滚。对此,出现了链式事务,可以把它理解成带保存点的扁平事务的变种。

链式事务的逻辑是,按序提交事务链中的一个事务时,会释放不需要的对象,对于事务链中的下一个事务需要的资源会自动传递下去。<是不是很像,保存点扁平事务的保存点变成了提交?>

它们的区别如下:

  • 带保存点的扁平事务可以回滚到任意正确的保存点,但是它占有的资源必须等整个事务提交后才会释放。

  • 链式事务的回滚仅限事务链中当前执行的事务,而且事务链中的任何一个事务提交后都会释放所有不再需要的资源,只是把事务链下一个事务需要的对象进行传递,从这里可以看出,链式事务对资源的利用更加合理了。

单个长事务被拆分成立多个事务组成的链,发散一下,我想到了小时候家里灌的腊肠,把长长的一条勒成多节带来了非常多的好处,出来好久了,思念家乡的腊肠啊。

4.嵌套事务

它是一个层次的框架,顶层事务之下嵌套的事务可以被称为子事务

  • 嵌套事务可以视作由若干事务构成的一棵树,子树既可以是嵌套事务,也可以是扁平事务;

  • 嵌套事务的树状结构中,处于叶节点上的事务必须是扁平事务;

  • 根节点上的事务叫顶层事务;

  • 嵌套事务中,子事务即可提交也可回滚,但是它的回滚或提交操作并不马上生效,直至它的父事务提交。所以: 任何子事务都在顶层事务提交后才会真正提交。

  • 树种任何一个事务的回滚,会引起它的所有子事务一起回滚,所以嵌套事务中的子事务,并不具有持久性。

我的理解是,所有事务都已经执行完成,不论是成功还是失败,不论需要提交还是回滚,顶层事务得到所有信息后统一进行合并操作。此外从最后一条特性也可以得到该结论,如果子事务早于父事务提交,那么该特性将无法实现。

5.分布式事务

分布式事务通常是在分布式环境下运行的扁平事务,需要根据数据库所在的不同位置访问网络中的不同节点,需要保证:要么网络中的所有数据库节点都成功,要么全部不成功。

二、事务的实现概述

我们知道MySQL中的文件包括,redo log 和 undo log,redo log 记录的是物理日志,它记录的页的物理修改操作;undo log 是逻辑日志,它记录的是每个行记录的变化(非锁定一致性读,并发多版本控制:MVCC)。undo log 和 ROW 模式的 binlong 概念有相似的地方,但是它们所支持的功能完全不同,持久化形式也不同,重做日志由Innodb存储引擎维护,binglog 由MySQL数据库层支持

上一篇文章中所介绍的 保证了事务的隔离性;而由 redo log 保证了事务的原子性和持久性,由undo log 保证事务的一致性(当事务执行破坏了一致性,那么此时需要进行回滚,保证事务的一致性。)、它也被用来支持MVCC功能。

Force Log at Commit 机制 : 当事务提交时,必须先将事务的所有日志写入磁盘文件中进行持久化。

三、redo log

1)组成

  • redo log buffer 重做日志缓冲,存在于内存中发生宕机事故时易失

Innodb 会先将重做日志写到重做日志缓冲,在事务提交时或者由Master Thread 定时每秒刷新的磁盘上的重做日志文件中,执行时机如下:

Master Thread 每秒调用 fsync 批量刷新。
每次事务提交后立即调用 fsync 刷新,innodb_flush_log_at_trx_commit = 1 时;
当 redo log buffer 空间使用量到达一半时。(默认为:8M)
  • redo log file 重做日志文件,保存在磁盘中,它是持久的。

为了确保每次事务的日志都成功写入磁盘上的重做日志文件中,在每次重做日志缓冲将重做日志写入磁盘后都应该调用一次 fsync 确保数据落盘。fsync的效率取决磁盘性能,所以说磁盘性能决定了事务提交的性能,即为数据库的性能。

可以通过 innodb_flush_log_at_trx_commit 配置重做日志落盘策略:

  • innodb_flush_log_at_trx_commit = 0,事务提交时不进行重做日志写磁盘的操作,而是等待后台线程:master Thread 每秒执行一次fsync落盘。它能带来性能的提升,但是数据库程序发生宕机事故时,可能导致部分事务丢失。

  • innodb_flush_log_at_trx_commit = 1,默认值;它是最严格的策略,能完整支持ACID特性,另外两种配置都破坏了事务的ACID特性;要求每次事务提交时必须调用fsync落盘,它牺牲性能换取了可靠性。

  • innodb_flush_log_at_trx_commit = 2,每次事务提交时将重做日志写入操作系统的文件系统中,不进行fsync,(类redo log buffer 但是它是操作系统的缓冲,redo log buffer 是数据库系统的缓冲)。该配置下,如果只是数据库宕机,操作系统本身没有宕机,那么是不会丢失数据的,但是操作系统宕机也会导致部分提交的事务丢失。

2)redo log 和 binlog

  • binlog 只在事务提交时进行一次写入磁盘操作,对于一个事务只包含一个binlog(或者理解成它们是一个整体)。

  • redo log 的操作伴随整个事务,它记录的是对页的物理操作,所以一个事务对应多个redo log 条目,它在整个事务过程中都在不断的写入重做日志缓冲( redo log buffer ),重做日志的写入是并发的。

假定有一个足够大的重做日志缓冲,并且有多个事务并发的执行,那么它们的redo log 也会被并发的记录下来,事务开始时间并不能决定不同事务的redo log 的写入顺序。

3)存储

重做日志以块(redo log block:重做日志块)的形式存贮,不论磁盘中的重做日志,还是重做日志缓冲中,重做日志块的大小都是512字节。

在重做日志缓冲(redo log buffer)中,内部的存储结构好比一个以 redo log block 组成的一个循环数组,循环递增的存储、复用。(redo log buffer 刷磁盘的时机之一:redo log buffer 占用空间超过一半时,主动写磁盘。)

4)LSN 重做日志序列号 (log Sequence Number )

lsn 在不同场景中有不同的意义

  • 表空间中页上的LSN表示当前页的版本,或者说是该页最后刷新时LSN的大小。(宕机时对比其lsn决定是否需要重做)

  • checkpoint 中的 lsn,表示checkpoint (innodb 脏页刷新机制) 执行的位置,它表示小于该LSN的重做日志都已经刷到了磁盘上表空间中的页上。

      1. LRU 列表淘汰末位时checkpoint
    2. redo log file 无可用空间时checkpoint
    3. Master Thread 定时触发checkpoint,将一定数量脏页刷回磁盘
    4. mysql系统关闭时触发checkpoint,默认将所有脏页刷回磁盘
  • 重做日志文件中的LSN,重做日志文件写入的总量;宕机恢复时如果页的lsn小于重做日志中某个事务的lsn,则该页需要重做。

四、undo log

概念

redo log 记录的是事务的行为,它针对发生变化的行进行逻辑记录,undo log 存在的主要目的为了,当事务发生异常支持回滚操作,除此之外,mysql的一致性非锁定读也可以依赖需要undo log支持的MVCC功能实现。

因为undo log 是根据行记录来进行记录的,回滚时候的操作是执行一个相反的操作。

1. 原事务执行的语句是向某表插入两条数据,那么回滚时根据undo log会执行两个删除语句。

2. 原事务执行的删除那么回滚时执行相反的插入语句。

3.原事务执行的是update操作,回滚时则进行一个反向的update操作。

至于多线程并发问题,那更不用操心了,因为X排它锁的存在当前事务提交前,都不会有任何事务获取到这些行的任意锁。

存储

相较于redo log 存放到重做日志文件中;undo log 存放于表中间中的 undo 段 ( undo log segment ) 中,可以是共享表空间中,也可以配置为存放到独立表空间中。

一个回滚段上可以申请 1024个undo 页,目前MySQL支持128个undo 段,所以MySQL最多支持的在线事务数为:1024 * 128 个。

purge 操作

  • undo log page undo日志页

undo log 正常来说只存在于事务提交前,当事务确定提交后,undo log 就没有意义了。

当事务提交后,并不会直接删除该undo log page ,该undo log page 会放被按事务提交顺序到一个列表中;Innodb存储引擎会进行判断,如果该undo log page 可被重用则会把它分配给别的事务。最后由前文提到的后台线程:purge Thread 来完成最终的删除操作。[判断是否可重用规则:该undo log page 剩余空间是否大于3/4 ]

insert 操作产生的行记录对其它事务来说是不可见的(严格ACID 事务隔离级别下),所以它产生的 undo log 在事务提交时是可以直接删除的。

对于 delete 和 update 操作并不会直接删除索引上的记录,而是把对应的记录改为删除状态。由于需要支持MVCC行多版本控制,需要最后确定该行记录没有被任何事务引用后,由后台线程purge thread 来执行真正的删除操作。

undo log page 可以被重用,说明undo log page 上可能存在着不同事务的 undo 日志,当purge Thread 线程清理undo log page 时是需要离散读取磁盘的,所以该操作较慢。

五、 group commit

1.不使用二进制日志时

任何非只读事务提交时,为了保证重做日志写入磁盘重做日志文件中,应当进行一次 fsync 刷盘操作,但是这个过程一般非常慢,为了更好利用fsync 性能,事务提交时一般会指向如下操作:

  1. 内存中修改事务信息,比如将缓冲池中数据页的内容更新;然后将对应的重做日志写入redo log buffer 中(重做日志缓冲)。
  2. 调用fsync 将redo log buffer 中多个事务的重做日志一起刷落磁盘。

上述操作让多个事务的重做再一次操作中刷回磁盘。

2.开启二进制日志

但是在使用了二进制日志时,上述group commit 就不能使用了。

如下为使用二进制日志后事务提交时的操作:

一般事务提交时会执行如下操作:

  • 1.存储引擎进行prepare操作。

  • 2.MySQL数据库上层写二进制日志( binlog )。

  • 3.存储引擎将 redo log 写入重做日志文件中。

      第三步可以细分:
    a.修改内存中的数据信息,将修改更新到重做日志缓冲。
    <这个操作在事务开始执行就在不断的进行,并不是事务提交时才写redo log buffer。> b.调用fsync,确保从重做日志缓冲写入磁盘。

此时需要确保binlog 写入顺序与 Innodb 存储引擎层,事务的提交顺序一致,否则可能出现主从库数据不一致的情况,为了支持该功能,mysql内部使用了一个锁,导致当有事务从redo log buffer 刷落磁盘时,别的事务不能向redo log buffer 中写入重做日志,依次保证顺序性。<例如:多个事务分别把同一行的同一列修改为了多个值,那么必须保证主从库中有同样的修改顺序,否则就可能导致主从库不一致的情况。>

3.解决方法

解决方法由 MariaDb 数据库开发人员提出,细节不再描述可以讲一下核心思想。

该方法不仅redo log 是 group commit , binlog 也是group commit。

解决的思想是:

  • 在数据库层将每个事务的binlog 记录到内存,并在队列中记录它们的顺序
  • 将多个事务的binlog 一起落盘
  • 最后根据队列中记录的顺序依次去完成事务的提交。

解决该问题后,group commit 的性能受限于每次提交时,队列中的事务数,事务数越多性能越高。

Innodb之事务的更多相关文章

  1. mysql的innodb中事务日志ib_logfile

    mysql的innodb中事务日志ib_logfile事务日志或称redo日志,在mysql中默认以ib_logfile0,ib_logfile1名称存在,可以手工修改参数,调节开启几组日志来服务于当 ...

  2. 一文说清 InnoDB 的事务机制

    我们从一个转账的故事开始. 隔壁小王从美团上找到了一家水饺店,准备中午吃水饺.下单成功,支付20元. 商家这里响了一下:叮叮,您有美团外卖新订单啦,请及时处理.水饺一份,好嘞,下锅. 很快小王吃到外卖 ...

  3. Innodb的事务与日志 & JTA事务

    InnoDB引擎的行锁是通过加在什么上完成(或称实现)的?为什么是这样子的 通过   行多版本控制 MyISAM                  Innodb 事物支持 :   不支持       ...

  4. 理解InnoDB的事务隔离级别

    隔离是ACID(Atomicity,Consistency,Isolation,Durability)的重要部分,它保证事务以一种可靠的方式运行.隔离确保同时运行的事务并不相互干扰.隔离确保数据一致性 ...

  5. InnoDB并发事务

    ​目录 1.行锁:索引加锁 2.意向锁 3.间隙锁 4.MVCC机制 行锁 InnoDB通过多版本并发控制MVCC来支持事务 InnoDB的设计是为了在处理大数据量的时候得到最好的性能.InnoDB存 ...

  6. (7)MySQL进阶篇SQL优化(InnoDB锁-事务隔离级别 )

    1.概述 在我们在学习InnoDB锁知识点之前,我觉得有必要让大家了解它的背景知识,因为这样才能让我们更系统地学习好它.InnoDB与MyISAM的最大不同有两点:一是支持事务(TRANSACTION ...

  7. InnoDB关于事务、锁、MVCC专题

    目录 并发所带来的的问题 脏写 脏读 不可重复读 幻读 事务 事务的特性 事务的四种隔离级别 锁 为什么要加锁 InnoDB的七种锁 不同事务RR和RC下加锁的规则 MVCC mvcc进一步提高并发 ...

  8. mysql innodb引擎事务的隔离级别

    一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做,不可能停滞在中间环节.事务执行过程中出错,会回滚到事务开始前的状态,所有的操作就像没有 ...

  9. MySQL数据库 InnoDB引擎 事务及行锁总结

    一.事务 1.事务的四大特性 (1)原子性:事务开始后所有的操作要么一起成功,要么一起失败,整个事务是一个不可分割的整体. (2)一致性:是物开始前到结束后,数据库的完整性约束没有被破坏. (3)隔离 ...

  10. InnoDB源码分析--事务日志(二)

    原创文章,转载请标明原文链接:http://www.cnblogs.com/wingsless/p/5708992.html 昨天写了有关事务日志的一些基本点(http://www.cnblogs.c ...

随机推荐

  1. [转帖]sql server 索引阐述系列六 碎片查看与解决方案

    https://www.cnblogs.com/MrHSR/p/9365720.html 一 . dm_db_index_physical_stats 重要字段说明 1.1 内部碎片:是avg_pag ...

  2. [转帖]pyinstaller实现将python程序打包成exe文件

    https://www.cnblogs.com/blogzyq/p/13939739.html 如果我们想要在一个没有python以及很多库环境的电脑上使用我们的小程序该怎么办呢? 我们想到,在Win ...

  3. [转帖]一次fork引发的惨案!

    https://www.cnblogs.com/xuanyuan/p/15502289.html "你还有什么要说的吗?没有的话我就要动手了",kill程序最后问道. 这一次,我没 ...

  4. [转帖]shell 实现行转列、列转行的几种方法

    目录 shell 实现行转列.列转行的几种方法 awk 行转列 xargs 行转列 tr 列转行 参考资料 shell 实现行转列.列转行的几种方法 awk 行转列 以空格为分隔符 awk -F &q ...

  5. [转帖]Linux使用Stress-ng测试CPU、内存、磁盘I/O满载情况教程与范例

    https://www.xiaoyuanjiu.com/108301.html 介绍如何在 Linux 系统上使用 stress-ng 负载测试工具,产生 CPU.内存等资源满载的状况. stress ...

  6. Linux 开启防火墙 避免非干系人误操作的处理

    公司里面进行系统集成测试. 不想让开发能够更改我的服务器信息, 但是改密码又太麻烦了. 想了想还是用 防火墙好一些. 第一步 开启防火墙 systemctl enable firewalld syst ...

  7. Opentelemetry Collector的配置和使用

    Collector的配置和使用 目录 Collector的配置和使用 Collector配置 Receivers Processors Exporters Service Extensions 使用环 ...

  8. echarts饼状图不要中间的文字提示

    饼状图不要中间的文字提示信息 emphasis: { label: { show: false, //将这个设置为false }, }, 为什么饼状图不要中间的问题提示信息 因为有些时候,在文字很多的 ...

  9. git查看自己是从那个分支建的分支

    可能发生的情况 很多时候,开始建分支的时候, 能够确认自己是那个分支建的,但是当写完功能之后, 再去回想,有时是忘记自己基于那个分支建的分支. 这时有一个命令的话就可以很快的定位了. 查看创建的分支来 ...

  10. 【scikit-learn基础】--『回归模型评估』之准确率分析

    分类模型的评估和回归模型的评估侧重点不一样,回归模型一般针对连续型的数据,而分类模型一般针对的是离散的数据. 所以,评估分类模型时,评估指标与回归模型也很不一样,比如,分类模型的评估指标通常包括准确率 ...