dbx OceanBase Oracle 分区 DDL 验证指南:从自动化重放脚本到 UI 存储属性偏好
2026/9/20 19:37:49 网站建设 项目流程

dbx OceanBase Oracle 分区 DDL 验证指南:从自动化重放脚本到 UI 存储属性偏好

【免费下载链接】dbx15MB,轻量级跨平台数据库客户端、数据库管理工具。支持 MySQL、PostgreSQL、SQLite、Redis、MongoDB、DuckDB、ClickHouse、SQL Server 等。15MB, lightweight, cross-platform database client. Supports MySQL, PostgreSQL, SQLite, Redis, MongoDB, DuckDB, ClickHouse, SQL Server and more.项目地址: https://gitcode.com/t8y2/dbx

本指南围绕开源数据库客户端 dbx 中 OceanBase Oracle 模式(Oracle 兼容租户)的分区表 DDL 验证方案展开,涵盖构建与运行自动化验证脚本、JSON-RPC 驱动下的分区元数据重放与语义检查、以及桌面端 "Omit storage attributes"(省略存储属性)偏好的 UI 验证。读完本文,你将掌握如何完整复现分区 DDL 的端到端验证流程,理解 dbx 底层如何生成分区 DDL 与读取分区信息,并能自行扩展验证用例。

一、为什么要验证 OceanBase Oracle 分区 DDL

OceanBase 的 Oracle 兼容模式在语法上与原生 Oracle 高度一致,但分区表的存储选项、元数据视图与DBMS_METADATA支持程度存在版本差异。dbx 作为数据库客户端,需要保证:

  • 在对象树中正确展示分区表的 Partitions / Subpartitions 分组;
  • 生成可再次执行的分区 DDL(含分区子句、约束、LOCAL 索引、默认值与注释);
  • 提供 "省略存储属性" 选项,导出的 DDL 可跨环境重放,而不丢失语义。

agents/drivers/oceanbase-oracle/scripts/README.md描述了一套针对以上目标的验证方案,其配套脚本与实现源码位于:

  • 验证脚本
  • Agent 实现
  • DDL 存储属性偏好实现

二、构建 OceanBase Oracle Agent(JDK 21)

验证脚本通过 JSON-RPC 启动一个已构建的 Agent 进程,因此第一步是从仓库根目录用 JDK 21 构建并打包。官方命令如下:

./agents/gradlew -p agents :common:test :oceanbase-oracle:test :oceanbase-oracle:shadowJar

该命令依次执行:

任务作用
:common:test构建并测试 Agent 公共模块(agents/common/src
:oceanbase-oracle:test运行 OceanBase Oracle Agent 的 JUnit 单元测试(OceanBaseOracleAgentTest.java)
:oceanbase-oracle:shadowJar打出包含全部依赖的 fat jar,产物为agents/drivers/oceanbase-oracle/build/libs/dbx-agent-oceanbase-oracle.jar

单元测试层已经覆盖了若干关键行为,例如 JDBC URL 构造(默认追加compatibleOjdbcVersion=8)、查询超时到 OceanBase 会话变量ob_query_timeout(微秒)的换算,以及分区键顺序与字典序保持等,可作为构建期的事实基线。

三、环境变量与一次性 Oracle 租户准备

运行脚本前需要设置以下环境变量:

环境变量含义默认值/要求
OB_HOSTOceanBase 主机地址必填
OB_PORT连接端口默认2881(脚本内process.env.OB_PORT ?? 2881
OB_TENANT租户名必填
OB_PASSWORD一次性 Oracle 租户中SYS用户的密码必填

注意事项:

  • OB_PASSWORD必须属于一个一次性(disposable)Oracle 租户——脚本会在该租户下创建、重放和删除测试对象,切勿使用生产租户;
  • 脚本以user@tenant形式构造连接用户名(见 verify-partition-ddl.ts),user分别为SYS与三个测试用户;
  • Agent 内置 profile 的默认端口为 2883(对应 OceanBase 常部署的 OBProxy 端口,见 OceanBaseOracleAgent.java),而验证脚本显式覆盖为 2881(observer 直连默认端口),两种端口均可根据实际拓扑调整。

四、运行分区 DDL 验证脚本

构建完成后,在仓库根目录执行:

pnpm exec tsx --tsconfig apps/desktop/tsconfig.json agents/drivers/oceanbase-oracle/scripts/verify-partition-ddl.ts

命令拆解:

  • pnpm exec tsx:以 tsx 运行时直接执行 TypeScript 脚本,无需单独编译;
  • --tsconfig apps/desktop/tsconfig.json:复用桌面端 TypeScript 配置,使脚本能够解析对apps/desktop/src前端源码的导入(见下文);
  • 脚本入口为 verify-partition-ddl.ts。

脚本通过子进程启动 Agent jar,并基于 stdio 之上的 JSON-RPC 2.0 协议与其通信({"jsonrpc":"2.0","id":...,"method":...,"params":...}每行一条),单次请求超时为 60 秒(verify-partition-ddl.ts)。

4.1 隔离 Schema 与测试夹具

脚本会创建三个相互隔离、以随机后缀命名的 Schema(避免并行运行时互相污染):

  • DBX7055_S<8位随机大写>:源 Schema,用于建表并采集 DDL/分区元数据;
  • DBX7055_L<8位随机大写>:逻辑重放目标,重放"省略存储属性"后的简化 DDL;
  • DBX7055_P<8位随机大写>:物理重放目标,重放包含存储属性的完整 DDL。

测试夹具共8 张表,覆盖了分区 DDL 的主要形态:

表名形态覆盖点
PARENT普通表 + 主键外键引用目标
RANGE_LISTRANGE 分区 + LIST 子分区复合分区、默认值含存储关键字文本、PK/CHECK 约束
RANGE_TRANGE 复合分区键(ID,D)多列分区键、多列 MAXVALUE 边界
LIST_TLIST 分区列表值中含'PCTFREE = 20'文本
HASH_THASH 分区PARTITIONS 4分区数量断言
CHILD普通表 + 外键外键语义重放验证
Mixed Table带引号标识符列名恰为"PCTFREE"、默认值含引号转义
TEMP_T全局临时表(ON COMMIT PRESERVE ROWS内部会话索引不得被导出

除此之外,源 Schema 还创建了一个 LOCAL 索引C_LOCAL ON RANGE_LIST(NOTE) LOCAL,以及表注释table's PCTFREE = 20和列注释note ; ) COMPRESS FOR ARCHIVE——这些文本刻意包含与存储选项关键字相似的子串,用于验证"清理存储选项"不会误伤字符串字面量与注释。

4.2 采集、重放与逐项断言

对每张表,脚本执行以下流程:

  1. source会话调用get_table_ddl获取完整 DDL,调用list_partitionslist_subpartitions获取分区/子分区元数据(verify-partition-ddl.ts);
  2. applyDdlStoragePreference(ddl, "oceanbase-oracle")生成简化 DDL,并断言applyDdlStoragePreference(ddl, "oceanbase-oracle", false) === ddl(关闭选项时原样返回)、简化结果不含REPLICA_NUM =
  3. 分别把简化 DDL 重放到logical会话、完整 DDL 重放到physical会话:先将源 Schema 限定名替换为目标 Schema,再用splitSqlStatementRanges(sqlStatementRanges.ts)切分语句逐条执行;
  4. 重放后断言list_partitionslist_subpartitionsget_columns结果与源 Schema 完全一致(assert.deepEqual),从而证明"省略存储属性"不影响分区结构与列元数据。

分区/子分区数量断言如下([分区数, 子分区数]):

断言
RANGE_LIST[2, 4](2 个分区 × 各 2 个子分区)
RANGE_T[2, 0]
LIST_T[2, 0]
HASH_T[4, 0]

随后,三个会话还会执行一组语义检查(verify-partition-ddl.ts):

  • RANGE_LIST插入落在P1/PM分区内的合法行成功,插入分区边界外(ID = -1)的行被拒绝;
  • 插入主键重复行被拒绝(PK 强制);
  • PARENT插入父行后,CHILD可插入合法外键行,插入指向不存在父行的孤儿行((2, 999))被拒绝(FK 强制);
  • 查询USER_TAB_COMMENTS确认注释原样保留(table's PCTFREE = 20);
  • 查询USER_PART_INDEXES确认 LOCAL 索引C_LOCALLOCALITYLOCAL

4.3 证据产物与清理

每个 DDL 文件名(去除引号后)对应两个文件,加上汇总报告,全部写入:

agents/drivers/oceanbase-oracle/build/partition-ddl-evidence/ ├── <Table>.full.sql # 完整 DDL(含存储属性) ├── <Table>.logical.sql # 省略存储属性后的逻辑 DDL └── verification.json # 汇总报告(schema 名、逐表断言、语义检查说明)

可通过OB_TEST_OUTPUT环境变量覆盖输出目录。verification.json记录了三个 Schema 的确切名称、每张表的partitions/subpartitions数量与重放结果,方便人工在 dbx 中打开这些 Schema 做界面复核。

清理方式:断开这些测试 Schema 的会话后,使用报告中的确切名称执行

DROP USER "<reported name>" CASCADE

需要注意:任何证据文件中都不会写入连接凭据,可放心归档或提交。

五、源码级原理:分区元数据与 DDL 生成

5.1 分区信息读取

Agent 的listPartitions/listSubpartitions最终都进入queryPartitions(OceanBaseOracleAgent.java),数据来源为 Oracle 兼容字典视图:

信息数据源
分区键列ALL_PART_KEY_COLUMNS/ALL_SUBPART_KEY_COLUMNS(按COLUMN_POSITION排序)
分区名、位置、边界值、分区类型ALL_TAB_PARTITIONS/ALL_TAB_SUBPARTITIONSJOINALL_PART_TABLES

分区键列会以双引号括起并转义内嵌引号(如测试中的"A""B"),边界值HIGH_VALUE原样保留(如100, 'East'MAXVALUE, MAXVALUE),HASH 子分区的边界值为空。单元测试 OceanBaseOracleAgentTest.java 明确验证了分区按字典序返回、复合键顺序保持以及 NULL HASH 边界不抛错。

5.2 分区 DDL 的拼装策略

getTableDdl(OceanBaseOracleAgent.java)的组装过程如下:

  1. 调用DBMS_METADATA.GET_DDL('TABLE', name, owner)获取基础 DDL——约束与分区子句已包含在内;
  2. OceanBase 4.2.5 在跨 Schema 场景下会省略 CREATE TABLE 的属主,Agent 通过正则将CREATE [GLOBAL TEMPORARY] TABLE "name"修正为CREATE ... "owner"."name"
  3. 查询ALL_INDEXES找出非约束索引,逐一追加GET_DDL('INDEX', ...)结果。查询同时排除两类索引:
    • ALL_CONSTRAINTSP/U约束关联的索引(已随约束输出);
    • 全局临时表内部的会话索引(IDX_FOR_HEAP_GTT_<表名>且包含SYS_SESSION_ID列)——这正是 README 强调的 "internal session index must not be exported" 的源码依据;
  4. 追加表注释COMMENT ON TABLE与非空列注释COMMENT ON COLUMN(单引号做''转义);
  5. 尽力追加对象授权(GRANT ... ON ... TO ...),无权限时静默跳过。

其中索引追加使用的是DdlBuilder.appendTrailingSql,保证多个语句以分号正确分隔。

5.3 DBMS_METADATA 的版本依赖与回退

README 明确说明验证基于DBMS_METADATA.GET_DDL,而该函数在 OceanBase 4.2.5 中TABLE 结果不包含独立索引与注释,因此 Agent 采用"单独追加"策略。此外,不同 OceanBase 版本与租户权限对DBMS_METADATA的覆盖度不一,getObjectSourceDBMS_METADATA不可用时(如视图、过程、函数、包等对象)会回退到ALL_VIEWS/ALL_SOURCE字典视图拼装可编辑源码(OceanBaseOracleAgent.java)。

六、UI 验证:Omit storage attributes(省略存储属性)

构建并安装 Agent(安装方式见仓库根目录 CONTRIBUTING.md)后,使用当前前端按以下步骤做界面验证:

  1. 展开一张分区表的PartitionsSubpartitions分组,确认分组数据正常加载;
  2. 打开该表的 DDL 视图,确认Omit storage attributes开关默认启用
  3. 复制并导出脚本,关闭开关后再次复制/导出,对比两份输出;
  4. 两次输出都必须保留:分区子句、约束(PK/CHECK/FK)、LOCAL 索引、默认值与注释;
  5. 切换该开关不会重新请求数据库,也不会覆盖缓存的原始 DDL——它只是对已缓存原始 DDL 的纯文本后处理;
  6. 在结构编辑器中,当 DDL 存在未保存的编辑时,该开关处于禁用状态(防止基于过期/未落盘的文本做清理)。

6.1 偏好生效范围与清理清单

该偏好仅对 OceanBase Oracle(oceanbase-oracle)生效,其他数据库类型(包括原生 Oracle)不受影响。开启后移除的已知表级存储选项为:

选项说明
COMPRESS FOR ARCHIVE [HIGH\|LOW]归档压缩,可选 HIGH/LOW 级别
NOCOMPRESS关闭压缩
REPLICA_NUM = <n>副本数(OceanBase 特有)
BLOCK_SIZE = <n>数据块大小
TABLET_SIZE = <n>分区单元(tablet)大小
PCTFREE = <n>块内预留空间比例
USE_BLOOM_FILTER = TRUE/FALSE布隆过滤器开关(OceanBase 特有)

未知选项与所有分区子句都会被保留——这是刻意设计:清理只针对白名单内的已知表选项,避免误删无法识别的新特性参数或分区边界表达式。

6.2 前端实现细节

前端实现位于 ddlStorage.ts 的applyDdlStoragePreference(sql, databaseType, excludeStorage = true)

  • oceanbase-oracleexcludeStorage = false时原样返回;
  • 使用 SQL 语义分词器(tokenizeSqlSemantic(sql, "oracle"))做词法级处理,而非正则替换——从而能区分字符串字面量、注释与真实关键字;
  • 仅在CREATE [GLOBAL TEMPORARY] TABLE ... )闭合括号之后的表选项区做匹配;一旦遇到PARTITION关键字即停止(分区子句永不触碰);
  • 对每个命中选项校验其取值合法性(REPLICA_NUM等要求整数、USE_BLOOM_FILTER要求TRUE/FALSE),非法取值宁可跳过也不误删;
  • 若 SQL 存在未闭合 token(分词不完整),直接返回原文本,不做破坏性清理。

配套测试 ddlStorage.spec.ts 覆盖了关键边界:默认值DEFAULT 'PCTFREE = 20'与注释文本'COMPRESS FOR ARCHIVE'不被误删、Oracle 替代字符串q'[can't ) PCTFREE=42]'保留、/* ... */注释保留、同一脚本内多张表各自独立清理、ALTER TABLE语句不受影响、未知属性TABLE_MODE='QUEUING'保留。

七、已验证环境与适用前提

  • 验证版本:脚本已针对 OceanBase4.2.5.7(Oracle 模式)通过;
  • 覆盖形态:RANGE、LIST、HASH 以及 RANGE/LIST 复合分区表,复合分区键,约束,默认值/注释,临时表;
  • DDL 获取:依赖DBMS_METADATA.GET_DDL(OceanBase 4.2.5 文档支持该函数),并因该版本 TABLE 结果省略索引与注释而单独追加原生索引 DDL 与 COMMENT 语句;
  • 适用限制:若目标 OceanBase 版本的DBMS_METADATA行为或字典视图字段有差异,需以实际版本为准调整断言;脚本要求一次性租户,测试 Schema 需按报告清理。

八、扩展建议

  • 新增分区形态(如PARTITION BY HASH多分区、RANGE-COMPOSITE其他子分区策略)时,在fixtures数组追加表定义并在expected中补充数量断言即可;
  • 若需要验证更多存储选项,可在源表 DDL 中追加选项并在脚本中增加"简化结果不含该选项"的断言,同时同步维护 ddlStorage.ts 的白名单与 ddlStorage.spec.ts 的用例;
  • OB_TEST_OUTPUT指向 CI 临时目录,即可把verification.json作为分区 DDL 回归检查的机器可读结果。

通过自动化脚本与 UI 双通道验证,dbx 保证 OceanBase Oracle 分区表在任何时候都能以"语义完整、格式干净"的 DDL 被浏览、复制与跨环境重放。

【免费下载链接】dbx15MB,轻量级跨平台数据库客户端、数据库管理工具。支持 MySQL、PostgreSQL、SQLite、Redis、MongoDB、DuckDB、ClickHouse、SQL Server 等。15MB, lightweight, cross-platform database client. Supports MySQL, PostgreSQL, SQLite, Redis, MongoDB, DuckDB, ClickHouse, SQL Server and more.项目地址: https://gitcode.com/t8y2/dbx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询