高性能MySQL到PostgreSQL异构数据库转换工具MySQL2PG
MySQL2PG 工具产生的背景
MySQL 到 PostgreSQL 转换同步工具存在着以下诸多的问题:
- 无法全自动转换
MySQL的DDL到PostgreSQL上,转换的过程中还存在着较多的语法不兼容问题,还需要手动处理,耗时耗力。 - 工具无法进行自动化全量表进行同步,需要手动一个表或者一批表进行选择配置、字段映射,在同步数据时进度无法进行可视化展示、很难评估需要同步的整体时间。
- 无法进行
MySQL数据库用户信息的自动同步、需要手动的确认哪些用户需要同步、用户的密码分别是多少、如果密码忘记对于手动进行确认,期间会消耗大量的时间和精力。 - 无法进行用户权限的自动化同步,无法精细化的控制用户的权限,存在较大的操作风险。
- 特别是
MySQL上的FUNCTION无法进行自动进行转移,几百个FUNCTION手动的转换会消耗不少的人力。。
针对以上的问题,首先进行了系统化的梳理了,工具需要哪些模块,以及每个模块都包含哪些功能进行了手稿第一版梳理。

最终实现的各模块及功能如下:
sql
开始
│
├─▶ [Step 0] test_only 模式?
│ ├─ 是 → 测试 MySQL & PostgreSQL 连接 → 显示版本 → 退出
│ └─ 否 → 继续
│
├─▶ [Step 1] 转换表结构 (tableddl: true)
│ ├─ 读取 MySQL 表定义
│ ├─ 字段类型智能映射(如 tinyint(1) → BOOLEAN)
│ ├─ lowercase_columns 控制字段名大小写
│ └─ 在 PostgreSQL 中创建表(skip_existing_tables 控制是否跳过)
│
├─▶ [Step 2] 同步数据 (data: true)
│ ├─ 若 use_table_list=true → 仅同步 table_list 中的表
│ ├─ 若 truncate_before_sync=true → 清空目标表
│ ├─ 分批读取 MySQL 数据(max_rows_per_batch)
│ ├─ 批量插入 PostgreSQL(batch_insert_size)
│ └─ 并发线程数由 concurrency 控制
│
├─▶ [Step 3] 转换索引 (indexes: true)
│ ├─ 主键、唯一索引、普通索引 → 自动重建
│ └─ 批量处理(max_indexes_per_batch=20)
│
├─▶ [Step 4] 转换函数 (functions: true) ←【V1.0 未完全实现】
│ └─ 支持函数映射(如 NOW() → CURRENT_TIMESTAMP)
│
├─▶ [Step 5] 转换用户 (users: true)
│ └─ MySQL 用户 → PostgreSQL 角色(带密码)
│
├─▶ [Step 6] 转换表权限 (table_privileges: true)
│ └─ GRANT SELECT ON table → GRANT USAGE, SELECT
│
└─▶ [Final Step] 数据校验 (validate_data: true)
├─ 查询 MySQL 和 PostgreSQL 表行数
├─ 若 truncate_before_sync=true 且不一致 → 报错中断
└─ 若 truncate_before_sync=false → 记录不一致表,继续执行
└─ 最终输出「数据量校验不一致的表统计」表格
源代码仓库在 https://github.com/xfg0218/MySQL2PG 欢迎大家使用和反馈意见,有好的想法及建议也欢迎随时交流。 👏🏻 👏🏻 👏🏻👏🏻
编程工具选择
主要调研了国内主流的AI IDE的工具,包括节旗下的Trae、腾讯云旗下的CodeBuddy和阿里云旗下的通义灵码,优劣势如下:
| 功能维度 | Trae | CodeBuddy | 通义灵码 |
|---|---|---|---|
| AI 核心模式 | 支持Builder 和Builder MCP的模式 | Craft 智能体、双模型驱动 | 支持智能代码补全、智能校验代码质量、测试CASE生成 |
| 代码生成能力 | 支持从0-1项目的生成 | 支持不同的语言 | 支持代码的优化、代码提示、代码续写 |
| 多模态支持 | 支持go/java/Python/C++ | 支持流程的编排、智能体的协作 | 编程智能体、工程级变更 |
| 生态集成 | 支持 VS Code 插件 | 支持微信的生态、疼腾讯云的服务等 | 阿里云的生态、可以对接钉钉 |
由于这个项目需要从0开始并且需要使用golang 语言开发,在开发时仅需要输入需要实现的功能,工具需要理解上下文的内容,和自动代码的编排、以及测试步骤需要由AI 进行完成的需求,最终选择了 Trae 作为了开发的工具。
参考资料:
trae:https://www.trae.cn/
codebuddy:https://www.codebuddy.ai/
为什么会选择golang 语言,主要是Golang 直接编译为机器码具有运行效率快、跨平台、内存占用率少、启动快、可以二进制部署等特点。
工具整体功能效果
使用的软件版本
采用 MySQL 和 PostgreSQL 都为单机版进行的测试,版本信息如下:
sql
-- go 的版本
$ go version
go version go1.24.2 darwin/amd64
-- mysql的版本
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.44 |
+-----------+
1 row in set (0.00 sec)
-- PG的版本
postgres=# select version();
version
---------------------------------------------------------------------------------------------------------
PostgreSQL 16.1 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit
(1 row)
使用的数据集
MySQL的数据库中有不同字段类型、不同储存引擎、不同字符编码、涉及到关键字、主外键、自增列等共 1339 张表进行的自动转换。MySQL数据库中的 1339 张上共有 1768 个索引,其中包含主键索引、单字段索引、符合索引等。MySQL数据库中存在5个不同的用户,在五个用户中有的用户仅有SELECT权限、有的用户仅有DELETE权限、有的用户仅有UPDATE权限,有的用户具有几十张全部的操作权限。- 以下为实际测试转换的对象数量信息汇总:
sql
+--------------------------+----------------+
| 阶段 | 对象数量 |
+--------------------------+----------------+
| 转换表结构 | 1339 |
| 同步表数据 | 1339 |
| 转换表索引 | 1768 |
| 转换库用户 | 5 |
| 转换表权限 | 15 |
+--------------------------+----------------+
仅测试连接部分
在 config.yml 配置文件中有测试连接数据库的功能参数 test_only 当该参数开启时,表示仅测试数据库的链接,其他的步骤不执行,在测试连接完成后输出日志信息便会退出。
mysql.test_only = true 时代表仅测试连接 MySQL 数据库的部分,日志信息如下 :
sql
+-------------------------------------------------------------+
1. MySQL连接测试完成,版本信息已显示,退出程序。
+-------------------------------------------------------------+
| 数据库版本信息: |
+--------------+----------------------------------------------+
| 数据库类型 | 版本信息 |
+--------------+----------------------------------------------+
| MySQL | 5.7.44 |
| PostgreSQL | PostgreSQL 16.1 on x86_64-pc-linux-gn... |
+--------------+----------------------------------------------+
postgresql.test_only = true 时代表仅测试连接 PostgreSQL 的部分,日志信息如下 :
sql
+-------------------------------------------------------------+
2. PostgreSQL 连接测试完成,版本信息已显示,退出程序。
+-------------------------------------------------------------+
| 数据库版本信息: |
+--------------+----------------------------------------------+
| 数据库类型 | 版本信息 |
+--------------+----------------------------------------------+
| MySQL | 5.7.44 |
| PostgreSQL | PostgreSQL 16.1 on x86_64-pc-linux-gn... |
+--------------+----------------------------------------------+
全流程运行结果
当在 config.yml 配置文件 conversion 模块中分别开启了tableddl/data/indexes/users/table_privileges/validate_data 会按照顺序依次执行,详细的日志输出如下,在转换完成后会总结每个阶段转换的对象及耗时。
sql
1. 开始转换表结构...
进度: 3.45% (1/29) : 表 acl_space 已存在,跳过创建
进度: 6.90% (2/29) : 表 users_20251201 已存在,跳过创建
进度: 10.34% (3/29) : 表 act_id_group 已存在,跳过创建
进度: 13.79% (4/29) : 表 user 已存在,跳过创建
2. 同步表数据...
进度: 17.24% (5/29) : 同步表 acl_space 数据成功,共有 0 行数据,数据校验一致
进度: 17.24% (6/29) : 同步表 users_20251201 [--------------------] 100.00%
进度: 20.69% (6/29) : 同步表 users_20251201 数据成功,共有 1 行数据,数据校验一致
进度: 24.14% (7/29) : 同步表 act_id_group 数据成功,共有 0 行数据,数据校验一致
进度: 27.59% (8/29) : 同步表 user 数据成功,共有 0 行数据,数据校验一致
3. 转换表索引...
进度: 31.03% (9/29) : 转换索引 idx_user_id 成功
5. 开始转换用户...
进度: 34.48% (10/29) : 转换用户 mysql2pg@% 的权限成功
进度: 37.93% (11/29) : 转换用户 user1@% 的权限成功
进度: 41.38% (12/29) : 转换用户 user2@% 的权限成功
进度: 44.83% (13/29) : 转换用户 user1@localhost 的权限成功
进度: 48.28% (14/29) : 转换用户 user2@localhost 的权限成功
6. 转换表权限...
进度: 51.72% (15/29) : 转换表权限成功
进度: 58.62% (17/29) : 转换表权限成功
进度: 68.97% (20/29) : 转换表权限成功
进度: 72.41% (21/29) : 转换表权限成功
进度: 82.76% (24/29) : 转换表权限成功
进度: 93.10% (27/29) : 转换表权限成功
进度: 95.30% (28/29) : 转换表权限成功
进度: 100.00% (29/29) : 转换表权限成功
----------------------------------------------------------------------
各阶段及耗时汇总如下:
+--------------------------+----------------+-----------------------+
| 阶段 | 对象数量 | 耗时(秒) |
+--------------------------+----------------+-----------------------+
| 转换表结构 | 4 | 0.84 |
| 同步表数据 | 4 | 1.69 |
| 转换表索引 | 1 | 0.05 |
| 转换库用户 | 5 | 0.24 |
| 转换表权限 | 15 | 1.41 |
+--------------------------+----------------+-----------------------+
| 总耗时 | | 4.23 |
+--------------------------+----------------+-----------------------+
按照指定表进行同步
当在 config.yml 配置文件 conversion 模块中把use_table_list设置成true 工具便会按照 table_list 内的表名进行转换,方便同步仅关注的表,转换完成后也会汇总该阶段的耗时。
sql
2. 同步表数据...
进度: 50.00% (1/2) : 同步表 user 数据成功,共有 0 行数据,数据校验一致
进度: 50.00% (2/2) : 同步表 users_20251201 [--------------------] 100.00%
进度: 100.00% (2/2) : 同步表 users_20251201 数据成功,共有 1 行数据,数据校验一致
----------------------------------------------------------------------
各阶段及耗时汇总如下:
+--------------------------+----------------+-----------------------+
| 阶段 | 对象数量 | 耗时(秒) |
+--------------------------+----------------+-----------------------+
| 同步表数据 | 2 | 0.91 |
+--------------------------+----------------+-----------------------+
| 总耗时 | | 0.91 |
+--------------------------+----------------+-----------------------+
在表数据同步的过程中有百分比的进度可视化,方便了解数据的同步进度。

数据同步不一致时的提示
当在 config.yml 配置文件 conversion 模块中把truncate_before_sync设置成false时存在可能会存在数据重复以及数据不一致的情况,同步时在 控制台的日志中 会显示 数据校验不一致 的提示,同时在转换完成后也会有 数据量校验不一致的表统计 的信息,方便进行排查。
sql
2. 同步表数据...
进度: 50.00% (1/2) : 同步表 user 数据成功,共有 0 行数据,数据校验一致
进度: 50.00% (2/2) : 同步表 users_20251201 [--------------------] 100.00%
进度: 100.00% (2/2) : 同步表 users_20251201 数据成功,共有 1 行数据,数据校验不一致
+------------------+----------------+------------------+
数据量校验不一致的表统计:
+------------------+----------------+------------------+
| 表名 | MySQL数据量 | PostgreSQL数据量 |
+------------------+----------------+------------------+
| users_20251201 | 1 | 2 |
+------------------+----------------+------------------+
----------------------------------------------------------------------
各阶段及耗时汇总如下:
+--------------------------+----------------+-----------------------+
| 阶段 | 对象数量 | 耗时(秒) |
+--------------------------+----------------+-----------------------+
| 同步表数据 | 2 | 0.66 |
+--------------------------+----------------+-----------------------+
| 总耗时 | | 0.66 |
+--------------------------+----------------+-----------------------+
仅转换用户及表权限时的提示
当在 config.yml 配置文件 conversion 模块中把users和table_privileges参数开启时,工具会自动转换用户以及表上的权限信息,整个过程无需手动的干预,同时也会汇总转换的对象及耗时。
sql
5. 开始转换用户...
进度: 5.00% (1/20) : 转换用户 mysql2pg@% 的权限成功
进度: 10.00% (2/20) : 转换用户 user1@% 的权限成功
进度: 15.00% (3/20) : 转换用户 user2@% 的权限成功
进度: 20.00% (4/20) : 转换用户 user1@localhost 的权限成功
进度: 25.00% (5/20) : 转换用户 user2@localhost 的权限成功
6. 转换表权限...
进度: 30.00% (6/20) : 转换表权限成功
进度: 40.00% (8/20) : 转换表权限成功
进度: 55.00% (11/20) : 转换表权限成功
进度: 60.00% (12/20) : 转换表权限成功
进度: 75.00% (15/20) : 转换表权限成功
进度: 90.00% (18/20) : 转换表权限成功
----------------------------------------------------------------------
各阶段及耗时汇总如下:
+--------------------------+----------------+-----------------------+
| 阶段 | 对象数量 | 耗时(秒) |
+--------------------------+----------------+-----------------------+
| 转换库用户 | 5 | 0.24 |
| 转换表权限 | 15 | 1.35 |
+--------------------------+----------------+-----------------------+
| 总耗时 | | 1.59 |
+--------------------------+----------------+-----------------------+
错误日志分析及执行日志查看
错误日志
MySQL2PG 工具运行时会默认在当前的路径下生成 errors.log 的日志,该日志主要会保存程序运行过程中相关错误的信息,根据该日志可以分析具体的错误原因。
sql
[2025-12-29 13:09:54] ERROR: 插入表 users_20251201 数据失败: 批量插入失败: ERROR: duplicate key value violates unique constraint "users_20251201_pkey" (SQLSTATE 23505), 数据样本: [[49] [50] [51]]
执行日志查看
MySQL2PG 工具运行时会默认在当前的路径下生成 conversion.log 的日志,该日志会详细的记录转换详细的过程,如果发现某一个过程有异常可以根据该日志进行排查。
sql
*****
[2025-12-29 14:14:17] 进度: 89.66% (26/29)
[2025-12-29 14:14:17] 表 users 在PostgreSQL中不存在,跳过权限授予
[2025-12-29 14:14:17] 进度: 93.10% (27/29)
[2025-12-29 14:14:17] 表 products 在PostgreSQL中不存在,跳过权限授予
[2025-12-29 14:14:17] 进度: 96.55% (28/29)
[2025-12-29 14:14:17] 表 orders 在PostgreSQL中不存在,跳过权限授予
[2025-12-29 14:14:17] 进度: 100.00% (29/29)
MySQL2PG 工具后续计划
MySQL的FUNCTION的自动转换成PostgreSQL函数。- 根据日志的级别在日志中添加转后的
PostgreSQL DDL的语句。 - 数据同步效率进一步优化,提升数据同步的效率。
MySQL不同版本到PostgreSQL不同版本的转换需要测试。- 在进行转换表权限时,需要提示用户权限的详细信息。
- 添加日志的级别,来显示不同的日志信息,如
INFO、DEBUG、ERROR等,避免再次生成conversion.log日志和errors.log的日志。