用 taskfile 替掉 Makefile 做元数据校验后,我的环境崩了

上周在本地用 Docker Compose 起了一套元数据服务,版本是 0.14.2,数据量不大,单表 200 万行左右。现象是每次改完 schema 再跑校验脚本,服务就会在启动 30 秒后 OOM,内存直接飙到 4G。

我一开始以为是容器内存限制没设,检查了 compose 文件,mem_limit 是 2G,没问题。后来用 docker stats 盯了一会儿,发现是校验脚本自己吃内存——它一次性把整张表的元数据读进内存做 diff。

我的做法是分两步。第一步,把校验脚本从 Makefile 里挪出来,用 taskfile 重新组织,因为 Makefile 的 tab 缩进和隐式规则在调试时太容易出岔子。taskfile.yml 片段:

version: '3'
tasks:
  validate:
    cmds:
      - python scripts/validate_meta.py --batch-size 5000 --source ${SOURCE}
    env:
      SOURCE: '{{.SOURCE | default "local"}}'

第二步,改脚本,把全量加载改成按主键区间分批读,每批 5000 行,diff 完就释放。关键代码:

for start in range(min_id, max_id + 1, batch_size):
    rows = fetch_meta(start, start + batch_size - 1)
    diff = compare(rows, expected)
    if diff:
        report(diff)
    del rows

为什么这样做:元数据校验的瓶颈不在 CPU,在内存驻留。分批之后,峰值内存从 3.8G 降到 400M 左右,代价是总耗时多了约 12%,因为多跑了几次查询。这个取舍对小团队来说划算,毕竟不用为了校验单独扩内存。

哪里会失效:分批依赖主键连续且分布均匀。我们有一张表的主键是 UUID,区间划分直接失效,只能退回去用游标分页。另外,taskfile 的 env 默认值在 CI 里会被覆盖,如果 CI 的 SOURCE 变量拼错,校验会静默跑本地配置,这个坑我踩过一次,后来在脚本开头加了一行打印实际参数才定位到。

你们在做元数据校验时,是倾向在应用层分批,还是直接在数据库侧用临时表算 diff?我这边因为权限限制没法建临时表,想听听别的做法。

0
赞同度 100% · 0 条评论 · 8 阅读

0 条评论

支持 Markdown · 回复会实时推送给对方

还没有评论,写下第一条。