pgloader 实战指南把异构数据库迁移到 PostgreSQL 从三天压到一小时【免费下载链接】pgloaderMigrate to PostgreSQL in a single command!项目地址: https://gitcode.com/gh_mirrors/pg/pgloader你大概率踩过这个坑手写脚本把 MySQL 库迁到 PostgreSQL跑到第 30 万行没问题第 30 万零 1 行冒出一个0000-00-00零日期整个事务回滚。你只好拆小批次、手工洗数据、改脚本、重跑折腾一天。pgloader 就是为这种场景而生的一条命令完成到 PostgreSQL 的迁移坏行自动隔离整体流程不中断。它到底解决了什么pgloader 对比手动迁移相比「手写 DDL 裸 COPY 预清洗脚本」的手动路线pgloader 帮你省掉四步不用逐张写目标表 DDL表、索引、外键从源库自动推导生成不用预清洗数据坏行进 reject 文件好行继续加载这是它相对裸 COPY 的核心优势裸 COPY 一行坏数据整表回滚不用写类型转换脚本零日期、字符宽度、编码这些差异有现成规则也可自定义迁移配置是一个.load文件可复用、可进版本库下次重跑不用重写脚本操作项没有它有它目标表结构手写 DDL 逐张建从源库自动生成表、索引、外键错误行一行坏数据整表回滚坏行入 reject 文件好行继续类型转换预写清洗脚本零日期、编码有内置规则并行加载自己写并发逻辑workers / batch 参数调配置管理脚本每次重写一个 .load 文件可审计你只需要知道它底层就是在正确时机发 COPY 命令但把「建表、切分、容错、重试、收尾」这些脏活全包了。从零跑通pgloader 安装与第一条命令Step 1装好 pgloader建好目标库v3 在 Debian/Ubuntu 官方源里直接可装v4 是 Clojure 重写版单个 JAR、需要 Java 21命令行和.load语法与 v3 完全兼容drop-in 替换。本文以 v3 为例两条命令就位apt-get install -y pgloader # Debian/Ubuntu 官方源装完即用 createdb demo # 目标库这步别跳过pgloader 不会自动建库Step 2写一个完全自包含的最小迁移文件为什么用 inline 方式因为不需要准备任何外部 CSV 文件数据直接写在加载文件里10 秒就能验证全链路建表 → 加载 → 事务提交cat hello.load EOF LOAD CSV FROM inline (id, name, amount) -- 数据来源本文件内联的 CSV INTO postgresql:///demo TARGET TABLE sales WITH truncate -- 加载前清空目标表 BEFORE LOAD DO $$ create table if not exists sales (id int, name text, amount numeric); $$ EOF cat hello.load EOF 1,alice,100.50 2,bob,20.25 3,carol, EOFStep 3先 dry-run再正式执行dry-run 只检查连接不写库生产库上执行前这步别省pgloader --dry-run hello.load # 只验证连接不写任何数据 pgloader hello.load # 正式执行 psql -d demo -c select * from sales; # 三行数据都在完事到此你已经会用它了。剩下的是把参数调到合适的位置。场景实战MySQL、CSV、DBF 三类迁移场景MySQL 5.7 的 ERP 库迁到 PostgreSQL 15 → 痛点零日期和无符号类型把迁移卡死MySQL 的0000-00-00在 PG 里解析必炸PG 历法没有公元 0 年unsigned int和on update current_timestamp这类列属性也是高频雷区。表又多又大全量一把梭容易中途失败。基础版——一条命令结构和数据全迁内置规则已覆盖多数常见差异pgloader mysql://usermysql-host/erp postgresql:///erp_new进阶版——生产加固写法.load 文件这段代码做了什么自定义并行度与批次、显式声明包含项drop/建表/建索引/重置序列、对零日期列做 NULL 转换、调大排序和建索引内存。LOAD DATABASE FROM mysql://user:passmysql-host/erp INTO postgresql:///erp_new WITH include drop, create tables, create indexes, reset sequences, workers 4, -- 并行工作线程数 batch rows 100000, -- 每批提交行数 set work_mem to 16MB, -- 排序操作内存 maintenance_work_mem to 512MB CAST column erp.orders.updated_at to timestamptz using zero-dates-to-null -- MySQL 零日期统一转 NULL SET search_path to erp;场景几百 MB 的历史订单 CSV 导入 → 痛点带表头、引号包裹字段、中间夹杂坏行业务导出的 CSV 三件套第一行表头、字段里有逗号引号、中间混着几行脏数据。裸\copy遇到坏行整批中止你只能回头翻文件找是哪行。基础版——跳过表头、声明分隔符先跑通LOAD CSV FROM data/orders_2023.csv INTO postgresql:///demo TARGET TABLE orders WITH skip header 1, -- 跳过表头行 fields terminated by ,, fields optionally enclosed by BEFORE LOAD DO $$ create table if not exists orders (id int, customer text, amount numeric); $$;进阶版——批量提交提速空串自动转 NULLLOAD CSV FROM data/orders_2023.csv INTO postgresql:///demo TARGET TABLE orders WITH truncate, skip header 1, batch rows 50000, -- 分批提交控制事务大小 batch size 10 MB, null if \N -- 源文件用 \N 表示空值 CAST column orders.amount to numeric using empty-string-to-null;坏行处理不需要你写代码pgloader 默认把错误行连同错误原因写进 reject 文件默认在/tmp/pgloader/下好行照常入库。想「宁停勿错」就加on error stop。场景老系统的 DBF 文件入库 → 痛点编码不是 UTF-8数字字段是文本DBF 文件来自二十年前的系统编码可能是 cp866、GBK 之类直接拷进 UTF-8 库就是乱码和报错。基础版——表自动创建先能跑LOAD DBF FROM data/DNORDOC.DBF INTO postgresql:///demo TARGET TABLE dnordoc WITH truncate, create table, disable triggers;进阶版——指定源编码字符型数字列转成真正的整数LOAD DBF FROM data/DNORDOC.DBF with encoding cp866 -- 源文件编码别猜 INTO postgresql:///demo TARGET TABLE dnordoc WITH truncate, create table, disable triggers CAST column dnordoc.doctype to integer using db3-numeric-to-pgsql-integer;调优与避坑大表迁移参数与常见报错坑 1零日期炸 timestamp症状invalid input syntax for type timestamp: 0000-00-00。根因MySQL 允许零日期PG 历法里没有公元 0 年解析直接失败。修复CAST column 表.列 to timestamptz using zero-dates-to-null一行搞定整列转 NULL。坑 2编码不匹配症状invalid byte sequence for encoding UTF8: 0x82。根因源文件或库是 GBK/cp1252 之类字节原样送进 UTF-8 库。修复来源处显式声明如FROM data/x.DBF with encoding cp866声明一次全局生效。坑 3大表迁移卡在某个百分比不动症状进度长时间不前进、内存持续上涨。根因默认批次偏小、读线程不足大表上吞吐上不去。修复——把 WITH 段换成生产参数按 CPU 核数调 workers这段代码做了什么提高并行度与批次大小开启多线程读取调大排序与建索引内存是百 GB 级数据量的常用配置。WITH workers 8, concurrency 4, batch rows 200000, batch size 50 MB, multiple readers per thread, -- 每个工作线程开多个读取器 set work_mem to 256MB, maintenance_work_mem to 1GB实际跑下来的体感同一张千万行大表默认参数和上面这套参数耗时能差出两三倍瓶颈主要在省掉的批次往返和并发读取上。速查卡片迁移前检查清单与报错速查迁移前 Checklistpgloader --dry-run通过源和目标连接都验证过目标库空闲空间 ≥ 源数据 2 倍索引和临时表很吃空间.load文件已进版本库配置可 review 可重跑源端编码已确认DBF/CSV 尤其要指定 encoding先在测试库完整跑一遍两端行数对得上预留 reject 文件处理时间修完脏数据要二次导入数据导入后确认序列需要重置reset sequences常见报错速查表报错关键词原因一句话修法invalid input syntax for type timestampMySQL 零日期 0000-00-00CAST 列 using zero-dates-to-nullinvalid byte sequence for encoding UTF8源编码非 UTF-8FROM 子句显式 with encodingrelation xxx does not exist目标表没建WITH 加 create table 或 BEFORE LOAD DO 预建duplicate key value violates unique constraint目标表有残留数据WITH 加 truncateconnection refused连接串或端口不对先跑 --dry-run 定位参数细节可以对照仓库内文档CSV 语法看docs/ref/csv.rstMySQL 迁移看docs/ref/mysql.rst转换函数清单看docs/ref/transforms.rst测试目录test/下几十份.load文件本身就是现成的参数样本库直接抄就行。【免费下载链接】pgloaderMigrate to PostgreSQL in a single command!项目地址: https://gitcode.com/gh_mirrors/pg/pgloader创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考