背景
交付现场最常被问到的一句话:Kingbase 开了 Oracle、MySQL、SQL Server 兼容,运维是不是也得拆成三套手册?
业务和开发更关注 SQL 兼容性,比如该用 nvl 还是 ifnull,分页写 TOP 还是 LIMIT,空串和 NULL 怎么处理。DBA 关心的则是另一件事:Oracle、MySQL、SQL Server 三种兼容模式,日常运维到底是不是三套东西。
如果启停、配置、权限、备份都能共用一套方法,后续写运维手册、做交接、处理故障都会简单很多。
所以这次专门搭了三套实例,把常见运维操作逐项跑了一遍。
结果比较明确:三种兼容模式主要差在初始化和 SQL 兼容层,到了 DBA 日常运维这一层,很多东西其实是共通的。
下面直接看实测。
实验环境
| 代号 | 兼容模式 | 主机 | 端口 | 版本 | 系统用户 | 数据目录 |
|---|---|---|---|---|---|---|
| O | oracle | 161.118.XXX.XXX | 54322 | V009R002C014 | kingbaseo | /opt/kingbaseo/data |
| M | mysql | 161.118.XXX.XXX | 54323 | V009R003C018 | kingbasemy | /opt/kingbasemy/data |
| S | sqlserver | 213.35.XXX.XXX | 54321 | V009R004C019 | kingbase | /opt/kingbase/data |
三端超级用户都是 system,测试库都是 test。
这里三个实例的版本号本身就不同。V009 后面的 R 段用于区分兼容版本:R002 对应 oracle,R003 对应 mysql,R004 对应 sqlserver。也就是说,这批产品是通过不同发行版来区分兼容模式的,安装时选了哪个 ISO,基本就确定了后面的模式。
因此本文比较的是日常运维接口是否一致,不是说三个版本内部行为完全相同。后面如果涉及升级、补丁或者版本变更,仍然需要分别验证。
先确认一下实际模式,避免后面测试时把环境搞混:
| 模式 | version | database_mode | port |
|---|---|---|---|
| oracle | KingbaseES V009R002C014 | oracle | 54322 |
| mysql | KingbaseES V009R003C018 | mysql | 54323 |
| sqlserver | KingbaseES V009R004C019 | sqlserver | 54321 |
version 可以看版本,database_mode 用来确认当前兼容模式。两个信息都确认无误后再继续测试。
共性一:启停入口相同
三端命令形态一模一样:
sys_ctl -D <DATA> status sys_ctl -D <DATA> stop -m fast sys_ctl -D <DATA> -l <logfile> start
实测:
| 模式 | status | stop | start |
|---|---|---|---|
| oracle | running → PID 明确 | done | started |
| mysql | running → PID 明确 | done | started |
| sqlserver | running → PID 明确 | done | started |
实测下来,三种模式的启停方式没有区别,统一使用 sys_ctl。兼容模式主要影响 SQL 兼容层,并不会改变实例进程的基本管理方式。
多实例部署时要特别注意 -D 后面的数据目录。Linux主机1 上 oracle 和 mysql 两个实例放在同一台机器,如果数据目录写错,实际操作的就会是另一个实例。
实际写脚本时建议把 DATA 目录做成变量或配置项,不要每次手工输入。
所以在运维手册里,启停部分完全可以统一写,不需要按兼容模式拆成三套。
共性二:配置与访问控制同源
三端都是这两个文件在管事:
- kingbase.conf:端口、监听、连接数、shared_buffers、日志
- sys_hba.conf:客户端认证
关键行抽出来对了一遍,结构完全一致:
| 参数 | oracle | mysql | sqlserver |
|---|---|---|---|
| listen_addresses | * | * | * |
| port | 54322 | 54323 | 54321 |
| max_connections | 100 | 100 | 100 |
| shared_buffers | 128MB | 128MB | 128MB |
| logging_collector | on | on | on |
表里的端口不同只是实验环境安排,并不是兼容模式造成的差异。三个版本默认端口都是 54321。sqlserver 实例单独放在一台机器上,所以保留默认端口;oracle 和 mysql 共用 Linux主机1,为了避免端口冲突,分别改成了 54322 和 54323。
参数生效方式也基本一致。比如三端的 max_connections 修改后都需要重启实例,单纯执行 reload 并不会生效。
所以改参数前最好先确认参数的 context,可以通过 SHOW 或 pg_settings 查看。sys_ctl reload 只适用于支持热加载的参数,需要 restart 的参数三种模式处理方式相同。
认证部分三端也一致,都是通过 sys_hba.conf 配置 local / host 规则。实验环境如果需要临时开放外网,可以增加对应的 host 规则。
不过生产环境不建议直接使用 0.0.0.0/0 + md5 这种配置,至少要限制来源网段,并结合更安全的认证方式和主机防火墙。
共性三:账号与只读权限一套脚本
三端都是 ROLE/USER + GRANT 那套权限模型,只读账号可以共用一份骨架:
- CREATE ROLE … LOGIN PASSWORD …
- GRANT CONNECT ON DATABASE
- GRANT USAGE ON SCHEMA public
- GRANT SELECT ON 表
- REVOKE INSERT/UPDATE/DELETE
- REVOKE CREATE ON SCHEMA public(含 PUBLIC)
拿一张 ops_demo 样例表验证,三端各塞 3 行数据,然后用只读账号去撞权限边界:
| 模式 | 只读 SELECT | INSERT 拒绝 | CREATE TABLE 拒绝 |
|---|---|---|---|
| oracle | count=3 | permission denied for table | permission denied for schema public |
| mysql | count=3 | permission denied for table | permission denied for schema public |
| sqlserver | count=3 | permission denied for table | 需先 REVOKE CREATE FROM PUBLIC,否则默认能建表 |
这里 sqlserver 兼容实例和另外两个有一个细节差异:新建只读用户之后,用户仍然可以在 public schema 下执行 CREATE TABLE。
原因是 PUBLIC 默认拥有 public schema 的 CREATE 权限。只对新建用户做 REVOKE 并不够,还需要检查 PUBLIC 本身的权限。
从安全基线角度看,三种模式都建议显式检查并收紧 public schema 的 CREATE 权限。sqlserver 兼容版在本次测试环境里尤其需要补上:
REVOKE CREATE ON SCHEMA public FROM PUBLIC;
在 SQL 里直接写一个固定日期,三端的写法也不一样:
- oracle / mysql:DATE ‘2024-01-01’ 直接可用
- sqlserver:本次环境用 CAST(‘2024-01-01’ AS date) 更稳
这个差异属于 SQL 兼容层,不影响权限模型。但如果迁移脚本里直接复用 Oracle/MySQL 的日期写法,在 sqlserver 兼容实例上就可能报错,需要单独处理。
共性四:逻辑备份恢复同源
逻辑备份方面,三端使用的命令和参数形式一致:
export KINGBASE_PASSWORD=...
sys_dump -h 127.0.0.1 -p <PORT> -U system -d test \
-t ops_demo -f /tmp/ops_demo_<mode>.sql
ksql ... -c "DROP TABLE ops_demo;"
ksql ... -f /tmp/ops_demo_<mode>.sql
先 dump 出来,再手动 DROP 掉原表,然后从 dump 文件恢复,数一下行数对不对得上:
| 模式 | dump 文件 | restore 后 count(*) |
|---|---|---|
| oracle | /tmp/ops_demo_oracle.sql | 3 |
| mysql | /tmp/ops_demo_mysql.sql | 3 |
| sqlserver | /tmp/ops_demo_sqlserver.sql | 3 |
三套实例恢复后都是 3 行,说明这组基础逻辑备份恢复操作在三种模式下可以直接复用。
实际做备份脚本时,可以把 HOST、PORT、USER、PASSWORD、DATA 等信息做成参数表,然后用同一套脚本处理不同实例,没有必要为三种兼容模式各维护一份。
这里验证的只是逻辑备份和恢复流程可以跑通,并不代表生产备份方案就只需要 sys_dump。
生产环境仍然要考虑物理备份、归档、PITR 和恢复演练。逻辑备份更适合小表、临时导出或跨版本数据迁移,不能替代完整的灾备方案。
共性五:观测手段一致
执行计划也用同一条 SQL 做了验证:
EXPLAIN (ANALYZE, BUFFERS)
SELECT id, name, amt FROM ops_demo WHERE id = 1;
三端都能正常返回 Planning Time、Execution Time 和 Buffers,执行计划结构也一致。对 DBA 来说,平时分析 SQL 的方式并不会因为兼容模式不同而改变。
pg_stat_activity 在三种模式下都可以使用,日志也都位于 data/sys_log 目录,按 kingbase-YYYY-MM-DD_*.log 的形式滚动。
因此常规排障时,查看会话、执行计划和日志的路径基本一致。
排障动线可以固化成一条:
- sys_ctl status —— 先确认进程活着
- EXPLAIN (ANALYZE, BUFFERS) —— 慢就看计划
- 翻 sys_log —— 报错和异常留痕在这
- 查会话视图 —— 锁等待、长事务、活动连接一眼看清
这套排障顺序三种模式都可以直接使用。
边界:SQL 语法不同,mode 不能热切换
不过,运维方式接近,并不代表 SQL 兼容性也完全一样。下面是本次抽查的一些函数和语法差异:
| 检查项 | oracle | mysql | sqlserver |
|---|---|---|---|
| dual | 有 | 有 | 无 |
| nvl(NULL,1) | 1 | 1 | 无此函数 |
| ifnull(NULL,1) | 1 | 1 | 无此函数 |
| isnull(NULL,1) | 1 | 语法失败 | 1 |
| if(1=1,‘Y’,‘N’) | Y | Y | 语法失败 |
| TOP 1 | 可用 | 可用 | 可用 |
| LIMIT 1 | 可用 | 可用 | 可用 |
| getdate() | 无 | 无 | 有 |
分页语法相对宽松,TOP 和 LIMIT 在三端都可以使用。但函数差异仍然比较明显,比如 nvl、isnull、getdate 等,还是带有各自兼容模式的特征。
从这组测试可以得到几个比较实用的结论:
- 兼容模式在初始化阶段确定。 本次使用的 ISO 中,sqlserver 版默认就是 sqlserver 模式,mysql 版只支持 mysql。database_mode 不是一个可以在运行期随意切换的参数。
- 多模式并存要按多个实例来部署。 比较稳妥的做法就是不同 OS 用户、不同安装/数据目录、不同端口。
- 应用兼容和 DBA 运维要分开看。 SQL 函数、语法、驱动等需要按模式单独测试;启停、备份、权限、日志这些日常运维内容则可以大量复用。
一张图说清分工

简单来说,兼容模式的主要分叉点出现在初始化和 SQL 兼容层;实例建立之后,DBA 日常操作的共性要明显更多。
统一运维 Checklist
如果要整理成现场运维 checklist,可以压缩成下面几条:
- 一实例一系统用户、一数据目录、一端口,别混
- 启停只认 sys_ctl -D,路径抽成变量,杜绝手打
- 参数改 kingbase.conf 或等价入口,先看 context 再决定 reload 还是 restart
- 访问控制改 sys_hba,外网开放单独评估,别拿实验环境的 0.0.0.0/0 上生产
- 业务账号给最小权限;只读账号只 SELECT,并显式收紧 public 的 CREATE
- 逻辑备份日备 sys_dump,物理备份 + PITR 另立方案,恢复演练定期真拉一次
- 故障动线:status → EXPLAIN → sys_log → 会话视图
- 要上新模式,老老实实重新 initdb,别幻想热切 database_mode
总结
两台 Linux主机、三种兼容模式跑下来,结论收敛成一张表:
| 维度 | 结论 |
|---|---|
| 启停 | 相同 |
| 配置文件 | 相同 |
| 账号权限 | 骨架相同,注意 public 默认权 |
| 逻辑备份 | 相同 |
| 计划与日志 | 相同 |
| SQL 语法与函数 | 不同 |
| mode 切换 | 初始化定型,改不了 |
如果只看这次实测,三种兼容模式最大的差异还是集中在 SQL 兼容性,而不是日常运维。
对于交付和运维团队来说,启停、配置、账号权限、逻辑备份、执行计划和日志排查这些内容,完全可以先整理成一套统一模板,再把不同实例的端口、目录、版本等信息参数化。真正需要按模式单独验证的,主要还是 SQL、函数、驱动以及应用侧兼容性。
后面做版本升级、参数调整或者批量迁移时,也建议把这份 checklist 在各模式实例上重新跑一遍。相比凭经验判断,实测结果更可靠。
附录:连接速查
# Oracle
export KINGBASE_PASSWORD=...
ksql -h 161.118.XXX.XXX -p 54322 -U system -d test
# MySQL
ksql -h 161.118.XXX.XXX -p 54323 -U system -d test
# SQL Server
ksql -h 213.35.XXX.XXX -p 54321 -U system -d test
# 通用启停
sys_ctl -D <DATA> status
sys_ctl -D <DATA> stop -m fast
sys_ctl -D <DATA> -l <LOG> start
# 通用表备份
sys_dump -h 127.0.0.1 -p <PORT> -U system -d test -t ops_demo -f ops_demo.sql




