pgloader能自动处理MySQL到PostgreSQL的类型映射和语法转换,但需严格配置连接权限、URL编码密码、预建目标库、合理设置并发参数,并注意模式映射与链路容错。

pgloader 能自动处理大部分 MySQL → PostgreSQL 的类型映射和语法转换,但不能无脑执行就成功——它对连接权限、字符集、模式结构、并发参数非常敏感,稍有偏差就会卡在 LOAD DATABASE 阶段或静默丢数据。
pgloader 连接字符串里密码含特殊字符会直接失败
MySQL 或 PostgreSQL 的连接 URL 中,如果密码含 @、/、:、? 等字符,pgloader 会把它们误解析为 URL 分隔符,导致认证失败或连接超时,错误信息通常不明确,只显示 failed to connect 或空日志。
- 必须对密码做 URL 编码(不是 Base64),例如密码
pa@ss/word?123要写成pa%40ss%2Fword%3F123 - 推荐用 Python 快速编码:
from urllib.parse import quote_plus<br>print(quote_plus("pa@ss/word?123")) - 不要手动替换,
%20(空格)和+在 URL 中含义不同,pgloader只认%xx形式
迁移前必须手动创建目标 PostgreSQL 数据库,且不能依赖 include drop
pgloader 的 include drop 只删表、索引、序列,不会删数据库本身,也不会建库。如果目标库不存在,会报错 database "dbtest" does not exist,即使配置里写了 INTO pgsql://...。
- PostgreSQL 目标库需提前用
createdb或psql -c "CREATE DATABASE dbtest;"创建 - 若想清空再迁,可先运行:
dropdb dbtest && createdb -E UTF8 -l C -T template0 dbtest
(加-l C -T template0避免区域设置冲突) -
include drop仅对库内对象生效,且要求连接用户有DROP权限(如app_user通常没有,得用postgres或owner)
ALTER SCHEMA 不是重命名数据库,而是把 MySQL 库映射为 PostgreSQL 模式
MySQL 没有“模式(schema)”概念,一个库对应一个逻辑单元;PostgreSQL 是“库 → 模式 → 表”三级结构。ALTER SCHEMA 'testdb1' RENAME TO 'test_db1' 这行不是改数据库名,而是把迁移过程中临时生成的 testdb1 模式重命名为 test_db1,并放入目标库中。
- 若不写这句,所有表会落到
public模式下,多个 MySQL 库会互相覆盖 - 若想让 MySQL 的
testdb1直接变成 PostgreSQL 的public模式内容,写:ALTER SCHEMA 'testdb1' RENAME TO 'public'; - 注意:目标库的
public模式必须为空,否则RENAME TO 'public'会失败
并发参数调太高反而导致 OOM 或连接池耗尽
workers=8、concurrency=1、batch size=50MB 这类参数看着能提速,但在 4GB 内存的机器上极易触发 Killed(OOM killer 杀进程)或 PostgreSQL 报 too many clients。
- 实测安全起点:
workers=2、concurrency=1、batch rows=500、prefetch rows=500 -
max parallel create index=2必须设,否则建索引阶段可能独占全部连接 - 如果 PostgreSQL 启用了
max_connections=100,pgloader默认最多占 20 个连接(每个 worker + prefetch),别忘了留余量给监控或运维操作
真正的难点不在语法转换,而在于连接链路每环的容错设计——MySQL 的 wait_timeout、PostgreSQL 的 tcp_keepalives、中间防火墙的 idle 断连、甚至 DNS 缓存 TTL,都可能让一个跑 2 小时的迁移中途静默中断。建议始终加 -v 参数跑,并把输出重定向到文件,出问题时第一眼就看最后 20 行日志里是卡在哪个 SQL 还是断在连接层。


















