• undo日志


    InnoDB’s Undo

    前言

    Undo log是InnoDB MVCC事务特性的重要组成部分。当我们对记录做了变更操作时就会产生undo记录,Undo记录默认被记录到系统表空间(ibdata)中,但从5.6开始,也可以使用独立的Undo 表空间。

    Undo记录中存储的是老版本数据,当一个旧的事务需要读取数据时,为了能读取到老版本的数据,需要顺着undo链找到满足其可见性的记录。当版本链很长时,通常可以认为这是个比较耗时的操作(例如bug#69812)。

    大多数对数据的变更操作包括INSERT/DELETE/UPDATE,其中INSERT操作在事务提交前只对当前事务可见,因此产生的Undo日志可以在事务提交后直接删除(谁会对刚插入的数据有可见性需求呢!!),而对于UPDATE/DELETE则需要维护多版本信息,在InnoDB里,UPDATE和DELETE操作产生的Undo日志被归成一类,即update_undo。

    what?

    DML操作导致的数据记录变化,均需要将记录的前镜像写入Undo日志;

    逻辑日志;

    when?

    DML操作修改聚簇索引前,记录Undo日志(Undo日志,先于Redo日志)

    二级索引记录的修改,不记录Undo日志;

    注意:Undo页面的修改,同样需要记录Redo日志;

    Insert/Delete/Update分别会如何记录日志?

    InnoDB内存中,DML操作顺序如下:
    –写Undo(获取ROLLBACK_PTR系统列)
    –修改Page
    –写Redo的顺序

    Insert:

    将插入记录的主键值,写入Undo;

    Delete:

    1. Delete,在InnoDB内部为Delete Mark操作,将记录上标识Delete_Bit,而不删除记录;
    2. 将当前记录的系统列写入Undo (DB_TRX_ID, ROLLBACK_PTR, ...);
    3. 将当前记录的主键列写入Undo;
    4. 将当前记录的所有索引列写入Undo;
    5. 将Undo Page的修改,写入Redo;

    Update(未修改聚簇索引键值)

    1. 将当前记录的系统列写入Undo (DB_TRX_ID, ROLLBACK_PTR, ...);
    2. 将当前记录的主键列写入Undo;
    3. 将当前Update列的前镜像写入Undo;
    4. 若Update列中包含二级索引列,则将二级索引其他未修改列写入Undo;
    5. 将Undo页面的修改,写入Redo;

    Update(修改聚簇索引键值)

    1. 不可进行In Place Update。Update = Delete Mark + Insert;
    2. 对原有记录进行Delete Mark操作,写入Delete Mark操作Undo;
    3. 将新纪录插入聚簇索引,写入Insert操作Undo;
    4. 将Undo页面的修改,写入Redo;

    undo的功能:

    1. 实现事务的原子性,即当事务由于意外情况未能运行时,可以使得事务回滚,从而使得数据恢复到事务开始运行时的状态;

    2. 实现一致性非锁定读。如果读取的行正在执行delete或者update操作,这时读取操作不会因此去等待行上锁的释放。相反,InnoDB存储引擎会去读取行的一个快照数据;

    3. 用户的DML操作,均要记录undo;

    undo页重用:

    InnoDB存储引擎允许在一个页中存放多个不同事务的undo日志。若在OLTP应用环境中,事务通常都比较小,因此产生的undo日志相对较小。而由于其他事务可能正在引用当前的记录,事务在提交时并不能直接将undo日志给删除。

    在InnoDB存储引擎的设计中对undo页可以进行重用,即一个undo页中允许存放多个不同事务的undo日志。具体来说,当事务提交时,首先将undo log放入到链表中,然后判断当前undo页的使用空间是否小于3/4。如果小于,表示该undo页可以被重用,之后新产生的undo记录保存在当前undo log的后面。由于存放undo log的history链表是以undo记录进行链接的,而undo页可能存放着不同事务的undo日志,因此purge操作需要涉及磁盘的离散读取操作,是一个比较缓慢的过程。  

    purge清理操作:

    purge操作主要进行2个清理操作:

    1. 清理记录。删除已经标记为delete mark的记录或者其他相关辅助索引记录;

    2. 清理undo日志。若undo页中的所有undo记录都被删除,则删除对应的undo段。

    在清理undo日志时,需要判断当前是否有其他事务在通过undo日志进行多版本并发控制,若有,则不能立即进行undo日志的清理,仅当没有任何一个用户事务使用该undo日志时,才可以进行清理。

    为何需要按照操作类型,分为insert_undo与update_undo?

    目标:为了实现Undo Page的分类回收;

    insert_undo:

    所有的Undo Page,在事务提交后,可直接回收释放;

    update_undo:

    所有的Undo Page,事务提交后,不可立即回收释放;

    需要遍历其中的Undo日志,删除索引中的过期版本记录(Purge);然后才可释放;

    mysql 5.1中undo的purge是和master thread 共用一个线程,则可能的purge的速度到达了瓶颈;

    mysql 5.5中有独立的purge线程可以很快的回收掉undo log;

    mysql 5.6中可以单独设置undo tablespace文件,避免与ibdata1混用在一起;

    innodb_undo_tablespaces 回滚表空间个数

     innodb_undo_directory 回滚表空间位置

    从共享表空间独立出来,从而不至于单个表空间文件过大。

                

  • 相关阅读:
    Linux驱动之USB(个人)
    iptables命令使用详解
    python操作mysql——mysql.connector
    linux下NFS实战
    CentOS6上ftp服务器搭建实战
    CentOS7下mariadb日常管理
    CentOS7配置httpd虚拟主机
    httpd常见配置
    常见加密算法
    HTTP安全通信:Https和SSL
  • 原文地址:https://www.cnblogs.com/yuyue2014/p/3946518.html
Copyright © 2020-2023  润新知