尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MySQL/Oracle迁移瀚高数据库实战:工具使用、配置调优与踩坑记录

MySQL/Oracle迁移瀚高数据库实战:工具使用、配置调优与踩坑记录 简介这是一份面向数据库迁移实施人员与运维开发的实用资源聚焦将MySQL、Oracle等主流数据库平滑迁移至瀚高数据库HGDB的场景。该迁移工具提供图形化操作界面支持通过新建源库与目标库连接、创建迁移任务、选择库表及字段类型匹配等步骤完成数据搬迁具体操作中常见的时间字段类型映射如将datetime调整为TIMESTAMP也有清晰指引。资源以RAR压缩包形式发布大小约247.77MB目前已有1819人学习下载。整份资料既包含工具本体也附带阅读说明与操作示例能够帮助读者理解从连接配置、任务启动到迁移日志核查的完整链路遇到错误时还可利用界面中的错误统计入口定位详情便于快速排查与二次迁移对正在推进国产数据库替换或业务上线的团队具有直接参考价值。1. 项目概述与迁移背景1.1 为什么需要这样一个迁移工具先说一个背景国内很多企业过去十年核心业务都跑在 MySQL 或 Oracle 上随着信创改造和数据库国产化逐步落地把存量业务迁到国产数据库成了绕不开的硬任务。瀚高数据库HighGo Database作为基于 PostgreSQL 内核的国产关系型数据库这几年在政务、金融、能源行业落地不少但真正卡进度的往往不是数据库本身而是怎么把老库里的东西弄过来。我第一次接触瀚高数据库迁移工具是在一个电力行业的项目上。客户那边生产环境是 Oracle 11g还有两套 MySQL 5.7 的分库分表要求在一个月内把核心业务切换到瀚高数据库上。当时第一反应是又要手工导表结构、对类型、改存储过程了吧结果用了瀚高自带的 migration 工具之后整个流程比我预想中顺畅不少但也不是开箱即用坑仍然不少。这篇博文就把我从 MySQL 和 Oracle 两个方向迁移到瀚高的完整经验整理出来包括工具的使用思路、参数配置、常见报错排查以及那些文档里不会写的细节给正在做数据库迁移选型或已经在迁移路上踩坑的朋友一个参考。1.2 工具能做什么不能做什么瀚高数据库迁移工具下文统一叫 migration 工具的核心能力可以总结为两大块元数据迁移和数据迁移。元数据迁移解决的是结构问题包括表、字段、主键、外键、索引、约束、视图、序列、触发器、存储过程、函数、包Oracle 场景等的转换。数据迁移解决的是内容问题全量数据从源库抽取、转换、加载到目标库。工具在设计上考虑了三个关键点多源支持MySQL、Oracle 是主打也支持 SQL Server、PostgreSQL、达梦等常见源库模式兼容瀚高本身提供 Oracle 兼容模式和 MySQL 兼容模式迁移工具可以配合目标库模式选择对应的转换规则可配置性对象映射、类型映射、并行度、批量大小等都可以调整。但它也有明显的边界。它不是一个CDC工具不支持源库在线增量同步你要做不停机迁移得配合其他同步方案它也不会自动帮你重写业务侧的 SQL 语句比如 Oracle 的分页写法、MySQL 的LIMIT语法迁移后应用代码里可能还要动刀子涉及嵌在存储过程里的复杂业务逻辑转换后大概率需要人工校对。理解这些边界后面安排迁移计划才不会想当然。2. 迁移前的准备工作与核心思路2.1 源库摸底先搞清楚要迁移什么很多人在迁移前容易犯一个错误上来就装工具、配连接、点开始迁移结果跑到一半发现源库某个表占用上亿行或者某个存储过程用了瀚高不支持的语法整个迁移被迫中断。我的习惯是动手之前先做一次完整的源库摸底。摸底分三步走。第一步统计元数据规模。用源库自带的数据字典查清楚有多少张表、多少个视图、多少套序列、多少存储过程和函数、有没有触发器、有没有物化视图、有没有自定义类型。Oracle 可以查ALL_OBJECTSMySQL 可以查information_schema.TABLES和ROUTINES。这一步的目的是评估迁移工作量和风险点。第二步查数据量分布。对每一张大表超过千万行的记录行数、表空间大小、是否有大字段CLOB、BLOB、TEXT、是否有分区。这决定了迁移时并行度和网络带宽规划。我的经验是一张超过 5000 万行的普通表单线程迁移基本跑不动必须在工具里配置并行。第三步做兼容性抽样。随机挑 5 到 10 个有代表性的对象比如一个带复杂 JOIN 的视图、一个用了游标的存储过程、一张含 JSON 字段的表先手动在瀚高里建一遍验证类型映射和语法兼容性。这一步花半天时间能帮你提前摸清工具转换规则的脾气避免正式迁移时大面积翻车。2.2 目标库模式选择先想清楚切换 MySQL 模式还是 Oracle 模式瀚高数据库一个很实用的特性是支持兼容模式切换。简单理解就是同一个数据库内核可以配置成更贴近 Oracle 语法习惯的模式或者更贴近 MySQL 语法习惯的模式。这个选择必须在迁移前定下来因为它直接影响迁移工具的转换规则和后续应用改造的工作量。我的建议是源库是 Oracle 就选 Oracle 兼容模式源库是 MySQL 就选 MySQL 兼容模式尽量不要混用。有人会想我能不能让目标库以 PostgreSQL 原生模式运行然后迁移工具把 Oracle 的 PL/SQL 转成标准 SQL理论上可以但实际改造量会大很多尤其是存储过程那一层Oracle 的 PL/SQL 和原生 PostgreSQL 的 PL/pgSQL 语法差异太大人工改写成本极高。这里要特别提醒一个细节瀚高的兼容模式不是简单地支持了 Oracle 或 MySQL 的 SQL 方言它是在内核层面做了语法解析、内置函数、数据类型、系统视图等多个层面的兼容。比如在 Oracle 兼容模式下你可以用DUAL表、NVL函数、ROWNUM伪列在 MySQL 兼容模式下你可以用AUTO_INCREMENT、LIMIT语法。迁移工具读取源库元数据时会根据目标库的兼容模式生成对应的 DDL 语句所以如果你的目标库是 MySQL 兼容模式却拿了一套 Oracle 的建表语句去执行大概率会报错。2.3 迁移方案选型逻辑迁移还是物理备份导入做数据库迁移业内其实有两条路线物理迁移基于文件级别的备份恢复和逻辑迁移基于 SQL 或数据文件格式的导入导出。瀚高 migration 工具走的是逻辑迁移路线。物理迁移的优势是速度快整个数据文件拷过去就行但劣势也很明显源库和目标库的操作系统、字节序、数据文件格式必须一致而且 PostgreSQL 内核的数据文件版本要求非常高跨大版本基本不兼容。对绝大多数业务系统来说源库是 Oracle 或 MySQL目标库是瀚高数据库类型都不同物理迁移这条路根本走不通。逻辑迁移虽然速度上慢一些但胜在跨数据库类型转换时灵活类型映射、语法转换、数据清洗都可以在迁移过程中处理。migration 工具的架构就是典型的 ETL 架构从源库读取元数据和数据经过内部的转换引擎处理后写入目标库。理解了这个本质你就知道为什么迁移速度取决于三个因素源库的读取速度SELECT 性能、网络传输带宽、目标库的写入速度INSERT/COPY 性能。2.4 迁移前环境检查清单这里给出一份实操中很关键的检查清单每一项都是我踩过坑之后总结出来的网络连通性迁移工具所在的机器必须能同时访问源库和目标库测试时不要只测端口通不通要实际跑一个简单查询确认账号权限足够账号权限源库账号需要读取元数据和数据的权限。Oracle 建议给SELECT_CATALOG_ROLE和SELECT ANY TABLEMySQL 建议给SELECT、SHOW VIEW、EVENT、TRIGGER相关权限目标库给CREATE、ALTER、INSERT、USAGE即可字符集统一源库字符集、迁移工具所在机器 locale、目标库字符集三条链路上的字符集设置要一致否则中文会出现乱码或无效的编码序列报错磁盘空间预判目标库的数据文件增长一般按源库数据量的 1.5 倍预留版本信息记录源库的精确小版本号瀚高迁移工具对不同版本的处理逻辑有差异这些小版本信息在排查问题时非常有用。3. 从 MySQL 迁移到瀚高实操全流程3.1 连接配置与参数设置以 MySQL 5.7 迁移到瀚高 MySQL 兼容模式为例第一次打开 migration 工具时会要求先配置源库和目标库连接。这一步有几个容易被忽略的参数JDBC 连接串里建议加上useUnicodetruecharacterEncodingutf8避免中文乱码源库驱动选择 MySQL Connector/J注意驱动版本和 MySQL 服务端版本的匹配。MySQL 8.0 的驱动连接 MySQL 5.7 没问题反向就不一定了目标库连接选择瀚高提供的 JDBC 驱动端口默认是 5866瀚高的默认端口和 PostgreSQL 的 5432 不一样别搞混了。连接测试通过后工具会读取源库的库表清单。MySQL 的库Database对应瀚高的 schema命名空间。这里有个映射选择你可以选择每个 MySQL 库映射为一个独立 schema也可以把多个库合并到一个 schema 里。考虑到应用改造的改动量我的习惯是保持 1:1 映射库名不变这样业务侧改 JDBC 连接串时只需要改数据库类型和 IP 端口。3.2 类型映射的隐藏细节附对照表MySQL 和瀚高PostgreSQL 内核的类型系统差异不小migration 工具内置了一张类型映射表我整理了核心类型在默认规则下的映射结果MySQL 类型瀚高 MySQL 兼容模式下的默认映射备注TINYINTSMALLINTMySQL 的 TINYINT(1) 常被当作布尔用迁移后注意检查SMALLINT / MEDIUMINTSMALLINT / INTEGER范围变化不大基本无感INT / INTEGERINTEGER无符号 int 迁移后可能溢出需人工改成 BIGINTBIGINTBIGINT常规FLOAT / DOUBLEREAL / DOUBLE PRECISION精度要注意建议迁移后用抽样数值对比DECIMAL(p,s)NUMERIC(p,s)映射稳定推荐CHAR(n) / VARCHAR(n)CHAR(n) / VARCHAR(n)注意 MySQL 的 VARCHAR(n) 是按字符算的瀚高也按字符天然对齐TEXT / LONGTEXTTEXT常规DATE / DATETIME / TIMESTAMPDATE / TIMESTAMP关键差异MySQL 的 TIMESTAMP 有时区概念后者没有迁移前后要确认应用逻辑BLOB / LONGBLOBBYTEA程序里处理方式不同JDBC 用setBinaryStream基本没问题JSONJSON瀚高有原生的 JSON 类型兼容良好ENUM / SETVARCHAR CHECK 约束默认会展开成 CHECK数据量大的时候注意约束检查开销遇到INT UNSIGNED这类类型工具默认会映射成BIGINT但有亿分之一概率源库数据实际超出了 BIGINT 范围比如用了BIGINT UNSIGNED且真实值超过 922 亿亿这种情况必须迁移前人工预警。你可以先在源库跑一个SELECT MAX(列名) FROM 表名确认边界。3.3 自增列迁移的两种姿势MySQL 迁移到瀚高最常见的第一个报错往往出在自增列上。MySQL 用的是AUTO_INCREMENT瀚高 MySQL 兼容模式下同样支持AUTO_INCREMENT所以建表语句可以无缝迁移。但有个细节MySQL 的自增值存在数据字典里不是表数据的一部分如果迁移工具只导数据不导下一个自增值插入新记录时可能发生主键冲突。实操中的解决办法有两种。第一种如果工具支持部分版本支持迁移元数据时把AUTO_INCREMENT的当前值一并提取转为瀚高的序列起始值。第二种如果不支持迁移完数据后手动执行一句SELECT setval(pg_get_serial_sequence(目标表名,自增列名), (SELECT MAX(自增列名) FROM 目标表名));这句的意思是把序列的当前值设置为表里已有的最大值这样下一条插入的自增 ID 就不会撞车。这个小操作我建议直接写进迁移后的校验脚本里每次迁移完必执行。3.4 数据迁移执行与校验元数据迁移完成后就是真正导数据的环节。migration 工具支持全量数据迁移执行时我建议按以下顺序来先迁小表数据量低于 10 万行的表快速验证链路再迁中表观察工具的并发和批量写入参数是否合理最后迁大表可以针对大表单开任务调大批量提交的批次大小比如每批 5000 条和并行线程数。一个比较隐蔽的性能瓶颈是工具默认使用INSERT INTO ... VALUES (...)逐行写入时遇到目标库有大量索引和约束性能会急剧下降。解决办法是在工具的参数配置里开启批量写入模式也就是COPY协议瀚高基于 PostgreSQL支持COPY高速导入。实测在同样的网络环境下COPY模式的导入速度是逐行 INSERT 的 5 到 10 倍。如果工具界面没有暴露这个开关可以在目标库侧配合pg_bulkload这类工具做二次导入或者用工具导出的数据文件走COPY。数据迁移完成后校验环节不能省。我最常用的校核方法有三个行数校验对每张表分别执行SELECT COUNT(*)源库和目标库对比抽样校验每张表抽 1%至少 1000 条按主键排序后对比几个关键字段的值业务冒烟用真实的业务查询语句在瀚高上跑一遍确认结果集和源库一致。4. 从 Oracle 迁移到瀚高难点与对策4.1 元数据迁移中的 Oracle 特性处理Oracle 是商业数据库里语法特性最丰富的从 Oracle 迁到瀚高 Oracle 兼容模式比 MySQL 要复杂一个量级。migration 工具虽然做了很多自动化转换但有几个 Oracle 特有的对象类型需要特别关注。同义词SynonymOracle 里大量使用公共同义词来解耦应用和表 owner 的绑定关系。迁移工具默认能识别CREATE PUBLIC SYNONYM但在瀚高里没有公共同义词的概念工具通常会把同义词转成视图普通同义词或者不做处理公共同义词。这就导致一个问题业务 SQL 里如果直接通过同义词访问表迁移后可能报relation does not exist。我的做法是迁移前先在源库跑一个脚本把所有同义词和最终指向的对象名对应关系列出来然后在瀚高里创建对应别名的视图来模拟同义词。物化视图Materialized ViewOracle 的物化视图支持刷新机制REFRESH FAST/COMPLETE瀚高虽然也支持物化视图PostgreSQL 内核自带MATERIALIZED VIEW但不支持自动刷新。迁移工具只能把物化视图的定义导过去刷新逻辑原本可能是 Oracle 的 JOB 定时任务需要你在迁移后用瀚高侧的定时任务重写。这块很容易漏漏了之后业务反映报表数据不对排查半天才发现是物化视图没刷新。分区表Partition TableOracle 的分区方式很多范围、列表、哈希、复合分区瀚高的分区语法基于 PostgreSQL 的声明式分区。迁移工具能转换大部分标准的分区表但遇到子分区、间隔分区INTERVAL PARTITION这类高级特性经常需要人工干预。间隔分区在 Oracle 里会根据插入数据自动创建新分区这个行为在瀚高里没有等价功能我的建议是迁移前就把间隔分区手动转成范围分区并提前规划好未来分区范围。4.2 存储过程与 PL/SQL 改写专项这是整个 Oracle 迁移工程里工作量最大、最不可控的部分。migration 工具对存储过程、函数、触发器、包的转换能力实测下来可以做到基础语法自动转换 高级语法人工兜底。举几个最常见的转换点异常处理语法Oracle 用EXCEPTION WHEN NO_DATA_FOUND THEN ...瀚高兼容模式下可以识别并转换但SQLCODE、SQLERRM这类函数在迁移后需要改写隐式游标Oracle 里的SELECT INTO不带INTO的隐式游标在 PostgreSQL 内核里行为不同工具会把过程拆开但涉及多行结果时必须在源库就改成FOR ... LOOP或加ROWNUM限制字符串拼接Oracle 用||瀚高同样支持||PostgreSQL 也支持这块算是兼容的分页写法应用 SQL 里 Oracle 的ROWNUM 10分页在瀚高 Oracle 兼容模式下8.0 以上的内核版本一般能识别但在嵌套子查询中会出问题建议统一改成LIMIT或FETCH FIRST语法日期运算Oracle 的SYSDATE可以直接加减SYSDATE - 1表示前一天瀚高兼容模式下要确认SYSDATE是否注册若没有则用CURRENT_TIMESTAMP - INTERVAL 1 day替代。我的实操建议是不要在工具转换结果上直接改。把工具生成的存储过程 DDL 全部导出来后连同源库的存储过程脚本一起交给开发团队做一次专项 review。工具负责把 80% 的基础语法转过来剩下 20% 的复杂逻辑由人用几天时间集中处理。这个 review 过程同时也是对业务逻辑的重新理解往往能发现源库脚本里隐藏的坏味道。4.3 序列、触发器与特殊数据类型的迁移Oracle 的序列Sequence是独立的数据库对象迁移到瀚高时映射成 PostgreSQL/瀚高的序列对象。这里有一个经常出问题的点序列缓存值CACHE不一致。Oracle 里默认CACHE 20迁移到瀚高后如果工具生成了CACHE 1默认不缓存高并发下序列从 1 取一个、写一次磁盘性能会非常差。迁移后务必手动执行ALTER SEQUENCE 序列名 CACHE 20;触发器方面Oracle 的语句级触发器和行级触发器在瀚高里都支持但游标遍历新老值的方式不同。Oracle 用:NEW.列名、OLD.列名瀚高在兼容模式下可以用NEW.列名、OLD.列名工具转换时一般能处理。需要注意的是BEFORE INSERT触发器里修改:NEW值的逻辑转换后可能退化成触发器里写不回新值导致自增赋值失效。这块建议迁移后针对每一个有触发器的表做一个插入更新测试。特殊数据类型方面Oracle 的CLOB、BLOB可以映射到瀚高的TEXT、BYTEA但 Oracle 的RAW、LONG RAW、ROWID要小心。ROWID在 Oracle 里是定位物理行的伪列迁移到瀚高后没有等价物业务 SQL 里如果显式使用了ROWID必须改成基于主键的逻辑定位。我的经验是先在源库搜一遍代码ROWID的使用点全部标注出来逐一改写。4.4 Oracle 迁移后的关键回归测试项Oracle 项目迁移完我一定会安排下面这几个回归测试场景分页查询把所有使用ROWNUM分页的接口在瀚高上实测一次重点关注第 2 页之后的数据是否正确空值行为Oracle 中等价于NULLPostgreSQL 内核默认也把空字符串当字符串但有些兼容模式下行为可能不一致需要建测试用例验证WHERE 列 和WHERE 列 IS NULL的区别隐式转换Oracle 对VARCHAR2和NUMBER之间的隐式转换非常宽松瀚高在兼容模式下内置函数能处理大部分但自定义函数中隐式转换失败是重灾区并发写入Oracle 默认的读不阻塞写、写不阻塞读MVCC瀚高基于 PostgreSQL 同样具备 MVCC但隔离级别默认不同PostgreSQL 默认读已提交Oracle 也是读已提交行为差异主要体现在SERIALIZABLE隔离级别下的异常处理需要应用层确认。5. 常见问题与排查技巧实录5.1 高频报错速查表把我在真实项目中遇到的典型报错整理成速查表按报错信息 - 可能原因 - 解决办法的格式列出报错信息可能原因解决办法relation xxx does not exist迁移对象时 schema 映射错误或同义词未转换检查目标库 schema 名称是否与源库一致为同义词重建视图invalid byte sequence for encoding UTF8源库字符集和目标库不一致确认 MySQL/Oracle 字符集迁移工具连接串指定characterEncodingutf8duplicate key value violates unique constraint自增序列起始值小于表内现有最大值执行setval脚本修正序列function xxx(integer) does not exist函数签名参数类型不兼容检查函数定义对参数做显式类型转换column xxx is of type bytea but expression is of type text大字段类型映射后 JDBC/写入类型不匹配在数据迁移配置中将对应列强制映射为BYTEAunsupported frontend protocol目标库连接串使用 PostgreSQL 原生驱动但瀚高未开启协议兼容换成瀚高官方 JDBC 驱动ORA-00942: table or view does not exist迁移脚本执行时索引或约束指向了未迁移的关联对象按依赖顺序迁移先表、再索引、后约束/外键cannot insert multiple commands into a prepared statementJDBC 批量插入时语句中包含了分号检查迁移工具是否开启了多语句执行模式这些报错里前三个出现频率最高。尤其是第一种relation does not exist我见过不止一个团队把 MySQL 的库名大小写问题带到了目标端MySQL 在 Linux 上表名区分大小写而 PostgreSQL/瀚高默认会把不带引号的表名折叠成小写。迁移后应用代码里写的SELECT * FROM Users会报错。解决办法有两种统一应用 SQL 都用小写表名或者在创建表时给表名加双引号强制保留大小写。5.2 迁移性能调优心得大表迁移速度慢是每个做迁移的人都会遇到的问题。除了前面提到的开启COPY模式还有几个调优方向值得尝试。第一调整目标库的写入参数。瀚高基于 PostgreSQL迁移期间可以临时把目标库的wal_level保持默认如果是逻辑复制则不能关但可以把synchronous_commit设为offfull_page_writes设为off注意生产环境必须迁移后改回否则异常断电可能导致数据损坏。同时把checkpoint_timeout调大减少检查点带来的写放大。这些参数修改后需要重启数据库生效我一般在迁移窗口内统一改迁移完成并做完全量校验后再改回。第二合理设置并行度。migration 工具的并行度不是越大越好。实测下来4 到 8 个并行任务对多数服务器是比较甜点的区间超过 16 个并行后源库的查询连接数、目标库的锁竞争会互相拖累整体吞吐反而下降。第三分批处理大表。对超过 1 亿行的表不要指望一个任务跑完。我习惯按主键范围或时间字段拆成多个任务每个任务处理 1000 万到 2000 万行这样单个任务失败后重跑的成本很低也方便观察进度。5.3 迁移后的持续性建议工具迁移完成不等于项目结束。根据我的经验迁移完成后还需要安排至少两到三周的双跑期即新老系统并行运行每天做数据比对和业务对账。在这个过程中要特别关注这些方面新增数据的自增主键是否冲突定时任务里的存储过程是否稳定执行应用连接池是否因为驱动替换出现新问题瀚高的慢查询日志里是否存在执行计划远差于源库的 SQL。瀚高兼容模式做得再完善也不可能做到 100% 行为一致这些差异只能靠真实的业务流量去暴露。另外migration 工具的迁移报告功能别浪费。每次迁移完成后工具会生成一个统计报告包括迁移的对象数量、成功/失败清单、转换告警等。这个报告不仅是给项目验收看的也是后续排查问题的重要依据。我习惯把这部分报告归档保存连同迁移前后的 DDL 脚本、数据校验结果形成一份完整的迁移档案。最后说一个我在多次迁移项目中总结的心得数据库迁移项目真正决定成败的不是工具而是流程。工具能帮你把 80% 的表结构和数据搬过去但剩下 20% 的存储过程改写、应用 SQL 适配、数据校验、双跑对账靠的是人力和责任心。migration 工具的价值在于把最耗时、最机械的部分自动化掉让你把精力集中在真正需要判断力的事务上。做迁移前先花一周时间把源库摸透把改造清单列出来再动手用工具你会发现整个迁移过程的痛苦程度会降低一半以上。本文还有配套的精品资源点击获取
返回列表