第二章的承诺,这里兑现
第 2 篇把「归档冷数据」列为拆表前的第一招,还留了一句「归档任务的纪律第 17 篇展开」。上一篇在线 DDL 已经讲完,本篇兑现承诺,把冷热分离从策略讲到落地。先复习那个铁律:互联网业务的查询高度集中在近期数据——订单查询九成落在近三个月,两年前的历史数据一年也翻不了几次。它们留在主表里,唯一的作用是压低每一层 B+ 树、稀释 Buffer Pool、拖慢每一次 DDL。
分片环境下的归档分工
先划清两件事的边界:归档不能替代分库分表,但两者是黄金搭档。归档解决「历史行数堆积」,水平拆分解决「热数据规模与写瓶颈」——正确顺序是先归档瘦身、再评估拆分,拆分之后归档继续作为日常代谢机制(第 18 篇的容量治理里它是常备手段)。分片环境里归档还有个额外红利:每张物理表都是按分片键切开的,归档任务按分片逐表执行,天然分片并行、天然限速单元,不会出现单库大表归档那种一边倒的 IO 压力。
冷库放哪儿:三种归宿
归档不是删除,冷数据要有归宿,按查询需求选:归宿一:归档库——独立的 MySQL 实例(通常大容量低配机器),表结构与主库相同或按时间分表。适合偶尔还要查、还要做后台报表的场景,SQL 兼容性最好;归宿二:对象存储加列式引擎——导出成 Parquet 放对象存储,挂在 ClickHouse 或数据仓库里查。适合基本不查、查就是批量分析的场景,成本最低、分析能力反而更强;归宿三:合规封存——金融、医疗类数据有法定保存年限,加密归档、限制访问、留审计日志。多数系统的组合拳是:近期冷数据进归档库,更老的进数据仓库,超期的合规封存。
归档任务的三条纪律
归档程序本身是个生产级组件,三条纪律缺一不可:限速——每批次只搬一小批(比如一千行)、批间休眠、总速率压在源库安全水位以下,归档任务打挂主库是真实高发事故(事故集锦里它有一席);幂等可重跑——按 ID 区间记账水位,中断续传,「先写冷库成功、再删主库」的顺序加事务边界保证不丢不重:
loop:
batch = 主库.select(主键 > 水位, limit 1000) // 小批
冷库.insertIgnore(batch) // 幂等写入
assert 冷库.count(batch.id) == batch.size // 确认落库
主库.delete(batch.id) // 再删主库
水位 = batch.maxId; sleep(50ms) // 限速推进可回捞——偶尔要查三年前的订单(客服纠纷、审计取证),查询入口要设计好:应用层按时间判断路由到冷库,或者干脆引导到后台离线查询。别让「用户查不到两年前的订单」变成事故——归档前和产品对齐查询预期,是流程的一部分。
归档的收益账
算一笔账收尾:两亿行主表归档掉八成,主表剩四千万——索引层级普遍降一层(多数查询少一到两次 IO)、热数据完整装进 Buffer Pool(命中率肉眼可见地上扬)、DDL 从八小时缩到一小时内。这一刀的成本是几条归档脚本加一台归档库,性价比碾压拆库拆表——再次呼应第 2 篇的告诫:便宜的手段先用尽,再动贵的刀。
数据瘦身讲完,系列进入治理收尾:分片系统上线之后的长期健康怎么维护——水位监控、数据倾斜、容量规划,下一篇盘点治理清单。
评论 (0)