磁盘告警在凌晨两点响,头一回遇到容易当成数据暴涨,其实是日志没清。/var/lib/mysql里八成的空间是mysql-bin开头的一串文件,业务库的真实数据只占很小一部分。
binlog记录所有改变数据的语句或者行,主从复制靠它传,按时间点恢复也靠它。只要开了log-bin,每一条写入都会落一份。业务量大的库一天写几十个G很正常。
过期时间在两个大版本之间不一样。8.0默认保留三十天,参数叫binlog_expire_logs_seconds,值是2592000,也就是两百五十九万二千秒。5.7默认不过期,expire_logs_days为0,等于一直留着,不清就一直涨。
你先看清有哪些文件,SHOW BINARY LOGS列出全部,带大小。哪一天的量突然变大,对着文件名的序号和大小能看出来,比如某天做过一次批量导入,那天的文件会比平时大好几倍。
不能直接rm。目录里有个mysql-bin.index,记着当前有哪些文件,删了文件不改索引,重启时MySQL找不到会报错,主从也会断。索引文件本身不要动,PURGE会同步维护它。
安全清理用PURGE BINARY LOGS,两种写法,TO后面跟文件名删到这个文件之前,BEFORE后面跟时间删到这个时间之前。执行前先在从库上看SHOW SLAVE STATUS,Relay_Master_Log_File这一项之前的文件才能删;8.0.22起这个命令也能写成SHOW REPLICA STATUS。开了GTID的(全局事务编号),在从库上看gtid_executed,和主库的gtid_executed比一下,差得远说明从库落后,这时候删日志会把复制的路截断,从库得重做全量。没有从库也不能随手删,PURGE到的位置要早于最近一次全量备份的起点,否则按时间点恢复会缺一段。备份文件也要看一眼,别只剩空壳,恢复时才发现。
根治有三条路。把binlog_expire_logs_seconds调小,按备份周期定,七天或十四天,改完写进配置文件,SET GLOBAL只在当前实例生效。8.0.20以后可以开binlog_transaction_compression,事务日志压缩后体积通常能降一半以上,代价是CPU多花一点。磁盘实在不够就加盘,用log-bin=/data/mysql-bin/mysql-bin把前缀指到另一块盘。
从库那边还有relay log,它落在datadir下,名字以relay-bin开头;relay_log_purge默认是开的,应用完就删,一般不会堆积到告警。慢查询日志和通用日志如果开着,量也不小,顺手一起看。
每秒几千次写入,一天下来就是几十个G,做容量规划要按峰值算,不能按均值。这个量级下binlog保留七天就是两百多G,规划磁盘的时候要把这部分单独算进去,别只按数据文件估。
保留期设成十四天,事务压缩开着,binlog单独放一块五百G的盘。清理脚本每天凌晨跑一次PURGE,执行前先查从库位点,位点落后就跳过并告警。这套跑了两个月,磁盘占用稳在一百八十G上下,没有再报过警。
A5创业网 版权所有