数据库迁移中,从MySQL切换到PostgreSQL往往需要处理字段类型映射、自增主键转换、默认值差异以及索引命名保留等细节。pgloader是一个开源的数据迁移工具,它把这些重复劳动抽象成配置和命令,能够从一个连接读取MySQL表结构,自动在PostgreSQL侧创建对应的表、序列、约束和索引,并按照一定批次写入数据。

本文将从安装部署、配置语法、类型转换、性能调优和排障几个方面展开,帮助你快速完成MySQL到PostgreSQL的迁移。
一、pgloader的安装与基础能力
pgloader最初是Python写的,后来用Common Lisp重写,支持从MySQL、SQLite、CSV、SQL Server等数据源向PostgreSQL迁移。它内置针对MySQL的类型映射,例如tinyint(1)自动识别为boolean,int auto_increment转为serial或identity,datetime保持时间精度等。安装方式比较简单,在Debian或Ubuntu上可以使用apt安装,macOS可以通过Homebrew安装,也可以下载官方编译好的二进制文件。需要说明的是,pgloader是一个命令行工具,迁移过程的配置通过一个专门的DSL文件来描述,不使用SQL转储脚本。
# Debian / Ubuntu sudo apt update sudo apt install pgloader # macOS brew install pgloader # 检查版本 pgloader --version
安装完成后,建议先检查pgloader能不能同时连通MySQL和PostgreSQL。MySQL用户需要SELECT、SHOW VIEW、TRIGGER等权限,PostgreSQL用户需要建库建表权限。如果两个数据库不在同一台机器,注意网络策略和防火墙。pgloader在命令行执行时会显示迁移进度和每个表的处理情况,初次使用时可以先在一个小库上验证流程。
二、编写迁移配置文件
pgloader使用.load文件描述迁移规则,核心命令是load database from源连接into目标连接,并使用with子句控制迁移行为。下面给出一个最小配置示例:
LOAD DATABASE
FROM mysql://migrator:mysql密码@127.0.0.1:3306/source_db
INTO postgresql://migrator:pg密码@127.0.0.1:5432/target_db
WITH
batch size = 25000,
batch concurrency = 4,
prefetch rows = 10000,
create tables = true,
create indexes = true,
drop tables = true,
truncate = true,
reset sequences = true,
only tables = ('users', 'orders', 'products');
这段配置中,batch size控制每个事务插入的行数;batch concurrency指定并发写入连接数;prefetch rows表示从MySQL读取时预取的行数;create tables为true时自动在PostgreSQL中建表;drop tables会在迁移前删除目标库同名表;truncate用于清空已有数据;reset sequences则会在导入完成后将自增序列更新到当前最大值。only tables可以限定只迁移指定的表,避免全库处理。
执行时运行pgloader 配置.load即可,也可以加--dry-run做试运行,只打印计划而不真正写数据。想要观察详细日志,可以使用--verbose参数。
pgloader migration.load # 仅检查不执行 pgloader --dry-run migration.load # 输出详细日志 pgloader --verbose migration.load
配置文件中的连接串如果包含特殊字符,建议使用URL编码。MySQL连接串格式为mysql://user:password@host:port/dbname,PostgreSQL为postgresql://user:password@host:port/dbname。实际项目里建议使用专用迁移账号,不要把生产数据库的超级用户直接写在配置文件中,尤其是配置文件需要提交到版本库时更要注意安全。
三、类型映射与数据转换
pgloader默认的MySQL类型转换规则比较实用。常见的映射包括:tinyint(1)转为boolean,smallint转为smallint,int转为integer,bigint转为bigint,varchar转为text或varchar,datetime转为timestamptz,text转为text,blob转为bytea。auto_increment列会转为PostgreSQL的serial或identity,并自动创建序列。如果不想完全依靠默认规则,可以在配置中使用CAST子句自定义列类型转换。
LOAD DATABASE
FROM mysql://migrator:mysql密码@127.0.0.1:3306/source_db
INTO postgresql://migrator:pg密码@127.0.0.1:5432/target_db
WITH
keep not null = true,
cast type datetime to timestamptz drop default drop not null using zero-dates-to-null,
cast type tinyint to boolean using tinyint-to-boolean;
上面的配置里,cast type datetime to timestamptz使用了zero-dates-to-null,把MySQL中的0000-00-00 00:00:00转换为NULL,避免PostgreSQL无法存储这样的日期值。tinyint转boolean可以避免所有tinyint列都被当作smallint处理。keep not null表示保留原字段的非空约束,这类细节在迁移后直接影响应用写入逻辑。
对于字段名大小写和保留字问题,pgloader会自动在PostgreSQL中使用小写表名和列名,并对与PostgreSQL关键字冲突的列名加双引号。也可以在配置中设置preserve index names保留索引名称,或者使用materialize views将视图物化。如果迁移后发现某些列类型不符合预期,完全可以修改CAST规则后重新执行pgloader,目标表会被重新创建并导入数据。
CAST type date to date drop default drop not null using zero-dates-to-null
自定义类型转换是pgloader很灵活的地方,通过组合drop default、drop not null和using转换函数,能够处理大多数MySQL历史数据中的脏值。对于更复杂的清洗需求,也可以先在MySQL侧通过临时表整理数据,再让pgloader负责传输和建结构。
四、性能调优与迁移实战
迁移大表时,默认参数可能不是最优。pgloader的写入性能受batch size、batch concurrency和prefetch rows影响。batch size过大可能导致单个事务时间过长,过小则提交频繁;batch concurrency过高会占用数据库连接和内存。一般建议从batch size=25000、concurrency=4开始,根据服务器配置调整。如果PostgreSQL使用了高性能磁盘,可以适当提高concurrency到8;如果MySQL从库压力大,则降低prefetch rows。
WITH
batch size = 50000,
batch concurrency = 8,
prefetch rows = 20000,
workers = 8
实战迁移建议先在测试库完整跑一遍,观察数据量和迁移时间。正式迁移前备份目标库,确认应用已经停止写入MySQL,或者使用只读账号避免迁移过程中数据变化。pgloader迁移过程默认先建表,再并行读取和写入数据,最后创建索引和外键。如果迁移完成后再建索引,可以减少插入过程中索引维护开销,可以设置create indexes = false,迁移完成后手动建索引:
-- 迁移完成后手动创建索引 CREATE INDEX idx_orders_user_id ON orders(user_id); ALTER TABLE orders ADD CONSTRAINT fk_orders_user FOREIGN KEY (user_id) REFERENCES users(id);
如果数据量非常大,还可以拆分多张表迁移,或者使用pgloader的parallel能力同时处理不同表。pgloader会自行调度不同表的读取和写入,但不同表之间不会相互锁等待,只有外键依赖需要在同一批次中处理。对于超大表,建议先迁基础数据,再单独处理大字段或历史归档表。
五、常见问题与排障
迁移过程中最常见的问题是权限不足。MySQL账号需要至少SELECT、SHOW VIEW、TRIGGER,PostgreSQL账号需要对目标数据库有CREATE、TEMP权限。如果出现连接超时,检查防火墙和数据库监听地址。MySQL的lower_case_table_names设置可能导致表名大小写不一致,pgloader会以MySQL返回的表名为准,需要提前确认。
字符集问题也可能导致迁移失败,尤其是表中有utf8mb4内容和旧版本MySQL默认latin1时。建议在MySQL连接串中明确指定字符集,或者在MySQL配置文件里统一设置default-character-set = utf8mb4。PostgreSQL侧一般使用UTF8编码,如果目标库不是UTF8,需要先重建目标库。
# 排查迁移日志中的具体错误 pgloader --verbose --logfile /tmp/pgloader.log migration.load tail -f /tmp/pgloader.log
如果迁移失败在某个表,可以查看日志中Table name等信息,定位到具体类型的转换错误。常见的还有MySQL自增主键已经手动插入0值导致PostgreSQL主键冲突,这类数据需要在迁移前清理或修正。pgloader不会自动修复业务数据中的逻辑错误,它只负责结构和数据搬运。
对于视图、存储过程、触发器等数据库对象,pgloader默认不会迁移存储过程和触发器,主要迁移表和视图。存储过程语法差异较大,需要人工改写为PL/pgSQL。触发器也需要重新创建。这一点在迁移规划时要提前考虑到,避免切换后才发现核心业务逻辑缺失。
pgloader让MySQL到PostgreSQL的迁移不再是手工脚本堆叠,通过一个配置文件即可完成结构转换、数据复制和约束重建。对于大多数中小型应用,掌握上述配置和调优方法已经足够顺利切换。大型系统还需要配合增量同步和双写方案,但pgloader仍然是全量迁移阶段的高效起点。
pgloaderMySQL迁移PostgreSQL修改时间:2026-08-27 19:08:10