文章目录
- 一、迁移前评估与准备
- 1.1
明确迁移目标
- 1.2
数据量与停机窗口评估
- 1.1
- 二、迁移工具选型与对比
- 2.1
pgloader
进行自动化迁移(推荐方案)
- 3.1
pgloader
- 3.2
编写迁移配置文件(`migrate.load`)
- 3.3
关键配置说明
- 3.4
执行迁移
- 3.1
- 四、数据类型与函数转换详解
- 4.1
常见数据类型映射
- 4.2
函数与操作符转换
- 4.1
- 五、处理自增主键与序列
- 5.1
MySQL
的实现方式
- 方式一:`SERIAL`(旧版)
- 方式二:`IDENTITY`(SQL
标准,PG
推荐)
- 5.3
迁移后修复序列值
- 5.1
- 六、索引、约束与性能调优
- 6.1
索引转换
- 6.2
性能调优建议
- 6.1
- 七、应用层适配与
SQL
事务与锁行为差异
- 2.1
- 八、数据一致性验证
- 8.1
行数校验
- 8.2
校验和比对(关键表)
- 8.3
抽样比对
- 8.4
应用端冒烟测试
- 8.1
- 九、上线切换策略
- 9.1
停机迁移(小系统)
- 9.2
+
切读(中大型系统)
- 9.3
CDC
实时同步(零停机)
- 9.1
- 十、常见问题
- 10.1
0000-00-00
大对象(BLOB)迁移
- 10.1
将数据从
MySQL
是许多企业因成本、开源策略、功能需求或云架构调整而采取的关键举措。
尽管两者均为关系型数据库,但在SQL
语法、数据类型、事务模型、索引机制、函数生态等方面存在显著差异。
若处理不当,迁移过程易出现数据丢失、性能下降、应用中断等问题。
参考资源:
- pgloader
官网:https://pgloader.io/
- PostgreSQL
MySQL
对比:https://wiki.postgresql.org/wiki/Converting_from_o***r_Databases_to_PostgreSQL
- AWS
DMS
文档:https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Source.MySQL.html
明确迁移目标
- 降低成本:摆脱
MySQL
Enterprise)
- 功能增强:利用
JSONB、GIS(PostGIS)、全文检索、窗口函数、物化视图等高级特性
- 架构统一:已有
技术栈,希望统一数据库平台
- 云战略:迁移到
AWS
模式,识别潜在问题:
差异点 MySQL PostgreSQL 迁移影响 标识符大小写 默认不区分(Linux 区分)
严格区分( "Name"≠name)需统一命名规范 字符串比较 忽略尾部空格 严格比较 可能导致 JOIN/UNIQUE
失败
布尔类型 无原生 BOOLEAN,用
BOOLEAN
需转换字段类型 自增主键 AUTO_INCREMENTSERIAL/IDENTITYDDL 需重写
LIMIT/OFFSET LIMIToffset,
count
LIMITcount
需调整
字符串连接 CONCAT()或`
`(需开启) 日期时间 DATETIME无时区TIMESTAMP/TIMESTAMPTZ时区处理需谨慎 默认值函数 NOW(),CURDATE()CURRENT_TIMESTAMP,CURRENT_DATE函数替换 反引号 `table`双引号 "table"或无引号需转义或移除 推荐工具:Ora2Pg(虽名含
Ora,但支持
模式解析)、pgloader内置检查、自定义脚本。
1.3
数据量与停机窗口评估
- 小数据量(<
100
GB)
:可接受短暂停机(分钟级) - 中大数据量(100
TB)
:需采用在线迁移+
增量同步
,最小化停机时间 - 超大数据量(>
TB)
:考虑分库分表迁移、并行导出导入
主流工具概览
工具 类型 优点 缺点 适用场景 pgloader 开源 ETL
自动转换 DDL/DML,支持在线迁移,速度快
复杂函数/存储过程不支持 中小规模,结构简单 AWS DMS
托管服务 支持 CDC(变更数据捕获),零停机
费用高,需 AWS
环境
云上迁移,大企业 MySQL PostgreSQL
Converters)
商业软件 图形界面,支持触发器/存储过程 闭源,收费 无开发资源团队 自定义脚本(mysqldump +
psql)
手动 完全可控 易出错,维护成本高 特殊定制需求 Debezium +
Connector
流式架构 实时同步,高可用 架构复杂 超大规模,高可用要求 推荐组合:
- 中小项目:
pgloader(主力)+
手动修正
- 大型项目:
AWS或DMS
Debezium(增量)+
pgloader(全量)
/>
三、使用
进行自动化迁移(推荐方案)
3.1
pgloader
#Ubuntu/Debian
sudoaptinstallpgloader#macOS
brewinstallpgloader#源码编译(推荐最新版)
gitclonehttps://github.com/dimitri/pgloader.gitcdpgloadermakepgloader
3.2
编写迁移配置文件(
migrate.load)LOADDATABASE
mysql://user:pass@mysql-host:3306/source_db
INTO
postgresql://pguser:pgpass@pg-host:5432/target_db
WITH
like'users','orders',
create
NOW();CREATE
INDEX
orders(user_id);$$;
3.3
关键配置说明
include:按需迁移表,避免无关数据only
names
create:自动建表(基于转换后tables
DDL)
reset序列值
CAST:类型映射规则(核心!)datetime:保留时区信息timestamptz
tinyint(1)0/1
true/false
varchar(N):移除长度限制(PGvarchar
支持无限长)
AFTERLOAD
SQL(如重建索引、设默认值)
3.4
migrate.load
输出包含错误日志、性能统计、未处理对象列表,便于排查。
/>
四、数据类型与函数转换详解
4.1
常见数据类型映射
MySQL 推荐类型
注意事项 INT,BIGINTINT4,INT8直接映射 TINYINT(1)BOOLEAN仅当表示真假时 TINYINT(n>1)SMALLINT避免误转 BOOLEAN
VARCHAR(N)VARCHAR或TEXTPG 无性能差异,建议用
TEXT
TEXT,MEDIUMTEXTTEXT统一为 TEXT
DATETIMETIMESTAMPWITHOUT
ZONE
若无时区需求 DATETIMETIMESTAMPTZ若需时区转换(推荐) DATEDATE直接映射 DECIMAL(M,D)NUMERIC(M,D)精确数值 FLOAT,DOUBLEREAL,DOUBLEPRECISION
直接映射 ENUMTEXT+CHECK
ENUM
JSONJSONB推荐 JSONB(支持索引、更快)
BLOBBYTEA二进制数据 4.2
函数与操作符转换
MySQL 等效写法
NOW()CURRENT_TIMESTAMPCURDATE()CURRENT_DATEIFNULL(a,b)
COALESCE(a,b)
ISNULL(a)aNULL
CONCAT(a,b)
`a SUBSTRING(str,pos,
len)
SUBSTR(str,pos,
开始)
RAND()RANDOM()LIMIT10,
10
`column`"column"或直接column(若无关键字冲突)建议:在应用层统一替换,或通过
PostgreSQL
的自定义函数兼容:
CREATEFUNCTIONifnull(anyelement,anyelement)RETURNSanyelementAS$$SELECTcoalesce($1,$2);$$LANGUAGEsql;MySQL
AUTO_INCREMENT
- 每张表独立计数器
- 插入时可显式指定
ID(需开启
NO_AUTO_VALUE_ON_ZERO)
5.2
PostgreSQL
的实现方式
方式一:
SERIAL(旧版)CREATETABLEusers(idSERIALPRIMARYKEY,--自动创建
users_id_seq
nameTEXT);方式二:
IDENTITY(SQL标准,PG
推荐)
CREATETABLEusers(idINTGENERATEDBYDEFAULTASIDENTITYPRIMARYKEY,nameTEXT);5.3
迁移后修复序列值
若数据已导入但序列未更新,会导致主键冲突:
--方法1:pgloader
sequences)
--方法2:手动重置
SELECTsetval('users_id_seq',(SELECTMAX(id)FROMusers));注意:
IDENTITY列的序列名可通过pg_get_serial_sequence('users','id')获取。
索引转换
- 普通索引:
CREATE直接迁移INDEX
- 唯一索引:
UNIQUE约束自动创建索引 - 全文索引:MySQL
GIN/GiST
索引
ALTERTABLEarticlesADDCOLUMNtitle_tstsvector;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;ALTERTABLEordersVALIDATECONSTRAINTfk_user;--
后台验证
6.3
性能调优建议
- 批量插入:关闭
autovacuum、增大
maintenance_work_mem - 并行迁移:pgloader
的
workers和concurrency参数 - 目标库配置:
shared_buffers=
适配
- Sequelize
TypeORM
为
postgres,调整连接字符串 - MyBatis:修改
XML
中的函数(如
NOW()→CURRENT_TIMESTAMP) - Laravel
Eloquent
:基本兼容,注意分页语法(skip/takevsoffset/limit)
7.2
SQL
改造点
场景 MySQL PostgreSQL 分页 LIMITOFFSET
不能为负)
插入返回 ...;
LAST_INSERT_ID();
INSERT...
id;
字符串转日期 STR_TO_DATE('20250101','%Y%m%d')TO_DATE('20250101','YYYYMMDD')随机排序 ORDERRAND()
ORDERRANDOM()
获取当前数据库 DATABASE()current_database()7.3
事务与锁行为差异
- 默认隔离级别:MySQL(RR),PG(Read
Committed)
- 幻读处理:PG
下无幻读(MVCC
实现不同)
- 锁粒度:PG
行锁更精细,死锁检测更主动
- 建议:测试高并发场景,必要时显式设置隔离级别:
BEGINISOLATIONLEVELREPEATABLEREAD;
MySQLSELECTCOUNT(*)FROMusers;--
PostgreSQLSELECTCOUNT(*)FROMusers;
8.2
校验和比对(关键表)
--MySQL
SELECTMD5(GROUP_CONCAT(CONCAT(id,name,email)ORDERBYid))FROMusers;--PostgreSQL
SELECTMD5(STRING_AGG(CONCAT(id,name,email),''ORDERBYid))FROMusers;注意:需处理
NULL(
CONCAT在NULL
NULL,可用
COALESCE)8.3
1000
行,逐字段比对
- Sequelize
- 重点验证:时间戳、浮点数、布尔值、JSON
内容
8.4
应用端冒烟测试
- 核心业务流程(注册、下单、查询)端到端测试
- 监控错误日志、慢查询
停机迁移(小系统)
- 停写
MySQL
- 执行最终增量同步(如有)
- 切换应用连接字符串至
PG
- 验证后恢复服务
9.2
+
切读(中大型系统)
- 应用同时写
MySQL
PG(双写)
- 数据校验工具持续比对
- 逐步切读流量至
PG(如
实时同步(零停机)
- 使用Debezium捕获
MySQL
PG
- 切换瞬间仅需处理秒级延迟数据
工具链:MySQL
Debezium
字符集与排序规则
- MySQL
默认
:utf8mb4+utf8mb4_general_ci(不区分大小写) - PostgreSQL
默认
:UTF8+en_US.UTF-8(区分大小写) - 解决方案:
- 应用层统一转小写比较
- 或创建不区分大小写的
collation(PG
12+):
CREATECOLLATIONcase_insensitive(provider=icu,locale='und-u-ks-level2');CREATETABLEusers(nameTEXTCOLLATE"case_insensitive");
10.2
0000-00-00
允许
0000-00-00,PG不允许
- 使用Debezium捕获
- 迁移前清洗:
UPDATEtableSETdate_col=NULLWHEREdate_col='0000-00-00';
- 小数据量(<
10.3
用反引号包裹关键字(如`order`)
用双引号("order"),但建议重命名字段避免冲突
10.4
大对象(BLOB)迁移
- pgloader
支持
BYTEA,但超大文件(>1GB)建议单独迁移 - 或存储为文件路径,数据库仅存
URL
的迁移是一项系统工程,成功的关键在于:
- 充分评估:识别语法、类型、行为差异
- 工具赋能:以
pgloader为核心,自动化DDL/DML
转换
- 渐进切换:通过双写、CDC
实现零停机
- 全面验证:行数、校验和、业务逻辑三层保障
- 长期优化:迁移后利用
特性(JSONB、分区表、扩展)提升系统能力
PostgreSQL
以其标准兼容性、功能丰富性、社区活跃度,已成为
MySQL
的强大替代者。
通过科学规划与严谨执行,迁移不仅是一次技术栈升级,更是系统架构现代化的重要契机。


