什么是数据库的事务?
事务是访问并更新数据库中各种数据的一个程序执行单元。事务也是数据库区别于文件系统的一个重要特性。

事务需要满足的特性

1.原子性

原子性就是指数据库中的一个完整的事务是不可分割的工作单位。要么都成功,要么都失败,不能执行一部分。

2.一致性

一致性指事务将数据库从一种状态转变为下一种一致的状态。

所谓一致性状态,就是数据库的数据满足约束的要求。

3.隔离性

事务的隔离性要求每个读写事务的对象对其他事务的操作对象能相互分离,也就是一个事务提交对其他事务不可见,可以用锁来实现。

4.持久性

持久性就是事务提交后的结果是永久的,如果发送宕机,也能将数据进行恢复。

持久性保证事务系统的高可靠性,而不是高可用性。高可靠性就是指连续可以正常工作的时间,可用性是指单位时间内,可用的时间比。

事务的分类

1.扁平事务

所有操作都处于同一层次,而且操作是原子的,要么都执行,要么都回滚。

特点:

  • 是事务类型最简单的一种,也是实际生产环境中最频繁的事务。
  • 不能提交或者回滚事务的某一个部分,或者几个步骤提交。

2.带有保存点的扁平事务

和扁平事务的不同点就是允许事务在执行过程中回滚到该事务之前的一个状态点。

保存点:用来通知系统应该记住事务当前的状态,以便之后能够回到保存点时的状态。一个事务中可以有很多个保存点。

3.链事务

是保存点模式的一种变种。将事务切分为多个串联的事务,当前事务提交之后,将处理的上下文再传给下一个事务,像一个链条一样,一环接一环。

目的: 为了解决保存点事务中,如果发生系统崩溃,保存点都消失的情况。这里将保存点都换成了事务提交,相当于在保存点就将事务提交了,这样就算宕机了,提交了的事务也不会损失。

问题: 链事务的回滚就只能在当前事务中了。所以需要将每个事务中的操作都减少一些。

4.嵌套事务

是一个层次结构框架,由一个顶层事务控制着各个层次的事务。

特点:

  • 嵌套事务是由若干事务组成的一棵树,子树既可以是嵌套事务,也可以是扁平事务。
  • 叶节点的事务是扁平事务。
  • 在根节点的事务是顶层事务,其他事务都是子事务。
  • 子事务可以提交也可以回滚,但是提交操作不会马上生效,要等到顶层事务提交才会真正提交。
  • 任一事务的回滚都会引起其儿子的回滚。

5.分布式事务

在一个分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点。

事务的具体实现

在InnoDB上各个事务级别有其具体的实现方式:

  • 锁:隔离性。
  • redo log:原子性和持久性。
  • undo long:一致性。

1. redo

什么是重做日志?
重做日志用来实现事务的持久性,也就是将产生一些数据库操作保存到日志。这些操作的特点是,其操作结果缓冲区中,并没有写到磁盘中。

重做日志的特点

  • 当触发事务提交时就需要将该事务的所有日志写到重做日志中进行持久化。
  • 重做日志是顺序写的。

如何确保重做日志的持久性?
为了确保每次日志都写入重做日志文件(磁盘),在每次将重做日志缓冲写入磁盘后,存储引擎都需要调用一次fsync操作(将内存数据写到磁盘)。所以,磁盘的性能决定了数据库的性能。

如何通过重做日志提高数据库性能?
用户可以设置重非持久性的情况发生。当事务提交的时候,不马上写入磁盘,而是等一个时间周期之后再执行fsync。这样可以优化日志的写入时间,从而提高数据库的性能。但是如果发生宕机,会丢失一部分未刷新的数据。

重做日志的存储方式
InnoDB的存储引擎中,重做日志缓存和重做日志文件以重做日志块的形式进程存储,一个块的大小为512字节。如果一个页的重做日志大于一个块能够存储的范围,则会被分割为多个块进行存储。
为什么是512字节呢? 因为磁盘的一个扇区大小512字节,可以保证原子性。

重做日志缓冲写到磁盘的触发条件:

  • 事务提交时;
  • 当日志缓冲的一半空间被使用;
  • log checkpoint时。

重做日志恢复数据的原理

  1. 不管上次数据库是否正常关闭,都会尝试进行恢复操作。
  2. checkpoint表示已经刷新到磁盘的日志序列号,所以,只需要恢复checkpoint之后的日志序列号的日志部分即可。
  3. 执行重做日志。

2.binlog

binlog也就是二进制文件,是数据库上层对已提交了的事务的SQL语句的记录。
binlog和redo log的区别:

  • 二者表面上看都是记录了数据库操作的日志,但是本质上有着很大的不同。
  • 重做日志是存储引擎层产生的,二进制日志是数据库的上层产生的。二进制日志不仅仅正对引擎层,数据库中任何的更改操作都会产生二进制日志。
  • 两种日志记录的内容形式不同。二进制文件是操作逻辑上的,重做日志是物理格式上的。二进制文件对应SQL语句,而重做日志对应引擎对数据页得修改。
  • 写入磁盘的时间点不同。二进制日志只在事务提交完成后进行一次写入,而InnoDB存储引擎的重做日志会不断地写入,不随事务提交的顺序影响。

3. undo

什么是undo日志?
用于事务的回滚操作。undo日志中记录了数据之前的版本,当执行回滚操作的时候,利用这些之前的数据信息即可修改到之前的样子。undo日志也用于版本控制(MVCC),当用户读取一行记录的时候,该记录已经被其他事务占用了,当前事务就可以根据事务隔离级别,读取过去相应版本的数据,实现非锁定读,提高并发性能。

undo日志会产生重做日志,因为undo日志也需要持久化。

undo日志的存储方式:
同样采用段的方式进行存储,每个回滚段中记录1024个undo日志段,而在每个undo日志段中进行undo页的申请。也就是undo日志是写入到undo日志段中的undo页。多个事务可以共享一个undo页。

4.purge

用于完成最终的delete和update操作。
当delete操作和update操作提交后,只是将相应记录的flag置为1,并没有删除或者修改记录,真正的操作会延时到purge操作来完成。

为什么需要这样设计,而不是直接操作?
当事务提交时,其他事务可能正在引用这行,如果直接删除会产生错误,所以,能不能删除,就需要purge操作进行判断。如果该技术已经不被其他事务引用,就可以进行真正的删除操作。这就优点像JVM垃圾回收判断机制。

5.group commit

什么是group commit?
顾名思义,就是写一堆数据到磁盘。每次事务提交都需要进行fsync操作,这样不能利用磁盘的效率,如果每次写入一组提交的数据,并进行写优化,减少磁盘IO次数,就能提高性能。

MySQL实现批量二进制日志提交的流程:
数据

  1. Flush阶段,将每个事务的二进制日志写入内存;
  2. Sync阶段,将内存中二进制文件写入磁盘,如果有多个事务,那么一次fsync操作就能完成日志写入;
  3. Cmmit阶段,队头事务根据顺序调用引擎层事务的提交。

事务的隔离级别

SQL标准定义的四个隔离级别:

  • 读未提交:会脏读。
  • 读已提交:会不可重复读。
  • 可重复读:会幻读。
  • 串行化:都不会

InnoDB事务隔离级别的特点: InnoDB的默认隔离级别是可重复读,其默认事务隔离级别是可重复读。它的可重复度级别下,通过Next-Key算法,避免了幻读。所以,InnoDB的可重复度就已经达到了串行化的隔离性要求。

分布式事务

什么是分布式事务?
是指允许多个独立的事务资源参与到一个全局的事务当中。

InnoDB提供了对XA事务的支持,并通过XA事务来支持分布式事务的实现。必须将隔离级别设置为串行化,才能使用分布式事务。

XA事务的实现原理
XA事务由一个或者多个资源管理、一个事务管理器和一个应用程序组成:

  • 资源管理器:提供访问事务资源的方法。也就是数据库
  • 事务管理器:协调参与全局事务的各个事务。就是链接数据库的客户端。
  • 应用程序:定义事务的边界,指定全局事务中的操作。

分布式事务两段式提交方式

  • 第一阶段,所有餐具全局事务的节点开始准备,告诉事务管理器它们准备好提交了。
  • 第二阶段,事务管理器告诉资源管理器执行回滚还是提交。如果任何一个节点不能提交,其他节点都需要回滚。

不好的事务习惯

1.在循环中提交

如果在循环中提交,那么循环很大,就需要提交很多次,每次提交都要重做日志,这样就会大大增加开销。如果在循环最后提交,则只需要写一个重做日志,降低开销。

InnoDB存储引擎会默认自动提交。

2.使用自动提交

开发人员不能很好的掌控事务。应该把事务的控制权交给开发人员。

3.使用自动回滚

如果InnoDB在存储过程中发生错误会自动执行回滚操作。

使用自动回滚无法张掌控准确信息。

长事务

长事务就是执行时间较长的事务。

长事务一旦执行失败,就需要回滚,会造成很大的损失,所以,需要将其切分为很多给小事务。

MySQL技术内幕InnoDB存储引擎(七)——事务的更多相关文章

  1. (转)Mysql技术内幕InnoDB存储引擎-事务&备份&性能调优

    事务 原文:http://yingminxing.com/mysql%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95innodb%E5%AD%98%E5%82%A8%E5%BC ...

  2. 《mysql技术内幕 InnoDB存储引擎(第二版)》阅读笔记

    一.mysql架构 mysql是一个单进程多线程架构的数据库. 二.存储引擎 InnoDB: 支持事务 行锁 读操作无锁 4种隔离级别,默认为repeatable 自适应hash索引 每张表的存储都是 ...

  3. Mysql技术内幕——InnoDB存储引擎

    Mysql技术内幕——InnoDB存储引擎 http://jingyan.baidu.com/article/fedf07377c493f35ac89770c.html 一.mysql体系结构和存储引 ...

  4. mysql技术内幕InnoDB存储引擎-阅读笔记

    mysql技术内幕InnoDB存储引擎这本书断断续续看了近10天左右,应该说作者有比较丰富的开发水平,在源码级别上分析的比较透彻.如果结合高可用mysql和高性能mysql来看或许效果会更好,可惜书太 ...

  5. MySQL技术内幕InnoDB存储引擎(三)——文件相关

    构成MySQL数据库和InnoDB存储引擎表的文件类型有: 参数文件:MySQL实例运行时需要的参数就是存储在这里. 日志文件:用来记录MySQL实例对某种条件做出响应时写入的文件. socket文件 ...

  6. (转)Mysql技术内幕InnoDB存储引擎-表&索引算法和锁

    表 原文:http://yingminxing.com/mysql%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95innodb%E5%AD%98%E5%82%A8%E5%BC% ...

  7. MySQL技术内幕InnoDB存储引擎(表&索引算法和锁)

    表 4.1.innodb存储引擎表类型 innodb表类似oracle的IOT表(索引聚集表-indexorganized table),在innodb表中每张表都会有一个主键,如果在创建表时没有显示 ...

  8. 《MySQL技术内幕 InnoDB存储引擎 》学习笔记

    第1章  MySQL体系结构和存储引擎 1.3 MySQL存储引擎 数据库和文件系统最大的区别在于:数据库是支持事务的 InnoDB存储引擎: MySQL5.5.8之后默认的存储引擎,主要面向OLTP ...

  9. 【Mysql技术内幕InnoDB存储引擎】读书笔记

    一.存储引擎 1.InnoDB引擎 设计目标是面向在线事务(OLTP)处理的应用. 支持事务.行级锁.通过多版本并发控制(MVCC)支持高并发.提供一致性非锁定读.next-key locking避免 ...

随机推荐

  1. 企业网络拓扑VRRP主备功能实例(一)

    组网图形  VRRP主备备份简介 通常,同一网段内的所有主机上都存在一条相同的.以网关为下一跳的缺省路由.主机发往其他网段的报文将通过缺省路由发往网关,再由网关进行转发,从而实现主机与外部网络的通信. ...

  2. rbd的image对象数与能写入文件数的关系

    前言 收到一个问题如下: 一个300TB 的RBD,只有7800万的objects,如果存储小文件的话,感觉不够用 对于这个问题,我原来的理解是:对象默认设置的大小是4M一个,存储下去的数据,如果小于 ...

  3. flink1.10版local模式提交job流程分析

    1.WordCount程序实例 2.本地监听9000端口后测试结果 3.job提交流程 4.local模式执行StreamGraph任务 5.流程分析 flink job提交流程个人理解可以大致分为定 ...

  4. sync_with_stdio(false)和cin.tie(NULL)

    std::ios::sync_with_stdio(false) 这个函数相当于是否兼容stdio的开关,默认为true C++为了兼容C,保证程序在使用了std::printf和std::cout的 ...

  5. HW弹药库之红队作战手册

    红方人员实战手册 声明 Author : By klion Date : 2020.2.15 寄语 : 愿 2020 后面的每一天都能一切安好 分享初衷 一来, 旨在为 "攻击" ...

  6. SpringBoot使用策略模式+工厂模式

    为了防止大量的if...else...或switch case代码的出现,可以使用策略模式+工厂模式进行优化. 在我的项目当中,报表繁多,所以尝试了这种方式进行优化报表的架构.代码很简单,如下: Fa ...

  7. 微软开源的 AI 工具,让旧照片焕发新生

    原文地址:Bringing Old Photos Back to Life 原文作者:Ziyu Wan 译者 & 校正:HelloGitHub-小鱼干 & 鸭鸭 写在前面 在 GitH ...

  8. 二分查找 leetcode704

    class Solution {    public int search(int[] nums, int target) {        int l=0;        int r=nums.le ...

  9. C语言讲义——错误处理

    errno C语言不提供对错误处理的直接支持. 以返回值的形式表示是否出错. 在发生错误时,大多数的C函数调用返回1或NULL. 同时设置一个错误代码errno(全局变量),表示在函数调用期间发生了错 ...

  10. 网络篇:朋友面试之TCP/IP,回去等通知吧

    前言 最近和一同学聊天,他想换工作,然后去面了一家大厂.当时,他在简历上写着精通TCP/IP,本着对TCP协议稍有了解,面试官也不会深问的想法,就写了精通二字.没想到,大意了 关注公众号,一起交流,微 ...