当前位置: 首页 > news >正文

PostgreSQL:详解 MySQL数据迁移,如何将数据平滑迁移到PostgreSQL

文章目录

    • 一、迁移前评估与准备
      • 1.1 明确迁移目标
      • 1.2 兼容性分析
      • 1.3 数据量与停机窗口评估
    • 二、迁移工具选型与对比
      • 2.1 主流工具概览
    • 三、使用 pgloader 进行自动化迁移(推荐方案)
      • 3.1 安装 pgloader
      • 3.2 编写迁移配置文件(`migrate.load`)
      • 3.3 关键配置说明
      • 3.4 执行迁移
    • 四、数据类型与函数转换详解
      • 4.1 常见数据类型映射
      • 4.2 函数与操作符转换
    • 五、处理自增主键与序列
      • 5.1 MySQL 的 AUTO_INCREMENT
      • 5.2 PostgreSQL 的实现方式
        • 方式一:`SERIAL`(旧版)
        • 方式二:`IDENTITY`(SQL 标准,PG 10+ 推荐)
      • 5.3 迁移后修复序列值
    • 六、索引、约束与性能调优
      • 6.1 索引转换
      • 6.2 外键与约束
      • 6.3 性能调优建议
    • 七、应用层适配与 SQL 改造
      • 7.1 ORM 适配
      • 7.2 常见 SQL 改造点
      • 7.3 事务与锁行为差异
    • 八、数据一致性验证
      • 8.1 行数校验
      • 8.2 校验和比对(关键表)
      • 8.3 抽样比对
      • 8.4 应用端冒烟测试
    • 九、上线切换策略
      • 9.1 停机迁移(小系统)
      • 9.2 双写 + 切读(中大型系统)
      • 9.3 CDC 实时同步(零停机)
    • 十、常见问题
      • 10.1 字符集与排序规则
      • 10.2 0000-00-00 日期问题
      • 10.3 反引号与关键字冲突
      • 10.4 大对象(BLOB)迁移

将数据从 MySQL 平滑迁移到 PostgreSQL 是许多企业因成本、开源策略、功能需求或云架构调整而采取的关键举措。尽管两者均为关系型数据库,但在SQL 语法、数据类型、事务模型、索引机制、函数生态等方面存在显著差异。若处理不当,迁移过程易出现数据丢失、性能下降、应用中断等问题。

参考资源:

  • pgloader 官网:https://pgloader.io/
  • PostgreSQL vs MySQL 对比:https://wiki.postgresql.org/wiki/Converting_from_other_Databases_to_PostgreSQL
  • AWS DMS 文档:https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MySQL.html

一、迁移前评估与准备

1.1 明确迁移目标

  • 降低成本:摆脱 MySQL 商业许可(如 Oracle MySQL Enterprise)
  • 功能增强:利用 PG 的 JSONB、GIS(PostGIS)、全文检索、窗口函数、物化视图等高级特性
  • 架构统一:已有 PG 技术栈,希望统一数据库平台
  • 云战略:迁移到 AWS RDS/Aurora PostgreSQL、Azure Database for PostgreSQL 等托管服务

1.2 兼容性分析

使用工具扫描 MySQL 模式,识别潜在问题:

差异点MySQLPostgreSQL迁移影响
标识符大小写默认不区分(Linux 区分)严格区分("Name"name需统一命名规范
字符串比较忽略尾部空格严格比较可能导致 JOIN/UNIQUE 失败
布尔类型无原生 BOOLEAN,用 TINYINT(1)原生 BOOLEAN需转换字段类型
自增主键AUTO_INCREMENTSERIAL/IDENTITYDDL 需重写
LIMIT/OFFSETLIMIT offset, countLIMIT count OFFSET offset应用 SQL 需调整
字符串连接CONCAT()或 ``(需开启)
日期时间DATETIME无时区TIMESTAMP/TIMESTAMPTZ时区处理需谨慎
默认值函数NOW(),CURDATE()CURRENT_TIMESTAMP,CURRENT_DATE函数替换
反引号`table`双引号"table"或无引号需转义或移除

推荐工具:Ora2Pg(虽名含 Ora,但支持 MySQL 模式解析)、pgloader内置检查、自定义脚本。

1.3 数据量与停机窗口评估

  • 小数据量(< 100 GB):可接受短暂停机(分钟级)
  • 中大数据量(100 GB ~ 10 TB):需采用在线迁移 + 增量同步,最小化停机时间
  • 超大数据量(> 10 TB):考虑分库分表迁移、并行导出导入

二、迁移工具选型与对比

2.1 主流工具概览

工具类型优点缺点适用场景
pgloader开源 ETL自动转换 DDL/DML,支持在线迁移,速度快复杂函数/存储过程不支持中小规模,结构简单
AWS DMS托管服务支持 CDC(变更数据捕获),零停机费用高,需 AWS 环境云上迁移,大企业
MySQL to PostgreSQL (from Intelligent Converters)商业软件图形界面,支持触发器/存储过程闭源,收费无开发资源团队
自定义脚本(mysqldump + sed + psql)手动完全可控易出错,维护成本高特殊定制需求
Debezium + Kafka + Sink Connector流式架构实时同步,高可用架构复杂超大规模,高可用要求

推荐组合

  • 中小项目pgloader(主力) + 手动修正
  • 大型项目AWS DMSDebezium(增量) +pgloader(全量)

三、使用 pgloader 进行自动化迁移(推荐方案)

3.1 安装 pgloader

# Ubuntu/Debiansudoaptinstallpgloader# macOSbrewinstallpgloader# 源码编译(推荐最新版)gitclone https://github.com/dimitri/pgloader.gitcdpgloadermakepgloader

3.2 编写迁移配置文件(migrate.load

LOAD DATABASE FROM mysql://user:pass@mysql-host:3306/source_db INTO postgresql://pguser:pgpass@pg-host:5432/target_db WITH include only table names like'users','orders', create tables, create indexes, reset sequences, workers = 8, concurrency =1CAST type datetime to timestamptz drop default drop not null, type date to date drop default, type tinyint to boolean using inline cast, type varchar to varchar drop typemod AFTER LOAD DO $$ ALTER TABLE users ALTER COLUMN created_at SET DEFAULT NOW();CREATE INDEX CONCURRENTLY idx_orders_user_id ON orders(user_id);$$;

3.3 关键配置说明

  • include only table names:按需迁移表,避免无关数据
  • create tables:自动建表(基于转换后 DDL)
  • reset sequences:修复自增 ID 序列值
  • CAST:类型映射规则(核心!)
    • datetime → timestamptz:保留时区信息
    • tinyint(1) → boolean:将 0/1 转为 true/false
    • varchar(N) → varchar:移除长度限制(PG 支持无限长)
  • AFTER LOAD DO:迁移后执行 SQL(如重建索引、设默认值)

3.4 执行迁移

pgloader migrate.load

输出包含错误日志、性能统计、未处理对象列表,便于排查。


四、数据类型与函数转换详解

4.1 常见数据类型映射

MySQL 类型PostgreSQL 推荐类型注意事项
INT,BIGINTINT4,INT8直接映射
TINYINT(1)BOOLEAN仅当表示真假时
TINYINT(n>1)SMALLINT避免误转 BOOLEAN
VARCHAR(N)VARCHARTEXTPG 无性能差异,建议用 TEXT
TEXT,MEDIUMTEXTTEXT统一为 TEXT
DATETIMETIMESTAMP WITHOUT TIME ZONE若无时区需求
DATETIMETIMESTAMPTZ若需时区转换(推荐)
DATEDATE直接映射
DECIMAL(M,D)NUMERIC(M,D)精确数值
FLOAT,DOUBLEREAL,DOUBLE PRECISION直接映射
ENUMTEXT+ CHECK 约束 或 自定义 DOMAINPG 不推荐 ENUM
JSONJSONB推荐 JSONB(支持索引、更快)
BLOBBYTEA二进制数据

4.2 函数与操作符转换

MySQL 表达式PostgreSQL 等效写法
NOW()CURRENT_TIMESTAMP
CURDATE()CURRENT_DATE
IFNULL(a, b)COALESCE(a, b)
ISNULL(a)a IS NULL
CONCAT(a, b)`a
SUBSTRING(str, pos, len)SUBSTR(str, pos, len)(pos 从 1 开始)
RAND()RANDOM()
LIMIT 10, 20LIMIT 20 OFFSET 10
`column`"column"或直接column(若无关键字冲突)

建议:在应用层统一替换,或通过 PostgreSQL 的自定义函数兼容:

CREATEFUNCTIONifnull(anyelement,anyelement)RETURNSanyelementAS$$SELECTcoalesce($1,$2);$$LANGUAGEsql;

五、处理自增主键与序列

5.1 MySQL 的 AUTO_INCREMENT

  • 每张表独立计数器
  • 插入时可显式指定 ID(需开启NO_AUTO_VALUE_ON_ZERO

5.2 PostgreSQL 的实现方式

方式一:SERIAL(旧版)
CREATETABLEusers(idSERIALPRIMARYKEY,-- 自动创建 sequence users_id_seqnameTEXT);
方式二:IDENTITY(SQL 标准,PG 10+ 推荐)
CREATETABLEusers(idINTGENERATEDBYDEFAULTASIDENTITYPRIMARYKEY,nameTEXT);

5.3 迁移后修复序列值

若数据已导入但序列未更新,会导致主键冲突:

-- 方法1:pgloader 自动处理(启用 reset sequences)-- 方法2:手动重置SELECTsetval('users_id_seq',(SELECTMAX(id)FROMusers));

注意:IDENTITY列的序列名可通过pg_get_serial_sequence('users', 'id')获取。


六、索引、约束与性能调优

6.1 索引转换

  • 普通索引CREATE INDEX直接迁移
  • 唯一索引UNIQUE约束自动创建索引
  • 全文索引:MySQL 的FULLTEXT需重写为 PG 的tsvector+ GIN/GiST 索引
    ALTERTABLEarticlesADDCOLUMNtitle_ts tsvector;UPDATEarticlesSETtitle_ts=to_tsvector('english',title);CREATEINDEXidx_title_ftsONarticlesUSINGGIN(title_ts);
  • 前缀索引:MySQL 支持INDEX(col(10)),PG 不支持,需用表达式索引:
    CREATEINDEXONusers((left(email,10)));

6.2 外键与约束

  • PG 默认启用外键约束,确保参照完整性
  • 若 MySQL 未启用外键,迁移后需评估是否添加
  • 使用NOT VALID延迟验证大表外键:
    ALTERTABLEordersADDCONSTRAINTfk_userFOREIGNKEY(user_id)REFERENCESusers(id)NOTVALID;ALTERTABLEorders VALIDATECONSTRAINTfk_user;-- 后台验证

6.3 性能调优建议

  • 批量插入:关闭 autovacuum、增大maintenance_work_mem
  • 并行迁移:pgloader 的workersconcurrency参数
  • 目标库配置
    shared_buffers = 4GB effective_cache_size = 12GB work_mem = 64MB max_wal_size = 4GB

七、应用层适配与 SQL 改造

7.1 ORM 适配

  • Sequelize / TypeORM / Django ORM:切换 dialect 为postgres,调整连接字符串
  • MyBatis:修改 XML 中的函数(如NOW()CURRENT_TIMESTAMP
  • Laravel Eloquent:基本兼容,注意分页语法(skip/takevsoffset/limit

7.2 常见 SQL 改造点

场景MySQLPostgreSQL
分页LIMIT 10 OFFSET 20同左(但 OFFSET 不能为负)
插入返回 IDINSERT ...; SELECT LAST_INSERT_ID();INSERT ... RETURNING id;
字符串转日期STR_TO_DATE('20250101','%Y%m%d')TO_DATE('20250101','YYYYMMDD')
随机排序ORDER BY RAND()ORDER BY RANDOM()
获取当前数据库DATABASE()current_database()

7.3 事务与锁行为差异

  • 默认隔离级别:MySQL(RR),PG(Read Committed)
  • 幻读处理:PG 在 RC 下无幻读(MVCC 实现不同)
  • 锁粒度:PG 行锁更精细,死锁检测更主动
  • 建议:测试高并发场景,必要时显式设置隔离级别:
    BEGINISOLATIONLEVELREPEATABLEREAD;

八、数据一致性验证

8.1 行数校验

-- MySQLSELECTCOUNT(*)FROMusers;-- PostgreSQLSELECTCOUNT(*)FROMusers;

8.2 校验和比对(关键表)

-- MySQLSELECTMD5(GROUP_CONCAT(CONCAT(id,name,email)ORDERBYid))FROMusers;-- PostgreSQLSELECTMD5(STRING_AGG(CONCAT(id,name,email),''ORDERBYid))FROMusers;

注意:需处理 NULL(CONCAT在 PG 中遇 NULL 返回 NULL,可用COALESCE

8.3 抽样比对

  • 随机抽取 1000 行,逐字段比对
  • 重点验证:时间戳、浮点数、布尔值、JSON 内容

8.4 应用端冒烟测试

  • 核心业务流程(注册、下单、查询)端到端测试
  • 监控错误日志、慢查询

九、上线切换策略

9.1 停机迁移(小系统)

  1. 停写 MySQL
  2. 执行最终增量同步(如有)
  3. 切换应用连接字符串至 PG
  4. 验证后恢复服务

9.2 双写 + 切读(中大型系统)

  1. 应用同时写 MySQL 和 PG(双写)
  2. 数据校验工具持续比对
  3. 逐步切读流量至 PG(如 10% → 50% → 100%)
  4. 确认稳定后停写 MySQL

9.3 CDC 实时同步(零停机)

  • 使用Debezium捕获 MySQL binlog
  • 通过 Kafka 将变更同步至 PG
  • 切换瞬间仅需处理秒级延迟数据

工具链:MySQL → Debezium → Kafka → Kafka Connect JDBC Sink → PostgreSQL


十、常见问题

10.1 字符集与排序规则

  • MySQL 默认utf8mb4+utf8mb4_general_ci(不区分大小写)
  • PostgreSQL 默认UTF8+en_US.UTF-8(区分大小写)
  • 解决方案
    • 应用层统一转小写比较
    • 或创建不区分大小写的 collation(PG 12+):
      CREATECOLLATION case_insensitive(provider=icu,locale='und-u-ks-level2');CREATETABLEusers(nameTEXTCOLLATE"case_insensitive");

10.2 0000-00-00 日期问题

  • MySQL 允许0000-00-00,PG 不允许
  • 迁移前清洗
    UPDATEtableSETdate_col=NULLWHEREdate_col='0000-00-00';

10.3 反引号与关键字冲突

  • MySQL 用反引号包裹关键字(如`order`
  • PG 用双引号("order"),但建议重命名字段避免冲突

10.4 大对象(BLOB)迁移

  • pgloader 支持BYTEA,但超大文件(>1GB)建议单独迁移
  • 或存储为文件路径,数据库仅存 URL

总结:MySQL 到 PostgreSQL 的迁移是一项系统工程,成功的关键在于:

  • 充分评估:识别语法、类型、行为差异
  • 工具赋能:以pgloader为核心,自动化 DDL/DML 转换
  • 渐进切换:通过双写、CDC 实现零停机
  • 全面验证:行数、校验和、业务逻辑三层保障
  • 长期优化:迁移后利用 PG 特性(JSONB、分区表、扩展)提升系统能力

PostgreSQL 以其标准兼容性、功能丰富性、社区活跃度,已成为 MySQL 的强大替代者。通过科学规划与严谨执行,迁移不仅是一次技术栈升级,更是系统架构现代化的重要契机。

http://www.jsqmd.com/news/389515/

相关文章:

  • 基于Nunchaku FLUX.1 CustomV3的动漫角色设计工作流
  • 2026年知名的走心机/精密加工走心机生产厂家采购指南帮我推荐几家 - 行业平台推荐
  • FLUX.1-dev-fp8-dit文生图快速部署教程:Docker镜像拉取→ComfyUI加载→风格切换三步法
  • Krea:SLG 建筑画到死?“实时渲染流”草图秒变等轴精修
  • 基于RexUniNLU的Visio流程图智能生成工具
  • Immersity:游戏登录界面像PPT?“伪3D视差流”,一张JPG也能做空间运镜
  • 2026年质量好的宁波化妆品注塑机/化妆品注塑机厂家推荐哪家好(高评价) - 行业平台推荐
  • 2026年热门的冷却塔填料/冷却塔实用供应商采购指南如何选 - 行业平台推荐
  • 2026年知名的宁波柔性力控打磨头/柔性打磨头厂家选择指南怎么选(真实参考) - 行业平台推荐
  • 查看自己电脑公网ip
  • 2026年比较好的江西原木全屋定制/高端整木全屋定制哪家靠谱可靠供应商参考 - 行业平台推荐
  • 题解:洛谷 P1152 欢乐的跳
  • Node.js 后端架构的“隐秘角落”:从 Fastify 引擎到类型框架的博弈
  • 2026年知名的加拿大签证/英国签证稳定服务推荐机构 - 行业平台推荐
  • 2026年评价高的数字科技数据化/四川数字科技工程公司口碑推荐哪家靠谱 - 行业平台推荐
  • 2026年质量好的江苏橡胶膨胀节/膨胀节厂家口碑推荐汇总 - 品牌宣传支持者
  • 2026年苏州做得好的家教机构哪家好,师范家教/一对一/大学生家教/封闭式全托集训营/家教/一对一家教,家教机构怎么收费 - 品牌推荐师
  • 2026年热门的上海露天矿无人驾驶/上海无人驾驶可靠供应商参考推荐几家 - 行业平台推荐
  • 2026年口碑好的国家研发的低GI包子馒头/舒汇慢谷低GI青菜包子馒头哪家强公司实力参考(精选) - 行业平台推荐
  • 好用还专业! 继续教育论文降AI神器 —— 千笔·专业降AI率智能体
  • 2026年靠谱的活性炭废气处理设备/废气处理设备用户好评厂家推荐 - 行业平台推荐
  • 对比一圈后!抢手爆款的AI论文软件 —— 千笔AI
  • LeVERB框架——基于潜在视觉-语言指令的人形全身控制 解读
  • 2026年质量好的套筒补偿器/江苏金属波纹补偿器厂家专业度参考(精选) - 品牌宣传支持者
  • 2026年知名的压铸件喷砂机/粉末冶金喷砂机厂家实力参考 - 品牌宣传支持者
  • 有序数组单一元素查找:从通用解法到算法极致优化——兼谈高性能计算基础思路
  • 学习笔记|LeetCode 739 每日温度:从暴力枚举到单调栈线性最优解
  • 世毫九实验室(Shardy Lab)深度调研报告——原创AGI根规则与碳硅共生体系:定位、技术、价值与风险评估
  • 2026年靠谱的大型洗涤设备/毛巾洗涤设备厂家选购完整指南 - 品牌宣传支持者
  • 2026年质量好的ETFE太阳能板/深圳异型太阳能板热门厂家推荐汇总 - 品牌宣传支持者