首页 > 数据库 > 数据库开发技术 > 面对MySQL的表空间文件膨胀你该如何出招呢?
碎碎念
本篇主要是以MySQL中日常运维工作中比较场景的日志文件膨胀为主旨,以MySQL5.7和MySQL8.0不同版本中日志的差别为主线,形成对比,正好最近工作中也遇到了相关的场景,便系统的整理了一下,大概雨神也是被杭州美景吸引,赖着不走了,好不容易昨天停了一天,今天又开始了,那就在家学习吧。
undo日志是与单个读写事务相关联的undo日志记录的集合,记录了包含有关如何撤销事务对聚簇索引记录的最新更改的信息,如果另一个事务需要将原始数据作为一致性读取操作的一部分来查看,则会从undo日志记录中检索未修改的数据,undo日志存在于undo日志段中,undo日志段包含在回滚段中,MySQL5.7和MySQL8.0存在差异,对于MySQL5.7,回滚段位于系统表空间、undo表空间和临时表空间中,对于MySQL8.0,回滚段位于undo表空间和全局临时表空间中。
对于MySQL5.7和MySQL8.0,undo日志相关有了不小的变化,下面从不同的角度进行展开对比:
默认配置:
MySQL5.7
undo log默认保留在系统表空间中,只能初始化时配置。不可动态调整。
MySQL8.0
MySQL8开始,MySQL实例初始化时自动创建两个默认的undo表空间,innodb_rollback_segments参数针对的是每个undo tablespace,而不是整体,按照版本发展轨迹如下:
MySQL8.0.14之前,可以通过innodb_undo_tablespace变量动态或静态指定undo表空间数量,包含两个默认undo表空间,最大值为127。通过其减少undo表空间文件个数不会立即删除undo表空间,待删除undo表空间直到其中的所有事务完成前都保持活跃状态。无法直接删除已停用的undo表空间,缓慢关闭后可以手动删除undo表空间文件,但是不建议手动删除,因为如果关闭服务器时存在打开的事务,则在服务器重新启动后一段时间,停用的undo表空间可能包含活跃的undo日志。可以使用drop undo tablespace语句删除undo表空间。
从MySQL 8.0.14开始,可以在运行时使用SQL创建额外的undo表空间。
从MySQL8.0.16开始,提供了undo和purge子系统计数器,用于监视与undo日志截断相关的后台活动。
从MySQL8.0.21开始,检查点之间对同一undo表空间的截断操作数量限制为64,如果超过限制,undo表空间仍然可以处于非活跃状态,但是直到下一个检查点之后才会被截断。MySQL8.0.22将限制从64提高到50000。
在MySQL8.0.23之前,undo表空间初始大小取决于innodb_page_size值,从MySQL8.0.23开始,undo表空间文件初始大小一般为16MB,当通过truncate操作创建新的undo表空间时,初始大小可能会不一样。取决于上一次文件扩展的时间。另外,MySQL8.0.23之前,undo表空间一次扩展4个数据块,从MySQL8.0.23开始,undo表空间一次至少扩展16MB。
回滚段配置:
MySQL5.7
1个回滚段总是分配给系统表空间,32个回滚段保留给临时表空间(ibtmp1)。因此,如果需要将回滚段分配给undo表空间,innodb_rollback_segments需设置为大于33的值,最大为128,因此innodb_undo_tablespaces值最大为95。例如,如果有两个undo表空间,将innodb_rollback_segments设置为35,以便为两个undo表空间中的每一个分配一个回滚段。回滚段以循环方式分布在undo表空间中。
MySQL8.0
回滚段位于undo表空间和全局临时表空间中,事务根据需要分配undo日志,对常规表执行操作的事务从分配的undo表空间回滚段分配undo日志,对临时表执行操作的事务从分配的全局临时表空间回滚段分配undo日志。位于全局临时表空间中的undo日志用于修改用户定义的临时表中的数据的事务,这些undo日志不会被重新记录,这些不是崩溃恢复所必须的,仅用于服务器运行时的回滚。可以提高性能,每个undo表空间和全局临时表空间分别支持最多128个回滚段。
截断undo表空间配置:
MySQL5.7
能够对undo log进行truncate的前提是MySQL中innodb_undo_log_truncate参数开启,且至少有两个活跃的undo表空间,使得可以一个undo表空间保持活跃状态,另外一个离线截断。超过innodb_max_undo_log_size设置的undo表空间被标记截断,对undo表空间进行截断是循环执行的,以避免每次截断同一个undo表空间,将被截断的undo表空间中的回滚段会处于非活跃状态,不会分配新的事务,但是当前正在使用该undo表空间中的回滚段的事务会正常完成。MySQL中的purge系统会通过释放undo日志来清空回滚段。释放undo表空间中的所有回滚段后,truncate操作将运行以将undo表空间文件大小截断到初始大小,undo表空间大小取决于innodb_page_size值,对于默认的页面大小,初始undo表空间文件大小为10MB,对于4KB,8KB,32KB,64KB的页面大小,undo表空间文件大小初始大小分别为7MB,8MB,20MB,40MB。因为操作后立即使用,截断操作后undo表空间的文件大小可能会大于初始大小。purge线程负责清空和截断undo表空间,默认情况下,purge线程每调用128次会查找需要截断的undo表空间,查找频率由innodb_purge_rseg_truncate_frequency变量控制,减小该参数的值可以提高查找的频率,当purge线程发现需要截断的undo表空间后,会以更高的频率返回以加速清空和截断undo表空间。
MySQL8.0
与MySQL5.7只支持自动化截断相比,MySQL8.0截断undo表空间有两种方式,一种是自动化,通过配置变量启用,另外一种是手动通过SQL语句执行,自动化方式不需要监视undo表空间大小,自动进行undo表空间的停用,截断,重新激活操作,无需手动干预,如果希望截断时间可控,例如避开业务高峰期,则手动截断方式更推荐。
并发事务:
一个事务最多分配四个undo日志:
对用户定义表的INSERT操作。
对用户定义的表执行UPDATE和DELETE操作。
对用户定义的临时表执行INSERT操作。
对用户定义的临时表执行UPDATE和DELETE操作。
对于不同的操作支持的最大并发读写事务数计算方式不一样,具体参考:
MySQL5.7
如果每个事务执行INSERT或UPDATE或DELETE操作,InnoDB能够支持的并发读写事务为:(innodb_page_size/16)*(innodb_rollback_segments - 32)
如果每个事务执行INSERT和UPDATE或DELETE操作,InnoDB能够支持的并发读写事务数为:(innodb_page_size/16/2)*(innodb_rollback_segments - 32)
如果每个事务对临时表执行INSERT或UPDATE或DELETE操作,InnoDB能够支持的并发读写事务数为:(innodb_page_size/16)*32
如果每个事务对临时表执行INSERT和UPDATE或DELETE操作,InnoDB能够支持的并发读写事务数为:(innodb_page_size/16/2)*32
MySQL8.0
如果每个事务执行INSERT或者UPDATE操作,InnoDB能够支持的并发读写事务数为:(innodb_page_size/16)innodb_rollback_segmentsundo表空间数
如果每个事务执行INSERT和UPDATE或DELETE操作,InnoDB能够支持的并发读写事务数为:(innodb_page_size/16/2)innodb_rollback_segmentsundo表空间数
如果每个事务对一个临时表执行INSERT操作,那么InnoDB能够支持的并发读写事务数为:(innodb_page_size/16)*innodb_rollback_segments
如果每个事务对临时表执行INSERT和UPDATE或DELETE操作,InnoDB能够支持的并发读写事务数为:(innodb_page_size/16/2)*innodb_rollback_segments
其他相关:
当undo表空间被截断时,其他undo表空间中的活跃回滚段负责整个系统的负载,可能会导致性能下降,性能受影响的程度取决于以下因素: undo表空间的数量, undo日志中的回滚段数量, undo表空间大小, 主机层IO速度, 现有的事务量, 系统负载, 避免潜在影响的最简单方法是增加undo表空间的数量,在undo表空间截断过程中,会有两个检查点操作,第一个检查点是从buffer pool缓冲池中删除旧的undo表空间数据页,第二个检查点是将新的undo表空间的初始页面刷新到磁盘,如果系统比较繁忙,删除大量页面会短暂影响系统性能。
使用create undo tablespace语法新建undo空间时文件名必须以.ibu结尾,创建的undo表空间文件可以在服务器脱机时移动到任何已知目录,已知目录指的是innodb_directories变量定义的目录,innodb_data_home_dir,innodb_undo_directory和datadir定义的目录会自动附加到innodb_directories值,服务启动时会自动扫描这些目录及其子目录以查找undo表空间文件。另外,undo日志相关的一些查询及参数如下:
查看undo日志信息:
mysql> SELECT TABLESPACE_NAME, FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE LIKE 'UNDO LOG';
+-----------------+------------+
| TABLESPACE_NAME | FILE_NAME |
+-----------------+------------+
| innodb_undo_001 | ./undo_001 |
| innodb_undo_002 | ./undo_002 |
+-----------------+------------+
2 rows in set (0.01 sec)
查看undo表空间状态,手动删除或截取undo表空间都需要先将其设置为inactive:
mysql> SELECT NAME, STATE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES ;
+------------------------------------+--------+
| NAME | STATE |
+------------------------------------+--------+
| mysql | normal |
| innodb_temporary | normal |
| innodb_undo_001 | active |
| innodb_undo_002 | active |
| sys/sys_config | normal |
| my_test/sbtest3 | normal |
+------------------------------------+--------+
6 rows in set (0.00 sec)
undo表空间相关的参数以及回滚段相关的参数如下:
mysql> show variables like "%undo%";
+--------------------------+------------+
| Variable_name | Value |
+--------------------------+------------+
| innodb_max_undo_log_size | 4294967296 |
| innodb_undo_directory | ./ |
| innodb_undo_log_encrypt | OFF |
| innodb_undo_log_truncate | ON |
| innodb_undo_tablespaces | 2 |
+--------------------------+------------+
5 rows in set (0.00 sec)
mysql>
mysql> show variables like "%rseg%";
+--------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------+-------+
| innodb_purge_rseg_truncate_frequency | 128 |
+--------------------------------------+-------+
1 row in set (0.01 sec)
mysql> SHOW STATUS LIKE 'Innodb_undo_tablespaces%';
+----------------------------------+-------+
| Variable_name | Value |
+----------------------------------+-------+
| Innodb_undo_tablespaces_total | 2 |
| Innodb_undo_tablespaces_implicit | 2 |
| Innodb_undo_tablespaces_explicit | 0 |
| Innodb_undo_tablespaces_active | 2 |
+----------------------------------+-------+
4 rows in set (0.00 sec)
上面通过对MySQL5.7和MySQL8.0的对比,可以感受到undo log在使用体验和功能以及性能方面有了很多的改善。最后的最后,自然绕不开表空间膨胀问题,生产上时常遇到undo文件膨胀过大问题,对于insert undo log,在事务提交后会被直接删除,对于delete和update操作,统一归类于update undo log,该undo log后期会被用于MVCC中,不能在提交的时候删除,提交后会放入到undo log的链表,等待purge线程进行最后删除。所以,这里我们可以提取一个关键词,事务提交,所以,尽可能避免长事务,未提交事务啊,另外,高并发下可能也会快速写入大量undo日志记录,所以提前根据前面的公式合理配置参数很重要。
系统表空空间膨胀也是日常工作中很容易遇到的一个场景,而MySQL5.7到MySQL8.0,MySQL的系统表空间包含的内容也发生了很大的变化。
对于MySQL5.7:系统表空间是InnoDB数据字典,doublewrite buffer(双写缓冲区), change buffer(更改缓冲区),默认undo日志的存储区域,如果表在系统表空间中创建,可能还包含表和索引数据。系统表空间可以有一个或多个数据文件。默认情况下,在数据目录中创建一个名为ibdata1的系统表空间数据文件。
增加系统表空间的大小有两种方式: 第一种方式是配置autoextend,对innodb_data_file_path中的最后一个数据文件加上autoextend属性,然后重启服务。第二种方式是增加一个新的系统表空间data文件,如果innodb_data_file_path中的最后一个数据文件已经有autoextend属性,修改当前文件size属性值到最接近文件大小的实际值,增加一个新的不存在的文件,指定autoextend属性,然后重启服务,注意,不能通过直接修改已存在的文件的size属性来增加系统表空间大小。目前不支持通过移除data文件方式减少系统表空间大小,比较麻烦,具体可以参考如下方式: a.使用mysqldump或类似工具导出所有Innodb引擎的表,包含mysql系统库中的InnoDB引擎表 b.停止服务 c.移除所有的存在的表空间文件,包含所有的*.ibd文件,ibdata文件和ib_log文件。d.移除所有的InnoDB引擎的表的.frm文件。e.配置文件配置innodb_data_file_path参数。f.重启服务 g.导入mysqldump备份的数据。
对于MySQL8.0: 系统表空间是change buffer(更改缓冲区),doublewrite buffer(双写缓冲区)的存储区域,如果表在系统表空间中创建,可能还包含表和索引数据。系统表空间可以有一个或多个数据文件。在MySQL8.0中,InnoDB将元数据存储在MySQL数据字典中,从MySQL8.0.20开始,doublewrite buffer(双写缓冲区)被划分到单独的双写文件。对于系统表空间大小变更,MySQL8.0中增加系统表空间的大小方式和MySQL5.7一样,不同的是,不支持减小已存在的系统表空间的大小,只能通过备份数据恢复到一个新的拥有更小系统表空间配置的MySQL实例方式实现。
另外,InnoDB存储引擎现在使用MySQL数据字典,而不是自己特定的数据字典。还有,mysql系统表和数据字典表现在在mysql数据目录中的一个名为mysql.ibd的InnoDB表空间文件中创建,而之前这些表是在mysql数据库目录中的各个InnoDB表空间文件中创建的。
需要注意的是,无论MySQL5.7还是MySQL8.0,对存在于系统表空间(或者通用表空间)中的表执行truncate或者drop操作并不会释放归还磁盘空间到操作系统,因此,选择独立表空间更多了一个理由。
mysql> show variables like "%innodb_data_file_path%";
+-----------------------+----------------------+
| Variable_name | Value |
+-----------------------+----------------------+
| innodb_data_file_path | ibdata:2G:autoextend |
+-----------------------+----------------------+
1 row in set (0.01 sec)
#MySQL8.0:
-rw-r----- 1 mysql mysql 393216 Jun 12 14:58 '#ib_16384_0.dblwr'
-rw-r----- 1 mysql mysql 8781824 Jun 12 14:56 '#ib_16384_1.dblwr'
-rw-r----- 1 mysql mysql 1073741824 Jun 12 14:56 ibdata1
从上面可以看出,对于MySQL8.0,doublewrite buffer已经默认为独立的文件了,然后,之前提到系统表空间膨胀通过mysqldump进行恢复,这里思考一个问题问题,一般我们恢复数据库时更偏向于使用xtrabackup工具,尤其数据量比较大的话,mysqldump逻辑恢复的时间相对于xtrabackup工具物理恢复的时间长很多,那这里为什么不提xtrabackup工具呢,来看一下xtrabackup拷贝的文件内容就知道了。
[root@localhost 2024-03-06_14-55-03]# ll
total 2367528
-rw------- 1 root root 496 Mar 6 14:55 backup-my.cnf
-rw------- 1 root root 15269 Mar 6 14:55 ib_buffer_pool
-rw------- 1 root root 1073741824 Mar 6 14:55 ibdata1
drwx------ 2 root root 4096 Mar 6 14:55 my_test
-rw------- 1 root root 192937984 Mar 6 14:55 undo001
-rw------- 1 root root 1065353216 Mar 6 14:55 undo002
-rw------- 1 root root 92274688 Mar 6 14:55 undo003
-rw------- 1 root root 70 Mar 6 14:55 xtrabackup_binlog_info
-rw------- 1 root root 147 Mar 6 14:55 xtrabackup_checkpoints
-rw------- 1 root root 683 Mar 6 14:55 xtrabackup_info
-rw------- 1 root root 2560 Mar 6 14:55 xtrabackup_logfile
这里是不是明白了,xtrabackup工具除了拷贝数据文件外,还会拷贝原实例的ib_buffer_pool(InnoDB缓存池文件)文件,ibdata1(系统表空间)文件,undo日志文件,xtrabackup_logfile(redo日志)文件,因此,xtrabackup工具并不能解决实例的系统表空间膨胀问题。所以独立表空间操作,分离undo日志文件,以及MySQL8.0的doublewrite buffer文件也单独划分,这一系列都是为了系统表空间减负。
工厂招人时有长期工和临时工,MySQL中也有长期表和临时表区分,临时表存储的空间成为临时表空间。对于MySQL5.7和MySQL8.0,临时表空间也进行了较大的变动。
对于MySQL5.7: 非压缩的,用户创建的临时表和磁盘上的内部临时表是在共享的临时表空间中创建的,innodb_temp_data_file_path变量定义临时表空间数据文件的相对路径,如果未指定,则默认在innodb_data_home_dir目录中创建一个名为ibtmp1的自动扩展数据文件,文件大小略大于12MB,共享临时表空间消除了为每个临时表创建和删除每个表空间文件的相关性能成本,不再需要将临时表元数据保存到InnoDB系统表中。压缩的临时表是使用row_format=compressed属性创建的临时表,在临时文件目录中以独立表空间形式创建。
对于MySQL8.0: Innodb使用会话临时表空间和全局临时表空间。当用户手动或优化器自动创建磁盘上的存储引擎为InnoDB的内部临时表时,使用会话临时表空间,从MySQL8.0.16开始,磁盘内部临时表存储引擎为InnoDB,之前由参数internal_tmp_disk_storage_engine值决定。
会话临时表空间是在第一次请求创建磁盘上临时表时从临时表空间池中分配给会话的,一个会话最多分配两个表空间,一个用于用户创建的临时表,另一个用于优化器创建的内部临时表,分配给会话的临时表空间用于会话创建的所有磁盘临时表,当会话断开连接时,其占用的临时表空间将会被截断释放回池,启动服务器时,会创建一个由10个临时表空间组成的池,池大小不会缩小,且会根据需要自动将表空间添加到池中,会话临时表空间文件创建时大小为五页,文件扩展名为.ibt。全局临时表空间存储对用户创建的临时表所作更改的回滚段。innodb_temp_data_file_path变量记录全局临时表空间数据文件的信息。即使版本不同,临时表空间在正常关闭或中止初始化时会被删除,并在每次启动服务器时重新创建,服务器意外停止时不会删除临时表空间,可以手动删除或重启服务,MySQL会自动删除并重建临时表空间。如果想要回收临时表空间数据文件占用的磁盘空间,需要重新启动MySQL服务器。为了防止临时数据文件过大,可以配置innodb_temp_data_file_path变量以指定最大文件大小。
#临时表空间参数
mysql> show variables like "%innodb_temp_data%";
+----------------------------+-------------------------------+
| Variable_name | Value |
+----------------------------+-------------------------------+
| innodb_temp_data_file_path | ibtmp1:12M:autoextend:max:50G |
+----------------------------+-------------------------------+
1 row in set (0.00 sec)
#
MySQL8.0临时表空间
[root@localhost data3316]# cd '#innodb_temp'
[root@localhost #innodb_temp]# ll
-rw-r----- 1 mysql mysql 81920 Jun 14 18:27 temp_10.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_1.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_2.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_3.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_4.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_5.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_6.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_7.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_8.ibt
-rw-r----- 1 mysql mysql 81920 Jun 7 10:45 temp_9.ibt
除了临时表空间文件,还需要注意的是临时目录,对应的参数为tmpdir,默认情况下为/tmp,以下场景下会使用tmpdir目录:
某些语句MySQL会创建不隐藏的临时SQL表,表名称以#SQL开头。部分SELECT查询会创建临时SQL表保存中间结果。对于会重建表的online ddl操作,在创建索引期间,会将临时排序文件写入到MySQL的临时目录。MySQL写binlog临时文件。
mysql> show variables like "%tmp%";
+----------------------------------+---------------------+
| Variable_name | Value |
+----------------------------------+---------------------+
| default_tmp_storage_engine | InnoDB |
| innodb_tmpdir | |
| internal_tmp_disk_storage_engine | InnoDB |
| max_tmp_tables | 32 |
| slave_load_tmpdir | /opt/mysql/tmp/3310 |
| tmp_table_size | 67108864 |
| tmpdir | /opt/mysql/tmp/3310 |
+----------------------------------+---------------------+
7 rows in set (0.01 sec)
mysql> show variables like "%binlog_cache%";
+-----------------------+----------------------+
| Variable_name | Value |
+-----------------------+----------------------+
| binlog_cache_size | 1048576 |
| max_binlog_cache_size | 18446744073709547520 |
+-----------------------+----------------------+
2 rows in set (0.00 sec)
对于max_binlog_cache_size参数,限制binlog cache的大小,源码中对应的写binlog临时文件可以看出,但是64位操作系统下max_binlog_cache_size默认值为一个很大很大的值,因此基本上就相当于无限制了,而如果恰好MySQL的tmpdir使用的是默认值,当触发上面场景时,如果表数据量较大,则可能会导致/根目录满,最终引发服务器宕机:
if (!cache_mngr)
{
DBUG_RETURN(1);
}
if (open_cached_file(&stmt_cache_log, mysql_tmpdir,
LOG_PREFIX, binlog_stmt_cache_size, MYF(MY_WME)))
{
my_free(cache_mngr);
DBUG_RETURN(1); // Didn't manage to set it up
}
if (open_cached_file(&trx_cache_log, mysql_tmpdir,
LOG_PREFIX, binlog_cache_size, MYF(MY_WME)))
{
close_cached_file(&stmt_cache_log);
my_free(cache_mngr);
DBUG_RETURN(1);
}
DBUG_PRINT("debug", ("Set ha_data slot %d to 0x%llx", binlog_hton->slot, (ulonglong) cache_mngr));
thd_set_ha_data(this, binlog_hton, cache_mngr);
cache_mngr= new (thd_get_cache_mngr(this))
binlog_cache_mngr(max_binlog_stmt_cache_size,
&binlog_stmt_cache_use,
&binlog_stmt_cache_disk_use,
max_binlog_cache_size,
&binlog_cache_use,
&binlog_cache_disk_use,
stmt_cache_log,
trx_cache_log);
DBUG_RETURN(0);
}
因此,对临时表空间和临时目录方面的建议有以下几点: 1.设置tmpdir目录为其他目录而不是默认/tmp目录。2.尽可能避免达大事务操作,例如大表全表更新。3.限制max_binlog_cache_size值,从侧面限制事务大小,本身大事务就可能会引发主从延时问题,另外,如果事务过大的话,主从同步中可能会引发心跳问题,具体可以看看黄炎老师一问一实验的第29讲。
除了系统表空间,undo日志,临时表文件可能会出现膨胀之外,如果业务写入量过大,而binlog日志过期时间设置过长的话也可能会导致占用空间大。
binlog过期时间并不是达到预定的时间点就会立即进行清理,而是会有一个触发机制,满足以下任一条件才会按照时间点进行逻辑判断是否清理: 1.binlog大小超过max_binlog_size,但是一个事务不会写两个binlog,因此如果遭遇大事务,binlog是可能会超过max_binlog_size很多的。2.手动执行flush logs。3.重新启动时,此时mysql将会new一个新文件用于记录binlog。
另外,很不错的一点是,相对于MySQL5.7,MySQL8.0的过期时间粒度更小,之前是以天为单位,现在是秒。
#MySQL5.7:
mysql> show variables like "%expire%";
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| disconnect_on_expired_password | ON |
| expire_logs_days | 7 |
+--------------------------------+-------+
2 rows in set (0.00 sec)
#MySQL8.0:
mysql> show variables like "%expire%";
+--------------------------------+---------+
| Variable_name | Value |
+--------------------------------+---------+
| binlog_expire_logs_auto_purge | ON |
| binlog_expire_logs_seconds | 2592000 |
+--------------------------------+---------+
3 rows in set (0.01 sec)
值得一提的是,redo文件虽然不至于导致空间膨胀,但是因为redo日志是循环写,如果业务写入量比较大,而恰好redo日志设置比较小的话,会导致在物理备份时由于redo日志被覆盖而恢复失败,在MySQL5.7中,redo日志不支持在线修改,这对于生产环境来说增加了很多麻烦,而在MySQL8.0.30及其以后,MySQL引入了innodb_redo_log_capacity参数,支持了在线修改redo日志容量,这对业务来说相对更加友好。
#MySQL5.7:
mysql> show variables like "%innodb_log_file%";
+---------------------------+------------+
| Variable_name | Value |
+---------------------------+------------+
| innodb_log_file_size | 2147483648 |
| innodb_log_files_in_group | 2 |
+---------------------------+------------+
2 rows in set (0.00 sec)
#MySQL8.0.30及以后:
mysql> show variables like "%innodb_redo_log_capacity%";
+--------------------------+-----------+
| Variable_name | Value |
+--------------------------+-----------+
| innodb_redo_log_capacity | 104857600 |
+--------------------------+-----------+
1 row in set (0.00 sec)
mysql> set global innodb_redo_log_capacity=2147483648;
Query OK, 0 rows affected (0.01 sec)
[root@localhost data3316]# cd '#innodb_redo'
[root@localhost #innodb_redo]# ll
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo59'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo60_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo61_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo62_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo63_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo64_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo65_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo66_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo67_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo68_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo69_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo70_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo71_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo72_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo73_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo74_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo75_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo76_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo77_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo78_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo79_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo80_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo81_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo82_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo83_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo84_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo85_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo86_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo87_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo88_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo89_tmp'
-rw-r----- 1 mysql mysql 67108864 Jun 30 11:32 '#ib_redo90_tmp'
redo日志文件位于#innodb_redo目录中。有两种类型的redo日志文件,普通和备用。正在使用的是普通的redo日志文件。备用redo日志文件是那些等待使用的文件。InnoDB尝试总共维护32个redo日志文件,每个文件的大小等于1/32*InnoDB_redo_log_cability。
又到了本篇的结尾,按照惯例,小结一下,从系统表空间,undo表空间以及临时表空间等等,可以看出MySQL8.0相对MySQL5.7做了很多改进和优化,能有效避免一些问题,尤其对新瘦和小白更加优化,因此,在选择MySQL8.0时,你是不是又多了一些理由。好了,最后,祝小伙伴们周末愉快。(ps:有时间就会及时更新案例的,如果你也热爱学习,也可以后台联系我,彼此就多了一个朋友,哈哈。)
原文作者:DBA修行之路;如有侵权,请联系管理员删除。