
简介面向国产化数据库适配需求这份资料针对使用Java技术栈的开发和运维人员提供在人大金仓数据库环境下改造SQL脚本、核对文件结构和理解适配流程的核心素材。压缩包共4个文件主要包含ZIP压缩包、SQL脚本和TXT说明文档并附少量系统辅助文件整体大小约242.67MB其中SQL脚本可用于实际排查或参考改写TXT说明文档针对各文件的用途及适配注意事项做了梳理能够帮助读者快速定位需要修改的环节避免在驱动、方言、数据类型等常见适配问题上反复踩坑。目前已有118人学习比较适合正在做信创项目迁移或初学人大金仓的中高级工程师也适用于需要向团队交付适配方案的场景。获取后可借助现成的脚本与说明减少从零摸索同时根据包内结构判断需要补强的环节从而更高效地完成国产化数据库适配工作。1. 从「换驱动就能跑」到「改三天 SQL」Java 接人大金仓的真实工作量一个做了五六年的 Java 老项目要迁到人大金仓一开始谁都觉得简单——金仓兼容 PostgreSQLPostgreSQL 又是开源界的熟面孔把 JDBC 驱动换掉总该差不多了吧。结果第一次联调启动五分钟就收到一堆 SQL 报错ROWNUM 不支持、SYSDATE 行为对不上、序列取不到值、表名明明建了却提示不存在。这些小问题单个看都不难连在一起就能把一个团队卡上一周。「适配国产化人大金仓」不是换个 jar 包的事而是驱动、连接池、数据库对象、SQL 写法、ORM 映射一起过一遍。这篇文章写给要做信创适配的 Java 后端工程师也适合第一次碰金仓的团队拿来当检查清单。2. 先连上再说驱动、连接串与连接池的四个关键参数数据库适配的第一道门槛永远是连接层。连接层要是没搭对后面所有的表结构迁移和 SQL 改造都无从验证。这一章把驱动选型、连接串写法、连接池参数三个环节逐一过一遍你会发现大部分「连不上、连上了但总断」的问题根源都在这里。2.1 驱动包选型kingbase8 而不是 PostgreSQL 驱动金仓官方提供的 JDBC 驱动叫 kingbase8驱动类名是com.kingbase8.Driver。它是在 PostgreSQL 驱动的基础上改的通信协议兼容但增加了金仓自己的类型映射和参数语义。有些人图省事直接用org.postgresql.Driver去连短连接可能能通但一碰到序列、返回类型、大批量 batch 场景就会出一些看着莫名其妙的怪问题。所以第一条建议是手里拿到什么驱动版本就用什么版本别拿 PostgreSQL 驱动硬顶。官方驱动不在 Maven 中央仓库常见做法是装到本地仓库或者用 system scope 直接引用。团队有 Nexus 私服的话先执行一次本地安装mvn install:install-file \ -Dfilelib/kingbase8-8.6.0.jar \ -DgroupIdcom.kingbase8 \ -DartifactIdkingbase8 \ -Dversion8.6.0 \ -Dpackagingjar说明-Dversion里的版本号以你从金仓安装包或官方渠道拿到的实际版本为准8.6.0 只是示例。装进私服之后pom 里就可以按正常依赖引入不需要再纠结路径问题。如果项目比较小、图省事用 system scope也可以dependency groupIdcom.kingbase8/groupId artifactIdkingbase8/artifactId version8.6.0/version scopesystem/scope systemPath${project.basedir}/lib/kingbase8-8.6.0.jar/systemPath /dependency注意 system scope 的坑在打包环节Spring Boot 的 fat jar 对 system scope 依赖处理得很保守不同版本的 maven plugin 行为还不一样容易出现「本地编译能跑、部署环境 ClassNotFoundException」的情况。如果你之前没吃过这个亏建议直接走 install-file省得后面排查打包问题。2.2 连接串与驱动配置端口、schema 与兼容模式金仓的默认端口是 54321不是 PostgreSQL 的 5432也不是 Oracle 的 1521。第一次连的人十有八九会在这里卡一下。完整的连接串格式是jdbc:kingbase8://127.0.0.1:54321/mydb?currentSchemapublicstringtypeunspecified这里几个参数值得单独说明参数作用建议currentSchema指定默认 schema显式指定别依赖用户默认 schema否则换一台机器就可能串库stringtypeunspecified让驱动把字符串当未指定类型处理减少隐式转换报错建议开启注意不同驱动版本对这个参数的支持度有差异connectTimeout连接超时时间建议 3000~5000ms避免网络抖动把应用启动拖死ApplicationName连接标识填服务名方便 DBA 在慢 SQL 日志里定位来源驱动加载和连接的 Java 代码很简单但有一个容易被忽略的动作——打印数据库元信息String url jdbc:kingbase8://127.0.0.1:54321/mydb?currentSchemapublicstringtypeunspecified; Properties props new Properties(); props.setProperty(user, system); props.setProperty(password, your_password); Class.forName(com.kingbase8.Driver); try (Connection conn DriverManager.getConnection(url, props)) { DatabaseMetaData meta conn.getMetaData(); System.out.println(product meta.getDatabaseProductName()); System.out.println(version meta.getDatabaseProductVersion()); }这段代码除了验证连接更重要的是把getDatabaseProductName()的实际返回值打出来。第 4 章配置 MyBatis 的 databaseId 时要拿这个值做映射金仓不同版本返回的字符串可能不一样有的带版本后缀有的不带先确认值再写配置比较稳。2.3 连接池参数HikariCP 与 Druid 的适配点Spring Boot 项目最常见的连接池是 HikariCP配置如下spring: datasource: driver-class-name: com.kingbase8.Driver url: jdbc:kingbase8://127.0.0.1:54321/mydb?currentSchemapublicstringtypeunspecified username: system password: your_password hikari: minimum-idle: 5 maximum-pool-size: 20 connection-timeout: 5000 validation-timeout: 3000 connection-test-query: SELECT 1还在用 Druid 的老项目也类似但多一个环节需要留意spring: datasource: druid: driver-class-name: com.kingbase8.Driver url: jdbc:kingbase8://127.0.0.1:54321/mydb validation-query: SELECT 1 test-while-idle: true test-on-borrow: false filters: stat,wall注意 wall 过滤器。某些版本的 Druid 会用语法树解析的方式拦截 SQL金仓的MERGE INTO、INSERT ... ON CONFLICT DO NOTHING这类语法可能被误判为非法 SQL。如果上线后看到 Druid 的拦截日志先把 filters 改成stat再确认是哪条 SQL 被误拦最后决定是加白名单还是全局关闭 wall。连接层还有一个团队容易忽略的场景如果本地没有现成的金仓测试实例拿 Docker 拉一个镜像起容器做联调是最省事的办法拉镜像时注意选对服务器 CPU 架构x86 和 ARM 的镜像不通用。应用要是跑在麒麟这类国产操作系统上JDBC 驱动因为是纯 Java 反而不挑系统但防火墙要放行 54321 端口。3. 表、序列与函数迁到金仓的三种改法与一个隐患连接通了只是开始。适配工作量的大头在数据库对象层表结构、序列、函数、视图每一类都有自己容易翻车的地方。这一章从数据类型映射讲起把序列挂默认值这个隐患单独拎出来说透。3.1 数据类型映射从 Oracle/MySQL 到金仓金仓基于 PostgreSQL 内核数据类型大体上是 PG 那一套但因为它同时提供 Oracle 兼容模式很多 Oracle 类型也能直接建。迁移时最稳妥的做法是先拉一张映射对照表按列逐个核对而不是让迁移工具全自动决定。OracleMySQL金仓推荐类型说明NUMBER(10)INTINTEGER整数场景够用NUMBER(18,2)DECIMAL(18,2)NUMERIC(18,2)金额场景保持精度VARCHAR2(100)VARCHAR(100)VARCHAR(100)长度按字符算不按字节DATEDATETIMETIMESTAMPOracle 的 DATE 带时分秒金仓 PG 模式 DATE 只有日期CLOBLONGTEXTTEXT大文本直接 TEXTBLOBBLOBBYTEA二进制文件LONGTEXTTEXT不建议继续用 LONG几个容易出问题的点单独说一下。Oracle 的 DATE 类型是带时分秒的金仓在 PostgreSQL 兼容模式下 DATE 不包含时间部分。从 Oracle 迁过来的代码里凡是把new Date()直接跟 Oracle DATE 字段做当天比较的到金仓要改成 TIMESTAMP或者显式写时间段范围否则当天凌晨到上午的数据会查不出来。另外NUMBER 不带精度时映射成 NUMERIC 最保险但别为了省事把所有列都映射成 NUMERIC(38,2)。整数列如果映射成带小数位的数值类型JDBC 返回的是 BigDecimal序列化给前端时会多出.0这种尾巴引发不必要的联调扯皮。VARCHAR 的长度计量单位是字符而不是字节中文场景下比 Oracle 在 AL32UTF8 字符集下的字节语义宽松一般不会因为长度报错但业务侧要是有超长字符串静默截断的测试用例行为会不一样需要回归。3.2 序列与自增主键让 INSERT 不再撞主键从 Oracle 迁过来的表主键多半是序列生成的。金仓支持序列但迁移工具经常把序列建出来之后忘了挂到列的默认值上。于是应用层的 INSERT 语句只要不带序列主键就会撞车。完整的做法是在目标库执行CREATE SEQUENCE seq_user_id START WITH 1 INCREMENT BY 1 CACHE 20; CREATE TABLE t_user ( user_id NUMERIC(10) NOT NULL PRIMARY KEY, user_name VARCHAR(50) ); ALTER TABLE t_user ALTER COLUMN user_id SET DEFAULT nextval(seq_user_id);说明CACHE 20表示数据库服务器内存里一次缓存 20 个序列值适合并发高的场景。如果担心应用重启导致序列跳号可以把 CACHE 调小到 1代价是每次取序列都走磁盘性能上会有损耗。关键步骤是最后的ALTER TABLE把序列挂成列默认值之后应用层 INSERT 再也不用关心主键怎么来。从 MySQL 迁过来的表原本用 AUTO_INCREMENT可以直接建 identity 列CREATE TABLE t_orders ( order_id NUMERIC(10) GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, order_no VARCHAR(32) );GENERATED BY DEFAULT允许应用显式插入主键值适合做数据合并迁移如果业务上强制主键必须由数据库生成用GENERATED ALWAYS。这里有一个经验序列如果由迁移工具导出来注意核对 START WITH 的值工具经常把当前值和序列的起始值搞混导致上线后主键从 1 开始跟存量数据冲突。3.3 存储过程与函数PL/SQL 与 PL/pgSQL 的兼容边界金仓的 Oracle 兼容模式能消化一部分 PL/SQL 语法但别指望原封不动搬过去。最常碰到的差异集中在默认值函数、时间函数和异常处理语法写法Oracle金仓/PostgreSQL 风格空值兜底NVL(a, 0)COALESCE(a, 0)当前时间SYSDATECURRENT_TIMESTAMP / NOW()函数返回声明RETURN NUMBERRETURNS INTEGER AS $$ ... $$异常语法WHEN OTHERS THENWHEN others THENRAISE 语法也完全不同一个简单函数在金仓里长这样CREATE OR REPLACE FUNCTION fn_get_user_name(p_id INTEGER) RETURNS VARCHAR(50) AS $$ DECLARE v_name VARCHAR(50); BEGIN SELECT user_name INTO v_name FROM t_user WHERE user_id p_id; RETURN COALESCE(v_name, unknown); END; $$ LANGUAGE plpgsql;说明$$是 plpgsql 函数体的美元符号定界符作用是隔离函数体里的单引号跟外部 SQL 的引号避免转义地狱。SELECT INTO是 PG 系给变量赋值的标准写法跟 Oracle 的 INTO 位置不同但思路一致。如果一个存储过程超过 200 行还大量使用动态拼接、包、自治事务这些特性别硬翻译。先把逻辑拆开再用几个简单函数组合成本往往比在兼容模式里抠细节低得多。自治事务PRAGMA AUTONOMOUS_TRANSACTION在金仓里支持度不稳定日志表写入这种场景建议改成应用层异步写别依赖数据库自治事务。3.4 迁移方式迁移工具优先手写脚本兜底金仓官方提供迁移工具能把 Oracle 的结构和数据整体搬过来。我的建议是工具迁移跑一遍拿到一份可执行的 DDL 和数据脚本但不要拿工具结果直接上线。实践中最靠谱的流程是用迁移工具导出一份完整的 DDL。手工 review 一遍重点看序列有没有挂默认值、DATE 有没有变成 TIMESTAMP、函数有没有成功转换。数据用工具导成大文件分批导入导入时关掉自动提交5000 条一批 commit。空库跑一遍应用的核心 SQL对照第 4 章的改写点逐个过。如果源库是 MySQL迁移方式类似但要注意 MySQL 的布尔类型在工具里可能被映射成 SMALLINT 而不是 BOOLEANMyBatis 里对应 Boolean 的属性在取数时会做一层类型转换数据量大时会有性能开销。金仓的兼容层覆盖不了所有语法随时做好手写脚本兜底的准备。4. Java 代码层改造MyBatis 方言、分页与批量写入的落地配置数据库对象迁完了接下来是应用代码。这一章解决三个实际问题一套 Mapper 怎么同时兼容多个数据库、分页插件怎么配、批量写入怎么才能不慢。4.1 让 MyBatis 识别金仓databaseId 配置一个项目同时兼容 MySQL、Oracle 和金仓时MyBatis 的 databaseId 机制是官方推荐的方案。先用一个 Bean 提供数据库厂商识别Bean public DatabaseIdProvider databaseIdProvider() { VendorDatabaseIdProvider provider new VendorDatabaseIdProvider(); Properties props new Properties(); props.setProperty(KingbaseES, kingbase); provider.setProperties(props); return provider; }说明VendorDatabaseIdProvider靠DatabaseMetaData.getDatabaseProductName()的返回值去匹配 Properties 的 key。第 2 章里打印出来的那个 product name 就是这里的 key不同版本的金仓返回的可能不完全一样所以要先打印确认。匹配成功的映射值写在 Mapper XML 上select idlistUser databaseIdkingbase resultTypeUser SELECT user_id, user_name FROM t_user ORDER BY user_id LIMIT #{limit} OFFSET #{offset} /select没有 databaseId 的 SQL 作为默认实现有 databaseId 的 SQL 在对应厂商下优先命中。这样一套 Mapper 撑住多数据库改动量比写多套 DAO 小得多。注意一个细节如果项目同时要兼容达梦这类国产库VendorDatabaseIdProvider的配置需要把每个产品的 product name 都写进去这会涉及一点点试错成本。4.2 分页与方言PageHelper 该配哪个 dialect如果项目在用 PageHelper最省事的方式是显式指定方言pagehelper: helper-dialect: kingbase reasonable: true supportMethodsArguments: true说明helper-dialect显式指定的原因是 PageHelper 对金仓的自动识别依赖产品名和版本号有些版本识别不到就回退到 PostgreSQL 方言语法本身没问题但分页 SQL 的生成细节可能跟金仓不完全匹配。金仓的分页语句本身就是 LIMIT/OFFSET和 PostgreSQL 一致。reasonable: true的作用是页码越界时自动修正到第一页或最后一页避免前端传 page0 直接把偏移量搞成负数。手写分页时注意一个容易翻车的地方LIMIT 和 OFFSET 后面的参数尽量走 PreparedStatement 绑定不要拼字符串。金仓对未绑定参数的 SQL 没法走预编译缓存高并发下 CPU 会突然飙高慢 SQL 日志里满屏都是不一样的语句文本DBA 想定位都没法下手。4.3 批量写入参数batchSize 与驱动行为批量插入是迁到金仓后最容易被低估的一块。同样的代码在 MySQL 上每秒能插几千条换到金仓只剩两三百条先别怀疑数据库先检查连接串有没有开批量重写参数。金仓驱动基于 PostgreSQL 驱动改很多版本支持这个参数jdbc:kingbase8://127.0.0.1:54321/mydb?rewriteBatchedInsertstrue加上参数之后批量 INSERT 会被重写成一条多 VALUES 的语句性能提升非常明显。配合手写批次控制的代码String sql INSERT INTO t_user(user_id, user_name) VALUES (?, ?); try (PreparedStatement ps conn.prepareStatement(sql)) { for (int i 0; i userList.size(); i) { ps.setLong(1, userList.get(i).getId()); ps.setString(2, userList.get(i).getName()); ps.addBatch(); if (i 0 i % 500 0) { ps.executeBatch(); conn.commit(); } } ps.executeBatch(); conn.commit(); }说明批次大小选 500 是个比较稳的经验值。太小了批量效果出不来太大了单次事务持锁时间太长在线业务容易把表锁住。如果压测时发现驱动版本不支持rewriteBatchedInserts退而求其次的做法是把 batchSize 压到 200再考虑调整数据库的同步提交参数用性能换稳定。注意这个优化参数和驱动版本强相关升级驱动后一定要回归一次批量写入场景。做定时任务批量同步时也可以参照同样的思路跟 xxl-job 这类调度框架配合时要注意任务中断后的事务回滚别让半截数据留在库里。4.4 常见 SQL 改写点ROWNUM、NVL、SYSDATE把生产环境里真实出现过的 SQL 改动整理成一张表原写法金仓写法说明ROWNUM 10LIMIT 10有条件排序时先 ORDER BY 再 LIMITNVL(column, 0)COALESCE(column, 0)兼容函数也能跑但 COALESCE 更稳SYSDATECURRENT_TIMESTAMP带时区时用 CURRENT_TIMESTAMP(3)TO_CHAR(now, YYYY-MM-DD HH24:MI:SS)格式串逐一验证YYYY 和 MM 的行为有差异SYS_GUID()gen_random_uuid()主键生成场景INSTR(a, b) 0STRPOS(a, b) 0字符串位置判断DECODE(x, a, b)CASE WHEN x a THEN b迁就 ORM尽量用标准 CASESQL 改写的原则是能用标准 SQL 就不用方言函数。很多人以为某些函数金仓「支持」就没问题实际是兼容模式翻译了一层执行计划上会有隐形成本。比如 NVL 在金仓里能跑但走的是兼容层COALESCE 是原生实现执行计划更干净。另外一个值得注意的习惯是大表查询里的字符串日期比较如果字段本身是 TIMESTAMP就不要写TO_CHAR(create_time, YYYY-MM-DD) 2025-01-01这种把索引字段包进函数里的写法改成create_time 2025-01-01 AND create_time 2025-01-02索引才能真正生效。5. 适配常见问题排查五个高频坑与对应解法以下是金仓适配里占了排查时间 80% 的五个问题。每条按「现象、原因、解决」来写照着这个顺序排查能少走不少弯路。5.1 本地能连测试环境 ClassNotFoundException现象本地启动正常部署到测试服务器后启动日志报java.lang.ClassNotFoundException: com.kingbase8.Driver。原因pom 里用了 system scope 引入驱动 jar本地编译时 IDE 能找到 classpath但打包环节没把 system scope 的依赖带进产物。Spring Boot 的 maven plugin 默认对 system scope 处理很保守不同版本行为不一致。解决优先把驱动安装到本地或私服仓库用正常依赖方式引入。如果必须 system scope在 spring-boot-maven-plugin 里显式把 jar 打进 BOOT-INF/lib或者在 maven-jar-plugin 里配置 extraClasspath。更简单的排查方法是解压产物看一眼jar 内有没有BOOT-INF/lib/kingbase8-xxx.jar没有就是打包配置问题。5.2 INSERT 不带主键导致主键冲突现象应用从 Oracle 迁过来上线后第一次写入就报主键冲突或者主键重复重试几回又有部分成功。原因源库 Oracle 的表用触发器或序列自动生成主键迁移工具把表和序列拆开导过来但没把序列挂到列的默认值上应用层 INSERT 语句里也没有显式取序列主键自然就撞了。解决建完表之后统一执行ALTER TABLE t_user ALTER COLUMN user_id SET DEFAULT nextval(seq_user_id);把序列和列绑死。上线前写一条检查 SQL找出所有「有主键但主键列没有默认值」的表SELECT c.table_name, c.column_name FROM information_schema.columns c JOIN information_schema.table_constraints tc ON c.table_name tc.table_name WHERE tc.constraint_type PRIMARY KEY AND c.column_default IS NULL;这条 SQL 在金仓的 PG 兼容模式下可以直接跑如果你手里的库跑不了就把 information_schema 换成当前模式下能用的目录视图。把结果逐一处理掉主键问题就算根治了。5.3 表确实建了查询却说「关系不存在」现象迁移工具导完表用工具改数据没问题应用查询时报relation t_user does not exist去数据库客户端里又能看到表。原因标识符大小写问题。金仓沿用 PostgreSQL 行为不加引号的标识符自动折叠成小写存储。Oracle 里的表名通常是大写存储迁移时大写表名加引号原样保留应用里不加引号的 SQL 就会去找小写表名自然找不到。解决统一策略要么全部小写要么全部带引号大写。我的习惯是让应用侧 SQL 全部使用小写表名和列名迁移时把 DDL 里的大写标识符批量转成小写。如果历史包袱太重没法改 SQL就在金仓里建大写带引号的别名视图把大写视图名暴露给旧应用代价是每加一张表都要同步一个视图。5.4 TO_CHAR 日期格式化结果跟 Oracle 不一样现象TO_CHAR(now(), YYYY-MM-DD)返回的结果在 Oracle 是 2025-06-01在金仓变成别的日期甚至跨年偏移或者月份对不上。原因Oracle 和 PostgreSQL 体系对 TO_CHAR 的格式化串解释不同。最典型的是YYYY在 PG 里按「年份字面值」解释跨年日期的边界会产生偏移MM在不同模式下也有差异。这个坑的特点是平时数据刚好不敏感一到 12 月 31 日、1 月 1 日这种临界点才冒出来。解决把所有 TO_CHAR 的格式串收敛到一个工具类里统一管理写一个单元测试用例里包含 2025-01-01、2025-12-31、2024-02-29 这类边界日期在测试环境全量对比 Oracle 和金仓的输出。凡是输出不一致的改成EXTRACT、日期运算等底层行为一致的方式。5.5 深分页查询越来越慢现象列表接口在 5000 页以内都正常超过 1 万条后每次翻页要等好几秒CPU 占用也高。原因LIMIT/OFFSET分页的实现方式是先扫描并丢弃 OFFSET 条记录再返回 LIMIT 条偏移量越大扫描成本越高。这个坑在 MySQL、PostgreSQL、金仓上表现一模一样Oracle 的 ROWNUM 分页反而在某些场景下因为优化器特殊处理没那么明显。解决把深分页改成 keyset 分页也就是WHERE user_id ? ORDER BY user_id LIMIT 20。前端继续传页码后端把上一页最后一条记录的主键带给 SQL。如果业务上不允许 keyset就退而求其次给 ORDER BY 的字段建联合索引把排序和过滤都在索引里完成。这个改造不难但收益非常明显尤其是金仓数据量过了几千万以后。6. 上线前最后一步连通性自检脚本与检查清单6.1 五分钟连通性自检脚本每次做金仓适配我的习惯是先写一个不依赖任何框架的 Java 自检脚本直接放进测试环境跑一遍。这个脚本用最原始的 JDBC作用是验证三件事驱动能加载、连接能建立、事务能回滚。public class KingbaseCheck { public static void main(String[] args) throws Exception { String url jdbc:kingbase8://127.0.0.1:54321/mydb?currentSchemapublic; Properties props new Properties(); props.setProperty(user, system); props.setProperty(password, args[0]); Class.forName(com.kingbase8.Driver); try (Connection conn DriverManager.getConnection(url, props)) { DatabaseMetaData meta conn.getMetaData(); System.out.println(product meta.getDatabaseProductName()); System.out.println(version meta.getDatabaseProductVersion()); try (Statement st conn.createStatement(); ResultSet rs st.executeQuery(SELECT 1)) { rs.next(); System.out.println(connect rs.getInt(1)); } conn.setAutoCommit(false); try (PreparedStatement ps conn.prepareStatement( SELECT count(*) FROM t_user)) { try (ResultSet rs ps.executeQuery()) { rs.next(); System.out.println(table_ok rs.getInt(1)); } } conn.rollback(); System.out.println(transactionok); } } }说明脚本第一个输出项是 product 字段用来确认 MyBatis databaseId 配置里填的值是否跟实际一致如果 product 值和你的配置对不上后面所有基于 databaseId 的 SQL 都不会命中。t_user换成你迁移清单里任选一张核心表。事务回滚验证是为了确认驱动不会在连接初始化阶段把事务行为搞坏。如果脚本跑通而应用起不来问题大概率在框架层而不是数据库层。6.2 上线检查清单跑完脚本之后我还会对着下面这张清单过一遍基本能覆盖适配中 90% 的坑检查项通过标准驱动版本与数据库小版本兼容确认官方文档说明连接串端口 54321、schema、时区参数正确连接池校验SELECT 1 通过wall filter 不误拦业务 SQLdatabaseId 映射product name 实际值已配置到数据库厂商映射标识符大小写所有业务表在应用默认 schema 下可查可写序列默认值所有主键列都有 DEFAULT nextval 或 identity日期格式边界日期用例全部通过批量写入rewriteBatchedInserts 已开启或压测达到预期值深分页超过 1 万条数据后翻页性能达标如果应用要部署在鲲鹏这类 ARM 服务器上额外确认一下服务端安装包是 ARM 版JDBC 驱动因为是纯 Java 反而不区分架构但连接池的线程池参数跟 x86 上可以保持一致不需要单独调。从那以后我每次做金仓适配不管多赶上线前都会先跑一遍这个脚本再对着清单逐项过。看起来像是在浪费时间但前面那五个坑几乎都能在十分钟内被这份清单拦住。这套脚本和检查清单我也整理成了一份模板放在下载文件里照着改数据库名、用户名和几张核心表就能直接用。希望帮到你。本文还有配套的精品资源点击获取