mysql如何实现数据归档策略_mysql项目实践说明

来源:这里教程网 时间:2026-02-28 20:50:42 作者:

归档前先确认表是否有合适的时间字段

没有时间维度的表几乎无法做自动化归档,

created_at
updated_at
log_time
这类字段必须存在且被索引。如果只有自增
id
,而业务上又明确“老数据”指“ID 小于某值”,那可以临时用
id
替代,但要注意:自增 ID 不等于时间顺序(比如批量回填、主从延迟、replace into 等场景会导致 ID 乱序)。

检查方式:

SHOW CREATE TABLE order_log;
看字段定义和索引;执行
SELECT MIN(created_at), MAX(created_at) FROM order_log;
确认时间范围是否连续、有无空值。

用 DELETE + LIMIT 分批删除老数据

直接

DELETE FROM order_log WHERE created_at  在大表上会锁表、打满 binlog、拖慢主库。必须分批删:

每次只删 5000–10000 行,用
WHERE created_at (注意加 <code>ORDER BY
避免重复或遗漏)
两次删除之间加
SLEEP(0.1)
(在存储过程中用
DO SLEEP(0.1)
),缓解 I/O 和复制压力
删除后立刻
ANALYZE TABLE order_log
,避免优化器因统计信息滞后选错执行计划
务必在低峰期执行,且提前在从库验证语句执行耗时

归档到历史库要用 INSERT … SELECT + 建好目标表结构

不要用 mysqldump 导出再导入——太慢、不可控、难断点续传。优先走 SQL 层迁移:

目标表必须提前建好,结构与源表一致(包括字符集、排序规则、索引),但可去掉不必要的二级索引(归档表一般只按时间查);主键保留,否则后续删源数据时难以精准定位。

示例归档语句:

INSERT INTO archive_db.order_log_2022 SELECT * FROM main_db.order_log WHERE created_at >= '2022-01-01' AND created_at < '2023-01-01';
注意:该语句需在事务内执行,且确保
max_allowed_packet
足够大(否则大批量插入会报
Packet too large
)。

归档后记得清理统计信息和监控残留

归档不是删完就结束。容易被忽略的点:

INFORMATION_SCHEMA.TABLES
中的
DATA_LENGTH
/
INDEX_LENGTH
不会实时更新,需等下次
ANALYZE
或重启才准;别靠它立刻判断空间是否释放
如果用了 pt-archiver 工具,它默认不删 binlog,归档完要手动
PURGE BINARY LOGS BEFORE '2024-01-01'
(前提是你确认从库已同步完)
监控项如
table_rows
是估算值,归档后可能不准;建议改用
SELECT COUNT(*)
抽样校验关键表行数
归档脚本里没写错误重试逻辑?网络抖动或锁冲突导致某一批失败,后续批次会跳过——得加
ROW_COUNT()
判断实际影响行数,不为 0 才继续

相关推荐