• MySQL-InnoDB事务日志


    1. InnoDB事务日志

    InnoDB的事务日志主要分为redo log(重做日志,提供前滚操作)和undo log(回滚日志,提供回滚操作和快照读)。

    2. redo log

    2.1 redo log 区分binlog

    1)binlog日志是在Server层产生的,适用所有存储引擎。所有对数据库变更的写入到binlog日志。redo log是由InnoDB存储引擎产生的,只记录改存储引擎对象的数据变更页。

    2)日志格式不同,binlog是一种逻辑日志,而redo log是物理格式日志,记录innodb引擎数据页的修改。

    3)刷盘时间点不同,binlog只在事务提交完成后一次写入,而redo log是在事务执行过程不断写入。


    2.2 redo log

    它包含两部分内容(日志缓存[redo log_buffer]和redo log file[datadir/ib_logfileN]),InnoDB通过force log at commit机制实现事务的持久性。


    clipboard

    1)log buffer刷日志文件配置参数

    MySQL通过控制innodb_flush_log_at_trx_commit参数值方式自定义刷盘方式,从log buffer中的日志刷log file中。这个变量只是控制commit动作是否刷新log buffer到磁盘。

    innodb_flush_log_at_trx_commit=1: 事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。
    innodb_flush_log_at_trx_commit=0: 事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
    innodb_flush_log_at_trx_commit=2: 每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file on disk。

    83-690986409

    2)redo log block(日志块)

    Innodb存储引擎中,redo log以块为单位进行存储的,每个块占512字节,这称为redo log block。所以不管是log buffer中还是os buffer中以及redo log file on disk中,都是这样以512字节的块存储的。


    3) rodo log参数

    > show global variables like 'innodb_log%';
    +-----------------------------+----------+
    | Variable_name               | Value    |
    +-----------------------------+----------+
    | innodb_log_buffer_size      | 16777216 |  # 重做日志缓冲区大小,默认16M
    | innodb_log_checksums        | ON       |  # 校验
    | innodb_log_compressed_pages | ON       |  # 是否启用压缩
    | innodb_log_file_size        | 50331648 |  # 日志文件大小
    | innodb_log_files_in_group   | 2        |  # 日志文件数量,默认2个日志文件
    | innodb_log_group_home_dir   | ./       |  # 日志文件目录,默认datadri
    | innodb_log_write_ahead_size | 8192     |  # 表示redo log写前的块大小(MySQL 5.7.4)
    +-----------------------------+----------+
    

    innodb_log_write_ahead_size:为了处理redo log block得大小和OS block间操作数据块大小协调一致得问题。在InnoDB中以512字节一个block的方式对齐写入redo file(ib_logfileN)文件,而操作系统一般以4096字节为一个block单位(OS block)读写。如果即将写入的日志块不在OS buffer Cache时,就需要将对应的4096字节的block读入内存,修改其中的512字节,然后再把该block写回磁盘。引入write-ahead是将当前写入redo文件的偏移量整除innodb_log_write_ahead_size参数值,不能整除时则补0补全,使得需要写入的内容刚好是block的倍数,那么就直接覆盖写入即可。不再需要read-modify-write得过程。提升效率。

    4)日志页刷盘规则

    log buffer中未刷到磁盘的日志称为脏日志(dirty log)。

    刷日志到磁盘规则:

    [1] 发出commit动作时,是否刷日志由变量 innodb_flush_log_at_trx_commit 控制。
    [2] 每秒刷一次。刷日志的频率由变量 innodb_flush_log_at_timeout 值决定,默认是1秒。这个刷日志频率和commit动作无关。
    [3] 当log buffer中已经使用的内存超过一半时。
    [4]当有checkpoint时,checkpoint在一定程度上代表了刷到磁盘时日志所处的LSN位置。

    5)数据页刷盘规则

    内存中(buffer pool)未刷到磁盘的数据称为脏数据(dirty data)。由于数据和日志都以页的形式存在,所以脏页表示脏数据和脏日志。在InnoDB中触发checkpoint动作将buffer中的脏数据页和脏日志页都刷到磁盘中。

    触发checkpoint的情形:

    [1] sharp checkpoint:在切换日志文件的时候,将所有已记录到redo log 文件中对应的脏数据刷到磁盘。
    [2] fuzzy checkpoint:一次只刷一小部分的日志到磁盘,而非将所有脏日志刷盘。有以下几种情况会触发该检查点:
         master thread checkpoint:由master线程控制,每秒或每10秒刷入一定比例的脏页到磁盘。
         flush_lru_list checkpoint:从MySQL5.6开始可通过 innodb_page_cleaners 变量指定专门负责脏页刷盘的page cleaner线程的个数,该线程的目的是为了保证lru列表有可用的空闲页。
         async/sync flush checkpoint:同步刷盘还是异步刷盘。例如还有非常多的脏页没刷到磁盘(非常多是多少,有比例控制),这时候会选择同步刷到磁盘,但这很少出现;如果脏页不是很多,可以选择异步刷到磁盘,如果脏页很少,可以暂时不刷脏页到磁盘
         dirty page too much checkpoint:脏页太多时强制触发检查点,目的是为了保证缓存有足够的空闲空间。too much的比例由变量 innodb_max_dirty_pages_pct 控制,MySQL 5.6默认的值为75,即当脏页占缓冲池的百分之75后,就强制刷一部分脏页到磁盘。
        
    由于刷脏页需要一定的时间来完成,所以记录检查点的位置是在每次刷盘结束之后才在redo log中标记的。

    MySQL服务停止时是否将脏数据和脏日志刷入磁盘,由变量innodb_fast_shutdown={ 0|1|2 }控制,默认值为1,即停止时只做一部分purge,忽略大多数flush操作(但至少会刷日志),在下次启动的时候再flush剩余的内容,实现fast shutdown。


    3. undo log

    undo log的作用是提供事务的回滚和多个行版本控制(MVCC-非锁定读)。undo log是逻辑日志,如执行一条delete操作时,undo log将它的反向操作记录下来,undo log也会产生redo日志。当事务失败需要回滚时,就可以从undo log中的逻辑记录进行回滚到修改前的样子。

    3.1 undo log存储方式

    undo存放在数据库内一个称为回滚段(rollback segment)的特殊段中。默认情况,undo segment在共享表空间(ibdata1)内,如果开启innodb_file_per_table ,将放在每个表的.ibd文件中。可以通过py_innodb_page_info.py工具查看当前biaokongji按中undo的数量。

    image

    每个回滚段有1024个undo log segment,在使用时在每个undo log segment中申请undo 页。在旧版本只有一个回滚段。mysql5.5开始支持128个回滚段。每个事务占用一个undo log segment,因此,可以支持最多128*1024个并发事务运行。

    image


    3.2 相关参数

    +--------------------------+------------+
    | Variable_name            | Value      |
    +--------------------------+------------+
    | innodb_max_undo_log_size | 1073741824 |    # undo log的最大容量限制,默认1G
    | innodb_undo_directory    | ./         |    # 设置回滚段文件路径,可以设置独立表空间(MySQL5.6)
    | innodb_undo_log_truncate | OFF        |    # 是否开启自动清理undo log的功能,MySQL5.7.5
    | innodb_undo_logs         | 128        |    # 设置undo log segment的数量,默认128
    | innodb_undo_tablespaces  | 0          |    # 设置undo 表空间的数量,至少2个。在初始化配置,以后不能修改
    +--------------------------+------------+
    

    3.3 查看undo信息

    show engine innodb statusG;
    ...
    ------------
    TRANSACTIONS
    ------------
    Trx id counter 2819
    Purge done for trx's n:o < 0 undo n:o < 0 state: running but idle
    History list length 12
    LIST OF TRANSACTIONS FOR EACH SESSION:
    ---TRANSACTION 421561295218512
    ...
    
    
    # 视图查看
    select * from information_schema.innodb_trx_rollback_segmentG;
    
    select * from information_schema.innodb_trx_undoG;
    



    4. rudo和undo日志工作过程




    备注:图片均来自互联网

  • 相关阅读:
    点分治 (等级排) codeforces 321C
    树上点分治 poj 1741
    判断点在直线的左侧还是右侧
    树的重心
    链式前向星
    树上点的分治
    构造 素数
    二进制 + 模拟
    枚举 + 三分 (游标)
    枚举 + 三分
  • 原文地址:https://www.cnblogs.com/binliubiao/p/12667326.html
Copyright © 2020-2023  润新知