作者:孙桥,爱可生华东交付服务部 DBA 成员,主要负责 MySQL 故障处理及相关技术支持。爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。
本文约 800 字,预计阅读需要 3 分钟。
一、背景在客户得生产环境中,数据表占用了大量得磁盘资源。主机上很多 ibd 文件都比较大,但是登录数据库查看,却发现表数据都是空的?
起初推测是这些表在做归档操作,最后没有做表碎片化整理导致的,但通过 binlog 分析得知,并没有发现大量 DELETE 操作。再通过开启并分析general log 日志发现,应用侧每天都会在凌晨时使用 insert into .. select * from xx 的 SQL 对前一天的数据大表进行备份。
由于数据库配置 max_binlog_cache_size[1] 参数限制,导致数据插入过程中达到 max_binlog_cache_size 最大值时出现事务回滚情况,但表空间没有得到释放。
以下是该问题现象的简单演示。
二、问题演示通过 sysbench 工具创建 1 张 1000W 行的测试源表 sbtest1,并通过数据库命令查看表空间的占用大小。
代码语言:javascript代码运行次数:0运行复制mysql> select count(*) from test.sbtest1;
+----------+
| count(*) |
+----------+
| 10000000 |
+----------+
1 row in set (4.17 sec)
mysql> selectname,FILE_SIZE/1024/1024/1024as GB from information_schema.INNODB_TABLESPACES wherename='test/sbtest1';
+--------------+----------------+
| name | GB |
+--------------+----------------+
| test/sbtest1 | 2.269531250000 |
+--------------+----------------+
1 row in set (0.00 sec)
配置参数 max_binlog_cache_size 的大小。
代码语言:javascript代码运行次数:0运行复制mysql> set global max_binlog_cache_size=1*1024*1024*1024;
Query OK, 0 rows affected (0.00 sec)
mysql> select @@max_binlog_cache_size;
+-------------------------+
| @@max_binlog_cache_size |
+-------------------------+
| 1073741824 |
+-------------------------+
1 row in set (0.00 sec)
手工模拟应用侧备份操作,将源表 sbtest1 数据备份到 t1 表中。
代码语言:javascript代码运行次数:0运行复制mysql> create table test.t1 like test.sbtest1;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into test.t1 select * from test.sbtest1;
ERROR 1197 (HY000): Multi-statement transaction required more than 'max_binlog_cache_size' bytes of storage; increase this mysqld variable and try again
查看 t1 表时,发现表中没有数据,但还是占用比较大的表空间。
代码语言:javascript代码运行次数:0运行复制mysql> select count(*) from test.t1;
+----------+
| count(*) |
+----------+
| 0 |
+----------+
1 row in set (0.00 sec)
mysql> selectname,FILE_SIZE/1024/1024/1024as GB from information_schema.INNODB_TABLESPACES wherename='test/t1';
+---------+----------------+
| name | GB |
+---------+----------------+
| test/t1 | 1.339843750000 |
+---------+----------------+
1 row in set (0.00 sec)
三、问题解决临时解决方法根据需要表数据大小,临时调大 max_binlog_cache_size 配置大小,让应用侧能正常完成数据备份。
长期解决方法针对于以上场景的数据备份,应用侧每天将新数据写入以日命名的新表中,这样可以减少数据库的压力和对内存的消耗。
四、总结在日常数据库的维护过程中,要注意合理配置及调整系统参数的配置,和减少一定量的大事务使用。需要我们制定一套数据库标准使用手册,并告知研发侧同学该如何更好地使用数据库。避免因为不当使用方式,给双方人员造成不必要的麻烦和财产损失。
五、max_binlog_cache_size 说明https://dev.mysql.com
该参数用于控制事务 SQL 执行时需要使用的最大内存大小。在 32 位操作系统,该参数默认为 4G;64 位操作系统上,该参数默认为 16E。
在 MySQL 数据库实例未开启 GTID 时,建议配置的最大值不要超过 4G;在开启 GTID 后,不需要明确限制其最大值。
参考资料
[1]
max_binlog_cache_size: https://dev.mysql.com/doc/refman/8.0/en/replication-options-binary-log.html#sysvar_max_binlog_cache_size
本文关键字:#MySQL #binlog