信创数据库适配(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 文本比较,就会把它识别成“字段定义不同”。
所以这里要分两层判断:
- 如果是
date和sys."date"这种类型命名空间差异,要判断数据库语义是否等价。 - 如果字段长度、精度、是否为空、默认值语义发生变化,就要进入风险项。
另一个常见差异是默认值写法。
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 varying和varchar的默认值写法差异。 - 需要确认:例如
date和sys."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'
这类差异看起来不大,但会影响结构比对结果。如果团队每次发版都要做数据库升级脚本核对,就建议把默认值比对规则做成“语义比对”,不要只做字符串比对。
否则会出现两个问题:
- 真正的高风险差异被大量等价差异淹没。
- 开发人员为了让比对结果干净,反复改无意义的 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 varying 和 DEFAULT 'enabled'::varchar,大概率只是文本写法不同;但 numeric 变成 decimal(65,30),text 变成 CLOB,就要结合业务认真判断。
第三,基准 DDL 要尽量明确。
如果字段本来只需要 64 位长度,就不要在不同环境里一会儿 varchar(32),一会儿 varchar(64)。如果金额只需要两位小数,就不要写一个没有精度约束的 numeric。基准越含糊,各目标库迁移后的差异越多。
第四,适配结论要沉淀成规则。
一次项目里遇到的 date / sys."date"、character varying / varchar、numeric / decimal、text / CLOB / longtext,后面项目大概率还会遇到。不要每次靠人肉判断,最好把它沉淀进结构比对脚本或适配检查表。
10、后续可以继续补充
这篇先记录表结构层面的适配问题。后面如果继续深入,可以再单独整理几篇:
- KingbaseES / openGauss / OceanBase / 达梦的分页 SQL 差异
- MyBatis Plus 在不同国产数据库上的方言配置
- PostgreSQL 迁移到国产数据库的数据校验清单
- 信创数据库适配自动化比对脚本
- 医疗信息化系统做国产数据库适配时的回归测试用例设计
总的来说,信创数据库适配最重要的不是记住每个数据库的所有语法差异,而是建立一套方法:先按业务对象梳理表结构,再按字段语义分类差异,最后把可忽略、需确认、需改造、需回归的内容分开处理。
浙公网安备 33010602011771号