pgloader数据迁移实战:5步完成MySQL与SQLite到PostgreSQL的搬迁
【免费下载链接】pgloaderMigrate to PostgreSQL in a single command!项目地址: https://gitcode.com/gh_mirrors/pg/pgloader
深夜十一点,你盯着屏幕上满屏的红色报错,第 5 次重跑数据导入脚本,只因为源文件里混进了几行脏数据,整个批次又被 PostgreSQL 的 COPY 命令原地打断。如果你正在用 PostgreSQL,却还没听说过pgloader 数据迁移工具,那今天的文章就是为你准备的:它会用一条命令,把这种噩梦变成三分钟的顺风局。
一句话破题:pgloader 到底是什么?
pgloader 是专为 PostgreSQL 设计的数据加载与迁移工具,主打口号是"Migrate to PostgreSQL in a single command!"——用一条命令完成迁移。它能从 MySQL、SQLite、SQL Server 等数据库,以及 CSV、DBF、固定宽度文件等多种来源读取数据,再通过 PostgreSQL 的 COPY 协议高速灌入目标库。
它最核心的杀手锏,是智能错误处理:默认的 PostgreSQL COPY 行为是"全有或全无",一行出错就整表回滚;而 pgloader 会把坏行单独写进 reject 文件,好数据继续前进,迁移不因个别脏数据而停摆。
三步搞定环境搭建
第一步,安装。Debian/Ubuntu 用户可以直接apt-get install pgloader(v3 版本);想尝鲜最新版,可以从源码编译:
git clone https://gitcode.com/gh_mirrors/pg/pgloader cd pgloader make编译产物在./build/bin/目录。值得一提的是,项目正在推进 v4 重构版:用 Clojure 重写、打包成单个 JAR,只需要 Java 21 运行时,无需任何原生依赖,用标准的-Xmx参数就能调堆内存,大迁移不再有内存耗尽焦虑。
第二步,准备目标库。给迁移建一个空数据库:
createdb newdb第三步,跑第一条命令。拿项目自带的 SQLite 测试库试水:
pgloader ./test/sqlite/sqlite.db postgresql:///newdb预期结果:终端里滚动出类似下面这样的表格——每个表一行,列出错误数、行数、字节数和耗时,最后一行给出总计。
table name │ errors │ rows │ bytes │ total time ────────────┼────────┼──────┼───────┼─────────── album │ 0 │ 347 │ 21 kB │ 0.014s ...看到"Total import time"那一行,恭喜你,第一条迁移已经完成。
实战走一遍:两个最具代表性的场景
场景一:整库搬迁 MySQL → PostgreSQL
这是 pgloader 最拿手的活儿。执行前它会自动连接 MySQL、抓取元数据(表结构、索引、外键、注释),做类型映射后再并行搬数据:
createdb pagila pgloader mysql://user@localhost/sakila postgresql:///pagila光这一条命令,表结构、索引、外键、自增序列就全给你安排明白了。它还内置了数据整形能力,比如把 MySQL 的 "0000-00-00" 这种不合法日期自动转成 PostgreSQL 的 NULL——因为我们的日历里从来没有"第 0 年"。
场景二:CSV 文件导入(带转换)
CSV 场景在命令行就能全权指挥,不需要写配置文件:
pgloader --type csv \ --field "id,name,email,created_at" \ --with "truncate" \ --with "fields terminated by ','" \ data.csv postgresql:///mydb?tablename=users注意目标连接串里的?tablename=users,它指定数据要落进哪张表。另外,pgloader 还支持从标准输入读数据,于是你可以用 Unix 管道把网络上下载的压缩包直接流式导入,一气呵成:
gunzip -c source.csv.gz | pgloader --type csv ... - pgsql:///target?tablename=foo进阶技巧:让迁移又快又稳的三个开关
1. 用 .load 配置文件管理复杂任务。当规则变多,命令行就装不下了。pgloader 提供了一套 SQL 风格的 DSL(领域专属语言),把规则写进my.load文件:
LOAD DATABASE FROM mysql://user:pass@localhost/source_db INTO postgresql://user:pass@localhost/target_db WITH include drop, create tables, create indexes, reset sequences, foreign keys, workers = 4, concurrency = 2 SET work_mem to '32MB', maintenance_work_mem to '64MB' CAST type datetime to timestamptz, type date drop not null drop default using zero-dates-to-null BEFORE LOAD DO $$ create schema if not exists target_schema; $$;WITH段控制迁移行为,比如include drop表示可重复执行(先删后建);SET段给 PostgreSQL 会话设参数;CAST段定义类型转换规则;BEFORE/AFTER LOAD DO在加载前后执行 SQL,比如建 schema、跑analyze。
项目里现成的示例非常多,比如test/sqlite-chinook.load就是一套教科书式配置,抄来改改就能用。
2. 并行与批量调优。迁移大库时,这四个参数是收益最高的调节旋钮:
| 参数 | 作用 | 建议 |
|---|---|---|
workers = 8 | 工作线程数 | 按 CPU 核数调整 |
concurrency = 4 | 并发连接数 | 别超过 PostgreSQL 连接上限 |
batch rows = 50000 | 每批行数 | 大表加大,减少网络往返 |
prefetch rows | 预取行数 | 让流水线不空转 |
打个比方,批量加载就像流水线传送带:batch rows决定每个托盘装多少件货,prefetch决定传送带前方堆多少件备货,调好了整条线就不会停顿。
3. 迁移前先体检。用--dry-run只检查连接和配置、不实际加载;用--on-error-stop在严格场景下遇错即停;用--summary report.txt把统计结果落盘归档。
避坑清单:新手最容易踩的 5 个坑
| 坑 | 现象 | 解法 |
|---|---|---|
| 忘了建目标库 | 连接报错 | 先createdb再迁移 |
| CSV 没指定表名 | 报"无法确定目标表" | 目标串加?tablename=xxx |
| 编码乱码 | 中文变"???" | --encoding latin1或SET client_encoding |
| 目标表已存在且不想清空 | 主键冲突 | WITH truncate或include drop |
| 想严格把关 | 坏行悄悄跳过 | 加--on-error-stop,或设on error stop |
另外记住:被拒绝的坏行不会丢,pgloader 会生成一对reject.dat(原始数据)和reject.log(错误原因),迁移完记得去核对这两份文件,把脏数据修好再补导。
量化对比:它凭什么比 COPY 好用
| 维度 | pgloader | 传统 COPY |
|---|---|---|
| 单行错误 | 隔离坏行,继续加载 ✅ | 整批回滚 ❌ |
| 数据源 | 数据库 + 文件共 8+ 种 ✅ | 基本只有 CSV ✅/❌ |
| 建表建索引 | 自动发现并创建 ✅ | 需手工预处理 ❌ |
| 类型转换 | 内置规则 + 自定义 CAST ✅ | 需提前清洗 ❌ |
| 并行度 | workers + concurrency ✅ | 有限 ⚠️ |
一句话总结:COPY 是"搬运工",pgloader 是"带装修队的搬家公司"——不仅搬得快,还把水电布线(索引、外键、序列)全给接通了。
生态与延伸:从哪儿继续挖
- 官方文档:docs/quickstart.rst 三分钟上手,docs/command.rst 是命令 DSL 全量参考
- 各数据源手册:docs/ref/csv.rst、docs/ref/mysql.rst、docs/ref/sqlite.rst
- 示例配置:test/ 目录下全是真实可跑的
.load文件,对应每种来源类型 - 核心源码:src/load/migrate-database.lisp(迁移总编排)、src/pg-copy/copy-retry-batch.lisp(坏行二分定位重试)、src/utils/transforms.lisp(转换函数库)
写在最后
数据迁移从来不该是加班夜的独角戏。pgloader 的价值不只是"快",而是把"出错时该怎么办"这个问题替你兜住了底——这恰恰是生产环境里最贵的部分。去test/目录挑一个离你场景最近的示例,改两行连接串,跑起来吧。试完如果遇到有意思的坑,欢迎回来聊聊你是怎么绕过去的。🚀
【免费下载链接】pgloaderMigrate to PostgreSQL in a single command!项目地址: https://gitcode.com/gh_mirrors/pg/pgloader
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考