找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2697

积分

0

好友

353

主题
发表于 4 天前 | 查看: 18| 回复: 0

MySQL2PG 工具产生的背景

在实际迁移场景里,把 MySQL、PostgreSQL 做异构转换与同步,经常会踩到这些坑:

  1. 无法全自动把 MySQL 的 DDL 转成 PostgreSQL。转换过程中还会遇到大量语法不兼容问题,最终仍要手工修修补补,耗时耗力。  
  2. 工具无法自动化完成全量表同步,往往需要手动选择单表/批量表、配置字段映射;同步进度也缺乏可视化,很难评估整体耗时。  
  3. 无法自动同步 MySQL 的数据库用户信息:哪些用户要迁移、每个用户的密码是多少;尤其密码遗忘时,人工核对会消耗大量时间。  
  4. 无法自动同步用户权限,难以做到精细化授权控制,操作风险高。  
  5. 尤其是 MySQL 上的 FUNCTION 很难自动迁移。几百个 FUNCTION 如果靠手动转换,人力成本会非常高。

围绕这些问题,先对工具所需模块与功能做了系统梳理,并形成手稿第一版设计。

MySQL2PG 功能模块设计手稿

最终实现的模块与功能流程如下(按执行顺序):

开始
 │
 ├─▶ [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

编程工具选择

项目从 0 到 1 开发前,调研了国内主流 AI IDE 工具,包括 Trae、CodeBuddy、通义灵码,优劣势对比如下。

功能维度 Trae CodeBuddy 通义灵码
AI 核心模式 支持 Builder 和 Builder MCP 的模式 Craft 智能体、双模型驱动 支持智能代码补全、智能校验代码质量、测试 CASE 生成
代码生成能力 支持从 0-1 项目的生成 支持不同的语言 支持代码的优化、代码提示、代码续写
多模态支持 支持 go/java/Python/C++ 支持流程的编排、智能体的协作 编程智能体、工程级变更
生态集成 支持 VS Code 插件 支持微信生态、腾讯云服务等 阿里云生态、可对接钉钉

由于该项目需要从 0 开始,并且选用 Go 语言开发,开发过程中更依赖“理解上下文 + 自动编排代码 + 生成测试步骤”的能力,因此最终选择 Trae 作为开发工具。

参考资料:
trae: https://www.trae.cn/
codebuddy: https://www.codebuddy.ai/
通义灵码: https://lingma.aliyun.com/

为什么会选择 golang?主要考虑到 Golang 可直接编译为机器码,具备运行效率快、跨平台、内存占用率少、启动快、可二进制部署等特点。

工具整体功能效果

使用的软件版本

本次测试使用 MySQL 与 PostgreSQL 单机版,版本信息如下:

-- 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)

使用的数据集

  1. MySQL 数据库中包含不同字段类型、不同存储引擎、不同字符编码、涉及关键字、主外键、自增列等,共 1339 张表用于自动转换。  
  2. 1339 张表共有 1768 个索引,包含主键索引、单字段索引、复合索引等。  
  3. 数据库内存在 5 个不同用户:有的用户仅有 SELECT 权限、有的仅有 DELETE 权限、有的仅有 UPDATE 权限,有的用户对几十张表具有全部操作权限。  
  4. 实际测试转换对象数量汇总如下:
+--------------------------+----------------+
| 阶段                     | 对象数量       |
+--------------------------+----------------+
| 转换表结构               | 1339           |
| 同步表数据               | 1339           |
| 转换表索引               | 1768           |
| 转换库用户               | 5              |
| 转换表权限               | 15             |
+--------------------------+----------------+

仅测试连接部分

config.yml 中提供测试连接参数 test_only。当该参数开启时,仅测试数据库连接,其余步骤不执行;连接测试完成后输出版本信息并退出。

mysql.test_only = true 时,仅测试连接 MySQL,日志如下:

+-------------------------------------------------------------+
1. MySQL连接测试完成,版本信息已显示,退出程序。
+-------------------------------------------------------------+
| 数据库版本信息:                                             |
+--------------+----------------------------------------------+
| 数据库类型   | 版本信息                                     |
+--------------+----------------------------------------------+
| MySQL        | 5.7.44                                       |
| PostgreSQL   | PostgreSQL 16.1 on x86_64-pc-linux-gn...      |
+--------------+----------------------------------------------+

postgresql.test_only = true 时,仅测试连接 PostgreSQL,日志如下:

+-------------------------------------------------------------+
2. PostgreSQL 连接测试完成,版本信息已显示,退出程序。
+-------------------------------------------------------------+
| 数据库版本信息:                                             |
+--------------+----------------------------------------------+
| 数据库类型   | 版本信息                                     |
+--------------+----------------------------------------------+
| MySQL        | 5.7.44                                       |
| PostgreSQL   | PostgreSQL 16.1 on x86_64-pc-linux-gn...      |
+--------------+----------------------------------------------+

全流程运行结果

config.ymlconversion 模块中分别开启 tableddl/data/indexes/users/table_privileges/validate_data 后,工具会按顺序依次执行,并在完成后汇总各阶段对象数量与耗时。

示例日志如下(截取):

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.ymlconversion 模块中把 use_table_list 设置为 true 时,工具会仅同步 table_list 中的表,适合只迁移关注表的场景;完成后同样会汇总耗时。

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                  |
+--------------------------+----------------+-----------------------+

同步过程中会显示百分比进度,便于随时掌握数据同步状态。

指定同步表进度展示

数据同步不一致时的提示

当把 truncate_before_sync 设置为 false 时,可能出现数据重复或不一致。同步期间控制台日志会提示 数据校验不一致,并在完成后输出 数据量校验不一致的表统计,方便定位问题。

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.ymlconversion 模块中只开启 userstable_privileges 时,工具会自动转换用户与表权限,全程无需手动干预,并在结束后汇总转换对象与耗时。

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,用于记录运行过程中的错误信息。排查失败原因时,优先从这里入手更高效。

[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,用于记录详细转换过程。如果某一步出现异常,可结合该日志快速定位问题(例如表不存在、权限跳过等)。

*****
[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)

如果你平时也在做迁移/同步的稳定性建设,把转换与运行日志纳入日常巡检流程会更稳;相关实践也经常会落到 运维/DevOps/SRE 的范畴里。

MySQL2PG 工具后续计划

  1. 支持 MySQL 的 FUNCTION 自动转换为 PostgreSQL 函数。  
  2. 根据日志级别,在日志中增加转换后的 PostgreSQL DDL 语句。  
  3. 继续优化数据同步效率,提升吞吐与总体耗时表现。  
  4. 增加 MySQL 不同版本到 PostgreSQL 不同版本的转换测试覆盖。  
  5. 转换表权限时,增加对用户权限明细的提示。  
  6. 增加日志级别(如 INFO、DEBUG、ERROR 等),避免重复生成 conversion.logerrors.log,并让日志更易检索与定位。

推荐阅读与讨论:你可以在 云栈社区 继续交流 MySQL/PostgreSQL 迁移与工具落地的细节问题。




上一篇:深入解析YOLOv8模型输出、后处理流程及DFL计算
下一篇:掌握DevOps核心能力:一张图看懂从代码到用户的完整建设链路
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-24 00:26 , Processed in 1.251452 second(s), 45 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表