pt-archiver在日常运维中的使用

朱康

背景

DBA的日常工作,免不了要对表的数据做清理或者归档,方法多种多样,但是在生产环境,比较安全可行的方法必须既要高效,又要尽可能减少对DB的影响。pt-archiver就是这样的一款归档利器。


原理

pt-archiver工具的原理也非常简单,通过给定的--where条件,查询出表中需要删除或者归档记录的主键信息,然后通过强制主键索引的方式,小批量(最小可以做到1行)的方式删除或者归档,最大化的减小归档或者删除操作对DB性能的影响。


实践

清理命令:

pt-archiver --source h=host,D=db,t=child --purge \  
  --where 'NOT EXISTS(SELECT * FROM parent WHERE col=child.col)'

清理命令必须要指定 --source和--purge选项。

归档命令:

pt-archiver --source h=oltp_server,D=test,t=tbl --dest h=olap_server \  
--where "1=1" --limit 1000 --commit-each

归档命令必须要指定 --source和--dest,当然pt-archiver也支持归档到文件。默认归档命令会删除--source指定的源表中已归档的记录。如果需要保留,必须要指定--no-delete选项。

流程化:

日常使用中,只需要和开发确认归档或者清理表数据的where条件,然后通过定时任务的方式使用pt-archiver在业务低峰执行即可。


总结:

使用pt-archiver的过程中也有一些需要注意的地方,总结成如下几个方面:

  1. 少删除一行的问题:这个问题的一个现象就是,当删除一个有自增id的表时,实际删除的时候,满足where条件的记录中,最大id的那一行没有删掉,导致少删掉一行的奇怪现象。指定--nosafe-auto-increment选项可以规避这个问题。深究这个选项设定的原因,其实是和MySQL长久没有解决的一个bug相关,这个bug直到8.0版本才解决。(细思恐极)
  2. 性能问题:要加快归档或者删除的速度,可以适当提高--limit选项指定的值,并配合--commit-each一起使用,效果更佳;如果只是删除记录的话,--primary-key-only选项在获取表数据的时候,只会提取出主键,能进一步提升性能。
  3. 中止任务:pt-archiver一般运行在低峰,而且是以定时任务的方式运行居多,如何控制在pt-archiver在DB进入高峰之前自动停止呢?答案是--sentinel选项,当pt-archiver工具检测到--sentinel选项指定的文件之后,会优雅的退出中止。
  4. 失败处理:--why-quit能打印出任务失败的原因,方便排查问题。

目前线上大约部署了几十套采用pt-archiver执行的归档或清理任务,运行的非常稳健,久经考验。