技术分享 | MySQL:你的 binlog_expire_logs_seconds 可能正在失效

作者:胡呈清

爱可生 DBA 团队成员,擅长故障分析、性能优化,个人博客:https://www.jianshu.com/u/a95ec11f67a8,欢迎讨论。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。


如果你正在使用 MySQL8.0 ,并且在使用物理热备工具,那么 binlog_expire_logs_seconds 可能不会如你预想的那样生效。

binlog_expire_logs_seconds

为了防止 binlog 文件过大导致无可用的磁盘空间,MySQL 提供了一个系统变量用来配置过期时间,MySQL5.7 时变量名为expire_logs_days,精确度为天;MySQL8.0 使用binlog_expire_logs_seconds来控制,其效果和名字的变化一样,精确度由天变成了秒。超过这个时间的 binlog 会被自动清理,自动清理的触发时机为(注意:并不是以每秒这样的固定频率检查是否有过期日志):

  1. MySQL 启动时;

  2. binlog 刷新时。

MySQL 启动不用多说,binlog 刷新又分两种情况:

  1. 当前的 binlog 大小达到max_binlog_size,写完当前事务的日志后,就会生成一个新的 binlog;

  2. 手工执行了flush [binary] logs; 命令后,也会生成一个新的 binlog。

下面我们来看一个 binlog_expire_logs_seconds 失效的场景。

失效场景&复现步骤

  1. 设置 set global binlog_expire_logs_seconds=60,然后执行几次 flush binary logs 生成多个 binlog(这样我们 60s 之后就可以看到过期的 binlog 是否被自动删除了):

  1. 等 60s 后,运行 xtrabackup 进行备份(我这里直接调的脚本,手工命令完全无影响):

  1. 备份完之后,可以看到刷新了 binlog(xtrabackup 运行过程中有一个步骤会执行FLUSH NO_WRITE_TO_BINLOG BINARY LOGS刷新 binlog),但是没有删除 60s 之前的 binlog:

这是因为 MySQL8.0 为了解决备份时的全局锁问题,新引入了LOCK INSTANCE FOR BACKUP备份锁,而这把锁恰好导致了binlog_expire_logs_seconds的失效,下面两张图说明这个问题:

释放锁再测试,可以正常触发过期 binlog 的自动删除:

总结

如果 MySQL 每天的数据修改很少,产生的 binlog 很小,而max_binlog_size设置很大。每次在达到单个 binlog 的最大大小前,执行定时任务调用 xtrabackup 备份,备份时加的备份锁LOCK INSTANCE FOR BACKUPFLUSH NO_WRITE_TO_BINLOG BINARY LOGS会导致:binlog 刷新了,但是无法自动删除过期的 binlog 。新的 binlog 写一天没有达到最大大小,又进行备份,每天循环这个逻辑,导致过期的 binlog 越来越多,一直无法被自动删除。

当然,如果你使用的是 MySQL5.7,那并不会有这个问题,虽然 MySQL5.7 时备份时会加全局锁,但是并不影响过期 binlog 的自动删除。从这个角度看,这是个 bug,所以报给官方后很快被确认了:https://bugs.mysql.com/bug.php?id=104785

等待修复的过程是漫长的,如果你恰好遇见了这个冷门的 bug,可以把 max_binlog_size调小,保证在备份前 binlog 就能够达到最大大小,自然的刷新可以正常触发自动删除。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,mysql内存参数"binlog_expire_logs_auto_purge"用于控制自动清理(binlog)日志的功能。该参数的作用是设置binlog日志的自动清理功能是否开启。默认情况下,该参数的值为"ON",表示开启自动清理功能。当开启自动清理功能后,系统将会根据"binlog_expire_logs_seconds"参数的设置来自动清理过期binlog日志。 需要注意的是,在MySQL 8.0以下版本中,binlog日志的保存时效是以天为单位,通过"expire_logs_days"参数来设置,默认为0,表示永不过期。而在MySQL 8.0以上版本中,binlog日志的保存时效是以秒为单位,通过"binlog_expire_logs_seconds"参数来设置,默认为2592000秒(30天)。 要对binlog日志进行手动清理,有几种常用的方法。一种是使用"PURGE BINARY LOGS"语句,可以清理指定的binlog文件之前的所有binlog日志。例如: PURGE BINARY LOGS TO 'mysql-bin.000035'; 另一种是使用"PURGE MASTER LOGS"语句,可以清理指定时间点之前的所有binlog日志。例如: PURGE MASTER LOGS BEFORE '2019-09-09 13:00:00'; 通过这些方法,可以手动清理过期binlog日志,从而释放数据库的存储空间。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [mysql8.0设置binlog保存时间,并清除过期日志释放空间](https://blog.csdn.net/Qingyunya/article/details/128395035)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [Mysql数据库清理binlog日志命令详解](https://download.csdn.net/download/weixin_38687277/14907673)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值