在MySQL运维场景中,动态调整Redo大小,清理Undo表空间的需求会持续存在,例如、大事务导致undo日志的“膨胀”,或者TPS变化导致原有Redo日志大小需要调整。
1、动态调整Undo表空间
在MySQL中Undo文件可以自动扩展,业务侧的大事务很容易就将Undo日志文件撑大。在MySQL 8.0中可以使用以下步骤清理被撑大的Undo日志。
#查看系统当前存在两个undo文件,都是active状态,大小为16M mysql> select * from information_schema.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: 4096 FILE_SIZE: 16777216 ALLOCATED_SIZE: 16777216 AUTOEXTEND_SIZE: 0 SERVER_VERSION: 8.0.30 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: 4096 FILE_SIZE: 16777216 ALLOCATED_SIZE: 16777216 AUTOEXTEND_SIZE: 0 SERVER_VERSION: 8.0.30 SPACE_VERSION: 1 ENCRYPTION: N STATE: active 2 rows in set (0.00 sec) mysql> system ls -lthr /data/mysql/data |grep undo -rw-r-----. 1 mysql mysql 16M Oct 17 22:26 undo_002 -rw-r-----. 1 mysql mysql 16M Oct 17 22:26 undo_001 #设置其中一个undo表空间为inactive状态,打开系统参数innodb_undo_log_truncate 交MySQL自动回收 mysql> alter undo tablespace innodb_undo_001 set inactive; ERROR 3655 (HY000): Cannot set innodb_undo_001 inactive since there would be less than 2 undo tablespaces left active. 可以看到系统需要保留至少2个active的undo表空间 #创建一个新的undo表空间,注意文件名必须为ibu,且表空间名前缀不能是innodb_ mysql> create undo tablespace undo_003 add datafile '/data/mysql/data/undo_003.ibu'; Query OK, 0 rows affected (0.13 sec) #现在有三个undo表空间了,可以设置其中一个undo表空间为inactive状态 mysql> select * from information_schema.innodb_tablespaces where ROW_FORMAT='undo'\G *************************** 1. row *************************** SPACE: 4294967152 NAME: innodb_undo_001 FLAG: 0 ROW_FORMAT: Undo PAGE_SIZE: 16384 ZIP_PAGE_SIZE: 0 SPACE_TYPE: Undo FS_BLOCK_SIZE: 4096 FILE_SIZE: 16777216 ALLOCATED_SIZE: 16777216 AUTOEXTEND_SIZE: 0 SERVER_VERSION: 8.0.30 SPACE_VERSION: 1 ENCRYPTION: N STATE: empty *************************** 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: 4096 FILE_SIZE: 16777216 ALLOCATED_SIZE: 16777216 AUTOEXTEND_SIZE: 0 SERVER_VERSION: 8.0.30 SPACE_VERSION: 1 ENCRYPTION: N STATE: active *************************** 3. row *************************** SPACE: 4294967277 NAME: undo_003 FLAG: 0 ROW_FORMAT: Undo PAGE_SIZE: 16384 ZIP_PAGE_SIZE: 0 SPACE_TYPE: Undo FS_BLOCK_SIZE: 4096 FILE_SIZE: 16777216 ALLOCATED_SIZE: 16777216 AUTOEXTEND_SIZE: 0 SERVER_VERSION: 8.0.31 SPACE_VERSION: 1 ENCRYPTION: N STATE: active 3 rows in set (0.00 sec) #确认自动回收是否开启 mysql> select @@global.innodb_undo_log_truncate; +-----------------------------------+ | @@global.innodb_undo_log_truncate | +-----------------------------------+ | 1 | +-----------------------------------+ 1 row in set (0.00 sec) #如果希望加快undo表空间的回收,可以适当调低innodb_purge_rseg_truncate_frequency的值。默认128 mysql> select @@global.innodb_purge_rseg_truncate_frequency; +-----------------------------------------------+ | @@global.innodb_purge_rseg_truncate_frequency | +-----------------------------------------------+ | 128 | +-----------------------------------------------+ 1 row in set (0.00 sec) #将回收的undo表空间设置为active,删除临时增加的undo3 mysql> alter undo tablespace innodb_undo_001 set active; Query OK, 0 rows affected (0.00 sec) mysql> alter undo tablespace undo_003 set inactive; Query OK, 0 rows affected (0.00 sec) mysql> drop undo tablespace undo_003; Query OK, 0 rows affected (0.00 sec) mysql> select * from information_schema.innodb_tablespaces where ROW_FORMAT='undo'\G *************************** 1. row *************************** SPACE: 4294966898 NAME: innodb_undo_001 FLAG: 0 ROW_FORMAT: Undo PAGE_SIZE: 16384 ZIP_PAGE_SIZE: 0 SPACE_TYPE: Undo FS_BLOCK_SIZE: 4096 FILE_SIZE: 16777216 ALLOCATED_SIZE: 16777216 AUTOEXTEND_SIZE: 0 SERVER_VERSION: 8.0.30 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: 4096 FILE_SIZE: 16777216 ALLOCATED_SIZE: 16777216 AUTOEXTEND_SIZE: 0 SERVER_VERSION: 8.0.30 SPACE_VERSION: 1 ENCRYPTION: N STATE: active 2 rows in set (0.00 sec)
复制
- 小结步骤如下
·1、增加undo表空间的数量大于2.
2、设置膨胀的undo表空间为inactive
3、系统参数innodb_undo_log_truncate打开后会自动回收。
4、设置原undo表空间为active,删除新添加的表空间。
2、动态调整Redo日志
从MySQL8.0.30开始支持参数innodb_redo_log_capacity。该参数设定redo日志的总大小,默认100MB,最大值为128G。该参数设置后原有的innodb_log_files_in_group和innodb_log_file_size参数将被忽略。
MySQL会自动在innodb_log_group_home_dir目录中创建#innodb_redo,每个文件大小为innodb_redo_log_capacity/32。测试环境中设置总大小320M,每一个redo文件大小10M。 未使用的redo日志文件名带_tmp后缀。
mysql> select @@global.innodb_redo_log_capacity; +-----------------------------------+ | @@global.innodb_redo_log_capacity | +-----------------------------------+ | 335544320 | +-----------------------------------+ 1 row in set (0.00 sec) mysql> system ls -lthr /data/mysql/log/#innodb_redo total 320M -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo2_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo3_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo4_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo5_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo1 -rw-r-----. 1 mysql mysql 10M Oct 19 15:58 #ib_redo6_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo7_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo8_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo9_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo10_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo11_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo12_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo13_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo14_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo15_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo16_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo17_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo18_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo19_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo20_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo21_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo22_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo23_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo24_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo25_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo26_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo27_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo28_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo29_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo30_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo31_tmp -rw-r----- 1 mysql mysql 10M Oct 19 15:58 #ib_redo32_tmp
复制
当前使用的redo日志可以通过以下SQL查询
mysql> select * from performance_schema.innodb_redo_log_files\G *************************** 1. row *************************** FILE_ID: 1 FILE_NAME: /data/mysql/log/#innodb_redo/#ib_redo1 START_LSN: 101996544 END_LSN: 112480256 SIZE_IN_BYTES: 10485760 IS_FULL: 0 CONSUMER_LEVEL: 0 1 row in set (0.00 sec)
复制
redo日志写入的当前LSN可以使用以下SQL查询,也可以用LSN的变化量预估一个合理的redo文件大小
mysql> show global status like 'Innodb_redo_log_current_lsn'; +-----------------------------+-----------+ | Variable_name | Value | +-----------------------------+-----------+ | Innodb_redo_log_current_lsn | 102001409 | +-----------------------------+-----------+ 1 row in set (0.00 sec) #可以使用以下SQL评估1分钟lsn的变化量,*60 作为innodb_redo_log_capacity select @a:=(select VARIABLE_VALUE from global_status where VARIABLE_NAME='Innodb_redo_log_current_lsn');select sleep(60);select @b:=(select VARIABLE_VALUE from global_status where VARIABLE_NAME='Innodb_redo_log_current_lsn');select (@b-@a)/1024/1024; mysql> select @a:=(select VARIABLE_VALUE from global_status where VARIABLE_NAME='Innodb_redo_log_current_lsn');select sleep(60);select @b:=(select VARIABLE_VALUE from global_status where VARIABLE_NAME='Innodb_redo_log_current_lsn');select (@b-@a)/1024/1024; +--------------------------------------------------------------------------------------------------+ | @a:=(select VARIABLE_VALUE from global_status where VARIABLE_NAME='Innodb_redo_log_current_lsn') | +--------------------------------------------------------------------------------------------------+ | 102016920 | +--------------------------------------------------------------------------------------------------+ 1 row in set, 1 warning (0.00 sec) +-----------+ | sleep(60) | +-----------+ | 0 | +-----------+ 1 row in set (1 min 0.00 sec) +--------------------------------------------------------------------------------------------------+ | @b:=(select VARIABLE_VALUE from global_status where VARIABLE_NAME='Innodb_redo_log_current_lsn') | +--------------------------------------------------------------------------------------------------+ | 102037622 | +--------------------------------------------------------------------------------------------------+ 1 row in set, 1 warning (0.00 sec) +----------------------+ | (@b-@a)/1024/1024 | +----------------------+ | 0.019742965698242188 | +----------------------+ 1 row in set (0.01 sec)
复制
MySQL 8.0随着这些特性的逐渐丰富,Undo、Redo的调整都不需要重启数据库了,有条件的同学可以多测试并推广使用。
最后修改时间:2022-10-19 17:00:56
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。