信创数据库适配(KingbaseES、OceanBase、openGauss、达梦)——数据结构

前言:

前面写过一篇《人大金仓数据库(KingbaseES)使用总结》,主要记录的是安装、授权、导数、search_path、序列、备份还原和 Java 对接这些落地过程中的坑。那篇更偏“把库装起来、连起来、数据导进去”。

最近又整理了一轮信创数据库适配材料,关注点往下沉了一层:同一套以 PostgreSQL 为基准的业务表结构,迁移或适配到 KingbaseES、OceanBase、openGauss、达梦以后,字段类型、默认值、长度精度这些细节到底会发生什么变化。

这类问题很容易被低估。因为很多时候 SQL 能执行、表能建出来、应用也能启动,但真正到数据写入、查询条件、ORM 自动生成 SQL、版本升级脚本比对时,才会发现“字段定义文本不一致”和“字段语义真的不一致”是两回事。

本文就基于一次 exam 相关表结构比对,记录一下信创数据库适配时更应该关注哪些点。

1、这次适配的范围

这次材料里主要涉及四类国产数据库:

  • KingbaseES
  • OceanBase
  • openGauss
  • 达梦

基准侧按 PostgreSQL 表结构来比对,重点看 exam 相关业务表。这里不是做数据库性能评测,也不是讲某个数据库好不好,而是站在业务系统适配角度,看字段定义迁移后会出现哪些差异。

一开始就发现一个很典型的问题:

age varchar(32) ? varchar(64) ?

这个问题看起来很小,但它代表了信创适配里最常见的一类风险:字段长度在不同环境、不同脚本、不同迁移工具之间不一致。对于年龄这种字段,短期可能没影响;但如果是申请单号、检查号、设备编码、报告编号、JSON 片段、第三方主键,就可能直接影响数据写入或接口兼容。

所以信创数据库适配不能只验证“建表成功”,还要验证“字段语义一致”。

2、KingbaseES:不要只看它像 PostgreSQL

KingbaseES 和 PostgreSQL 的兼容性比较高,实际项目里也确实可以按 PostgreSQL 客户端方式连接,很多 SQL 和工具链都能沿用。

但在表结构比对时,仍然会看到一些定义差异。

例如 PG 里的字段:

birthday date NULL
schedule_date date NULL
surgery_date date NULL

迁到 KingbaseES 后,可能表现为:

birthday sys."date" NULL
schedule_date sys."date" NULL
surgery_date sys."date" NULL

这类差异出现在多个 exam 表里,例如申请主表、随访记录、检查主表、登记排班表等。

从业务语义看,它仍然是日期类型,不一定需要修改业务代码。但如果你用脚本做结构比对,直接按 DDL 文本比较,就会把它识别成“字段定义不同”。

所以这里要分两层判断:

  1. 如果是 datesys."date" 这种类型命名空间差异,要判断数据库语义是否等价。
  2. 如果字段长度、精度、是否为空、默认值语义发生变化,就要进入风险项。

另一个常见差异是默认值写法。

PG 中可能是:

status varchar(50) DEFAULT 'enabled'::character varying NULL
page_size varchar(64) DEFAULT 'a4'::character varying NOT NULL

KingbaseES 中可能表现为:

status varchar(50) DEFAULT 'enabled'::varchar NULL
page_size varchar(64) DEFAULT 'a4'::varchar NOT NULL

这类差异属于默认值文本差异,语义上基本等价。结构比对工具如果不做归一化,就会把它报成差异;但从适配工作量看,它不应该和字段长度变化、字段类型变化放在同一级别。

我的建议是:结构比对结果里要增加“差异分类”,至少分成三类:

  • 语义等价:例如 character varyingvarchar 的默认值写法差异。
  • 需要确认:例如 datesys."date" 这种类型命名空间差异。
  • 高风险差异:字段长度、精度、是否为空、默认值真实含义变化。

3、OceanBase:类型映射和默认值表现要重点看

OceanBase 这类数据库在 PG 类型迁移后,会出现比较明显的类型映射。

常见映射包括:

int2       -> smallint(6)
int4       -> int(11)
int8       -> bigint(20)
numeric    -> decimal(65,30)
numeric(5,2)  -> decimal(5,2)
numeric(10,2) -> decimal(10,2)
numeric(15,5) -> decimal(15,5)
text       -> longtext
timestamp  -> datetime
timestamp(3) -> datetime(3)
timestamp(6) -> datetime(6)
varchar    -> longtext

这里最容易踩坑的是两个点。

第一,整数默认值可能从数字表现成字符串形式。

例如:

PG:         int2 default 0
OceanBase: smallint(6) default '0'

PG:         int4 default 1
OceanBase: int(11) default '1'

PG:         int8 default 0
OceanBase: bigint(20) default '0'

对于数据库执行来说,这类差异通常可以正常工作。但如果你的升级脚本、元数据校验、自动化测试用的是文本级比对,就会出现大量“看起来不一致”的结果。

第二,numeric 如果没有显式精度,迁移后可能变成很宽的 decimal(65,30)

例如:

PG:         numeric default 0
OceanBase: decimal(65,30) default '0.000000000000000000000000000000'

这在金额、比例、检查指标数值等字段上需要特别注意。不是说它一定错,而是要确认业务代码、前端展示、接口序列化、报表统计是否依赖固定小数位。

如果业务上本来只需要两位小数,就不要长期保留一个没有约束的 numeric,最好在基准脚本里明确成:

numeric(10,2)

再让各数据库按明确精度去映射。

4、openGauss:兼容不是免检

openGauss 和 PostgreSQL 也有较强的亲缘关系,所以很多 PG 风格字段定义可以比较平滑地迁过去。

但从这次比对看,默认值的表现方式仍然可能不同。例如 PG 里常见的:

'enabled'::character varying
'a4'::character varying

迁移后可能表现为更简化的:

'enabled'
'a4'

这类差异看起来不大,但会影响结构比对结果。如果团队每次发版都要做数据库升级脚本核对,就建议把默认值比对规则做成“语义比对”,不要只做字符串比对。

否则会出现两个问题:

  1. 真正的高风险差异被大量等价差异淹没。
  2. 开发人员为了让比对结果干净,反复改无意义的 DDL 文本。

适配国产数据库时,最忌讳的不是有差异,而是不知道哪些差异真正影响业务。

5、达梦:长度、精度、文本大字段要单独关注

达梦的字段定义表现和 PG 差异更明显一些。

这次材料里看到的典型映射包括:

int2 -> SMALLINT,长度 5
int4 -> INT,长度 10
int8 -> BIGINT,长度 19
text -> CLOB

这里要关注的不是名字变了,而是业务侧有没有对字段类型做隐含假设。

例如:

  • text 变成 CLOB 后,ORM 查询、排序、条件过滤是否还保持原来的行为。
  • 大字段能不能参与 where 条件、like 查询、索引策略是否需要调整。
  • Java 类型映射是否仍然稳定,尤其是 MyBatis / MyBatis Plus 返回结果时是否需要单独处理。
  • 备份、导入导出、数据迁移工具对 CLOB 的处理是否完整。

以前做 MySQL、Oracle、PG 之间迁移时,大字段就是高频问题。到了信创数据库适配,这个问题仍然存在,只是表现形式换了。

6、结构比对不要只输出“不同”,要输出“怎么处理”

这次 Wiki 材料里最有价值的地方,不是列出了很多差异,而是提醒我们:适配工作最终要变成一个可执行的差异处理流程。

我建议表结构比对至少输出下面几列:

序号
差异类别
表名
字段名
PG 字段定义
目标库字段定义
差异项
处理建议
风险等级
是否需要改脚本
是否需要回归测试

差异项不要只写“字段定义不同”,最好进一步拆细:

数据类型
字段长度
字段精度
默认值写法
默认值语义
是否为空
字符集/排序规则
自增/序列
索引/约束

处理建议也要明确:

等价,忽略
等价,但比对工具需要归一化
需要 DBA 确认
需要修改基准 DDL
需要修改 ORM 映射
需要补充回归用例
需要补充数据迁移脚本

这样后续项目复用时,适配工作就不会变成“谁看到报错谁临时修”。

7、建议的核对 SQL

实际项目里可以先从 information_schema.columns 把字段元数据导出来,再和基准库做比对。

例如:

select
    table_schema,
    table_name,
    column_name,
    ordinal_position,
    data_type,
    character_maximum_length,
    numeric_precision,
    numeric_scale,
    datetime_precision,
    is_nullable,
    column_default
from information_schema.columns
where table_schema = 'public'
  and table_name like 'exam_%'
order by table_schema, table_name, ordinal_position;

再补一类约束和索引核对:

select
    tc.table_schema,
    tc.table_name,
    tc.constraint_name,
    tc.constraint_type,
    kcu.column_name
from information_schema.table_constraints tc
left join information_schema.key_column_usage kcu
    on tc.constraint_name = kcu.constraint_name
   and tc.table_schema = kcu.table_schema
   and tc.table_name = kcu.table_name
where tc.table_schema = 'public'
  and tc.table_name like 'exam_%'
order by tc.table_name, tc.constraint_name;

不同数据库对 information_schema 的支持程度和字段表现可能不完全一样,实际落地时需要按目标库微调。但思路是一样的:不要只看建表脚本,要看数据库真实落下来的元数据。

8、适配时我会优先检查这些点

结合这次表结构比对和之前 KingbaseES 项目经验,我会把信创数据库适配检查项整理成下面这份清单。

第一,安装和连接。

  • 授权文件是否正确,连接数是否够用。
  • 服务端口、远程访问、客户端工具是否正常。
  • JDBC 驱动和 ORM 方言是否替换完整。
  • schema / search_path / 模式是否符合预期。

第二,表结构。

  • 字段类型是否语义一致。
  • varchar 长度是否一致,尤其是编码、编号、状态、JSON 字符串字段。
  • numeric 是否显式设置精度和标度。
  • timestamp / datetime 精度是否一致。
  • text / CLOB / longtext 是否影响查询和 ORM 映射。
  • 默认值是文本差异还是语义差异。
  • 主键、唯一约束、索引、序列是否完整。

第三,数据迁移。

  • 不建议完全依赖手工导出的原生 SQL 脚本。
  • JSON、双引号、转义字符、大字段要重点抽样校验。
  • 基础字典、配置表、规则表要做前后数量和内容校验。
  • 对核心业务表做抽样查询和页面功能验证。

第四,应用回归。

  • 新增、修改、删除、查询都要覆盖。
  • 涉及日期、金额、状态、报告内容、申请单流转的功能优先测。
  • ORM 自动填充、分页、排序、模糊查询要单独测。
  • 定时任务和升级脚本要在目标库跑一遍。

9、几个经验结论

第一,国产数据库适配不是“换个 JDBC 驱动”。

驱动能连上只是第一步。真正影响稳定性的,是类型映射、默认值、schema、序列、函数、分页、大小写、关键字、迁移工具这些细节。

第二,表结构差异要区分“文本差异”和“语义差异”。

例如 DEFAULT 'enabled'::character varyingDEFAULT 'enabled'::varchar,大概率只是文本写法不同;但 numeric 变成 decimal(65,30)text 变成 CLOB,就要结合业务认真判断。

第三,基准 DDL 要尽量明确。

如果字段本来只需要 64 位长度,就不要在不同环境里一会儿 varchar(32),一会儿 varchar(64)。如果金额只需要两位小数,就不要写一个没有精度约束的 numeric。基准越含糊,各目标库迁移后的差异越多。

第四,适配结论要沉淀成规则。

一次项目里遇到的 date / sys."date"character varying / varcharnumeric / decimaltext / CLOB / longtext,后面项目大概率还会遇到。不要每次靠人肉判断,最好把它沉淀进结构比对脚本或适配检查表。

10、后续可以继续补充

这篇先记录表结构层面的适配问题。后面如果继续深入,可以再单独整理几篇:

  • KingbaseES / openGauss / OceanBase / 达梦的分页 SQL 差异
  • MyBatis Plus 在不同国产数据库上的方言配置
  • PostgreSQL 迁移到国产数据库的数据校验清单
  • 信创数据库适配自动化比对脚本
  • 医疗信息化系统做国产数据库适配时的回归测试用例设计

总的来说,信创数据库适配最重要的不是记住每个数据库的所有语法差异,而是建立一套方法:先按业务对象梳理表结构,再按字段语义分类差异,最后把可忽略、需确认、需改造、需回归的内容分开处理。

posted @ 2026-08-18 08:53  IT王师傅  阅读(11)  评论(0)    收藏  举报