一个 solo 开发者做了个「带收据」的数据迁移工具:迁移完还能回头验真假
在 Hacker News 上刷到一个叫 Paganel 的项目。一句话概括,就是数据迁移做完以后,它给你一张「迁移收据」,几周之后还能翻出来,重新核对一遍目的库里的数据有没有被人动过、有没有迁错。
作者在 Show HN 里提过这个工具的来历,说是他自己踩过的一个坑。当时要做一次大型 schema 迁移,涉及大量转换和多个环境,最重要的一条要求是「验证数据有没有正确搬过去」,而且数据不允许出网,任何 SaaS 工具都用不上。他找了一圈,没有找到既能做转换又能做验证的隔离环境工具,最后只能自己手写一堆脚本把整个过程跑完。
从那天起他就一直惦记着怎么把复杂的迁移自动化,花了大概一年半做了 Paganel,目前还在 pre-v1.0。
设计上有个比较特别的地方:一次迁移就是一份声明式文件,数据从哪来、往哪去、join、filter、计算字段、验证规则,全写在同一个文件里。缺某个 source、sink、transform 或 filter,可以自己写 WASM 插件,用 Rust 或 JS 都行。插件跑在严格的沙箱里,默认没有文件系统和网络访问权限,除非在迁移配置里显式放开。这一点正好接住了作者当年「数据不能出网」的硬约束——验证和转换都在自己网络内完成。
大迁移之前可以跑 pag plan,它会预览输出 schema、DDL,给出时间和内存估算,还会抽样真正走一遍整条 pipeline,让你看清实际要插入的是什么。
最核心的是 --integrity 这个标志。启用之后,Paganel 迁移过程中边跑边对行做哈希,把哈希按主键存到磁盘。跑完后对整张表算出一个 32 字节的根哈希,也就是那张「迁移收据」。过了几分钟或者几周,随时可以跑 pag verify,它只读目的库、重新算哈希、和收据比对,全程不连 source。根哈希对不上,说明有东西变了,它再逐行哈希告诉你具体是哪几行出了问题。
作者也把边界说得很清楚:它只能证明「目的库里现在的内容还是 Paganel 当初写进去的那些」,没法证明「转换逻辑本身是对的」。也就是说,如果迁移逻辑本身就写错了,收据也会诚实地反映这个错——它保证的是你没有悄悄丢数据、数据没被改过,不是保证业务转换写对了。
速度方面,作者自己建了个基准。1 亿行从 MySQL 迁到 PostgreSQL,默认单流配置大约每秒 39 万行;把带整数主键的表拆成 4 个并行流,能冲到将近 94 万行每秒。启用 --integrity 会有额外开销,两个数字分别掉到 34 万和 67 万左右。对于有整数主键的表,流的数量是可以配置的。
因为是单人开发的 pre-1.0 项目,作者列了不少还没打磨好的地方:还没有 CDC,目前只支持批处理,最终目标是带验证的持续同步,不过先把批处理引擎做扎实;原生只支持 MySQL 和 PostgreSQL;配置语法还在活跃开发中,版本之间可能会变;完整集成测试和手动测试跑在 Linux 上,macOS 和 Windows 有预编译二进制,但只过了基本冒烟测试。想试的话,README 里的 quickstart 会用 Docker 起几个样例数据库。
这个工具最有意思的点,是把「迁移完成」从一句口头汇报变成一件可以事后复核的事。现实中很多迁移事故,不是当时没迁成功,而是过了几周才发现某张表悄悄少了数据,或者被下游脚本动过。有一张能随时回查的收据,至少能把「不知道什么时候开始错的」变成「就是这行、这条记录」。它当然不解决转换逻辑写错的问题,但能把排查范围从整张表缩到具体某几行。对做过数据迁移的人来说,光是这一点就值回票价了。作者在帖子里问大家现在都是怎么验证迁移的,如果 Paganel 这种收据机制能嵌进你的工作流,他大概很想听听。