先说个题外话:我身边不少同学提到 Navicat 就觉得它是"数据库工具箱顶配",日常连库、看数据、跑个查询确实舒服。可一旦到了"把这张几千万行的表挪到另一台服务器"或者"把 MySQL 数据同步到 PostgreSQL"的场景,Navicat 的导出导入功能基本就成了一场煎熬。进度条转半天,内存越吃越高,最后还可能直接崩给你看。这篇文章不贩卖焦虑,也不把 Navicat 说得一无是处,我只想分享一个我实际踩坑踩出来的结论:大批量 PostgreSQL 数据同步和跨库迁移,应该交给更底层的开源工具。它们用 COPY 协议、并行分片和断点续传,把同步这件事彻底提速——在我试过的场景里,从 MySQL 迁 500 万行到 PostgreSQL,Navicat 折腾 20 多分钟,pgloader 跑完两分半,快的不止 10 倍。而且这些工具完全开源,支持跨库迁移,也有日志和进度视图做可视化。这篇文章会从原理、选型、实操到排障完整走一遍,适合所有被数据迁移折磨过的运维、后端和数据工程师。
1. 先搞清楚:为什么 Navicat 做数据迁移会那么慢
1.1 慢的根本原因不在 SQL,而在架构
很多人以为 Navicat 同步慢是因为它生成的 SQL 不够高效,其实不完全是。最核心的问题出在它的执行路径:它是一个图形化客户端,数据要经过"源库 → 客户端内存 → 目标库"这样一条链路。你可以把 Navicat 想象成一个搬运工,它每次从源库 SELECT 一批数据,塞进自己的内存,再拼成 INSERT 语句一条条往目标库插。这个链条上有三处天然瓶颈。
第一,客户端中转。源库和目标库之间所有数据都要先流经你本地电脑的内存和网卡,如果你的机器性能一般,或者网络链路有损耗,整体吞吐瞬间就下来了。第二,INSERT 语句逐条执行。每一条 INSERT 都要走完整的解析、权限检查、生成事务日志、写入数据页这条链路。单条插入和批量导入的开销完全不是一个量级。第三,单线程串行。Navicat 的表导入导出基本是逐表进行的,表内部也是顺序读取、顺序写入,完全没利用上 PostgreSQL 的多核并行能力。
这不是说 Navicat 做得不好,而是这个产品天生就不是为了"大数据量搬迁"设计的。它更擅长的是交互式管理、写个小查询、导出一份报表。把它当成数据迁移工具,属于用错工具。
提示:判断一个工具适不适合做大规模同步,先问三个问题:数据流是否经过客户端中转?写入是否走批量 COPY 而不是单条 INSERT?是否支持并行和断点续传?Navicat 在这三项上都不占优势。
1.2 三种常见"龟速"现场与真实体验
我自己踩过的坑大致能归成三类。
第一类是跨服务器拷贝大表。一张 2 亿行的业务日志表,从生产 PostgreSQL 库同步到分析库,Navicat 导出的 SQL 文件有好几十 GB,中途还经常因为网络闪断导致导出失败。重新来一遍的时间成本非常高,最后只能硬着头皮用命令行 psql 分片导入,那体验完全不一样。
第二类是异构数据库迁移。把 MySQL 里的用户表、订单表逻辑迁移到 PostgreSQL,Navicat 虽然有表结构和数据的转换模板,但批量插入一次只能处理少量行,跑了一整夜还没跑完,第二天一看还有几个大表没处理。这个场景下,Navicat 的"转储 SQL"功能还会因为语法兼容性问题报错,你得手工改 SQL,越改越崩溃。
第三类是后续增量同步。Navicat 本质上只是"一次性搬家"工具,如果你需要把源库实时的更新持续同步到目标库,它根本做不了。真正的增量同步依赖的是 PostgreSQL 的逻辑复制机制或者专门的数据同步工具,而不是图形客户端。
这些痛点叠加起来,我基本得出结论:图形客户端适合"看"数据库,不适合"搬"数据库。想要高效搬迁,就得把目光投向那些直接和数据库底层协议打交道的开源工具。
2. 开源工具阵营盘点:这几个方案我实测能打
先说结论:目前开源工具里,能干净利落处理 PostgreSQL 数据同步和跨库迁移的,主力就三个:pgloader、pgcopydb、pgsync。它们定位不同,适合的场景也完全不同。
2.1 pgloader:全能型"混源"迁移选手
pgloader 是我个人最喜欢的一个工具。它由 PostgreSQL 社区的资深开发者 Dimitri Fontaine 用 Common Lisp 编写,虽然这个语言听起来有点冷门,但工具本身非常成熟。它最强的地方在于异构迁移:可以把 MySQL、SQLite、MS SQL Server、MongoDB 的数据迁移到 PostgreSQL,PostgreSQL 到 PostgreSQL 的迁移也支持。
它的底层逻辑很聪明:读取源库数据后,直接使用 PostgreSQL 的 COPY 协议批量装载数据,同时通过多个 worker 并行读取。更重要的是,它会自动迁移表结构、索引、外键、序列,还可以在迁移过程中做数据清洗和类型转换。整个迁移过程会在终端输出实时进度和详细统计信息,这样迁移过程中的"可视化"基本是开箱即用。
适合场景:MySQL / SQLite / SQL Server 迁移到 PostgreSQL,以及轻量级的 PostgreSQL 互迁。我自己用的最多的就是 MySQL 搬迁到 PG。
2.2 pgcopydb:PostgreSQL 到 PostgreSQL 的事实标准
pgcopydb 是 Dimitri Fontaine 的另一个作品,是专为 PostgreSQL 到 PostgreSQL 迁移设计的。它在社区里口碑极好,很多 PostgreSQL 大版本升级和高可用架构改造都在用它。它的核心思路是把 PostgreSQL 的物理备份和逻辑复制结合起来:先用并行导出导入的方式把全量数据搬过去,然后借助逻辑复制槽把搬迁期间产生的新增数据持续追平。
这意味着它天然支持跨版本迁移(比如从 PostgreSQL 13 迁到 16),支持表空间、序列、权限、发布订阅等高级对象,最重要的是它支持低停机时间迁移。你在业务运行期间就能把数据提前搬到新库,最后切换的时候只需要让应用停机几秒钟,让它把最后一点增量同步过去。
适合场景:PostgreSQL 大版本升级、跨机搬迁、异地容灾、低停机迁移。凡是源库和目标库都是 PostgreSQL 的严肃场景,我基本都用 pgcopydb。
2.3 pgsync:开发环境数据刷新的小快灵
pgsync 是 Andrew Kane 写的工具,定位是开发者的贴心伴侣。它主要解决的是"把生产库数据同步到本地开发库"这类需求。你可以一条命令把生产环境某个表甚至整个库拉回本地,它同样基于 COPY 协议,也支持只同步部分数据、脱敏字段、指定并发度。
pgsync 和上面两个工具不是一个赛道。它不是为几十 TB 的大库迁移准备的,但如果你每周都要刷新开发环境,或者需要把生产数据脱敏后同步到测试环境,用 pgsync 能省下大量时间。它支持 PostgreSQL 之间的同步,也支持 MySQL 作为源库。
2.4 选型建议:什么时候用哪个
我整理了一个选型表,方便大家按场景直接对号入座。
| 场景 | 首选工具 | 备选 | 原因 |
|---|---|---|---|
| MySQL/MSSQL/SQLite 迁到 PostgreSQL | pgloader | pgsync(仅部分场景) | 异构支持最强,自动转换类型和结构 |
| PostgreSQL 到 PostgreSQL 全量+增量 | pgcopydb | pgloader | 支持复制槽,低停机,对象覆盖全 |
| PostgreSQL 大版本升级 | pgcopydb | pg_dump/restore | 物理快照+逻辑复制,迁移风险低 |
| 生产库刷新到开发环境 | pgsync | pgloader | 轻量、快速、可做数据脱敏 |
| 临时导出一张小表 | pgloader | 命令行 psql | 一条命令搞定 |
实操心得:工具不是选越先进的越好,而是要匹配你的"源库类型、目标库类型、停机窗口、数据量、对象复杂度"这五个维度。我自己吃过亏:为了图方便,在 PG 到 PG 的迁移任务里用 pgloader 而不是 pgcopydb,结果遇到物化视图和发布订阅等对象时要手动补,很折腾。
3. 上手实操:pgloader 从 MySQL 迁移到 PostgreSQL 的完整流程
跨库迁移是标题里最核心的关键词,也是我日常用 pgloader 最多的场景。下面我以"MySQL 业务库迁移到 PostgreSQL"为例,把完整流程拆开讲,包括安装、配置、调优和核对。
3.1 安装与前置检查
pgloader 的安装非常友好。macOS 上执行brew install pgloader,Debian/Ubuntu 系执行apt install pgloader,CentOS 系的 EPEL 源里也有。如果你喜欢容器化,直接跑docker pull dimitri/pgloader也行。这里有一个细节:pgloader 是 Common Lisp 写的,源码编译依赖 SBCL 和一堆 Lisp 库,比较折腾,我个人不建议源码编译,除非你有特殊需求。
安装完之后先别急着跑,做几个前置检查:
- 确认源库和目标库都能从你的机器访问,网络连通性没问题;
- 确认源库账号至少有读取权限,目标库账号有建表、写数据、建索引的权限;
- 确认目标库的字符集和源库兼容,尤其是源库是 latin1 或者 gbk 这种编码时,提前想好转换规则;
- 大表迁移前先在目标库建一个空库,别直接和现有数据混在一起。
我习惯先跑一次pgloader --dry-run,它会只分析对象和数据大小、打印迁移计划而不实际执行,非常有用。
3.2 写一个最小可用的 load 配置文件
pgloader 支持命令行直接传连接串,比如:
pgloader mysql://root:password@192.168.1.10:3306/app_db postgresql://postgres:password@192.168.1.20:5432/app_db_pg但真实项目里参数太多,我推荐用.load配置文件。下面是一个我反复使用的最小配置:
LOAD DATABASE FROM mysql://root:password@192.168.1.10:3306/app_db INTO postgresql://postgres:password@192.168.1.20:5432/app_db_pg WITH workers = 8, concurrency = 1, batch rows = 50000, batch size = 64MB, prefetch rows = 100000, create tables, create indexes, reset sequences, include drop SET PostgreSQL PARAMETERS maintenance_work_mem = '1GB' work_mem = '128MB' ;这个配置的含义并不复杂。workers = 8是让 pgloader 用 8 个并发进程读取源库,batch rows = 50000和batch size = 64MB控制每次 COPY 写入的数据量,create tables和create indexes表示自动迁移表结构并在迁移后创建索引,reset sequences是把自增序列重置到当前最大值。include drop则是如果目标库里已有同名表,先删掉再重建。
这里有个经验:batch size不是越大越好。如果单批数据超过 64MB,目标端的 WAL 写入压力会很大,而且一旦某个批次失败,回滚代价也高。我一般根据表大小调整,几十 GB 的大表用 64MB,小表用 16MB 就够。
3.3 并行参数与 Batch 大小的调优
很多人第一次用 pgloader 就直接默认参数跑,结果发现速度一般,以为工具不行。其实关键在参数调优。pgloader 的并行模型是"源端多 worker 读取 + 目标端 COPY 写入",你可以在配置里同时控制读取并发和写入并发。
workers控制源端读取并发,concurrency控制目标端写入并发。我自己的经验是:
- 源库是 SSD、目标库是 SSD 时,
workers = 8, concurrency = 2能跑满网络带宽; - 源库是机械盘或者目标端 CPU 核数较少时,
workers = 4, concurrency = 1更稳定,避免把目标库拖垮; - 如果源库是 MySQL,注意 MySQL 的
max_allowed_packet限制,批量读取时不要超过这个值,否则会报错。
另外一个容易被忽略的点是prefetch rows。这个参数控制 pgloader 在内存里预取的记录数,相当于给管道加了个缓冲。如果这个值太小,worker 经常要停下来等数据;如果太大,内存会飙高。我通常按"总行数 / workers / 10"估算一个合理的预取值。
3.4 迁移完成后的核对
迁移跑完,终端会输出一张表级统计报表,包含每个表的读行数、错误数、耗时和数据速率。但依赖报表还不够,我还会做四个额外核对:
- 行数核对:分别对源库和目标库执行 count(*),抽样几张表对比;
- 序列核对:确认自增主键的序列当前值比表内最大 id 大,否则插入会报主键冲突;
- 索引核对:确认目标库的索引和源库一致,尤其注意唯一索引;
- 外键核对:把
create indexes跑出来的索引、约束列出来,和源库对比。
如果迁移过程中有错误,pgloader 会在工作目录下生成.reject文件,里面记录每条失败记录的原因。这个文件非常有用,我通常在排查"个别记录为什么没进去"时直接翻它,省去写复杂 SQL 去比对。
注意:pgloader 的默认事务粒度是"一批记录一个事务",所以中途失败不会导致前面全部回滚。但这意味着失败后你需要认真看 reject 文件,而不是直接重跑。重跑命令会先
include drop把已有表删掉重建,如果没有include drop,则可能报"表已存在"。
4. pgcopydb 实战:跨库迁移 + 增量同步一步到位
如果你的源库和目标库都是 PostgreSQL,并且追求更低的停机时间和更高的对象兼容性,pgcopydb 才是正主。这个工具的设计思路值得好好理解一遍,理解了你就知道为什么它比 Navicat 快那么多。
4.1 pgcopydb 的核心思路
pgcopydb 本质上是一个"编排器",它把 PostgreSQL 生态里原本零散的能力组合成一条流水线。全量数据搬迁阶段,它使用 pg_dump / pg_restore 的并行模式,把表数据直接以 COPY 格式传输,这比 Navicat 的逐条 INSERT 快一个数量级。
增量追平阶段,它利用 PostgreSQL 的逻辑复制功能。逻辑复制是 PostgreSQL 原生机制,源库会在 WAL 日志里记录每一条数据变更,逻辑复制槽负责把这些变更以流式方式推给目标端,目标端再按顺序应用。pgcopydb 做的事情,就是自动帮你配置好这一切,省去手工执行CREATE SUBSCRIPTION等一堆命令的麻烦。
你可以把 pgcopydb 理解成一个"带增量功能的搬家队":全量搬家的时候,业务还在持续写入新数据,搬家队一边搬旧家具,一边盯着新搬进来的家具,全部搬完之后再把新家具补齐,最后让你无缝切换到新家。
4.2 clone 一把梭:全量 + 增量
pgcopydb 的使用方式特别简洁,它通过环境变量传递连接信息。我的标准操作流程是这样的:
export PGCOPYDB_SOURCE_PGURI='postgres://postgres:password@192.168.1.10:5432/app_db' export PGCOPYDB_TARGET_PGURI='postgres://postgres:password@192.168.1.20:5432/app_db' export PGCOPYDB_TARGET_DATADIR='/tmp/pgcopydb' pgcopydb clone --follow这里有三个环境变量,PGCOPYDB_SOURCE_PGURI是源库连接串,PGCOPYDB_TARGET_PGURI是目标库连接串,PGCOPYDB_TARGET_DATADIR是 pgcopydb 存放快照和状态信息的目录。--follow参数表示全量迁移完成后,继续跟随源库的增量变更。
在执行之前,我有几个习惯:
- 目标库先用
createdb建好,避免 pgcopydb 在目标库不存在时中途报错; - 确认源库的
wal_level为logical,否则逻辑复制槽无法建立,增量同步会失败; - 如果目标库里已经有数据,建议先备份,pgcopydb 默认会重建表结构。
执行过程中,pgcopydb 会在PGCOPYDB_TARGET_DATADIR下生成一个.log文件。你可以用tail -f实时看迁移进度:
tail -f /tmp/pgcopydb/pgcopydb.log日志里会按表输出行数、耗时、速率,信息密度比 Navicat 的进度条高得多。
4.3 迁移进度与"可视化"怎么看
标题里提到"可视化",这里我想多说一句:数据同步类的可视化,不一定非要有炫酷的 Web 界面。真正有用的可视化是"能实时看到进度、延迟和异常"。pgcopydb 和 pgloader 都遵循这个原则。
pgloader 终端里的动态进度报表就是一种可视化,它会每秒钟刷新一次,显示当前表、已处理行数、失败数、当前速率。pgcopydb 的日志同样记录了每个表的处理情况。
如果你还想看得更细,可以直接查询 PostgreSQL 的进度视图。PostgreSQL 14 起有一个pg_stat_progress_copy视图,专门展示正在进行中的 COPY 导入进度:
SELECT datname, command, phase, tuples_done, tuples_total FROM pg_stat_progress_copy;在 pgcopydb 或 pgloader 执行期间,你能实时看到已经 COPY 了多少行,总行数大概多少,这对大表迁移非常有用。
增量同步阶段,关注两个东西:复制槽的restart_lsn和目标库的<pg_stat_subscription>视图(PostgreSQL 10 以后都有)。复制槽的延迟增长说明目标端跟不上源端的写入速度,这时候需要排查目标库的磁盘 I/O 或 CPU。
如果你确实需要一个面向领导的、看得见摸得着的大屏,也简单:把pg_stat_replication和pg_stat_subscription的数据采集到 Prometheus,再接 Grafana 做个迁移动态面板,延迟、速率、WAL 堆积量一目了然。这个后文我会再细说。
5. 跑数加速背后的原理:COPY、并行、断点续传
把工具用熟之后,我建议花点时间理解它们为什么快。理解了原理,遇到问题时你就知道从哪个方向排查。
5.1 COPY 协议为什么比 INSERT 快
Navicat 的默认导出行径是生成INSERT INTO ... VALUES (...)语句,而开源工具用的是 PostgreSQL 的 COPY 协议。COPY 这条路径是完全绕开标准 SQL 解析的:它直接把数据按二进制或文本格式写入表,跳过查询计划器,也不需要逐条维护对触发器的支持(除非你显式开启)。
有人做过对比:同样插入 100 万行数据,单条 INSERT 可能需要几十秒到几分钟,而 COPY 一般只要几秒。COPY 更快的原因很简单——它把"100 万次零散操作"变成"100 万行数据一次到手,数据库自己批量写"。这个和你在文件系统里逐个创建 1 万个小文件,和打包成一个 tar 包再解压是类似的逻辑。
开源工具选择 COPY 作为核心装载方式,等于选择了数据库厂商提供的最快写入通道。
5.2 并行分片如何正确设置
光有 COPY 还不够,单个连接读数据还是有上限。pgloader 和 pgcopydb 都采用多 worker 并行读取源库的方式。pgloader 会自动把一张大表按主键范围切成多个分片,由不同 worker 分别读取,最后目标端再用 COPY 批量写入。这样源端多个连接同时读,目标端也有多个 COPY 流在写,系统资源的利用率才真正上来。
这里就引出两个经验:
第一,并行度不是越高越好。workers 数量超过源库 CPU 核数,源库的查询解析就会成为瓶颈;超过目标库 CPU 核数,目标端的索引维护和 WAL 写入会成为瓶颈。我一般从 4 起步,压测后逐步往上加,找到一个吞吐峰值而不是盲目往 32、64 加。
第二,大表是否有主键,直接影响分片效率。没有主键的表,pgloader 没法高效切片,只能退化为单线程顺序读取,速度会明显下降。所以在迁移前,我会给源库那些没有主键的大表临时加一个自增主键或者选择一个唯一列作为分片键。
5.3 断点续传与异常恢复
Navicat 的导入导出最让人恼火的一点是:跑到 80% 网络断了,整个活儿白干。开源工具对这种情况的处理就好得多。
pgsync 从设计上就内置了"先创建临时表,全部导入完成后替换正式表"的机制,失败后重跑不会产生脏数据。pgloader 的每个批次是独立事务,失败后你只要处理 reject 文件里的错误记录,或者调整参数重跑即可。pgcopydb 更彻底,它支持断点续传,迁移过程中会在本地数据目录里保存每一步的状态,重启后可以接着跑,不用从头再来。
这一特性在几十 GB 甚至几 TB 的库上价值巨大。我见过有人用传统方式迁移 2TB 的库,中途断了几次,硬生生折腾了一个星期;后来改用支持断点续传的工具,一个通宵全部搞定。
实操心得:如果你的迁移任务非常重,我强烈建议全程守着日志,而不是撒手不管。启动命令不要用
nohup简单丢后台,建议配合tmux或screen会话,这样你可以随时回到终端看进度、断掉重连也不会把命令搞丢。
6. 常见问题与排查技巧实录
工具用久了,各种怪问题都见过。我把最常见的几类问题和排查思路整理如下,希望帮你少走一些弯路。
6.1 内存与带宽问题
高并发迁移时,最常见的是内存被吃满。pgloader 的预取行数和批次大小都挺吃内存,如果超过机器物理内存,进程会被 OOM Killer 干掉。遇到这种情况,先别急着加机器配置,检查一下你的prefetch rows是不是设得太大。比如一张表 1 亿行,prefetch rows = 100000,再乘上 8 个 worker,内存瞬间就爆了。我通常把预取值控制在"总行数 / 1000"左右。
网络带宽问题则比较隐蔽:工具在本地跑得飞快,一旦源库和目标库跨机房,速度就断崖式下跌。你需要先用量带宽工具跑一下源库到目标库的网速,如果带宽本身只有 20Mbps,那工具再快也没有用,瓶颈在链路上。这种情况下,只能考虑在源库所在机房先做一次本地同步,再用物理方式搬运快照,或者提高链路带宽。
6.2 字符集与编码踩坑
异构迁移最容易出错的就是字符集。源库是 MySQL 的utf8mb4,目标库是 PostgreSQL 的UTF8还好,但如果源库是gbk或latin1,目标库里就可能出现乱码或者非法字节序列错误。
我的处理方式是:在 pgloader 的配置里显式指定源端编码转换规则,比如在FROM mysql://...的 MySQL 连接串里加上?charset=gbk参数,让 pgloader 按正确编码读取。目标端 PostgreSQL 则必须保证数据库本身是 UTF8 编码,这样字符串可以在写入时统一转换到 UTF8。
还有一个隐蔽问题:MySQL 里的DATETIME默认不带时区,迁移到 PostgreSQL 的timestamp without time zone时看似正常,但如果你后续要做跨时区分析,一定要在迁移前想清楚是否要转成timestamptz。这类逻辑问题工具不会帮你区分,必须自己提前调研。
6.3 权限与参数检查清单
权限这种东西,平时风平浪静,迁移时刻突然跳出来卡你一下。我把容易踩的坑整理成了一张清单,建议执行前逐项核对:
| 检查项 | 源库 | 目标库 | 说明 |
|---|---|---|---|
| 连接权限 | SELECT, SHOW | CREATE, INSERT | 大表迁移前的权限预检 |
| wal_level | logical(pgcopydb 增量需要用) | 不改 | 源库要支持逻辑复制 |
| max_replication_slots | 至少 1 个空闲 | 不需要 | 源库要能建立复制槽 |
| 磁盘空间 | 需预留 WAL | 建议 1.2~1.5 倍数据量 | pgcopydb 快照和数据双份 |
| maintenance_work_mem | 无 | 大一点 | 影响索引创建速度 |
| 目标库版本 | 无 | 建议与源库相同或更高 | 高版本迁低版本容易遇到兼容问题 |
另外一个常见坑是目标库的 PostgreSQL 版本低于源库,导致 pg_dump 导出的对象定义在高版本上才能解析。所以我一贯的建议是:目标库版本尽量不低于源库,最好比源库高一到两个大版本。跨版本升级本来就是 pgcopydb 的强项,别浪费这个能力。
6.4 快速排查速查表
最后给一个排查速查表,都是我在实际操作中反复用到的:
| 症状 | 可能原因 | 快速解决办法 |
|---|---|---|
| 迁移刚开始就报连接失败 | 连接串写错、防火墙封端口、密码带特殊字符未转义 | 先用 psql 手动测通连接 |
| 迁移中途进程被杀 | 内存不足、batch 太大 | 降低 prefetch 和 batch size,或者分表迁移 |
| 目标库索引创建极慢 | maintenance_work_mem 太小 | 在配置里SET maintenance_work_mem to '2GB' |
| 大表迁移速率不稳定 | 网络抖动、源库负载波动 | 降低并发、增加超时容忍、避开业务高峰期 |
| 增量同步不生效 | 源库 wal_level 不是 logical | 修改wal_level=logical后重启源库 |
| 主键冲突 | 目标库已有残留数据 | 清理目标库,或用include drop重建 |
| 乱码 | 源库字符集和目标库不一致 | 在连接串中指定 charset,转换到 UTF8 |
我自己在实测中还有一个体会:很多问题是因为"没看日志"造成的。pgloader 的 reject 文件、pgcopydb 的 log 文件里,问题原因写得明明白白。有时候你只要打开日志看一眼,问题就解决一半了。不要凭感觉猜,日志不会骗你。
最后再分享一个小技巧。大数据量迁移之前,我总会先拿一张中等大小的表(比如几十万行)完整跑一遍流程,从配置、执行到核对都过一遍。这样能把大部分权限问题、编码问题、网络问题暴露在小范围内,真正跑全库的时候就心里有底了。这套"先小后大、先局部后全量"的思路,比任何工具技巧都管用。