ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Oracle 11g到达梦数据库迁移三步走:盘点、搬迁、验证

Oracle 11g到达梦数据库迁移三步走:盘点、搬迁、验证 最近被问到最多的问题已经不再是“要不要做国产数据库改造”而是更实际的一句“手里这套跑了七八年的 Oracle 11g到底怎么迁到国产数据库才不出事”这种焦虑很正常。一说到去 Oracle 化、去中心化仓库很多人第一反应就是无穷无尽的兼容性改造和随时可能爆发的生产事故。但如果你把迁移这件事真的拆开看会发现绝大多数系统的迁移难点根本不在“把数据搬过去”这一步而在前面的盘点评估和后面的应用验证。换句话说表和数据本身迁移难度可控最怕的是你对源库的运行状态、对象种类、脏数据规则一无所知直接拿着导出工具闷头干。这篇文章不会写那种“国产数据库万物皆可迁”的水文。我以最典型的场景为例——Oracle 11g 迁移到达梦数据库顺带说明 DBeaver、若依这类管理系统适配国产库时的操作方法。核心只讲三件事迁移前要盘点什么迁移中怎么把结构和数据搬得又稳又快迁移后怎么验证才算真正上线。如果你是第一次接手这类任务这篇文章可以当一份检查清单来用。1. 国产数据库迁移的真正难点与常见误区1.1 难点不是“搬数据”而是“搬语义”先给一个容易误导人的认知纠偏很多人一听国产数据库迁移就以为要先把源库几十张表导出再在目标库导入导完就完事。这种思路只适用于“纯数据备份恢复”用在真实业务系统上一定会出问题。真正的迁移对象不仅是表里的数据还包括数据类型、约束、索引、序列、视图、存储过程、函数、包、触发器和应用 JDBC 代码。Oracle 里的空字符串会被当作 NULL而 MySQL 里的空字符串就是空字符串Oracle 的 DATE 可以带时分秒而某些国产库的 DATE 语义不一定一致。这些“看不见的语义”才是最容易在功能回归时炸雷的地方。所以请你先建立一个判断结构迁移和数据迁移只是中间过程应用在目标库上能按原业务语义运行才是迁移成功的唯一标准。这个标准会直接影响你怎么安排工作量和验证计划。1.2 三种迁移路线停机全量、增量同步、双跑切换从工程上划分国产数据库迁移通常有三种路线不同路线适用于不同停机要求。迁移路线核心思路适用场景注意事项停机全量迁移停写维护窗口全量搬迁后直接切换中小系统、允许停机的业务操作简单但时间窗口要评估充分增量同步迁移全量 日志或同步工具做增量追平停机时间要求高、数据量大依赖数据同步工具需要做好断点校验双跑切换迁移新旧库并行运行业务逐步切流重要核心系统、需要灰度验证成本高需要完善的核对机制和回滚预案标题里说的“3 个步骤”主要是面向第一种停机全量迁移。这也是“Oracle 11g 数据库怎么冷迁移”这类问题最常被搜索的原因对于很多内部管理系统业务侧完全可以接受一个周末的维护窗口性价比最高的路径就是冷迁移。2. 迁移前准备工作资产盘点与兼容性评估2.1 用 SQL 盘点源库对象别靠 DBA 记忆很多人第一步就做错了不看源库里到底有什么就直接去装迁移工具。Oracle 实例里可能有几十个用户 Schema有些 Schema 已经废弃里面还堆着大量历史表和临时表。如果全量迁移浪费的不仅是时间还会把一堆不需要暴露的对象搬到新库给后续安全审计留下隐患。正确做法是先做资产盘点。下面这段 SQL 可以在 Oracle 上用具备查询权限的账号执行按 Schema 统计对象分布-- 文件路径在源 Oracle 库执行 SELECT owner AS schema_name, object_type AS object_type, COUNT(*) AS object_cnt FROM dba_objects WHERE owner NOT IN (SYS, SYSTEM, OUTLN, DBSNMP) GROUP BY owner, object_type ORDER BY owner, object_cnt DESC;执行后你会得到一张类似下面的表格知道自己要迁移的对象规模SCHEMATABLEINDEXVIEWSEQUENCEPROCEDURETRIGGERSCOTT20155283APPUSER5040124206除了表以外你更需要关注的是“业务代码对象”也就是存储过程、函数、包、触发器、序列。这些对象的语法兼容性是评估工作量的大头。Oracle 里如果用了大量自定义包例如访问 UTL_HTTP、DBMS_SCHEDULER、DBMS_LOCK迁移到达梦时需要逐项确认替代方案。普通 OLTP 系统问题不大但重度 PL/SQL 系统一定要提前评估。2.2 兼容性评估的关键维度拿到对象清单后不要急着开始建库先做一个粗糙的兼容性矩阵。可以从下面几个维度过一遍评估维度Oracle 常见写法需要确认的问题数据类型NUMBER、VARCHAR2、DATE、CLOB目标库的类型映射是否会导致精度变化空字符串语义Oracle 将当作 NULL目标库兼容模式是否与源一致分页写法ROWNUM 嵌套分页目标库是否兼容 ROWNUM或需要改 LIMIT存储过程PL/SQL 包、游标、异常内置包和系统视图是否都兼容序列SEQ.NEXTVAL、SEQ.CURRVAL迁移后初始化值是否正确字符串拼接日期函数SYSDATE、TO_CHAR、TO_DATE默认格式与 NLS 是否符合预期这个表格不需要一次做完更合理的方式是先找目标数据库厂商或社区提供的“兼容性分析工具”把 Oracle 的 DDL 脚本和存储过程脚本导入由工具报告不兼容的地方。之后再针对报告逐条确认效率会远高于人工阅读。2.3 字符集与账号权限准备迁移前还有一个特别容易被低估的环节字符集。Oracle 服务端如果用了 ZHS16GBK目标库也建议采用兼容的中文字符集方案否则导入中文数据后很容易出现长度判断错误或乱码。最稳妥的办法是在迁移测试环境提前建一个和目标版本一致的库用一小批真实数据做全链路试跑。源库侧建议创建只读账号用于数据盘点目标库侧不要直接用 SYSDBA 做业务用户。长期运行的应用账号应单独创建并只授予业务需要的对象权限。这一点既是数据安全要求也是国产数据库上线后权限审计的正常边界。3. 第一步结构迁移——表结构、序列与约束3.1 类型映射要先过一遍不能让 DTS 完全代劳达梦数据库提供了比较成熟的可视化迁移工具 DTS很多常规对象它都能自动翻译但你不能完全当甩手掌柜。因为 DTS 只能按照通用规则转换无法知道你业务里某个字段“为什么是 NUMBER(38)”这个字段到底需不需要大整数精度。从 Oracle 迁移到达梦时常见的类型映射逻辑是这样的Oracle 数据类型达梦推荐类型说明VARCHAR2(n)VARCHAR2(n)注意 n 是按字符还是字节NUMBER(p,s)DECIMAL(p,s)保留精度与小数位NUMBER(10) 以下整数INT / BIGINT可按业务情况收紧NUMBER(*,0)BIGINT纯整数场景可用DATEDATEOracle 兼容模式下语义需要验证TIMESTAMPTIMESTAMP与 Oracle 的 TIMESTAMP 基本对应CLOBCLOB / TEXT大文本字段BLOBBLOB二进制字段这里最需要人工确认的是VARCHAR2的长度单位。Oracle 里定义VARCHAR2(20)究竟按字节还是按字符取决于 NLS_LENGTH_SEMANTICS。如果以前是VARCHAR2(20 CHAR)到目标库建表时也应当显式声明字符语义否则可能出现中文长度超出限制的问题。3.2 一个兼容 Oracle 方式的最小建表示例达梦在 Oracle 兼容模式下可以保留很多 Oracle 风格语法。假设我们有一个用户表和它的序列结构迁移后 DDL 大体如下-- 文件路径目标库执行采用 Oracle 兼容模式 CREATE TABLE user_info ( id NUMBER(19) NOT NULL, user_name VARCHAR2(64 CHAR) NOT NULL, balance NUMBER(12,2) DEFAULT 0, remark VARCHAR2(500 CHAR), create_time DATE DEFAULT SYSDATE, CONSTRAINT pk_user_info PRIMARY KEY (id) ); COMMENT ON TABLE user_info IS 用户信息表; COMMENT ON COLUMN user_info.user_name IS 用户名; CREATE SEQUENCE seq_user_info_id START WITH 1 INCREMENT BY 1 NOCACHE;这段建表语句重点看两个地方主键、默认值、注释都直接写在结构迁移里这样业务代码通常不需要改动。序列用 Oracle 风格的CREATE SEQUENCE后续在 INSERT 时可以直接写seq_user_info_id.NEXTVAL。很多开发人员会把“建表”和“迁移结构”混为一谈实际上结构迁移还包括统计信息、分区、外键、授权等对象。目标库建完后建议再执行一次对象清单对比确保源端和目标端的表数量一致。3.3 序列迁移必须重置起点结构迁移阶段最常见的翻车场景是序列没有重置。假设 Oracle 源表里有 12 万条数据序列当前值已经到了 120000但 DTS 只给你建了序列没有自动同步当前值。导入后应用插入第一条数据主键从 1 开始立刻撞上已经存在的主键生产直接报错。解决办法是明确知道每张表的业务主键最大值然后重建序列。以用户表为例-- 目标库执行假设当前最大业务ID是 118762 DROP SEQUENCE seq_user_info_id; CREATE SEQUENCE seq_user_info_id START WITH 118763 INCREMENT BY 1 NOCACHE;INSERT 语句里的 ID 是序列还是应用自己生成的也需要提前摸清。如果是应用传入 UUID 或雪花 ID那么序列问题就不存在如果把序列值当成主键迁移后必须把起跑线调到源端一致。4. 第二步数据迁移——DTS、DBeaver与大批量导入优化4.1 用达梦 DTS 完成全量数据搬迁达梦自带的 DTS 数据迁移工具是“Oracle 到达梦”最常用的图形化工具。典型操作流程如下打开 DTS新建“迁移工程”添加 Oracle 源连接。添加达梦目标连接确认模式名与目标表结构已存在。选择需要迁移的对象类型可以只勾选“数据”也可以同时处理结构。设置迁移策略例如分批提交行数、LOB 字段处理方式。执行迁移查看导入日志。如果你的源端是 Oracle 11g目标端是达梦 DM8DTS 一般能直接读取 Oracle 的元数据不需要中间导出文件。这种方式比较适合全量冷迁移网络连通且停机窗口允许。4.2 用 DBeaver 也能做数据库传输很多开发团队平时就在用 DBeaver遇到迁移任务时也想用它完成。DBeaver 的“数据库传输”功能确实可以做跨数据库复制但请你把它理解为“表结构和数据复制器”而不是专业的数据库迁移平台。操作上大致是这样在 DBeaver 中同时配置好 Oracle 源连接和达梦目标连接。在数据库导航里选中要迁移的表或整个 Schema。右键选择“导出数据”或“数据传输Database Transfer”。选择目标连接选择目标表勾选“创建表结构”和“复制数据”。点击开始观察底部任务日志。DBeaver 更适合数据量中等、对象不复杂的迁移场景。如果你的源库有上百张表、大量触发器和复杂视图建议主力还是用 DTS或先通过 DBeaver 快速把业务开发库迁过去做功能联调生产环境再用达梦官方工具完成。4.3 大批量导入之前先做减法只要导过百万级以上数据的人都会有一个体感直接建好全部索引再导数据速度会很感人。原因很好理解每插入一条记录数据库都要同步维护索引和约束等于干活时随身背着装满东西的包。所以工程化做法是结构迁移时先只建表不建二级索引和触发器只保留主键和 NOT NULL 约束。数据迁移完成后再批量创建索引、外键和触发器。如果外键关系复杂导入前先禁用外键约束导入完成后再启用并校验。这样做的好处不仅是快还便于在数据迁移失败时快速定位问题。否则你很难判断报错到底来自数据本身还是来自索引维护过程中的排序冲突。DBeaver 或 DTS 中都可以设置批量提交行数典型场景可以先设为 500 或 1000 行一批。如果迁移中途失败日志会告诉你中断在哪个表哪一行而不是整批回滚后什么信息都没有。5. 第三步应用适配——JDBC配置、若依系统与SQL改造5.1 换数据库连接最核心的是驱动和URL数据搬完只是第一步应用连不上或者连上后跑不通迁移就不算完成。换国产数据库后应用层最先要动的就是 JDBC 驱动和数据源 URL。以 Java Spring Boot 项目为例如果原来是 Oraclejdbc.driverClassNameoracle.jdbc.OracleDriver jdbc.urljdbc:oracle:thin:127.0.0.1:1521:ORCL jdbc.usernameapp_user jdbc.passwordxxxxxx改成达梦后典型配置如下jdbc.driverClassNamedm.jdbc.driver.DmDriver jdbc.urljdbc:dm://127.0.0.1:5236?schemaAPP_SCHEMA jdbc.usernameapp_user jdbc.passwordxxxxxx这段配置里需要解释三个点达梦默认端口一般是 5236不需要写成 5236/Oracle 服务名。schema参数决定默认模式具体参数名以你使用的驱动版本为准。驱动 jar 需要提前打进应用或安装到私有 Maven 仓库不要在测试环境用“能连上”就代表生产也能连上。5.2 若依这类管理系统的适配思路若依是国内使用量很大的后台管理系统基础框架默认更贴近 MySQL 生态。很多团队拿到若依代码后需要把它适配到国产数据库上。这里的核心不是改 Java 代码而是处理三层问题数据源配置、持久层方言、系统表结构初始化。数据源层把若依中的 Druid 配置改成达梦即可。常见文件是ruoyi-admin/src/main/resources/application-druid.yml写法可以简化为spring: datasource: druid: driver-class-name: dm.jdbc.driver.DmDriver url: jdbc:dm://127.0.0.1:5236?schemaRUOYI username: ruoyi_user password: 你的数据库密码持久层要注意的是若依默认 SQL 中有不少 MySQL 特有的写法例如LIMIT自增主键以及 MyBatis XML 里可能出现的反引号。适配国产库时建议全局检索以下几类关键词反引号包裹的表名和列名。LIMIT分页写法。IFNULL、NOW()、DATE_FORMAT。MyBatis 的useGeneratedKeys自增策略。XML 里的布尔判断是否依赖 MySQL 的 1/0 语义。达梦 Oracle 兼容模式对许多常用函数做了兼容但如果项目原来跑在 MySQL 和若依组合上还是需要逐条检查 XML 文件。更稳妥的做法是先启动应用让页面功能把常见 SQL 全部触发一遍再看日志补漏。5.3 常见 SQL 改写的方向提前做好心理建设从 Oracle 迁移到国产库时最常遇到的是分页和空值语义差异。Oracle 11g 的分页普遍用 ROWNUM 嵌套某些国产库可以在兼容模式下直接支持 ROWNUM但如果你的项目也包含 MySQL 迁移来源习惯写法可能是LIMIT。这就会造成一种尴尬同一个团队有人写 ROWNUM有人写 LIMIT两种写法都要在目标库验证。分页写法示例-- Oracle 风格ROWNUM 嵌套 SELECT * FROM ( SELECT t.*, ROWNUM AS rn FROM user_info t WHERE ROWNUM 20 ) tmp WHERE rn 10;如果目标库支持 LIMIT也可以写得更直观-- 若目标库兼容 LIMIT 语法 SELECT * FROM user_info ORDER BY id LIMIT 10, 10;这里千万不要认为“能跑通就行”。分页查询还涉及 ORDER BY 的排序一致性如果没有唯一排序字段分页结果可能出现重复或漏行。迁移完成后建议对高频分页接口做翻页对比测试。6. 数据一致性校验与上线切换6.1 数据量一致性校验相同 SQL、两个库分别执行很多团队做完数据导入只查一下两张表行数一致就宣布成功这在数据量不大时问题不大但如果一张表有几百万行行数一致完全不能说明数据一致。最实用的办法是设计一组“业务摘要 SQL”分别在源库和目标库执行再对比结果。下面这段 SQL 就是一个典型的聚合校验模板Oracle 和达梦都能执行-- 源库和目标库分别执行结果需要保持一致 SELECT COUNT(*) AS record_cnt, COUNT(DISTINCT business_key) AS key_cnt, SUM(amount) AS amount_sum, MAX(create_time) AS max_create_time, MIN(update_time) AS min_update_time FROM account_trans WHERE busi_date DATE 2024-06-01;为什么要用COUNT(DISTINCT...)和MAX/MIN因为行数只能反映有没有“行”却不能反映业务关键字段是否在搬迁过程中丢失或变形。建议针对每张核心大表设计一组这样的模板跑完后把结果导出成 CSV再用文本比对工具核对。6.2 是否存在两张表完全一致可以用集合差运算符做抽查如果参与迁移的表数据量不大而且 Oracle 与目标库可以建立跨库访问能力可以尝试用MINUS做集合对比。Oracle 有MINUS达梦在 Oracle 兼容模式下通常也支持。跨库执行这类 SQL 需要满足目标库能访问源库的条件通用的思路是把两边的数据抽到中间登录会话中互相引用。为了便于理解用简化写法表达-- 假设当前会话可以同时访问两个库的对象 SELECT u1.user_id, u1.user_name FROM oracle_user_infolink_oracle u1 MINUS SELECT u2.user_id, u2.user_name FROM dm_user_info u2;如果返回 0 行说明源库对象的内容能在目标库中找到对应记录。反过来再执行一次就可以看出两边是否有互相缺失。这里有个前提user_id、user_name的类型和长度必须兼容否则比较结果没有意义。不过在实际项目中跨库 MINUS 只适合在数据量可控时使用。几百 G 的大表不建议直接集合差比较应优先用聚合摘要 抽样明细的双重策略。6.3 上线切换要有回滚位不能只顾着喊“切成功”我见过不少团队上线窗口只有“迁移 切换”没有预留回滚验证时间结果业务字段语义一跑通就立刻对外放量出了问题只能仓促回滚源库。冷静一点的做法是把切换动作拆成“可以回退”的步骤。迁移前记录 Oracle 源库的 SCHEMA 导出备份和业务侧当前版本号。迁移后不要立即销毁源库连接保留只读访问至少一个业务验证周期。应用发布时使用新数据源配置但保留旧配置文件的备份。如果业务验收发现致命问题可以通过版本开关切回源库配置而不是临时改代码。只有完成了业务侧的核心链路联调并有一个明确的可接受标准才建议把流量正式指向国产数据库。7. 常见问题与排查思路迁移过程中最容易出现的几类问题基本都集中在下面这张表里。你可以先收藏等服务出问题时直接对照查找。问题现象可能原因排查方式解决方案结构迁移后某些表找不到大小写模式不一致建表时的小写标识符访问时没有带引号查目标库ALL_TABLES中表名大小写统一 SQL 标识符大小写策略或显式加引号访问中文数据导入后乱码源库与目标库字符集不一致检查两边的字符集配置重新确认迁移字符集转换规则导入前先做小批试跑插入数据报主键冲突序列没有重置到业务当前最大值查询表最大 ID 和序列当前值DROP 后重建序列从最大 ID 1 开始VARCHAR2 字段长度不准报字符超长源库按字符目标库按字节计算长度看建表 SQL 是否明确CHAR统一增加CHAR字符语义分页查询结果错乱或重复排序字段缺少唯一性复现前端翻页并对比 Oracle 与目标库结果在 ORDER BY 中追加主键或唯一字段存储过程执行报错使用了 Oracle 特有内置包或系统视图查看报错行引用了哪个包用目标库等价函数或应用层逻辑改写应用启动报 “driver not found”JDBC 驱动 jar 没有正确打进应用查依赖 tree 或日志中的类加载报错本地引入达梦驱动并确认运行时打包范围大批量表迁移很慢导入前索引已全部建好查看导入期间索引维护状态先禁约束和二级索引数据完成后再重建8. 最佳实践与工程建议前面提到的都是“怎么做”下面这份清单想解决的是“怎么少走弯路”。下次再有人问国产数据库迁移难不难可以把这份建议当成团队的内部规范。第一先在测试环境完整跑通一次迁移。所谓“跑通”不是只导完几十张表而是让应用在达梦上能完成登录、查询、导出、审核等核心业务流。测试环境的目的是暴露问题和估算时间不要省掉这一步就直接申请生产窗口。第二把迁移脚本与配置纳入版本管理。结构 DDL、序列重置 SQL、数据校验 SQL、数据源配置文件都应该是可重复执行的产物而不是 DBA 一个人在晚上手动点的按钮。提交到 Git 仓库后续复盘和二次迁移才有依据。第三账号权限控制在第一天就设计好。源库给只读账号目标库给业务最小权限生产不要长期使用 SYSDBA 运行应用。国产数据库在上线后通常也会经历等保审计如果一开始就做到了最小权限后面会省很多沟通成本。第四不要忽略统计信息和慢 SQL。数据迁移完成不代表 SQL 执行计划就正常。刚导入的数据由于统计信息不准确可能出现目标库上同样的查询比 Oracle 慢几倍的情况。上线前对核心表执行一次统计信息更新并把以前 Oracle 的慢 SQL 日志重新跑一遍对比。第五分阶段定义“成功”。只有数据一致叫“数据迁移成功”只有应用启动不报错叫“应用适配成功”只有核心业务流程验收通过才叫“系统上线成功”。团队里每个人对成功的理解不同项目就很容易在边界模糊时出问题。9. 结语与下一步实践思路如果只看国产数据库迁移这件事本身它并没有传言中那么夸张。一个库表规范、SQL 以增删改查为主的管理系统在停机窗口允许的情况下按照“资产盘点与兼容性评估、结构与数据迁移、应用适配与上线验证”这三步走下去往往一个周末就能完成主体工作。真正需要投入时间的是那些不常被数据迁移工具展示的细节字符集是否一致、序列是否重置、空字符串语义是否对齐、应用里的 SQL 写法是否符合目标库习惯。只要你把每个细节都当成可验证的检查项而不是依赖直觉判断迁移就会变成一个可以重复执行的工程流程。如果你想找一个练手项目建议先把若依这类开源管理系统跑在达梦上从建库、初始化 SQL、改数据源、调整分页 SQL 开始完整走一遍迁移链路。把第一步盘点、第二步搬迁、第三步验证的节奏跑熟后再面对生产库就不会心里发虚。下一篇可以继续深入讲讲达梦与 Oracle 在存储过程和调度任务上的具体差异这一块也是迁移中不容易一次写对的地方。
返回列表