Pt-archiver清理Mariadb旧数据实践案例

环境信息

机器IP 组件描述 组件版本 环境信息
10.13.240.254 pt-archiver 3.6.0 服务机
10.13.222.3 Mariadb 10.6.21 数据库

安装pt-archiver

复制代码
# 安装 Percona 官方仓库
sudo yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm

# 启用 Percona Toolkit 仓库
sudo percona-release enable tools release

# 安装 Percona Toolkit
sudo yum install percona-toolkit

# 查看版本
pt-archiver --version

# 查看帮助
pt-archiver --help

清理数据脚本

复制代码
#!/bin/bash

# =====================================================
# 分库分表数据清理脚本 - 直接使用你的元数据表
# 数据来源:你提供的表信息
# =====================================================

# 连接信息配置
HOST="10.13.222.3"
PORT="3306"
USER="xxx"
PASSWORD="xxx"
CHARSET="utf8mb4"

# 清理参数配置
WHERE_CONDITION="ctime < '2025-01-01'"
LIMIT=1000
TXN_SIZE=500
SLEEP=1
PROGRESS=100000

# 日志配置
LOG_DIR="/var/log/pt-archiver"
DATE=$(date +%Y%m%d_%H%M%S)
LOG_FILE="${LOG_DIR}/cleanup_${DATE}.log"
SUMMARY_FILE="${LOG_DIR}/summary_${DATE}.txt"

# 创建日志目录
mkdir -p ${LOG_DIR}

echo "开始清理任务 - $(date)" | tee -a ${LOG_FILE}
echo "清理条件: ${WHERE_CONDITION}" | tee -a ${LOG_FILE}
echo "==================================" | tee -a ${LOG_FILE}

# =====================================================
# 直接从你提供的数据生成表列表
# 格式:database_name.table_name_table_number
# =====================================================

# 生成所有表的完整名称(映射关系)
TABLES=(
    "database_0.table_0"
    "database_1.table_1"
    "database_2.table_2"
    "database_3.table_3"

)

# 计数器
TOTAL_TABLES=${#TABLES[@]}
SUCCESS_COUNT=0
FAIL_COUNT=0
TOTAL_DELETED=0
CURRENT=0

echo "总共需要处理 ${TOTAL_TABLES} 张表" | tee -a ${LOG_FILE}
echo "==================================" | tee -a ${LOG_FILE}

# 开始时间
START_TIME=$(date +%s)

# 遍历所有表
for TABLE in "${TABLES[@]}"; do
    CURRENT=$((CURRENT + 1))

    # 拆分数据库名和表名
    DB=$(echo $TABLE | cut -d'.' -f1)
    TB=$(echo $TABLE | cut -d'.' -f2)

    echo "[${CURRENT}/${TOTAL_TABLES}] 处理表: ${DB}.${TB} - $(date)" | tee -a ${LOG_FILE}

    # 检查表是否存在
    TABLE_EXISTS=$(mysql -h${HOST} -P${PORT} -u${USER} -p${PASSWORD} -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='${DB}' AND table_name='${TB}'" 2>/dev/null)

    if [ "${TABLE_EXISTS}" -eq 0 ]; then
        echo "⚠️ 表 ${DB}.${TB} 不存在,跳过" | tee -a ${LOG_FILE}
        continue
    fi

    # 统计要删除的数据量
    COUNT=$(mysql -h${HOST} -P${PORT} -u${USER} -p${PASSWORD} -D${DB} -N -e "SELECT COUNT(*) FROM ${TB} WHERE ${WHERE_CONDITION}" 2>/dev/null)
    echo "待删除数据: ${COUNT} 行" | tee -a ${LOG_FILE}

    if [ "${COUNT}" -gt 0 ]; then
        # 执行清理
        pt-archiver \
            --source h=${HOST},P=${PORT},u=${USER},p=${PASSWORD},D=${DB},t=${TB} \
            --purge \
            --where "${WHERE_CONDITION}" \
            --limit ${LIMIT} \
            --txn-size ${TXN_SIZE} \
            --sleep ${SLEEP} \
            --progress ${PROGRESS} \
            --statistics \
            --no-check-charset \
            --why-quit \
            --charset ${CHARSET} \
            >> ${LOG_FILE} 2>&1

        # 检查执行结果
        if [ $? -eq 0 ]; then
            echo "✅ 表 ${DB}.${TB} 清理成功,删除 ${COUNT} 行" | tee -a ${LOG_FILE}
            SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
            TOTAL_DELETED=$((TOTAL_DELETED + COUNT))
        else
            echo "❌ 表 ${DB}.${TB} 清理失败" | tee -a ${LOG_FILE}
            FAIL_COUNT=$((FAIL_COUNT + 1))
        fi
    else
        echo "表 ${DB}.${TB} 没有需要清理的数据" | tee -a ${LOG_FILE}
        SUCCESS_COUNT=$((SUCCESS_COUNT + 1))
    fi

    # 每张表之间添加短暂间隔
    sleep 1
done

# 计算耗时
END_TIME=$(date +%s)
DURATION=$((END_TIME - START_TIME))

# 输出汇总信息
echo "==================================" | tee -a ${LOG_FILE} ${SUMMARY_FILE}
echo "清理完成 - $(date)" | tee -a ${LOG_FILE} ${SUMMARY_FILE}
echo "总处理表数: ${TOTAL_TABLES}" | tee -a ${LOG_FILE} ${SUMMARY_FILE}
echo "成功表数: ${SUCCESS_COUNT}" | tee -a ${LOG_FILE} ${SUMMARY_FILE}
echo "失败表数: ${FAIL_COUNT}" | tee -a ${LOG_FILE} ${SUMMARY_FILE}
echo "总计删除行数: ${TOTAL_DELETED}" | tee -a ${LOG_FILE} ${SUMMARY_FILE}
echo "总耗时: ${DURATION} 秒" | tee -a ${LOG_FILE} ${SUMMARY_FILE}

echo "详细日志请查看: ${LOG_FILE}"
echo "汇总信息请查看: ${SUMMARY_FILE}"

参数解释

1. --source - 数据源连接
bash 复制代码
--source h=${HOST},P=${PORT},u=${USER},p=${PASSWORD},D=${DB},t=${TB}

h: 数据库主机IP

P: 端口号

u: 用户名

p: 密码

D: 数据库名

t: 表名

2. --purge - 只删除,不归档
bash 复制代码
--purge

作用: 只删除数据,不同时归档到其他表

不加的话: 默认会尝试将删除的数据插入到 --dest 指定的表

适用场景: 直接清理过期数据,不需要备份

3. --where - 删除条件
bash 复制代码
--where "ctime < '2025-01-01'"

作用: 指定要删除哪些数据

实际执行:

sql 复制代码
-- 每次循环实际执行的查询
SELECT * FROM table WHERE ctime < '2025-01-01' ORDER BY id LIMIT ${LIMIT}

⚠️ 重要: ctime字段必须有索引,否则全表扫描

4. --limit - 每批获取的行数
bash 复制代码
--limit 2000

作用: 每次 SELECT 查询获取多少行

执行流程:

bash 复制代码
第1批: SELECT ... LIMIT 2000
第2批: SELECT ... WHERE id > 上一批最大id LIMIT 2000
第3批: SELECT ... WHERE id > 第二批最大id LIMIT 2000
...
5. --txn-size - 事务大小
bash 复制代码
--txn-size 500

作用: 每删除多少行提交一次事务

执行流程:

bash 复制代码
BEGIN;
DELETE WHERE id = 1;  # 第1条
DELETE WHERE id = 2;  # 第2条
...                   # 直到500条
COMMIT;               # 提交

为什么小于limit: 即使一批获取2000条,也分成4次事务提交,避免大事务

6. --sleep - 休眠时间
bash 复制代码
--sleep 1

作用: 每批数据处理完成后,暂停1秒

目的:

  • 给主从复制留出同步时间
  • 降低磁盘IO压力
  • 让数据库有喘息机会

7. --progress - 进度显示

bash 复制代码
--progress 100000

作用: 每处理10万行输出一次进度

输出示例:

bash 复制代码
pt-archiver: 100000 rows affected (1.2 sec)
pt-archiver: 200000 rows affected (2.5 sec)
pt-archiver: 300000 rows affected (3.8 sec)
8. --statistics - 统计信息
bash 复制代码
--statistics

作用: 结束时输出详细统计信息

输出示例:

bash 复制代码
Started at 2024-01-15T10:00:00, ended at 2024-01-15T10:30:00
Source: D=test,t=users
SELECT 50000 rows
DELETE 50000 rows
Rows affected per second: 27.78
...

9. --no-check-charset - 跳过字符集检查

bash 复制代码
--no-check-charset

作用: 不检查源和目标的字符集是否一致

10. --why-quit - 退出原因
bash 复制代码
--why-quit

作用: 程序退出时显示原因

输出示例:

bash 复制代码
Exiting because: 批处理完成 (正常结束)
Exiting because: 被用户中断 (Ctrl+C)
Exiting because: 连接超时 (异常)
11. --charset - 连接字符集
bash 复制代码
--charset utf8mb4

作用: 指定数据库连接的字符集

执行案例

bash 复制代码
开始清理任务 - Mon Mar  9 06:34:29 UTC 2026
清理条件: ctime < '2025-01-01'
==================================
总共需要处理 64 张表
==================================
[1/64] 处理表: database_0.table_0 - Mon Mar  9 06:34:29 UTC 2026
待删除数据: 488496 行
✅ 表 bill_intl_0.fp_stat_alt_0 清理成功,删除 488496 行
[2/64] 处理表: database_1.table_1 - Mon Mar  9 06:44:50 UTC 2026
待删除数据: 296442 行

结语

通过此次 pt-archiver 实践,我们成功实现了对 MariaDB 历史数据的高效、安全归档与清理。该工具以低负载、可控批量的方式,有效缓解了表膨胀问题,提升了数据库性能,并为后续数据生命周期管理提供了可复用的自动化方案。建议将其纳入定期运维任务,并持续监控执行效率与集群状态,以保障业务稳定运行。

相关推荐
czlczl200209252 小时前
Redis数据编码
数据库·redis·缓存
Wpa.wk2 小时前
pb协议接口测试
数据库·redis·缓存
IpdataCloud2 小时前
资源受限设备上轻量级IP查询模块的部署方法
网络·数据库·网络协议·tcp/ip
青槿吖2 小时前
SpringMVC通关秘籍(下):日期转换器、拦截器与文件上传的奇幻冒险
java·开发语言·数据库·sql·mybatis·状态模式
楼田莉子3 小时前
MySQL数据库:表及其表相关的操作
数据库·学习·mysql
ZTLJQ3 小时前
驾驭高并发:Python协程与 async/await 完全解析
服务器·数据库·python
百年੭ ᐕ)੭*⁾⁾3 小时前
DataFrame存入mysql以及读取操作
数据库·mysql·numpy·pandas·ipython
²º²²এ松3 小时前
vs code连接ubuntu esp项目
linux·数据库·ubuntu
Maverick063 小时前
02-SQL执行计划与优化器:Oracle是怎么决定“该怎么查“的
数据库·sql·oracle·ffmpeg