Oracle Skills实战:AI辅助MySQL迁移Oracle

Oracle Skills 实战:AI 辅助 MySQL 迁移 Oracle

80 张表,5000 行建表语句,数百处致命问题------从数天人工审查压缩到 5 分钟自动化,这是用 Oracle Database Skills + AI Agent 完成 MySQL→Oracle 迁移的真实体验。本文重点演示如何让 AI 接入 Oracle Skills 来协助数据库工作。


一、迁移之痛:DDL 表结构转换是最大瓶颈

做过跨库迁移的人都清楚,数据搬运不是最难的------mysqldump 导出、SQL*Loader 导入,工具链相对成熟。真正折磨人的是 DDL 表结构的兼容性转换

两个数据库虽然都叫"关系型数据库",但在类型体系、关键字规则、索引约束、存储过程语法上的差异,远比想象的复杂。一个典型的迁移项目中,DDL 转换通常要占总工时的 40% 以上。

看似简单的建表语句,埋了多少雷

拿一个中等规模的业务系统来说:80 张表、约 5000 行建表语句。如果用可视化建模工具从 MySQL 自动导出 Oracle 脚本,工具通常只能做最基础的字面转换------去掉反引号、把 AUTO_INCREMENT 替换为 IDENTITY------然后剩下大量的深层问题原封不动地留给你。

我最近在一个项目的 MySQL→Oracle 12c 迁移中,拿到这样一份"半成品" DDL 后,逐表检查了一遍,发现的问题比预想的多得多:

  • 数据类型原样保留:BIGINT、TINYINT、SMALLINT、BIT------这四个关键字 Oracle 12c 一个都不认识。工具只转了 INT→NUMBER 和 VARCHAR→VARCHAR2,其他类型照搬了 MySQL 写法。
  • UNSIGNED 修饰符遍布全文件 :Oracle 从来没有 UNSIGNED 这个概念。MySQL 允许 INT UNSIGNED,Oracle 会直接报语法错误。而这个文件中 UNSIGNED 出现了近 150 次。
  • 列名与 Oracle 保留字冲突SIZELEVELNUMBER------这些在 MySQL 中是合法的列名,到了 Oracle 就成了保留字,建表直接失败。
  • 索引名跨表重复 :MySQL 允许不同表使用相同的索引名(如多个表都有 idx_flag)。Oracle 要求索引名在全 Schema 范围内唯一------20 多个索引名存在重复,必须逐个加表名前缀区分。
  • JSON 类型不支持 :MySQL 5.7 起就支持原生 JSON 列,但 Oracle 直到 21c 才引入 JSON 类型。12c 环境下必须改为 CLOB 并加 IS JSON 约束。

这些问题的任何一个,都会导致 CREATE TABLE 直接报错。按传统方式逐表审查、逐列对照、手动修改,两到三天的工作量起步。


二、Oracle Database Skills:把官方文档"注入" AI Agent

解决问题的关键是 Oracle Database Skills------Oracle 官方在 GitHub 上维护的一套 AI 技能仓库。

它是什么

简单说,这是一套结构化的技术指导文件,专门为 AI 编程助手(Claude Code、Codex、Hermes Agent 等)设计。仓库地址:https://github.com/oracle/skills

它并非传统的"把整本手册塞给 AI",而是采用了一种更聪明的设计:

复制代码
oracle/skills/
├── db/                    ← Oracle 数据库(本文核心)
│   ├── SKILL.md           ← 路由索引(仅 5KB)
│   ├── migrations/        ← 迁移专题
│   │   ├── migrate-mysql-to-oracle.md
│   │   ├── migrate-postgresql-to-oracle.md
│   │   ├── migration-assessment.md
│   │   └── ...
│   ├── performance/       ← AWR/ASH/执行计划
│   ├── plsql/             ← 包设计/游标/异常
│   ├── security/          ← 权限/VPD/数据加密
│   ├── sql-dev/           ← SQL 调优/动态 SQL
│   └── ...共 18 个分类
├── oci/                   ← Oracle Cloud
├── graal/                 ← GraalVM
└── apex/                  ← Oracle APEX

路由索引设计:按需加载,不浪费 Token

db/SKILL.md 只有 5KB,本身不包含具体知识。它是一张路由表

你问什么 AI 去读哪个文件
MySQL 类型怎么映射到 Oracle? migrations/migrate-mysql-to-oracle.md
执行计划怎么分析? performance/explain-plan.md
PL/SQL 包怎么设计? plsql/plsql-package-design.md
Data Guard 怎么配置? admin/data-guard.md

AI Agent 只在回答问题时才去拉取对应的子文件。不相关的 17 个分类完全不进上下文,Token 消耗比全量注入降低了 90% 以上。

覆盖到什么程度

以迁移场景最常用的 migrate-mysql-to-oracle.md 为例,它覆盖了:

  • 25 种以上数据类型的完整映射(含精度对应、示例 SQL)
  • 24 个字符串函数转换(CONCAT→||、GROUP_CONCAT→LISTAGG 等)
  • 16 个日期函数转换(含 MySQL↔Oracle 格式掩码对照表)
  • 存储过程全量转换:变量声明、控制流(注意 ELSIF 不是 ELSEIF)、游标处理、异常捕获
  • 数据迁移工作流:mysqldump 导出→Schema 转换→SQL*Loader 导入

所有转换建议都直接引用 Oracle 官方文档,每个示例都有完整的"改前 / 改后"代码对比,不是社区论坛水平的一句"试试 NUMBER 代替 INT"。


三、实战:如何让 AI Agent 接入 Oracle Skills 完成迁移

下面以 MySQL→Oracle 12c 迁移为例,演示从接入到完成的完整流程。

Step 1:接入 Oracle Skills

在 Hermes Agent 中安装 Oracle Skills 的 db 域:

bash 复制代码
hermes skills install skills-sh/oracle/skills/db

安装后,164 个数据库相关的结构化文件自动可用。你也可以把常用的迁移参考文件下载到本地:

bash 复制代码
mkdir -p ~/.hermes/skills/database/oracle-migration-review/references/
curl -o ~/.hermes/skills/database/oracle-migration-review/references/migrate-mysql-to-oracle.md \
  https://raw.githubusercontent.com/oracle/skills/main/db/migrations/migrate-mysql-to-oracle.md

参考文件来源于 https://github.com/oracle/skills ,可按需下载任意子目录文件。

对于 Claude Code 或其他通用 AI 工具,可将 db/SKILL.md 的路由表粘贴到项目的 AGENTS.md 中,AI 会自动按需拉取子文件。

Step 2:AI Agent 自动路由

把 DDL 文件交给 AI Agent(我用的是 Hermes Agent,也可以用 Claude Code 或 Codex):

复制代码
用户: "帮我审查这份 MySQL DDL 在 Oracle 12c 上的兼容性"
    ↓
AI 判断: 这是迁移任务 → 触发 db skill
    ↓
查看路由表: migrations → migrate-mysql-to-oracle.md
    ↓
加载官方类型映射表作为权威参考

整个过程不需要手动指定用哪个 skill、读哪个文件------AI 自己判断。

官方 Skill 的盲区:知识完整,但缺执行

migrate-mysql-to-oracle.md 在类型映射上非常权威,但实际迁移中你会发现它有明显的覆盖盲区:

  • 不含 Oracle 保留字列表------它只说了句"避免使用保留字做标识符",既没有列出哪些是保留字,也没有检测逻辑
  • 不含索引名唯一性检查------MySQL 允许不同表同名索引,Oracle 要求全局唯一,这个差异它没提
  • 不含 COMMENT ON 同步逻辑------改列名时注释也得跟着改,这个细节不在它的范围内
  • FLOAT 语法差异标注不够 ------官方文档只说了 MySQL FLOAT 应对标 Oracle BINARY_FLOAT,但没有区分 FLOAT(p) 单参数(显示宽度)和 FLOAT(p,s) 双参数(精度约束)两种语法。前者用 BINARY_FLOAT 完全对标;后者 Oracle 根本不支持 BINARY_FLOAT(p,s) 语法,必须改为 NUMBER(p,s)
  • TEXT 族类型覆盖不全 ------TINYTEXT、MEDIUMTEXT、LONGTEXT 这些 MySQL 特有的文本类型并未在映射表中逐项列出,实际迁移中它们都需统一变为 CLOB
  • 不含自动检测和修正脚本------它是参考文档,不是执行工具

换句话说:官方 Skill 是字典,但你还需要一个编译器。

所以我在项目里写了一个配套的 Python 扫描脚本(约 150 行),把官方文档的映射规则变成可执行的检测和替换逻辑。下面按这个"字典 + 编译器"的组合来演示完整流程。

Step 3:扫描脚本自动化,3 秒出结果

脚本读取 DDL 后,按官方类型映射表逐一检查,一键输出:

text 复制代码
🔴 致命问题(会导致 CREATE TABLE 失败)
├── BIGINT:      300+ 处 → 改为 NUMBER(19)
├── TINYINT:     50+ 处  → 改为 NUMBER(3)
├── SMALLINT:    8 处    → 改为 NUMBER(5)
├── BIT:         5 处    → 改为 NUMBER(n)
├── FLOAT(p,s):  3 处    → 改为 NUMBER(p,s)(双参数语法的精度约束)
├── FLOAT(p):    2 处    → 改为 BINARY_FLOAT(单参数显示宽度,对标 IEEE 754)
├── UNSIGNED:    150 处  → 删除该关键字
├── JSON:        2 处    → CLOB + IS JSON 约束
├── TINYTEXT:    3 处    → 改为 CLOB
├── MEDIUMTEXT:  4 处    → 改为 CLOB
└── 重复索引:     20+ 个  → 加表名前缀区分

🟡 保留字列名
├── SIZE   → XXX_SIZE  (3 处,含 COMMENT ON 同步)
├── LEVEL  → AAA_LEVEL / BBB_LEVEL (3 处)
└── NUMBER → XXX_NUM   (2 处)

🟠 设计建议
├── INT 类型 150+ 处 → Oracle 中 INT=NUMBER(38),建议改为 NUMBER(10)
└── 3 张表无主键 → 需业务确认

Step 4:官方文档兜底,边缘类型不抓瞎

扫描脚本处理常见类型足够快,但遇到 ENUM、BIT、GEOMETRY、MEDIUMINT 这种"一年碰不到几次"的类型时,直接查阅官方文件:

sql 复制代码
-- MySQL ENUM 类型
CREATE TABLE orders (
    order_id INT AUTO_INCREMENT PRIMARY KEY,
    status   ENUM('pending','processing','shipped','delivered')
);

-- Oracle 等价写法(来自 migrate-mysql-to-oracle.md)
CREATE TABLE orders (
    order_id NUMBER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
    status   VARCHAR2(20) NOT NULL,
    CONSTRAINT chk_orders_status
        CHECK (status IN ('pending','processing','shipped','delivered'))
);

不需要凭记忆猜,不需要翻 StackOverflow------官方文件给出了完整的类型对照表和可执行的示例代码。

Step 5:自动修正 + 验证

所有修改一次性完成,输出可直接在 Oracle 执行的文件。验证环节自动化:

text 复制代码
残留检查结果:
  BIGINT:      0 ✅
  TINYINT:     0 ✅
  SMALLINT:    0 ✅
  UNSIGNED:    0 ✅
  TINYTEXT:    0 ✅
  MEDIUMTEXT:  0 ✅
  保留字列名:   0 ✅
  重复索引:     0 ✅
  COMMENT ON 同步: 全部完成 ✅
  FLOAT 语法检查:  BINARY_FLOAT/NUMBER(p,s) 正确 ✅

四、避坑指南:三个容易犯的错误

坑 1:保留字检测的盲区

前面提到的扫描脚本,第一版的保留字检测正则只匹配了 6 种常见 Oracle 数据类型:

python 复制代码
# ❌ 问题版本:类型列表太窄
col_defs = re.findall(r'^\s+(\w+)\s+(NUMBER|VARCHAR2|DATE|DECIMAL|CHAR|CLOB)', ...)

问题在于------这份 DDL 还没完成转换,大量列用的是 MySQL 类型(SIZE INTLEVEL TINYINT)。这些列因为类型不在正则里,被直接跳过了保留字检测。

修法:把 MySQL 常见的列类型也加进去:

python 复制代码
# ✅ 修复版本:覆盖 17 种常见类型
col_defs = re.findall(r'^\s+(\w+)\s+(NUMBER|VARCHAR2|DATE|DECIMAL|CHAR|CLOB|INT|BIGINT|TINYINT|SMALLINT|BIT|BLOB|RAW|TIMESTAMP|FLOAT|DOUBLE|VARCHAR)', ...)

坑 2:改列名忘了 COMMENT ON

Oracle 的 COMMENT ON COLUMN 语法里列名是硬编码字符串。把 SIZE 改成 XXX_SIZE 后,如果不更新 COMMENT ON:

sql 复制代码
-- 改前列定义
SIZE INT,

-- 改后列定义
XXX_SIZE NUMBER(10),

-- 忘了改这个 👇
COMMENT ON COLUMN orders.SIZE IS '文件大小';  -- 指向不存在的列!

脚本必须同时替换列定义行和 COMMENT ON 行,用正则一次性完成。

坑 3:自动修正后必须验证,不要盲目信任

脚本可以帮你改 600 多处,但不代表改完就能直接上生产。有三件事必须手动确认:

  • 改列名后检查关联代码 ------SIZE 改成 XXX_SIZE,应用层的 SQL、ORM 映射、报表查询都得跟着改。脚本只管 DDL,管不了你的 Java 代码。
  • 验证修正后的 DDL 能在目标 Oracle 版本上执行 ------12.1 和 12.2 的标识符长度限制不同(30 vs 128 字节),IDENTITY 列在 12.1 之后才支持。如果你的目标环境版本不确定,先确认。
  • 残留检查不要只信脚本的报告 ------用 grep 再扫一遍 BIGINT、TINYINT、UNSIGNED 等关键字,确保 0 残留。两次验证总比一次可靠。

记住:脚本是提效工具,最终拍板的是你。

坑 4:FLOAT 参数语法,单双有别

MySQL 的 FLOAT 在 Oracle 中有个大坑------参数数量的含义完全不同:

sql 复制代码
-- MySQL                                 -- Oracle 映射
OPACITY FLOAT(12)                        -- BINARY_FLOAT(p=显示宽度,不约束值)
CT_SCORE FLOAT(2,1)                      -- NUMBER(2,1)(p,s=精度+标度,真约束)
RATIO   FLOAT(5,3)                       -- NUMBER(5,3)

关键规则:

语法 含义 Oracle 映射 原因
FLOAT(p) 单参数 显示宽度 BINARY_FLOAT IEEE 754 单精度完全对标
FLOAT(p,s) 双参数 精度+标度 NUMBER(p,s) Oracle 无 BINARY_FLOAT(p,s) 语法

两个常见错误:

  • NUMBER(12) 映射 FLOAT(12) → Oracle 中 NUMBER(12) 是整数,会截断所有小数位
  • NUMBER(18,6) 试图"万能兜底" → FLOAT 的范围是 ±3.4×10³⁸,NUMBER(18,6) 上限只有约 10¹²,超出直接报错

五、延伸:不止迁移,18 个分类覆盖全链路

db 域下除了 migrations/,还有另外 17 个分类值得 DBA 关注:

分类 解决什么问题
performance/ 慢 SQL 诊断:explain plan→wait events→optimizer stats→AWR reports
plsql/ 包设计规范、游标优化、异常处理最佳实践
security/ 最小权限原则、VPD 行级安全、TDE 透明加密
sql-dev/ SQL 调优 Checklist、动态 SQL 安全写法、SQL 注入防护
sqlcl/ SQLcl Liquibase 做版本化迁移、MCP Server 让 AI 直连数据库
admin/ Data Guard 搭建、redo/undo 管理、用户与角色
devops/ Schema 在线变更、Edition-Based Redefinition、零停机迁移

这些分类都是"用到时才加载"的模式。装一个 db 入口就够,不需要担心 Token 膨胀。


六、效率实测

维度 纯人工审查 Oracle Skill + AI Agent
审查耗时 2~3 天(逐表逐列核对) ~5 分钟(自动扫描 + 人工复核)
漏检风险 数百处问题,人工极易遗漏 脚本 + 官方类型表双重验证
COMMENT ON 同步 手工逐行修改,容易漏 脚本自动同步
可复现性 依赖审查人经验 脚本可重复执行
版本差异处理 凭个人记忆(12.1 vs 12.2 标识符长度等) 官方文档明确标注版本差异
边缘类型处理 需要查官方文档或社区 官方文件直接给出对照表和示例

七、总结与建议

Oracle Database Skills 把 Oracle 官方技术文档结构化地注入了 AI Agent,让数据库迁移从「人肉逐行审查」变成了「Agent 自动扫描 + 官方文档验证」。

接入 Oracle Skills 的操作步骤:

  1. 安装 db 域hermes skills install skills-sh/oracle/skills/db
  2. 本地缓存 :把 migrate-mysql-to-oracle.md 等常用文件下载到 ~/.hermes/skills/ 目录,避免 GitHub 不可达时影响工作
  3. 编写自建脚本 :官方 Skill 保证类型映射的准确性,自建脚本保证检测和修正的效率------两者加起来才是完整的 Oracle AI 工作流

把重复性的兼容性检查交给 Agent,把精力留给真正需要专业判断的------比如分区策略选择、索引设计优化、迁移切换方案制定。


📎 相关链接