Mysql 清理 bin log 、relay log
MySQL 通过 binlog 和 relay log 进行主从数据的同步,binlog 由主库产生,从库通过复制 IO 线程拉取 binlog,写入到 relay log 中,sql 线程读取 relay log 中的事务信息,并进行应用,实现数据库的主从同步。
正常情况下,binlog 和 relay log 并不需要人为干预删除,但是在某些场景下,比如数据写入量大,磁盘空间小,binlog 保留的时间设置的过长,这时候就需要人工清理 binlog。
bin log 删除方式
1、自动删除,删除 3 天之前生成的 binlog
a,修改 my.cnf 参数, 添加参数 expire_logs_days = 3,单位是天。
b,该参数支持动态修改,方法如下:
1 2 |
mysql> show variables like '%expire%'; mysql> set global expire_logs_days=3; |
2、手工删除
1 2 |
show master status show slave status\G |
mysql binlog 删除命令 purge 格式:
mysql>help purge;
Name: 'PURGE BINARY LOGS' Description: Syntax:
PURGE { BINARY | MASTER } LOGS { TO 'log_name' | BEFOREdatetime_expr }
Examples: PURGE BINARY LOGS TO 'mysql-bin.010';
PURGE BINARY LOGS BEFORE '2008-04-02 22:46:26';
1 2 3 4 5 6 |
#按文件名删除 log mysql>purge binary logs to 'mysql-bin.005522'; #按日期删除 log purge master logs before '2020-07-26 00:00:00'; purge master logs before now() - INTERVAL 3 day; |
这样我们就可以删除一些特定的 binlog 日志,并将 mysql-bin.index 中对应路径删除,切勿删除正在使用的 binlog。
在极端情况下,如果 binlog 已经把磁盘写满,这时候连接到 MySQL 执行清除 binlog 的命令会被卡住,那么只能手动删除 binlog 物理文件了,但是这样并不会更新 mysql-bin.index,先尝试删除最旧的几个 binlog 文件,然后再连接到 MySQL,执行清除 binlog 的命令。
1 2 3 |
rm -rf mysql-bin.00040*; vim mysql-bin.log.index 清除掉里面的mysql-bin.0004**纪录 |
BINLOG 文件生成与删除
binlog 文件生成:
在每条二进制日志写入到日志文件后,会判断该文件是否超过 max_binlog_size,如果超过则生成一个新的 binlog
binlog 文件删除:
1>当使用 RESET MASTER命令后,会清空全部二进制日志
命令:RESET MASTER;
reset master:
也会清除已执行的 gtid 相关信息,这个操作会立即导致从库复制中断,除非你真的了解这个命令的作用,否则慎用,也不推荐使用这个命令删除binlog文件。
2>当执行 PURGE MASTER LOG TO 命令后,会删除指定 binlog 以及之前的二进制日志
命令:PURGE MASTER LOGS TO 'binlog file name';
3>当执行 PURGE MASTER LOG BEFORE 命令后,会删除指定时间前的所有二进制
命令:PURGE MASTER LOGS TO 'datetime';
4>当实例启动或执行 flush logs 时,按照 expire_logs_days 设置,如果超过该参数指定天数的二进制会被全部删除
命令:mysqladmin flush-log
清理 binlog文件顺序:
先从文件系统中清理文件, 再修改索引文件。
RELAY LOG 生产与删除
relay log通常不需要人工清理,因为从库的复制线程在应用完relay log中的事务后,会自动把relay log删除。每次复制的IO线程重启,都会生成一个新的relay log,每个relay log文件的大小由参数max_relay_log_size控制,该参数默认为0,即表示其大小和binlog文件大小一致,通常也为1G。
从库上有些命令,也会导致relay log文件被清除,比如:reset slave 和 reset slave all。这两个命令会将relay log文件全部删除,并且生成新的索引从1开始的relay log文件。
Relay Log rotate 机制:
Rotate:每从 Master fetch 一个 events 后,判断当前文件是否超过 max_relay_log_size 如果超过则自动生成一个新的 relay-log-file
Delete: purge-relay-log 在 SQL Thread 每执行完一个 events 时判断,如果该 relay-log 已经不再需要则自动删除
Delete: expire-logs-days 只在 实例启动时 和 flush logs 时判断,如果文件访问时间早于设定值,则purge file (同 Binlog file) (updated: expire-logs-days 和 relaylog 的 purge 没有关系)
PS:因此还是建议配置 expire-logs-days , 否则当我们的外部脚本因意外而停止时,还能有一层保障。
MySQL数据库主从复制在缺省情况下从库的relay logs会在SQL线程执行完毕后被自动删除,但是对于MHA场景下,对于某些滞后从库的恢复依赖于其他从库的relay log,因此采取禁用自动删除功能以及定期清理的办法。对于清理过多过大的relay log需要注意引起的复制延迟资源开销等。MHA可通过purge_relay_logs脚本及配合cronjob来完成此项任务,具体描述如下。
在 ext3 的文件系统下,删除大的文件需要一定的时间,会导致严 重的复制延时。为了避免复制延时,需要暂时为中继日志创建硬链接,因为在 linux 系统中通过硬链接删除大文件速度会很快。(在 mysql 数据库中,删除大表时,通常也采用建立硬链接的方式)
情景
MySQL 数据库主从复制在默认情况下从库的 relay logs 会在 SQL 线程执行完毕后被自动删除。但是:在relay_log_purge = 0和MHA 集群下,不会被自动删除,需要手动删除。如何安全的删除 relay logs 就比较关键了!
主要有两种方式:
方式一:
通过MHA中自带的工具 purge_relay_logs 工具来删除。
(1) purge_relay_logs 工具包括三个功能,它可以为中继日志创建硬链接,执行SET GLOBAL relay_log_purge=1,等待几秒钟以便SQL线程切换到新的中继日志,再执行SET GLOBAL relay_log_purge=0,删除 relay log 硬连接数据。
a、为relay日志创建硬链接(最小化批量删除大文件导致的性能问题)
b、SET GLOBAL relay_log_purge=1; FLUSH LOGS; SET GLOBAL relay_log_purge=0;
c、删除relay log(rm –f /path/to/archive_dir/*)
purge_relay_logs的用法及相关参数:
1 2 3 4 5 |
--user mysql 用户名 --password mysql 密码 --port 端口号 --workdir 指定创建relay log的硬链接的位置,默认是/var/tmp,由于系统不同分区创建硬链接文件会失败,故需要执行硬链接具体位置,成功执行脚本后,硬链接的中继日志文件被删除 --disable_relay_log_purge 默认情况下,如果relay_log_purge=1,脚本会什么都不清理,自动退出,通过设定这个参数,当relay_log_purge=1的情况下会将relay_log_purge设置为0。清理relay log之后,最后将参数设置为OFF。 |
(2)设置定期清理relay脚本(每台slave服务器),pureg_relay_logs 脚本在不阻塞 SQL 线程的情况下自动清理 relay log。对于不断产生的 relay log 直接将该脚本部署到 crontab 以实现按天或按小时定期清理。
1 2 3 4 5 |
$ crontab -l #purge relay logs at 5am 0 5 * * * /usr/bin/purge_relay_logs --user=root --password=PASSWORD --disable_relay_log_purge >> /var/log/masterha/purge_relay_logs.log 2>&1 |
(3)手动清理示例。purge_relay_logs脚本删除中继日志不会阻塞SQL线程。下面我们手动执行看看什么情况。
1 2 3 4 5 6 7 8 9 10 11 12 |
[root@10.142.132.47 ~]# purge_relay_logs --user=root --password=123456 --port=3306 -disable_relay_log_purge --workdir=/data/ 2014-04-20 15:47:24: purge_relay_logs script started. Found relay_log.info: /data/mysql/relay-log.info Removing hard linked relay log files server03-relay-bin* under /data/.. done. Current relay log file: /data/mysql/server03-relay-bin.000002 Archiving unused relay log files (up to /data/mysql/server03-relay-bin.000001) ... Creating hard link for /data/mysql/server03-relay-bin.000001 under /data//server03-relay-bin.000001 .. ok. Creating hard links for unused relay log files completed. Executing SET GLOBAL relay_log_purge=1; FLUSH LOGS; sleeping a few seconds so that SQL thread can delete older relay log files (if it keeps up); SET GLOBAL relay_log_purge=0; .. ok. Removing hard linked relay log files server03-relay-bin* under /data/.. done. 2014-04-20 15:47:27: All relay log purging operations succeeded. |
方式二:
手动删除 relay log
1.设置relay_log_purge = 1
1 |
SET GLOBAL relay_log_purge = 1 |
2.flush logs
通过管理员用户登陆从数据库,然后执行下面命令:
1 |
flush logs; |
可以执行多次!
注意:
观察堆积的relay logs日志是否已经删除,如果删除,直接执行下面第6步“恢复relay_log_purge = 0“;如果未删除,继续从下面第3步”停止slave“往下操作!!!
3.停止slave
通过管理员用户登陆从数据库,然后执行下面命令:
1 |
stop slave; |
4.删除relay logs
可以通过rm直接删除relay logs
通使用下面方式安全删除:
(1) 统计所有关于relay的文件(包括 relay_log_name.index)总个数
1 |
ls -A1 |grep relay | sort -rn | wc -l |
(2) 列出要删除所有有关relay的文件:
1 |
ls -A1 |grep relay | sort -rn | tail -n 100 |
说明: 100 为要删除的relay logs 数量
(3) 确定没有问题,删除relay logs:
1 |
ls -A1 |grep relay | sort -rn | tail -n 100 | xargs rm -rf {} |
注意:
要保留最新的两个relay log
要保留relay log的index文件
relay log的index一般命名为: relay_log_name.index
例如: relay-bin.index
5. 启动slave
通过管理员用户登陆从数据库,然后执行下面命令:
1 |
start slave; |
6 . 恢复relay_log_purge = 0
通过管理员用户登陆从数据库,然后执行下面命令:
1 |
SET GLOBAL relay_log_purge=0; |
扩展
如果你对从数据库要求不高,可以将relay_log_purge = 1