美文网首页
mysql数据库InnoDB存储引擎Log漫游(2)

mysql数据库InnoDB存储引擎Log漫游(2)

作者: 快点给我想个名 | 来源:发表于2019-06-24 17:42 被阅读0次

原文地址http://www.zhdba.com/mysqlops/2012/04/06/innodb-log2/

日志的内容
  • 数据是什么
    从不同的角度和层次来看,我们可以将数据库中的数据看作:
    A. 关系数据
    B. 元组或对象
    C. 存在Page中的二进制序列
    因此Log中也可以记录不同的内容:
    • 物理的日志(Physical Log)
      A. 记录完整的Page
      B. 记录Page中被修改的部分(page中的偏移,内容和长度).
      优点:因为恢复时,完全不依赖原页面上的内容,所以不要求持久化了的数据保持在一个一致的状态。比如在写一个页面到磁盘上时,系统发生故障,页面上的一部数据写入了磁盘,另一部分丢失了。这时仍然可以恢复出正确的数据。
      缺点:Log记录的内容很多,占用很大的空间。如B-Tree的分裂操作,要记录约一个完整Page的内容。
    • 逻辑的日志(Logical Log)
      记录在关系(表)上的一个元组操作。
      A. 插入一行记录。
      B. 修改一行记录。
      C. 删除一行记录。
      逻辑日志比起物理的日志,显得简洁的多。而且占用的空间也要小的多。
      但是逻辑日志有2个缺点:
      A. 部分执行
      例如:表T有2个索引,在向T插入1条记录时,需要分别向2个B-Tree中插入记录。有可能第一个B-Tree插入成功了,但是第二个B-Tree没有插入成功。在恢复或回滚时,需要处理这些特殊情况。
      B. 操作的一致性问题
      一个插入操作有一个B-Tree的分裂,页A的一半数据移到了B页,A页写入了磁盘,B页没有写入磁盘。如果这时候发生了故障,需要进行恢复,逻辑日志是很难搞定的。
      逻辑的日志上的‘部分执行’的问题是比较好维护的,但是‘一致性’的问题维护起来是很复杂的。
    • 物理和逻辑结合的日志(Physiological Log)
      这种日志将物理和逻辑日志相结合,取其利,去其害。从而达到一个相对更好的一个状态。这种日志有2个特点:
      A. 物理到page. 将操作细分到页级别。为每个页上的操作单独记日志。
      比如,一个Insert分别在2个B-Tree的节点上做了插入操作,那么就分别为每一个页的操作记录一条日志。
      B. Page内采用逻辑的日志。比如对一个B-Tree的页内插入一条记录时,物理上来说要修改Page Header的
      内容(如,页内的记录数要加1),要插入一行数据到某个位置,要修改相邻记录里的链表指针,要修改Slot的
      属性等。从逻辑上来说,就是在这个页内插入了一行记录。因此Page内的逻辑日志只记录:’这是一个
      插入操作’和’这行数据的内容‘。

MySQL数据库InnoDB存储引擎的Redo Log 记录的就是这种物理和逻辑相结合的日志。
使用页内的逻辑日志,可以减少日志占用的空间。但是它毕竟还是逻辑日志,上面提到的2个问题能够避免吗?
A. 页面内的部分执行的情况可以认为不存在了。因为整个页面的操作是原子操作,在完成之前是不会写到磁盘上的。
B. 操作一致性的问题仍然存在。如果在写一个Page到磁盘时发生了故障,可能导致Page Header的记 录数被加1了,但是数据没有刷新到磁盘上,总之页面上的数据不一致了。
好在这个问题被缩小到了一个页面的范围内,因此比较容易解决。InnoDB存储引擎中用Double Write的方法来解决这个问题。

  • Double Write
    Double Write的思路很简单:
    A. 在覆盖磁盘上的数据前,先将Page的内容写入到磁盘上的其他地方(InnoDB存储引擎中的doublewrite buffer,这里的buffer不是内存空间,是持久存储上的空间).
    B. 然后再将Page的内容覆盖到磁盘上原来的数据。如果在A步骤时系统故障,原来的数据没有被覆盖,还是完整的。如果在B步骤时系统故障,原来的数据不完整了,但是新数据已经被完整的写入了doublewrite buffer.因此系统恢复时就可以用doublewrite buffer中的新Page来覆盖这个不完整的page.
    Double write 显然会曾加磁盘的IO。直觉上IO次数增加了1倍,但是性能损失并不是很大。Peter在 innodb-double-write中说性能损失不超过5-10%。应该是因为多数情况下使用了批量写入的缘故。
    A. Double write buffer是一段连续的存储空间,可以顺序写入。
    B. Double write有自己的写buffer.
    C. 先将多个要做doublewrite的page写入内存的buffer,然后再一起写到磁盘上。
    代码在:buf0dblwr.cc
    buf_flush_write_block_low()调用
    buf_dblwr_write_single_page()或 buf_dblwr_add_to_batch()来实现doublewrite.
  • Checksum
    检测页面是否一致的功能是靠Checksum来完成的,每个页面修改完成后都会记算一个页面的checksum。这个checksum存放在页面的尾部.每次从磁盘读一个页到内存时,都需要检测页的一致性。函数buf_page_is_corrupted()是用来检测page的一致性的.
  • InnoDB Redo Log的日志类型
    InnoDB redo log的格式可以概括为:
    <Space ID>+<Page NO.>+<操作类型>+<数据>.
    Redo Log记录的页面操作大致可以分为以下几种类型:
    A. 在页面上写入N个字节的内容,这些可以看作是物理的Log.
    MLOG_1BYTE, MLOG_2BYTES, MLOG_4BYTES, MLOG_8BYTES, MLOG_WRITE_STRING
    各种Page链表的指针修改,以及文件头,段页等的内容的修改都是以这种方式记录的日志。
    B. 页面上的记录操作。
    MLOG_REC_, MLOG_LIST_, MLOG_COMP_REC_, MLOG_COMP_LIST_
    这些日志记录了对B-Tree页的INSER, DELETE, UPDATE操作和分裂合并操作。
    C. 文件和Page操作
    MLOG_FILE_CREATE, MLOG_FILE_RENAME, MLOG_FILE_DELETE,
    MLOG_PAGE_CREATE, MLOG_INIT_FILE_PAGE, MLOG_PAGE_REORGANIZE
    D. Undo Log操作
    MLOG_UNDO_*
    InnoDB中将undo log的操作也记入了redo log. 为什么要这样做,在前面‘恢复’已经说了.
    这里只提到了部分Redo Log的类型,完整的定义在mtr0mtr.h文件中. 通过这个类型的定义,可以很容易的找到都在哪些地方使用了。
    虽说Redo Log将数据的操作细分到了页面级别。但是有些在多个页面上的操作是逻辑上不可分裂的。比如B-Tree的分裂操作,对父节点和2个子节点的修改。当进行恢复时,要么全部恢复,要么全部不 恢复,不能只恢复其中的部分页面。InnoDB中通过mini-transaction(MTR)来保证这些不可再分 的操作的原子性。
    • InnoDB Undo Log的日志类型
      MySQL数据库InnoDB存储引擎的undo log采用了逻辑的日志。
      InnoDB undo log的格式可以概括为:<操作类型>+<Table ID>+<数据>
      A. 从表中删除一行记录
      TRX_UNDO_DEL_MARK_REC(将主键记入日志)
      在删除一条记录时,并不是真正的将数据从数据库中删除,只是标记为已删除.这样做的好处是 Undo Log中不用记录整行的信息.在undo时操作也变得很简单.
      B. 向表中插入一行记录
      TRX_UNDO_INSERT_REC(将主键记入日志)
      TRX_UNDO_UPD_DEL_REC(仅将主键记入日志) 当表中有一条被标记为删除的记录和要插入的数据主键相同时, 实际的操作是更新这个被标记为删除的记录。
      C. 更新表中的一条记录
      TRX_UNDO_UPD_EXIST_REC(将主键和被更新了的字段内容记入日志)
      TRX_UNDO_DEL_MARK_REC和TRX_UNDO_INSERT_REC,当更新主键字段时,实际执行的过程是删除旧的记录然后,再插入一条新的记录。
      因为undo log还要被MVCC和Purge使用,所以还有TRX_ID和DATA_ROLL_PTR等特殊的内容记录
      在日志中。TRX_UNDO_INSERT_REC不需要记录这些内容.因为MVCC中不可内引用一个不存在的数据。
      这也是事务将insert和update、delete的undo log分开存放的原因。事务提交后,insert的undo占用的空间就可以立即释放了.
    • 逻辑日志的一致性问题
      前面说了逻辑日志的一致性问题是很复杂的,为什么undo log要用逻辑日志呢?
      因为redo log使用了physiological日志和MTR,就可以保证在恢复时重做完redo log后,数据是一致。在执行undo时,就不必考虑这个问题了。

相关文章

  • MYSQL REDO UNDO

    本文是介绍MySQL数据库InnoDB存储引擎重做日志漫游 00 – Undo Log Undo Log 是为了实...

  • InnoDB学习笔记(3)Redo log

    MySQL · 引擎特性 · InnoDB redo log漫游MySQL · 引擎特性 · The design...

  • MySQL存储引擎

    MySQL:单进程多线程数据库 一、InnoDB存储引擎InnoDB存储引擎支持事务(5.5.8MySQL默认版本...

  • mysql数据库InnoDB存储引擎Log漫游(2)

    原文地址http://www.zhdba.com/mysqlops/2012/04/06/innodb-log2/...

  • 浅谈InnoDB存储引擎中的锁

    InnoDB存储引擎是MySQL数据库默认的事务型存储引擎,也是使用比较多的存储引擎。InnoDB存储引擎不紧支持...

  • Mysql数据引擎

    InnoDB数据存储引擎(Mysql5.5+ 默认数据存储引擎)主要特性: InnoDB引擎提供了对数据库ACID...

  • 推荐书单

    MySQL 内核 INNODB存储引擎第1版 MySQL技术内幕 InnoDB存储引擎 第2版 RabbitM...

  • MySQL-存储引擎

    零、本文纲要 一、MySQL存储引擎 二、InnoDB存储引擎1、InnoDB逻辑存储结构2、InnoDB架构3、...

  • MySQL数据库引擎

    MySQL数据库引擎有哪些 mysql的存储引擎包括:MyISAM 、 InnoDB 、 BDB 、 MEMORY...

  • InnoDB学习笔记(2)Undo log

    MySQL · 引擎特性 · InnoDB undo log 漫游 INSERT操作在事务提交前只对当前事务可见,...

网友评论

      本文标题:mysql数据库InnoDB存储引擎Log漫游(2)

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