MySQL日志之撤销日志undo log

1.1 基本概念

  undo log是逻辑日志,记录了变更操作的反向操作。主要用于事务的回滚 和 一致性非锁定读。根据行为不同undo分为insert undo和update undo。

insert undo log(包含INSERT操作)
  在insert操作中产生的undo log,因为insert操作的记录只对事务本身可见。因此该undo log在事务提交后直接删除,不需要进行purge操作。

update undo log(包含UPDATE及DELETE操作)
  记录的是对delete和update操作产生的undo log,该log需要提供mvcc机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行清除。

1.2 相关参数&视图

mysql> show variables like '%undo%';
+--------------------------+-------------------+
| Variable_name            | Value             |
+--------------------------+-------------------+
| innodb_max_undo_log_size | 4294967296        |
| innodb_undo_directory    | /data/mysql8/data |
| innodb_undo_log_encrypt  | OFF               |
| innodb_undo_log_truncate | ON                |
| innodb_undo_tablespaces  | 2                 |
+--------------------------+-------------------+
5 rows in set (0.00 sec)

mysql> show variables like '%purge%';
+--------------------------------------+--------------------------------------------+
| Variable_name                        | Value                                      |
+--------------------------------------+--------------------------------------------+
| gtid_purged                          | 6ac2c3ad-c5b7-11ea-8d1a-00163e0c8a51:1-304 |
| innodb_max_purge_lag                 | 0                                          |
| innodb_max_purge_lag_delay           | 0                                          |
| innodb_purge_batch_size              | 300                                        |
| innodb_purge_rseg_truncate_frequency | 128                                        |
| innodb_purge_threads                 | 4                                          |
| relay_log_purge                      | ON                                         |
+--------------------------------------+--------------------------------------------+
7 rows in set (0.00 sec)

mysql> select * from INNODB_TABLESPACES where ROW_FORMAT='undo'\G
*************************** 1. row ***************************
         SPACE: 4294967279
          NAME: innodb_undo_001
          FLAG: 0
    ROW_FORMAT: Undo
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Undo
 FS_BLOCK_SIZE: 0
     FILE_SIZE: 0
ALLOCATED_SIZE: 0
SERVER_VERSION: 8.0.21
 SPACE_VERSION: 1
    ENCRYPTION: N
         STATE: active
*************************** 2. row ***************************
         SPACE: 4294967278
          NAME: innodb_undo_002
          FLAG: 0
    ROW_FORMAT: Undo
     PAGE_SIZE: 16384
 ZIP_PAGE_SIZE: 0
    SPACE_TYPE: Undo
 FS_BLOCK_SIZE: 0
     FILE_SIZE: 0
ALLOCATED_SIZE: 0
SERVER_VERSION: 8.0.21
 SPACE_VERSION: 1
    ENCRYPTION: N
         STATE: active
2 rows in set (0.00 sec)

mysql> select * from INNODB_BUFFER_PAGE where PAGE_TYPE='UNDO_LOG'limit 1\G
*************************** 1. row ***************************
            POOL_ID: 0
           BLOCK_ID: 8
              SPACE: 4294967279
        PAGE_NUMBER: 252
          PAGE_TYPE: UNDO_LOG
         FLUSH_TYPE: 0
          FIX_COUNT: 0
          IS_HASHED: NO
NEWEST_MODIFICATION: 0
OLDEST_MODIFICATION: 0
        ACCESS_TIME: 3685402668
         TABLE_NAME: NULL
         INDEX_NAME: NULL
     NUMBER_RECORDS: 0
          DATA_SIZE: 0
    COMPRESSED_SIZE: 0
         PAGE_STATE: FILE_PAGE
             IO_FIX: IO_NONE
             IS_OLD: YES
    FREE_PAGE_CLOCK: 0
1 row in set (0.10 sec)

1.3 undo log 结构

  undo log是由rollback segment(回滚段),MySQL默认支持支持128个rollback segment,每个rollback segment中有1024个undo log segment。每个undo操作在记录的时候占用一个undo log segment,undo log也会产生redo log,因为undo log也要实现持久性保护。
rollback segment分布:

  • slot 0 ,预留给系统表空间;
  • slot 1- 32,预留给临时表空间,每次数据库重启的时候,都会重建临时表空间;
  • slot33-127,如果有独立表空间,则预留给UNDO独立表空间;如果没有,则预留给系统表空间;
    在这里插入图片描述

1.4 undo log purge

  当事务提交的时候,innodb不会立即删除undo log,因为后续还可能会用到undo log,如隔离级别为RR时,事务读取的都是开启事务时的最新提交行版本,只要该事务不结束,该行版本就不能删除,即undo log不能删除。但是在事务提交的时候,会将该事务对应的undo log放入到删除列表中,未来通过purge线程来删除。并且提交事务时,还会判断undo log分配的页是否可以重用,如果可以重用,则会分配给后面来的事务,避免为每个独立的事务分配独立的undo log页而浪费存储空间和性能。

  • insert操作在事务提交后直接删除。

  • delete操作实际上不会直接删除,而是将delete对象打上delete flag,标记为删除,最终的删除操作是purge线程完成的。

  • update分为两种情况:update的列是否是主键列。

    • 如果不是主键列,在undo log中直接反向记录是如何update的。即update是直接进行的。
    • 如果是主键列,update分两部执行:先删除该行,再插入一行目标行。

  innodb通过innodb_purge_threads参数控制开启多少个独立的purge线程,然后将innodb_purge_batch_size定义的批量清除的undo log日志页数分配给purge线程;通过innodb_purge_rseg_truncate_frequency定义purge线程的清除系统释放回滚段的频率,undo log表空间在其对应的回滚段被释放之前是不能被回收的。默认情况下,清除系统会在回滚段被调用128次之 后执行一次释放回滚段操作。

参考文章
https://www.cnblogs.com/xibuhaohao/p/11947041.html

猜你喜欢

转载自blog.csdn.net/qq_42979842/article/details/107837735
今日推荐