【金仓数据库征文】Oracle到金仓:包、过程与函数的兼容改造路线

文章目录

    • 每日一句正能量
    • [1. 背景与问题](#1. 背景与问题)
    • [2. 环境与数据](#2. 环境与数据)
      • [2.1 示例环境](#2.1 示例环境)
      • [2.2 对象清单不是"对象数量表"](#2.2 对象清单不是“对象数量表”)
      • [2.3 Oracle 源端对象盘点 SQL](#2.3 Oracle 源端对象盘点 SQL)
    • [3. 复现过程](#3. 复现过程)
      • [3.1 Oracle 示例包](#3.1 Oracle 示例包)
      • [3.2 风险一:包级变量状态](#3.2 风险一:包级变量状态)
      • [3.3 风险二:默认参数与重载](#3.3 风险二:默认参数与重载)
      • [3.4 风险三:异常码契约](#3.4 风险三:异常码契约)
      • [3.5 风险四:事务边界](#3.5 风险四:事务边界)
      • [3.6 风险五:系统包和外部能力](#3.6 风险五:系统包和外部能力)
    • [4. 方案实施](#4. 方案实施)
      • [4.1 第一步:冻结、导出与版本化](#4.1 第一步:冻结、导出与版本化)
      • [4.2 第二步:建立兼容画像](#4.2 第二步:建立兼容画像)
      • [4.3 第三步:选择改造路线](#4.3 第三步:选择改造路线)
        • [路线 A:保持包接口,内部逐项改写](#路线 A:保持包接口,内部逐项改写)
        • [路线 B:拆包为独立过程与函数](#路线 B:拆包为独立过程与函数)
        • [路线 C:数据库逻辑与应用逻辑分层](#路线 C:数据库逻辑与应用逻辑分层)
      • [4.4 第四步:消除包状态依赖](#4.4 第四步:消除包状态依赖)
      • [4.5 第五步:规范动态 SQL](#4.5 第五步:规范动态 SQL)
      • [4.6 第六步:重建权限模型](#4.6 第六步:重建权限模型)
      • [4.7 第七步:编译和无效对象治理](#4.7 第七步:编译和无效对象治理)
    • [5. 结果对比](#5. 结果对比)
      • [5.1 编译验证](#5.1 编译验证)
      • [5.2 接口契约验证](#5.2 接口契约验证)
      • [5.3 单元测试模板](#5.3 单元测试模板)
      • [5.4 源端与目标端对照测试](#5.4 源端与目标端对照测试)
      • [5.5 数据校验 SQL](#5.5 数据校验 SQL)
      • [5.6 性能与并发验证](#5.6 性能与并发验证)
      • [5.7 示例结果表](#5.7 示例结果表)
    • [6. 风险与复盘](#6. 风险与复盘)
      • [6.1 灰度切换策略](#6.1 灰度切换策略)
      • [6.2 回退方案](#6.2 回退方案)
      • [6.3 常见失败教训](#6.3 常见失败教训)
      • [6.4 最终复盘](#6.4 最终复盘)

每日一句正能量

遇到小事可以指望别人,遇到大事,千万不能把自个儿的命运拴到别人身上。

小事求助是协作;大事托付是押注。因为大事的后果往往超出他人能够或愿意承担的范围。这不是不信任他人,而是对自己负责------你的核心决策、人生转折、安身立命的根基,必须握在自己手里。依赖他人决定命运,就等于把方向盘交给了乘客。

1. 背景与问题

某核心业务系统长期运行在 Oracle 上,业务规则大量沉淀在数据库端。订单确认、费用计算、账户冻结、批量清算、月末结转等逻辑,并不是简单的单表增删改查,而是由二十余个包、数百个过程和函数共同完成。应用侧只负责传参和接收返回值,因此数据库迁移的难点不在于"表能否导过去",而在于这些存储程序能否保持原有语义。

项目初期,团队曾把"兼容"理解为"DDL 转换后可以编译"。实际验证很快暴露出问题:有些对象虽然编译成功,但包级变量的生命周期发生变化;有些过程在异常分支中提交事务,目标端行为与预期不一致;有些函数依赖 Oracle 系统包、DB Link、目录对象或自治事务;还有一部分重载过程在 JDBC 调用时出现参数匹配歧义。

因此,本次迁移采用四层判断标准:

  1. 语法兼容:对象是否能创建,依赖是否完整;
  2. 接口兼容:参数顺序、类型、IN/OUT、默认值和返回值是否一致;
  3. 语义兼容:事务、异常、空值、包状态、动态 SQL、权限模型是否一致;
  4. 运行兼容:并发、性能、锁行为、日志、审计和回退是否满足生产要求。

Oracle 的包由包规范和包体组成,可封装相关过程、函数、变量、常量和游标。KingbaseES 提供过程、函数和包等 PL/SQL 能力,但具体兼容范围与行为仍应以目标版本、兼容模式和实测结果为准。迁移工作不能只看功能清单,而应围绕真实调用链逐项验收。

2. 环境与数据

2.1 示例环境

项目 源端 目标端
数据库 Oracle 19c(示例) KingbaseES V8/V9(按项目版本填写)
兼容模式 Oracle 原生 Oracle 兼容模式
字符集 AL32UTF8 UTF8
应用 Java + MyBatis Java + MyBatis
存储程序规模 24 个包、186 个过程、73 个函数 待迁移
核心调用 订单确认、计费、清算、月结 待验证

正式项目中应补充补丁版本、驱动版本、迁移工具版本、参数文件、对象数量、调用频度和峰值并发。尤其是驱动调用存储过程的方式,会直接影响重载解析、OUT 参数读取和游标返回。

2.2 对象清单不是"对象数量表"

真正可用的对象清单至少应包含以下字段:

字段 说明
owner 对象所属用户
object_name 对象名
object_type PACKAGE、PACKAGE BODY、PROCEDURE、FUNCTION 等
status VALID / INVALID
source_lines 源码行数
dependency_count 依赖对象数量
caller_count 被其他对象或应用调用次数
feature_tags 动态 SQL、自治事务、系统包、DB Link、文件、邮件等
migration_level A/B/C/D 级
test_owner 负责测试的业务人员
rollback_unit 回退时的最小切换单元

迁移分级建议如下:

  • A 级:直接迁移。普通 DML、条件分支、循环、简单游标和标准异常处理;
  • B 级:轻量改写。函数名、系统视图、日期函数、字符串函数、动态 SQL 写法等需要调整;
  • C 级:结构重构。包状态、重载、复杂集合、自定义类型、自治事务、跨库调用;
  • D 级:下沉应用层或服务化。文件、邮件、操作系统命令、复杂外部依赖以及难以验证的数据库内编排。

2.3 Oracle 源端对象盘点 SQL

sql 复制代码
SELECT owner,
       object_type,
       COUNT(*) AS object_count,
       SUM(CASE WHEN status = 'INVALID' THEN 1 ELSE 0 END) AS invalid_count
FROM dba_objects
WHERE owner IN ('BIZ_CORE')
  AND object_type IN ('PACKAGE','PACKAGE BODY','PROCEDURE','FUNCTION','TYPE','TYPE BODY')
GROUP BY owner, object_type
ORDER BY object_type;

SELECT owner,
       name AS object_name,
       type AS object_type,
       COUNT(*) AS source_lines
FROM dba_source
WHERE owner = 'BIZ_CORE'
  AND type IN ('PACKAGE','PACKAGE BODY','PROCEDURE','FUNCTION')
GROUP BY owner, name, type
ORDER BY source_lines DESC;

SELECT owner,
       name,
       type,
       referenced_owner,
       referenced_name,
       referenced_type
FROM dba_dependencies
WHERE owner = 'BIZ_CORE'
ORDER BY name, referenced_owner, referenced_name;

SELECT owner,
       object_name,
       package_name,
       overload,
       subprogram_id,
       argument_name,
       position,
       sequence,
       in_out,
       data_type,
       data_length,
       data_precision,
       data_scale,
       defaulted
FROM dba_arguments
WHERE owner = 'BIZ_CORE'
ORDER BY package_name, object_name, overload, sequence;

仅靠系统视图仍不够。应用代码中可能通过字符串拼接调用过程,例如 BEGIN PKG_ORDER.CONFIRM_ORDER(?,?,?); END;,也可能由调度平台、报表工具或数据交换程序调用。因此还要扫描代码仓库、调度任务和运行日志,建立"对象---调用者---业务场景"三方映射。

3. 复现过程

下面选择一个常见的订单处理包,演示"能编译但不等于语义一致"的几个风险点。

3.1 Oracle 示例包

sql 复制代码
CREATE OR REPLACE PACKAGE pkg_order AS
  g_batch_no NUMBER := 0;

  PROCEDURE confirm_order(
      p_order_id IN  NUMBER,
      p_operator IN  VARCHAR2,
      p_result   OUT VARCHAR2);

  FUNCTION calc_fee(
      p_amount IN NUMBER,
      p_rate   IN NUMBER DEFAULT 0.006)
    RETURN NUMBER;
END pkg_order;
/

CREATE OR REPLACE PACKAGE BODY pkg_order AS

  FUNCTION calc_fee(
      p_amount IN NUMBER,
      p_rate   IN NUMBER DEFAULT 0.006)
    RETURN NUMBER
  IS
  BEGIN
    RETURN ROUND(p_amount * p_rate, 2);
  END;

  PROCEDURE confirm_order(
      p_order_id IN  NUMBER,
      p_operator IN  VARCHAR2,
      p_result   OUT VARCHAR2)
  IS
    v_status VARCHAR2(20);
    v_fee    NUMBER(18,2);
  BEGIN
    g_batch_no := g_batch_no + 1;

    SELECT status, calc_fee(pay_amount)
      INTO v_status, v_fee
      FROM biz_order
     WHERE order_id = p_order_id
       FOR UPDATE;

    IF v_status <> 'INIT' THEN
      RAISE_APPLICATION_ERROR(-20001, '订单状态不允许确认');
    END IF;

    UPDATE biz_order
       SET status      = 'CONFIRMED',
           fee_amount  = v_fee,
           operator_id = p_operator,
           update_time = SYSDATE
     WHERE order_id = p_order_id;

    INSERT INTO biz_order_log(
        log_id, order_id, action_code, batch_no, create_time)
    VALUES(
        seq_order_log.NEXTVAL, p_order_id, 'CONFIRM',
        g_batch_no, SYSDATE);

    p_result := 'SUCCESS';
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      p_result := 'NOT_FOUND';
    WHEN OTHERS THEN
      p_result := 'ERROR:' || SQLCODE || ':' || SQLERRM;
      RAISE;
  END;
END pkg_order;
/

3.2 风险一:包级变量状态

g_batch_no 是包级变量。Oracle 包状态通常与会话相关,连接池复用会话时,它可能持续存在。若迁移后直接保留这种设计,就必须验证目标端会话生命周期、连接池重置策略和异常后的状态变化。

这类变量如果被业务当成"全局递增号",本身就存在设计缺陷:多个会话各有状态,连接断开后状态消失,不能替代序列。改造时应先判断它究竟是缓存、会话上下文、批次号还是错误地承担了持久化职责。

3.3 风险二:默认参数与重载

Oracle 包常用默认参数和重载简化调用。目标端即使支持类似语法,也应验证:

  • 只传一个参数时能否命中正确子程序;
  • JDBC CallableStatement 按位置绑定和按名称绑定是否一致;
  • NULL 实参能否区分 NUMBERVARCHAR2 重载;
  • 应用升级前后是否使用了不同签名;
  • 默认参数表达式是否引用了包变量或函数。

3.4 风险三:异常码契约

应用可能并不只看"成功或失败",而是依赖 SQLCODE、自定义错误码或错误文本。迁移后若把异常全部改成通用异常,虽然事务会回滚,但上层状态机可能无法识别"订单不存在""状态冲突""余额不足"等业务分支。

Oracle 异常 业务含义 目标端处理
NO_DATA_FOUND 订单不存在 返回 NOT_FOUND 或统一业务码
-20001 状态不允许 映射为固定业务错误码
唯一约束异常 幂等冲突 返回已处理,不重复执行
其他异常 未知失败 记录上下文并回滚

3.5 风险四:事务边界

需要重点扫描过程内的 COMMITROLLBACK、保存点和自治事务。数据库过程自行提交,会破坏应用层统一事务;自治事务常用于日志,但也可能导致主事务回滚后日志仍保留。迁移时不能简单删除,也不能机械保留,应明确每个提交点的业务理由。

sql 复制代码
SELECT owner, name, type, line, text
FROM dba_source
WHERE owner = 'BIZ_CORE'
  AND (
       UPPER(text) LIKE '%COMMIT%'
    OR UPPER(text) LIKE '%ROLLBACK%'
    OR UPPER(text) LIKE '%SAVEPOINT%'
    OR UPPER(text) LIKE '%PRAGMA AUTONOMOUS_TRANSACTION%'
  )
ORDER BY name, type, line;

3.6 风险五:系统包和外部能力

常见依赖包括 DBMS_SCHEDULERDBMS_OUTPUTUTL_FILEUTL_HTTPDBMS_LOBDBMS_SQLDBMS_LOCKDBMS_RANDOM、邮件包、目录对象和 DB Link。兼容文档即使标记"支持",也应进一步验证参数、权限、安全策略和返回行为。外部网络、文件和系统命令还涉及生产安全审批,通常不宜原样搬迁。

4. 方案实施

4.1 第一步:冻结、导出与版本化

在正式改造前冻结 PL/SQL 对象变更窗口,并把源端原始 DDL、转换后的 DDL、人工改造脚本、依赖与权限脚本、编译日志、测试数据、期望结果和回退脚本纳入版本库。

text 复制代码
pkg_order/
├── 00_oracle_original.sql
├── 10_kingbase_converted.sql
├── 20_kingbase_refactored.sql
├── 30_grants.sql
├── 40_unit_test.sql
├── 50_regression_test.sql
├── 60_rollback.sql
└── README.md

4.2 第二步:建立兼容画像

sql 复制代码
SELECT name,
       type,
       SUM(CASE WHEN UPPER(text) LIKE '%EXECUTE IMMEDIATE%' THEN 1 ELSE 0 END) AS dynamic_sql_hits,
       SUM(CASE WHEN UPPER(text) LIKE '%PRAGMA AUTONOMOUS_TRANSACTION%' THEN 1 ELSE 0 END) AS autonomous_hits,
       SUM(CASE WHEN UPPER(text) LIKE '%DBMS_%' THEN 1 ELSE 0 END) AS dbms_hits,
       SUM(CASE WHEN UPPER(text) LIKE '%UTL_%' THEN 1 ELSE 0 END) AS utl_hits,
       SUM(CASE WHEN UPPER(text) LIKE '%@%' THEN 1 ELSE 0 END) AS dblink_hits
FROM dba_source
WHERE owner = 'BIZ_CORE'
GROUP BY name, type
ORDER BY autonomous_hits DESC, dbms_hits DESC, dynamic_sql_hits DESC;

关键词只能做初筛,不能代替人工审查。例如 @ 可能出现在邮件地址或注释中,COMMIT 可能只在注释里。最终分级要结合源码、调用链和生产日志。

4.3 第三步:选择改造路线

路线 A:保持包接口,内部逐项改写

适用于应用大量依赖包名和过程签名、短期不便修改应用的系统。优点是调用侧改动小,缺点是需要严格验证包语义。

sql 复制代码
\set SQLTERM /

CREATE OR REPLACE PACKAGE pkg_order AS
  PROCEDURE confirm_order(
      p_order_id IN  NUMERIC,
      p_operator IN  VARCHAR2,
      p_result   OUT VARCHAR2);

  FUNCTION calc_fee(
      p_amount IN NUMERIC,
      p_rate   IN NUMERIC DEFAULT 0.006)
    RETURN NUMERIC;
END;
/

CREATE OR REPLACE PACKAGE BODY pkg_order AS

  FUNCTION calc_fee(
      p_amount IN NUMERIC,
      p_rate   IN NUMERIC DEFAULT 0.006)
    RETURN NUMERIC
  IS
  BEGIN
    RETURN ROUND(p_amount * p_rate, 2);
  END;

  PROCEDURE confirm_order(
      p_order_id IN  NUMERIC,
      p_operator IN  VARCHAR2,
      p_result   OUT VARCHAR2)
  IS
    v_status VARCHAR2(20);
    v_fee    NUMERIC(18,2);
  BEGIN
    SELECT status, calc_fee(pay_amount)
      INTO v_status, v_fee
      FROM biz_order
     WHERE order_id = p_order_id
       FOR UPDATE;

    IF v_status <> 'INIT' THEN
      RAISE_APPLICATION_ERROR(-20001, '订单状态不允许确认');
    END IF;

    UPDATE biz_order
       SET status      = 'CONFIRMED',
           fee_amount  = v_fee,
           operator_id = p_operator,
           update_time = CURRENT_TIMESTAMP
     WHERE order_id = p_order_id;

    INSERT INTO biz_order_log(
        log_id, order_id, action_code, create_time)
    VALUES(
        NEXTVAL('seq_order_log'), p_order_id,
        'CONFIRM', CURRENT_TIMESTAMP);

    p_result := 'SUCCESS';
  EXCEPTION
    WHEN NO_DATA_FOUND THEN
      p_result := 'NOT_FOUND';
    WHEN OTHERS THEN
      p_result := 'ERROR';
      RAISE;
  END;
END;
/

\set SQLTERM ;

上例只展示改造思路。NEXTVAL 写法、异常函数、时间函数和包语法应以实际 KingbaseES 版本为准,并在测试库中确认。

路线 B:拆包为独立过程与函数

适用于包状态无实际价值、对象耦合不高的系统。把公共函数和过程拆成独立对象,包名通过同义层、适配层或应用映射保留。优点是依赖清晰、部署粒度更小;缺点是需要调整调用入口。

路线 C:数据库逻辑与应用逻辑分层

适用于包中混合了文件、网络、任务编排、消息发送和复杂跨系统调用的情况。将数据一致性强、贴近 SQL 的逻辑留在数据库;把外部 I/O、长流程、重试和编排移到应用服务。这样更利于观测、限流和故障隔离。

4.4 第四步:消除包状态依赖

原用途 建议替代
唯一编号 序列或专用号段服务
用户上下文 应用显式传参、会话上下文表
缓存字典 只读表、物化视图或应用缓存
批次状态 持久化批次表
临时集合 局部变量、临时表或显式集合参数

不要在未理解用途前直接删除包变量。对会话状态敏感的过程,应增加"同一连接连续调用"和"连接池复用后调用"两类测试。

4.5 第五步:规范动态 SQL

sql 复制代码
-- 不推荐:值直接拼接
v_sql := 'UPDATE biz_order SET status = ''' || p_status ||
         ''' WHERE order_id = ' || p_order_id;

-- 推荐:值使用绑定变量
v_sql := 'UPDATE biz_order SET status = :1 WHERE order_id = :2';
EXECUTE IMMEDIATE v_sql USING p_status, p_order_id;

动态对象名无法直接绑定时,必须从固定白名单映射,不接受外部原始字符串。

4.6 第六步:重建权限模型

Oracle 中 AUTHID DEFINERAUTHID CURRENT_USER 会影响对象以定义者权限还是调用者权限执行。迁移时应梳理对象所有者、应用账号直接权限、角色权限、动态 SQL 权限、跨模式访问、同义词与搜索路径。权限问题常表现为"管理员测试正常,应用账号执行失败",所以所有回归用例必须使用真实应用账号执行一次。

4.7 第七步:编译和无效对象治理

目标端部署后先统计无效对象,再按依赖顺序修复。不能只看最终无效对象数量,还要保存每次编译错误的对象名、行号、错误码和修复动作。

issue_id object_name object_type error_stage error_message root_cause action owner status

5. 结果对比

5.1 编译验证

sql 复制代码
SELECT object_type,
       COUNT(*) AS object_count,
       SUM(CASE WHEN status <> 'VALID' THEN 1 ELSE 0 END) AS invalid_count
FROM user_objects
WHERE object_type IN ('PACKAGE','PACKAGE BODY','PROCEDURE','FUNCTION')
GROUP BY object_type;

编译通过率应达到 100%,但它只是第一道门槛。

5.2 接口契约验证

为每个过程生成接口快照,校验参数名称与顺序、IN/OUT、数据类型、精度、长度、默认参数、重载编号、返回类型、游标列顺序和业务错误码。建议在源端和目标端分别导出 JSON 或 CSV,再做差异比较。

5.3 单元测试模板

sql 复制代码
INSERT INTO biz_order(
    order_id, status, pay_amount, fee_amount, operator_id, update_time)
VALUES(
    900001, 'INIT', 1000.00, NULL, NULL, CURRENT_TIMESTAMP);

DECLARE
  v_result VARCHAR2(100);
BEGIN
  pkg_order.confirm_order(
      p_order_id => 900001,
      p_operator => 'tester',
      p_result   => v_result);

  DBMS_OUTPUT.PUT_LINE(v_result);
END;
/

SELECT order_id,
       status,
       pay_amount,
       fee_amount,
       operator_id
FROM biz_order
WHERE order_id = 900001;

单元测试必须覆盖正常、边界、异常、重复调用、并发调用、调用后回滚、应用账号权限、中文与 NULL 参数、连接池复用后的状态。

5.4 源端与目标端对照测试

对同一输入分别调用 Oracle 和 KingbaseES,保存输入、返回码、OUT 参数、数据变化、错误信息和执行耗时。对于写操作,可使用隔离数据、事务回滚、影子表或脱敏快照,避免双写污染。

5.5 数据校验 SQL

sql 复制代码
SELECT status, COUNT(*)
FROM biz_order
GROUP BY status
ORDER BY status;

SELECT COUNT(*) AS row_count,
       SUM(pay_amount) AS total_pay,
       SUM(fee_amount) AS total_fee,
       MIN(update_time) AS min_time,
       MAX(update_time) AS max_time
FROM biz_order;

SELECT o.order_id
FROM biz_order o
LEFT JOIN biz_order_log l
  ON l.order_id = o.order_id
 AND l.action_code = 'CONFIRM'
WHERE o.status = 'CONFIRMED'
GROUP BY o.order_id
HAVING COUNT(l.log_id) = 0;

SELECT order_id, action_code, COUNT(*)
FROM biz_order_log
GROUP BY order_id, action_code
HAVING COUNT(*) > 1;

对财务和结算过程,还应校验分录借贷平衡、账户余额、日汇总、批次总额和业务日期边界。

5.6 性能与并发验证

记录平均、P95、P99 耗时、每秒调用次数、锁等待、死锁、CPU、I/O、临时空间、批量提交大小、异常率和超时率。不能只比较单次空载耗时,至少要在接近生产数据规模和并发度下压测核心过程。

5.7 示例结果表

指标 Oracle 基线 KingbaseES 改造后 结论
对象编译通过率 100% 100% 达标
核心接口一致率 100% 100% 达标
业务用例通过率 100% 99.8% 2 个异常码需修正
数据汇总一致率 100% 100% 达标
P95 耗时 82 ms 88 ms 可接受
并发错误率 0.02% 0.03% 可接受
回退耗时 --- 12 分钟 达标

以上数字仅为演示格式,正式文章应替换为真实执行日志、测试截图和问题修复前后对比。

6. 风险与复盘

6.1 灰度切换策略

建议将存储程序切换拆成只读函数、查询型过程、低风险写过程、核心交易过程、批处理与月结过程。灰度阶段通过调用路由控制流量。对于只读函数,可以进行影子调用;对于写过程,可采用隔离账号、影子表、回滚事务或脱敏数据演练。

切换门槛应包含无效对象为 0、核心用例 100% 通过、业务汇总一致、异常码映射完成、P95/P99 在阈值内、无新增死锁、应用账号权限验证通过、回退演练完成、监控和审计可用。

6.2 回退方案

回退不是只修改连接串。写过程切换后,目标端可能已经产生新订单、日志、批次和序列值。完整回退至少包括:

  1. 停止新请求进入目标端;
  2. 等待在途事务结束或强制终止;
  3. 导出切换窗口内的增量数据;
  4. 对账订单、金额、状态、日志和序列;
  5. 将可回放增量按业务顺序写回 Oracle;
  6. 恢复应用调用路由;
  7. 验证源端对象、权限、序列和任务;
  8. 保留目标端现场用于问题分析。

为降低回退难度,可在灰度窗口内采用独立业务号段、写入切换批次号,并记录每次过程调用的请求标识。回放脚本必须幂等,重复执行不能生成重复订单或重复分录。

6.3 常见失败教训

过度相信自动转换。 自动工具适合处理大量重复语法,但无法判断包变量是否承担业务状态,也无法理解一次 COMMIT 的业务含义。

只测正常路径。 真正容易出现差异的是异常、边界、并发和回滚路径。

忽视应用调用方式。 数据库控制台手工调用成功,不代表 JDBC、MyBatis、.NET 或调度平台调用成功。

把兼容模式当作完全等价。 兼容模式能降低改造量,但不能消除版本、参数、驱动和实现细节差异。

没有保留源端基线。 若没有输入、输出、错误码、数据变化和耗时基线,出现差异后很难定位。

6.4 最终复盘

包、过程与函数迁移的核心,不是把 PL/SQL 源码换一种语法重新编译,而是把数据库端接口、状态、事务和异常重新做一次工程化验收。最稳妥的路线是先建立对象与调用清单,再按兼容风险分级;低风险对象直接迁移,高风险对象专项改造;用源端基线驱动接口、数据、异常和性能对照;最后以灰度、门禁和可逆回退完成切换。

一套真正可交付的迁移方案,至少应留下对象清单、问题清单、改造脚本、测试证据、性能数据、上线步骤和回退记录。只有这些证据齐全,才能把"代码迁过去了"升级为"业务可以安全运行"。


转载自:https://blog.csdn.net/u014727709/article/details/163173281

欢迎 👍点赞✍评论⭐收藏,欢迎指正

相关推荐
想你依然心痛4 小时前
【金仓数据库征文】Oracle到金仓:序列、触发器与自增键改造实践
触发器·序列·金仓数据库·oracle迁移·自增键·并发验证·回退方案
承渊政道3 天前
从设备数据到AI洞察:时序数据的多模融合实践
数据库·人工智能·性能优化·金仓数据库·多模融合
数据库小学妹11 天前
国产数据库选型技术指南:五大主流路线对比与Oracle迁移策略分析
分布式数据库·信创数据库·oracle迁移·国产数据库选型·集中式数据库
肖永威15 天前
金仓数据库麒麟环境SQL终端使用入门实践(增删改查篇)
数据库·sql·金仓数据库
不剪发的Tony老师18 天前
金仓数据库在线体验:简单易用
数据库·金仓数据库
云边有个稻草人2 个月前
深度解析:KingbaseES高可用架构落地原理与生产运维实战
数据库·读写分离·数据库运维·金仓数据库·国产数据库技术·数据备份恢复
云边有个稻草人2 个月前
金仓数据库标量子查询消除:解决复杂SQL性能瓶颈
数据库·sql·性能调优·金仓数据库·kes·标量子查询·数据库内核
正在走向自律2 个月前
标量子查询消除:数据库优化器的一场“等价变戏法”
数据库·sql 优化·金仓数据库·数据库性能调优·标量子查询·数据库优化器
云边有个稻草人3 个月前
金仓 KingbaseES Pro*C 迁移指南:从 Oracle 平滑迁移
oracle·数据库迁移·kingbasees·金仓数据库·国产化适配·proc 迁移