简介面向国产化数据库适配需求这份资源配置人大金仓KingbaseES环境下的 Java 配套文件适合正在做信创迁移、数据库国产化替换的开发者参考。资源共4个文件含 zip 打包文件、txt 说明文档与 SQL 脚本整体大小约 242.67MB。说明文档用于快速梳理适配思路与注意事项SQL 脚本提供建表、初始化及迁移验证所需的语句可帮助开发者在 Java 业务中减少数据库差异带来的改造工作量。当前已有118人学习下载对需要熟悉人大金仓适配流程、排查常见兼容问题的技术人员有直接参考价值。通过资源包能了解国产化环境下各类文件如何组织与配合避免从零摸索数据库差异快速在项目中完成基础适配验证也为后续扩展其他国产数据库迁移提供可复用的操作参照。1. 适配国产化人大金仓文件为什么 80% 的坑都在“文件之外”“适配国产化人大金仓文件”是信创项目里最容易被低估的一步。多数人接到任务后第一反应是把 Oracle 或 MySQL 的数据文件导出再导进 KingbaseES 就完事。真跑起来才发现难的不是文件本身而是驱动类名、SQL 方言、字符集、权限和连接池参数。本文按我自己的迁移顺序把 KingbaseES人大金仓在银河麒麟环境下的适配路径拆开讲先定兼容基线再做应用和数据的迁移最后落到备份文件和上线验证。目标读者是两类人要把存量 Oracle/MySQL 业务迁到金仓的应用开发以及负责国产化改造落地的运维。读完这套东西你能得到一份可以直接照着执行的最小适配清单也能少走别人踩了三天的弯路。2. 先定兼容基线再做适配版本、部署形态与最小环境清单2.1 三个决定部署形态、兼容模式、运行身份我在评估金仓适配工作量时通常先逼客户回答三个问题这三个问题直接影响后面所有步骤。第一个是部署形态。常见做法有三种物理机、虚拟机、容器。很多人为了快速验证语法兼容性直接拉一个人大金仓数据库 docker 镜像起来跑业务 SQL这是合理的试用路径。但生产环境我不建议把数据目录放在容器可写层因为容器重建、镜像更新都可能把数据文件冲掉。生产要么用物理机要么用虚拟机挂独立数据盘数据目录单独规划。第二个是兼容模式。KingbaseES 同时兼容 Oracle 和 PostgreSQL 两套方言这个选择要在初始化或建库阶段决定后期切换成本高。如果源系统是 Oracle选 Oracle 兼容模式如果源系统是 MySQL但存储过程写得少用 PostgreSQL 兼容模式通常更干净。关键是这个决定要先做别等程序跑起来报语法错误再回头改。第三个是运行身份。金仓数据库进程不允许以 root 身份长期运行需要单独建一个系统用户。很多第一次接触国产化数据库的人在这里翻车用 root 初始化启动时报权限错误或者数据文件属主变成 root后面备份、归档全部踩坑。提示这三个问题不解决后面的 JDBC 驱动和 SQL 改写做得再对也会被环境问题拖住。2.2 最小环境清单银河麒麟上的文件与依赖先给一份我常用的最小环境清单表格里的每一项都有明确理由。项目推荐配置原因操作系统银河麒麟 V10 SP1/SP2信创项目最常见基线CPU 架构x86_64 或 aarch64安装包和 JDK 必须匹配别再混装内存4C8G 起步生产建议 16C32G编译执行计划和排序都要内存数据盘/data 单独挂载ext4 或 xfs避免系统盘和数据文件抢 I/O运行用户kingbase数据库进程安全要求JDKOpenJDK 8 或 11需匹配 CPU 架构aarch64 和 x86_64 的包不一样基础依赖libaio、numactl、unixODBC数据库运行和 ODBC 访问都要用这里要单独说“文件”这个词。适配工作接触的文件不只是业务数据文件还包括安装目录下的配置文件KingbaseES 实例级配置文件、客户端认证文件、日志目录。在麒麟系统上很多人下载离线依赖包时没注意架构把 x86_64 的 rpm 传到鲲鹏机器上装结果依赖检测直接失败。正确的做法是安装前先确认arch命令输出再下载对应架构的包。这一步属于“适配银河麒麟系统应用软件下载列表”里的第一道坑。2.3 初始化实例initdb 与 sys_ctl 的基础命令和参数说明环境准备好后初始化实例是整个适配动作的起点。下面这套命令是我验证过多次的最小流程以一个数据目录/data/kingbase/data为例。# 创建系统用户注意不能用 root 直接跑数据库 useradd -m kingbase # 数据目录单独挂载避免和系统盘抢 I/O mkdir -p /data/kingbase/data chown -R kingbase:kingbase /data/kingbase # 初始化数据库实例重点看 encoding 和 locale su - kingbase -c /opt/kingbase/ES/V8/install/bin/initdb \ -D /data/kingbase/data \ -U system \ --encodingUTF8 \ --localeC \ -E UTF8 # 启动实例日志写到独立目录 su - kingbase -c /opt/kingbase/ES/V8/install/bin/sys_ctl \ -D /data/kingbase/data \ -l /data/kingbase/log/startup.log \ start这里面有几个参数值得展开。-U system是金仓默认的超级用户相当于 Oracle 的 sys--encodingUTF8和-E UTF8共同保证数据库内部字符集是 UTF8这直接影响后续导入中文数据是否乱码--localeC我建议固定因为某些 Linux 发行版默认 locale 可能导致排序结果和源库不一致还会在日志里刷警告。启动后别急着连先确认端口状态。金仓默认端口是 54321和 PostgreSQL 的 5432 不同改应用配置的时候容易忘。ss -lntp | grep 54321如果端口没起来去看启动日志文件startup.log最后 50 行90% 的问题无非三种端口被占、数据目录权限不对、初始化参数冲突。日志文件里写得很直白比任何诊断工具都可靠。到这里环境基线就立住了。后面所有驱动替换、SQL 改写、迁移和备份都跑在这套基线之上。3. 国产化迁移的驱动替换与 SQL 方言校正从 Oracle/MySQL 到 KingbaseES3.1 JDBC 驱动替换四个要改的位置应用连数据库的第一步是换驱动。很多项目的报错都集中在“找不到类”或“URL 格式不对”本质上是只改了依赖没有同步改连接串和驱动类名。我一般会把下面四个位置一起改避免漏项。第一个是构建依赖。假设原来用的是 Oracle 的 ojdbc或者 MySQL 的 connector要换成金仓的 JDBC 驱动。Maven 里的坐标写法如下。dependency groupIdcom.kingbase/groupId artifactIdkingbase8/artifactId version以官方发布版本为准/version /dependency第二个是驱动类名。改成com.kingbase8.Driver不再用oracle.jdbc.OracleDriver或com.mysql.cj.jdbc.Driver。第三个是连接 URL。格式是jdbc:kingbase8://主机IP:54321/数据库名还可以带参数。下面这段 Spring Boot 的配置是一个常见写法。spring: datasource: driver-class-name: com.kingbase8.Driver url: jdbc:kingbase8://192.168.1.10:54321/appdb?currentSchemaappcharacterEncodingUTF-8 username: app_user password: App2025 hikari: connection-test-query: select 1 maximum-pool-size: 20第四个是连接池验证语句。HikariCP 默认验证连接用select 1在 Oracle 下也能跑但在某些兼容模式下最好显式写select 1避免连接池误判连接失效。currentSchemaapp这个参数要重点说它决定了会话默认的 schema 搜索路径应用如果习惯不写 schema 前缀必须通过这个参数把业务 schema 指定清楚否则会去 public 里找表结果全是表不存在。3.2 建库建用户与权限绑定别用超级用户跑业务驱动换好之后数据库侧要建业务用户和业务库。这里的基本原则是业务连接永远不用 system 超级用户否则权限审计和后续回收都会很被动。CREATE USER app_user WITH PASSWORD App2025 CONNECTION LIMIT 50; CREATE DATABASE appdb OWNER app_user ENCODING UTF8 TEMPLATE template0; GRANT CONNECT, TEMPORARY ON DATABASE appdb TO app_user; -- 切换到业务库后创建业务 schema \c appdb CREATE SCHEMA IF NOT EXISTS app; ALTER USER app_user SET search_path TO app, public;TEMPLATE template0这一句容易被忽略。默认新建库用的是 template1如果 template1 里被塞过额外对象或非 UTF8 排序规则新库会被一起传染。search_path的设置解决的是对象解析顺序问题把业务 schema 放在 public 前面避免应用查错表。3.3 SQL 方言差异从 Oracle/MySQL 迁来最容易报错的地方SQL 方言校正是我见过的工作量最大的部分。下面的对照表是迁移时最常改的几类写法。Oracle / MySQL 写法KingbaseES 推荐写法说明WHERE ROWNUM 10LIMIT 10Oracle 兼容模式可跑 ROWNUMPG 模式不行NVL(a, 0)COALESCE(a, 0)两个数据库迁移过来都通用DECODE(a, 1, x, y)CASE WHEN a 1 THEN x ELSE y END标准 SQL 可移植性最好SYSDATECURRENT_TIMESTAMP金仓里也有对应函数但标准写法更稳字符串拼接用 在 MyBatis 的 XML 里翻车最多的场景是分页。Oracle 习惯写ROWNUMMySQL 习惯写LIMIT迁到金仓后如果开的是 PostgreSQL 兼容模式ROWNUM直接不认。下面这段是一个改写后的分页查询。select idqueryPage resultTypemap SELECT id, COALESCE(nickname, ) AS nickname FROM app_user_info WHERE status #{status} ORDER BY id LIMIT #{limit} OFFSET #{offset} /select这里要特别注意#{}和${}的区别。#{}是预编译参数不会产生 SQL 注入风险${}是字符串拼接只应该用于表名、列名这种结构场景。很多迁移项目为了省事把过去写死的分页参数直接拼进去结果金仓的预编译检查比 MySQL 严格运行时直接报语法错误。4. 数据特征适配与存量迁移KDTS 参数和五条避坑记录4.1 迁移前先做数据特征适配用统计结果决定类型映射存量数据迁移的第一步不是导文件而是先摸清源库的数据特征。常见做法是写一段统计 SQL把目标表的行数、空值率、字段最大长度跑出来再决定类型映射。这一步我称之为“数据特征适配”不做的话VARCHAR2 字段长度设错了导入到一半才发现超长。SELECT MAX(LENGTH(nickname)) AS max_nickname_len, COUNT(*) AS total_rows, COUNT(nickname) AS not_null_rows, COUNT(DISTINCT nickname) AS distinct_cnt FROM app_user_info;MAX(LENGTH(...))给的是实际最大长度不是定义长度。很多 Oracle 表把VARCHAR2(4000)定义得很吓人实际数据最长只有 200 字符金仓里建表就可以收敛到VARCHAR(256)索引大小和查询性能都会更好。COUNT(DISTINCT ...)用来估算重复度决定要不要在目标表上建唯一索引。特征确认后再使用金仓官方的数据迁移工具 KDTS 做存量搬迁。KDTS 作为国产化工具支持从 Oracle/MySQL/SQL Server 迁到 KingbaseES图形界面和命令行都可以。关键是几个迁移参数下面是一个任务配置文件的常见形态。{ source: { type: oracle, url: jdbc:oracle:thin://192.168.1.20:1521/ORCL, user: mig_user }, target: { type: kingbase, url: jdbc:kingbase8://127.0.0.1:54321/appdb, user: app_user }, option: { batchSize: 500, fetchSize: 200, parallel: 4, dropTarget: false, convertLOBMode: file, convertEmptyStringToNull: false } }batchSize控制每次批量写入的条数500 是兼顾内存和提交频率的保守值fetchSize控制从源端一次抓取的行数源端是 Oracle 时这个值太大会吃满网络和内存parallel是并行度建议按源端 CPU 核数的一半起步别一上来就开 16容易把源库打挂。convertLOBMode设置为file会把 CLOB/BLOB 拆到文件再以文件方式导入目标端避免大字段挤爆单个事务。convertEmptyStringToNull建议保持falseOracle 里空字符串和 NULL 是同义的但业务经常需要区分保持原样迁移更安全。4.2 避坑记录迁移失败的五种典型现象与解法这一节写我自己经历过的五条踩坑记录每条都按“现象 → 原因 → 解决”说。第一条迁移到一半连接中断日志报Connection reset。现象是表结构全建完了数据倒到某个大表时报连接重置任务失败。原因通常是源端空闲超时或者fetchSize设置得太大加上中间有防火墙拦截长时间空闲连接。解决方法是给源连接配置 keepAlive把fetchSize从 5000 降到 200同时在数据库和应用两侧把 TCP 空闲超时调长。第二条目标表行数比源表少了几千行。现象是迁移任务显示成功但两张表count(*)对不上。原因多半是源端表上有触发器迁移工具用 JDBC 读取时触发了触发器产生额外操作或者是目标表存在主键冲突被工具默认跳过。解决方法是迁移前先对比源和目标的主键最大值并打开迁移工具的冲突日志把跳过记录单独导出检查。只信迁移工具的“成功”标志是不行的必须用行数核对兜底。第三条导入后中文全部变成问号。现象是源端查出来正常导进金仓后所有中文字段变成?。原因是源端连接字符集没设置成 UTF8或者客户端的 NLS 环境变量不是 UTF8。解决方法是源连接串里显式加characterEncodingUTF-8同时确认金仓库本身是 UTF8 编码也就是第 2 章里initdb阶段那两个编码参数没填错。第四条时间字段读写差异DATE 类型丢失时间部分。现象是 Oracle 的DATE字段迁移后应用查询时只显示日期没有时分秒。原因是金仓的DATE类型行为和 Oracle 不完全一致Oracle 的DATE带时间而金仓的DATE更接近“日历日期”。解决方法是迁移映射时把 Oracle 的DATE定义为TIMESTAMP并在应用代码里把对应的实体类型从java.sql.Date改成java.sql.Timestamp。第五条迁移后自增序列错位新插入数据主键重复。现象是应用上线后第一次插入就报唯一约束冲突。原因是源端序列的currval没有同步到金仓目标序列从 1 开始而表里已有数据的主键可能已经到 5000。解决方法是在迁移完大表后手动重置序列到MAX(id)1。SELECT setval( pg_get_serial_sequence(app_user_info, id), (SELECT COALESCE(MAX(id), 1) 1 FROM app_user_info) );5. 麒麟系统上的信创适配与安全管理文件权限、系统参数与备份验证5.1 数据文件与日志文件分开内核参数和进程文件句柄数据库跑起来只是第一步在麒麟系统上做生产适配文件层面的规划比软件安装更要紧。我的基本原则是数据文件、日志文件、归档文件分三个目录避免一个盘写满把数据库拖死。mkdir -p /data/kingbase/data mkdir -p /data/kingbase/log mkdir -p /data/kingbase/archive chown -R kingbase:kingbase /data/kingbase # 内核参数写入 /etc/sysctl.conf vm.swappiness 10 vm.dirty_ratio 20 fs.file-max 655360 # 进程文件句柄限制 cat /etc/security/limits.conf EOF kingbase soft nofile 65535 kingbase hard nofile 65535 kingbase soft nproc 65535 kingbase hard nproc 65535 EOF sysctl -pvm.swappiness设置为 10 是让内存尽量少做 swap 交换数据库进程的访问模式是随机读多swap 会放大延迟。vm.dirty_ratio限制脏页占内存比例避免一次刷盘风暴把 I/O 打满。fs.file-max和nofile是给数据库进程开足够多的文件句柄金仓实例在跑大量并发查询时会同时打开很多文件默认 1024 完全不够。5.2 关键配置文件参数从默认值改成生产值金仓的主配置文件在数据目录下不同版本文件名略有不同但内容形式和 PostgreSQL 很像。下面这几个参数是我每次必调的。参数推荐值调整理由shared_buffers物理内存的 25%默认值太小缓存命中率上不去work_mem8MB 起步排序和哈希 JOIN 的内存上限max_connections按连接池峰值加 30%设太大反而浪费内存archive_modeon开启后才有归档文件可恢复log_min_duration_statement500ms慢查询日志文件从这里开始记修改方式可以直接用ALTER SYSTEM和 PostgreSQL 的体验一致。ALTER SYSTEM SET shared_buffers 2GB; ALTER SYSTEM SET work_mem 16MB; ALTER SYSTEM SET max_connections 300; ALTER SYSTEM SET archive_mode on; ALTER SYSTEM SET log_min_duration_statement 500ms;执行后需要重载配置才生效。金仓在 PostgreSQL 兼容模式下可以用SELECT pg_reload_conf();部分版本也提供sys_reload_conf()。这两个函数在重载后返回 true不用重启实例。备份文件方面金仓自带的物理备份工具通常以脚本形式提供比如sys_backup.sh。具体参数以安装目录下--help输出为准我不在这里写死。更通用且优先推荐的方式是归档开启后把归档目录定期复制到异地再加上数据目录的文件系统快照。下面是一个简单的归档复制脚本思路。# 把当天的归档文件同步到备份盘保留 30 天 find /data/kingbase/archive -type f -name *.log -mtime 30 -delete cp -a /data/kingbase/archive /data/backup/archive_$(date %F)5.3 上线前验证执行计划、慢查询与一致性核对验收阶段我会在麒麟环境上做三件事看慢查询日志是否正常输出、检查表膨胀情况、对比原系统与目标库的核心 SQL 执行计划。慢查询日志先打开并确认日志文件路径免得上线后才发现日志没写。ALTER SYSTEM SET log_directory /data/kingbase/log; ALTER SYSTEM SET log_filename slowlog-%Y%m%d.log;表膨胀检查用系统视图。长期频繁更新和删除后死元组占比过高会导致查询变慢而且让数据文件异常膨胀。SELECT schemaname, relname, n_live_tup, n_dead_tup, pg_size_pretty(pg_total_relation_size(relid)) AS total_size FROM pg_stat_user_tables WHERE n_dead_tup 10000 ORDER BY n_dead_tup DESC LIMIT 10;一致性核对不能只靠count(*)。我在实践中会把原系统的核心交易 SQL 原样拿出来在源库和目标库分别执行对比结果集的行数和关键字段的校验和。下面的命令用金仓自带的 ksql 导出目标端结果再和源端导出文件做 diff。/opt/kingbase/ES/V8/install/bin/ksql \ -h 127.0.0.1 -p 54321 -U app_user -d appdb \ -c SELECT id, status, amount FROM orders WHERE create_time 2025-01-01 ORDER BY id \ -o /tmp/orders_target.txt对比文件时注意排序字段要一致ORDER BY id能保证行的输出顺序稳定否则diff会输出一堆没有意义的顺序差异。6. 适配验证技巧用 Top SQL 回归矩阵判定能否上线最后一关是验证适配是否真的完成。我的判断标准不是“数据库能启动”而是“原系统的 Top SQL 在目标库跑完一遍执行计划和行数都对得上”。具体做法是分三步。第一步从原系统的慢查询日志或监控平台里拉出 Top 30 的 SQL去掉具体参数值做成一个参数化的 SQL 回归脚本按业务模块分文件存放。第二步在目标库打开慢语句自动记录让回归脚本跑一遍把金仓的慢日志文件当作“差分依据”。第三步逐条对比执行计划和返回行数行数不一致说明数据迁移有问题执行计划出现全表扫描说明索引没建对或统计信息没收集。开启自动记录可以用金仓对 PostgreSQL 兼容的auto_explain扩展。LOAD auto_explain; SET auto_explain.log_min_duration 200ms; SET auto_explain.log_analyze on;log_min_duration设置成 200ms意思是超过 200ms 的 SQL 会被自动记录带上真实的执行计划和耗时log_analyze on会在日志里输出实际执行时间和行数。跑完回归脚本后去日志文件里搜duration低于你预期的 SQL 直接划掉高于预期且执行计划里出现Seq Scan的逐条回来看索引。我踩过的一次教训是迁移完只验证了启动和简单查询没跑慢 SQL 回归。上线第一晚一条 2000 万行事实表的大 JOIN 把生产库拖死执行计划里两个表全是全表扫描而原 Oracle 库里是走索引的嵌套循环。后来我把“Top SQL 回归矩阵执行计划比对”写进了所有适配项目的验收清单再没出过同类事故。这个习惯坚持到现在希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?