并不是每项工作都需要整个数据库。在本地开发一个功能时,你很少会想让一份完整的生产转储塞满磁盘、还要花一个小时才能导入。你想要的,是这个功能真正会用到的那几张表。
当你在调试某一张表时也是如此——在 orders 里复现一个数据问题,用不着其余那 126 张表——或者做部分迁移时,只有少数几张表要挪到新服务上。所有这些情况里,问题都是同一个:怎样才能只把这几张表干净利落地从一个巨型转储里取出来?
sed/grep 的办法,以及它为何会出错
经典答案是用 sed 在 mysqldump 为每张表写出的段落标题之间切割文件:
# 从一个 mysqldump 文件里取出 users 表
sed -n '/-- Table structure for table `users`/,/-- Table structure for table/p' dump.sql > users.sql
这看着挺聪明,在一个小巧整洁的转储上说不定还真能成一次。可放到一个真实的 7 GB 文件上,它会在许多不易察觉的地方崩掉:
- 多行 INSERT。单条
INSERT INTO ... VALUES可能跨越好几千行。像sed和grep这样面向行的工具会把这些行拦腰截断,生成一个无法解析的文件。 - 反引号和特殊字符。列值里含有
--、分号、反引号、引号,以及字符串内部的换行符。你的模式会匹配到数据内部那些本不该当作分隔符的文本。 - 表名成了子串。提取
user会连带抓到user_roles、user_sessions和password_user,因为这个名字作为子串出现在其他名字里。 - 注释和标题会漂移。确切的注释文本在 MySQL、MariaDB 和 PostgreSQL 各版本之间各不相同,而
pg_dump根本不用同样的标题——于是同一条命令会悄无声息地什么都取不到。 - 没有外键意识。就算你把
orders切得完美无缺,它的行还是引用着users。sed对此一无所知,所以提取出来的东西会因为外键错误而导入失败。
你最后会把 awk 叠在 grep 上、再叠在 sed 上,在子集上反复测试,却仍然不敢相信结果。有更好的办法。
用 DumpCleaner 提取表
DumpCleaner 会正确解析转储——它理解语句边界、多行 INSERT、反引号和注释——所以它总是切在正确的行上。提取你需要的表只需四步:
- 把你的
.sql转储拖进来。DumpCleaner 流式读取文件,所以一个 7 GB 的转储以恒定内存打开,而不是把整个文件都加载进来。 - 查看自动检测出的表清单。每张表都会被解析出来,并列出行数和大小——不用在几百万行里滚来滚去找它有什么。
- 挑选你想要的表。勾选
users、orders和products,或者输入正则/排除模式,比如用*_logs一次性丢掉整组表。 - 包含外键父表并导出。可选地自动把被引用的父表也拉进来,然后导出一个干净、可导入的文件。
有几点让这件事比 shell 工具省心得多:
- 排除模式如
*_logs或*_sessions能剔除审计和会话这类噪声,而不用手动去掉几十张表的勾选。 - 正则筛选让你按前缀、后缀或任意模式匹配——比如保留所有匹配
shop_*的表。 - 实时预览随着你改动选择,精确显示最终会进入输出的是哪些表。
- 预估输出大小在你导出之前就告诉你提取结果会有多大,让你确信它能装进本地。
- 外键依赖可以自动包含进来,于是选中
orders就悄悄把users一并带上,提取结果导入时不会有约束错误。
只要你需要的表——别的一概不要
DumpCleaner 从任意大小的转储中提取指定的表——流式处理、内存恒定,还替你把外键解析妥当。原生 macOS 与 iPadOS 应用,一次性买断。
在 App Store 下载常见问题
我能一次提取多张表吗?
可以。想勾多少张表都行——把 users、orders 和 products 一起勾上——DumpCleaner 会一趟就把它们全写进一个文件。
它会保留外键依赖吗?
可选地会。打开包含外键依赖,你所选表引用的任何父表都会被自动拉进来,于是提取结果导入时不会有约束错误。
我能按模式排除表吗?
可以。用 *_logs 或 *_sessions 这样的排除模式,或用一个正则表达式,来整组丢掉表,而不必一张一张去掉勾选。
它对 PostgreSQL 也适用吗?
适用。DumpCleaner 能读取 MySQL、MariaDB 和 PostgreSQL(pg_dump)转储,并在提取表时处理像 public.users 这样带 schema 限定的名字。