searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Innodb写redolog的无修改操作

2023-10-27 06:28:56
8
0

一、大致现象

如图,启动操作和某些查询均改变redolog和lsn。

二、堆栈情况及分析

1. 启动时更新max_trx_id

2. 启动时更新临时表空间元数据

3. 表空间变更,即便没有变更也要提交

4. collation和charset

更新collation,从charset重新生成,无论是否有更新

更新charset对collation的引用,无论是否有更新

提交collation和charset的更新

5. 验证resource_group,如果不通过则禁用,重新设置用户默认组和系统默认组

疑问:为何用户默认组和系统默认组即便没有修改也要更新?

默认组在启动时无视数据字典中的配置,通过硬编码的方式直接更新数据字典,覆盖原配置,不检查是否有修改。

6. Flush prepared gtid

PREPARE_GTID机制即在事务中两次写GTID到undo log中,第一次是在prepare时,第二次是在commit时,但没找到注释里描述的只在commit时写GTID的老版本,在8.0.30中反倒是只在XA prepare时才会写GTID,在8.0.18中是在本地prepare时写GTID,18和30的版本均会在本地提交时写GTID,在更早的5.7版本中根本不会写入GTID到undo log中,因此注释中所述不再在写COMMIT GTID前等待PREPARE GTID flush暂时还无法理解。Clone_persist_gtid::flush_gtids将新生成的GTID从内存中写入到mysql.gtid_executed表,这一般是一种周期性的写入,但在启动时,会一次性将启动过程中积累的GTID写入到mysql.gtid_executed表。这里写入redolog的并不是server层的GTID,而是trx->no,是从serialisation_list写入最大的trx->no到系统头,然后数据库启动初始化回滚段的时候会用到。注意到trx->no的更新与是否积累了GTID无关,只要serialisation_list被更新就会触发,在每次周期性写入中都要做,并且有相关事件机制,因此如果只读查询触发了serialisation_list的更新就会导致redolog的写入。

7. 重新安装performance_schema.innodb_redo_log_files表,先drop再add

疑问:为何要清空数据,为何必须使用drop-add方式?

该表存储在内存中,每次查询都会清空数据并重新生成数据,因此没必要在启动时清空数据,也没必要使用drop-add方式。这里的考虑或许是以防该表元数据被人为修改过?

删除performance_schema.innodb_redo_log_files表

删除performance_schema.innodb_redo_log_files表的提交操作

重新创建performance_schema.innodb_redo_log_files表

重新创建performance_schema.innodb_redo_log_files表的提交操作

8. checkpoint线程中元数据刷脏

疑问:为何元数据刷脏要写redolog?如果之前不是在redolog中,那是在哪里?

这里的刷脏并不是数据字典回写脏页的含义,DDL中对数据字典的修改一般在用户线程完成,和DDL log一起记在redolog中,这些数据回写脏页显然是不须要再次写redolog的。这里的刷脏是指将DDL中涉及到的元数据信息持久化到mysql.tables, mysql.columns, mysql.indexes, mysql.tablespaces, mysql.innodb_ddl_log等几个表中。在启动中,由于要重新创建performance_schema.innodb_redo_log_files表,会修改mysql.tables和mysql.columns。

9. purge线程组

purge worker线程,删辅助索引节点

purge worker线程,从聚簇索引中删除

purge coordinator线程,LOB的完整purge由于worker线程的多线程协作原因,被延迟到批处理之后

purge coordinator线程,truncate undo log

10. 查询时,可能会更新统计数据

0条评论
作者已关闭评论
曾****江
5文章数
1粉丝数
曾****江
5 文章 | 1 粉丝
原创

Innodb写redolog的无修改操作

2023-10-27 06:28:56
8
0

一、大致现象

如图,启动操作和某些查询均改变redolog和lsn。

二、堆栈情况及分析

1. 启动时更新max_trx_id

2. 启动时更新临时表空间元数据

3. 表空间变更,即便没有变更也要提交

4. collation和charset

更新collation,从charset重新生成,无论是否有更新

更新charset对collation的引用,无论是否有更新

提交collation和charset的更新

5. 验证resource_group,如果不通过则禁用,重新设置用户默认组和系统默认组

疑问:为何用户默认组和系统默认组即便没有修改也要更新?

默认组在启动时无视数据字典中的配置,通过硬编码的方式直接更新数据字典,覆盖原配置,不检查是否有修改。

6. Flush prepared gtid

PREPARE_GTID机制即在事务中两次写GTID到undo log中,第一次是在prepare时,第二次是在commit时,但没找到注释里描述的只在commit时写GTID的老版本,在8.0.30中反倒是只在XA prepare时才会写GTID,在8.0.18中是在本地prepare时写GTID,18和30的版本均会在本地提交时写GTID,在更早的5.7版本中根本不会写入GTID到undo log中,因此注释中所述不再在写COMMIT GTID前等待PREPARE GTID flush暂时还无法理解。Clone_persist_gtid::flush_gtids将新生成的GTID从内存中写入到mysql.gtid_executed表,这一般是一种周期性的写入,但在启动时,会一次性将启动过程中积累的GTID写入到mysql.gtid_executed表。这里写入redolog的并不是server层的GTID,而是trx->no,是从serialisation_list写入最大的trx->no到系统头,然后数据库启动初始化回滚段的时候会用到。注意到trx->no的更新与是否积累了GTID无关,只要serialisation_list被更新就会触发,在每次周期性写入中都要做,并且有相关事件机制,因此如果只读查询触发了serialisation_list的更新就会导致redolog的写入。

7. 重新安装performance_schema.innodb_redo_log_files表,先drop再add

疑问:为何要清空数据,为何必须使用drop-add方式?

该表存储在内存中,每次查询都会清空数据并重新生成数据,因此没必要在启动时清空数据,也没必要使用drop-add方式。这里的考虑或许是以防该表元数据被人为修改过?

删除performance_schema.innodb_redo_log_files表

删除performance_schema.innodb_redo_log_files表的提交操作

重新创建performance_schema.innodb_redo_log_files表

重新创建performance_schema.innodb_redo_log_files表的提交操作

8. checkpoint线程中元数据刷脏

疑问:为何元数据刷脏要写redolog?如果之前不是在redolog中,那是在哪里?

这里的刷脏并不是数据字典回写脏页的含义,DDL中对数据字典的修改一般在用户线程完成,和DDL log一起记在redolog中,这些数据回写脏页显然是不须要再次写redolog的。这里的刷脏是指将DDL中涉及到的元数据信息持久化到mysql.tables, mysql.columns, mysql.indexes, mysql.tablespaces, mysql.innodb_ddl_log等几个表中。在启动中,由于要重新创建performance_schema.innodb_redo_log_files表,会修改mysql.tables和mysql.columns。

9. purge线程组

purge worker线程,删辅助索引节点

purge worker线程,从聚簇索引中删除

purge coordinator线程,LOB的完整purge由于worker线程的多线程协作原因,被延迟到批处理之后

purge coordinator线程,truncate undo log

10. 查询时,可能会更新统计数据

文章来自个人专栏
文章 | 订阅
0条评论
作者已关闭评论
作者已关闭评论
0
0