美文网首页
InnoDB 事务

InnoDB 事务

作者: 10xjzheng | 来源:发表于2018-09-06 18:06 被阅读26次

    本文摘自《MYSQL技术内幕(InnoDB存储引擎)》

    1.认识事务

    1.1 概述

    InnoDB在事务完全符合ACID的特性。

    • 原子性(atomicity):要么都全部执行,要么全部不执行,没有中间态;
    • 一致性(consistency):指事务将数据库从一种状态转变为下一种一致性的状态;
    • 隔离性(isolation):要求每个读写事务的对象对其它事务的操作对象互相分离;
    • 持久性(durability):事务一旦提交,其结果就是永久性的。

    1.2. 分类

    • 扁平事务
    • 带有保存点的扁平事务
    • 链事务
    • 嵌套事务
    • 分布式事务

    2.事务的实现

    事务隔离性由锁来实现。原子性、一致性、持久性通过数据库的redo log和undo log来完成。
    redo log称为重做日志,用来保证事务的原子性和持久性。undo log用来保证事务的一致性。

    redo和undo的作用都可以视为是一种恢复操作,redo恢复提交事务修改的页操作,而undo回滚行记录到某个特定版本。因此两者记录的内容不同,redo通常是物理日志,记录的是页的物理修改操作。undo是逻辑日志,根据每行记录进行记录。

    2.1 redo

    • 1.基本概念
      重做日志用来实现事务的持久性,即事务ACID中的D。其由两部分组成:一是内存中的重做日志缓冲(redo log buffer),其是易失的;二是重做日志文件(redo log file),其是持久的。

    InnoDB是事务的存储引擎,其通过Force Log at Commit机制实现事务的持久性,即当事务提交时,必须先将该事务的所有日志写入到重做日志文件进行持久化,待事务的COMMIT操作完成才算完成。redo log基本上都是顺序写的,在数据库运行时不需要对redo log的文件进行读取操作。而undo log是需要随机读写的。

    为了确保每次日志都写入重做日志文件,在每次重做日志缓冲写入重做日志文件后,InnoDB都需要调用一次fsync操作。由于重做日志文件打开并没有使用O_DIRECT选项,因此重做日志缓冲先写入文件系统缓存。为了确保重做日志写入磁盘,必须进行一次fsync操作。由于fsync的效率取决于磁盘的性能,因此磁盘的性能决定了事务提交的性能,也就是数据库的性能。

    InnoDB允许用户手工设置非持久化的情况发生,以此提高数据库的性能。即当事务提交时,日志不写入重做日志文件,而是等待一个时间周期后再执行fsync操作。但宕机会丢失一部分数据。

    参数innodb_flush_log_at_trx_commit用来控制重做日志刷新到磁盘的策略。默认值是1,表示事务提交时必须调用一次fsync操作, 0表示事务提交时不进行写入重做日志操作,这个操作仅在master thread中完成,而在master thread中每1s会进行一次重做日志文件的fsync操作。2表示事务提交时将重做日志写入重做日志文件,但仅写入缓存,不进行fsync操作。


    image.png
      1. log block
        在InnoDB中,重做日志都是以512字节进行存储的。这意味着重做日志缓存、重做日志文件都是以块(block)的方式进行保存的,称之为重做日志块(redo log block),每块的大小为512字节。

    若一个页中产生的重做日志数量大于512字节,那么需要分割为多个重做日志块进行存储。此外,由于重做日志块的大小和磁盘扇区大小一样,都是512字节,因此重做的日志的写入可以保证原子性,不需要doublewrite技术。


    image.png
      1. log group
        log group为重做日志组,其中有多个重做日志文件。

    2.2 undo

    • 1.基本概念
      重做日志记录了事务的行为,可以很好地通过其对页进行重做操作。但是事务有时还需要进行回滚操作。这时候就需要undo。因此在对数据库进行修改时,InnoDB不但会产生redo,还会产生一定量的undo。这样如果用户执行的事务或语句由于某种原因失败了,又或者用户用一条ROLLBACK语句请求回滚,就可以利用这些undo信息将数据回滚到修改之前的样子。

    redo存放在重做日志文件中,与redo不同,undo存放在数据库内部的一个特殊段(segment)中,这个段称为undo段(undo segment)。undo段位于共享表空间内。可以通过py_innodb_page_info.py工具来查看当前共享表空间中undo的数量。

      1. undo存储管理
        InnoDB对undo的管理同样采用段的方式。但是这个段和之前介绍的段有所不同。首先InnoDB有rollback segment,每个回滚段种记录了1024个undo log segment,而在每个undo log segment段中进行undo页的申请。共享表空间偏移量为5的页(0,5)记录了所有rollback segment header所在的页,这个页的类型为FIL_PAGE_TYPE_SYS。
    • 3 undo log 格式
      分为:

    • insert undo log;

    • update undo log;

      1. 查看undo信息

    相关文章

      网友评论

          本文标题:InnoDB 事务

          本文链接:https://www.haomeiwen.com/subject/joxleftx.html