使用 pgloader 将 MySQL 迁移到 PostgreSQL
使用 pgloader 将 MySQL 迁移到 PostgreSQL
pgloader 是一款开源的批量数据迁移工具,支持从 MySQL / SQLite / MSSQL / CSV 等多种数据源将表结构和数据导入到 PostgreSQL
一、镜像准备
# 也可以使用这个镜像:swr.cn-east-3.myhuaweicloud.com/r4in/dimitri/pgloader:3.6.9
docker pull ghcr.io/dimitri/pgloader:3.6.9
二、执行迁移
2.1 核心命令
也可以直接运行为容器,后续在容器中操作
在测试时,迁移 300w+ 数据大概使用5分钟
docker run --rm ghcr.io/dimitri/pgloader:3.6.9 pgloader \
--dynamic-space-size 4096 \
--with "workers = 2" \
--with "concurrency = 1" \
--with "prefetch rows = 1000" \
--with "batch rows = 1000" \
'mysql://<mysql_user>:<mysql_password>@<mysql_host>:3306/<mysql_db>' \
'postgresql://<pg_user>:<pg_password>@<pg_host>:5432/<pg_db>'
上例中的
<mysql_user>、<mysql_password>、<mysql_host>、<pg_host>等均为占位符,实际执行时替换为目标数据库的真实账号、密码、地址和库名即可。
注意:避免在密码中包含@这样的符号,否则可能会解析地址有问题
2.2 参数说明
| 参数 | 说明 |
|---|---|
--dynamic-space-size 4096 | 给 pgloader 的 SBCL Lisp 运行时分配 4096 MB 动态堆空间,大库迁移时防止堆溢出 |
--with "workers = 2" | 启用 2 个并行 worker 同时处理不同表 |
--with "concurrency = 1" | 每个 worker 的并发度为 1,适合源库读压力敏感的场景 |
--with "prefetch rows = 1000" | 每次从源库预取 1000 行到内存缓冲 |
--with "batch rows = 1000" | 每 1000 行批量写入目标库一次 |
workers与concurrency根据源库负载和目标库写入能力进行调整。单库、表数量不多时上述默认值较为稳妥。
三、迁移后修正 Schema
pgloader 默认会把 MySQL 数据导入到与源库同名的 schema 中(例如 <mysql_db>)。如果目标 PG 库中业务代码默认使用 public schema,需要在迁移完成后做一次 schema 重命名。
3.1 检查现有 schema 和表
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname = 'public';
3.2 重命名 schema
BEGIN;
-- RESTRICT:如果 public 里存在对象会直接报错,不会误删
DROP SCHEMA public RESTRICT;
-- 将 pgloader 自动创建的 schema 重命名为 public
ALTER SCHEMA <mysql_db> RENAME TO public;
ALTER SCHEMA public OWNER TO postgres;
GRANT USAGE ON SCHEMA public TO PUBLIC;
COMMIT;
关键点:
DROP SCHEMA public RESTRICT只在public为空时才能执行成功,避免误删已存在的对象。ALTER SCHEMA ... RENAME TO public把 pgloader 导入的 schema 重命名为业务使用的public。- 整个过程放在一个事务里,方便回滚。
3.3 验证
-- 列出 public schema 下所有表
\dt public.*
-- 校验数据行数
SELECT COUNT(*) FROM public.logs;
SELECT COUNT(*) FROM <mysql_db>.logs;
第二条
SELECT COUNT(*) FROM <mysql_db>.logs;在 schema 重命名后应该报「schema 不存在」错误,说明重命名生效;第一条返回的行数应与迁移前源 MySQL 中对应表的行数一致。