一、迁移路上的"拦路虎":那些让人头疼的真实痛点
痛点1:OCI连接失败频发——应用系统的"水土不服"
真实场景还原:
某金融机构的核心交易系统,在迁移测试阶段,每到凌晨批处理时段,OCI连接池就会莫名其妙地耗尽。运维团队盯着监控屏幕,看着连接数从100飙升到上限,然后系统开始报错、回滚、重试……这种煎熬,只有经历过的人才懂。
为什么会这样?
Oracle的OCI(Oracle Call Interface)连接机制有其独特的"脾气":
- 连接池管理策略与其他数据库存在差异
- 会话保持机制的实现方式不同
- 事务处理的超时控制各有千秋
KingbaseES的解决之道:
电科金仓深度研究了Oracle的连接协议,在KingbaseES中实现了OCI接口的原生兼容。这意味着:
- 应用层代码无需修改
- 连接池配置可以平滑迁移
- 会话管理机制完全对齐
痛点2:PL/SQL代码无法直接运行——多年积累的"技术债"
一个让人崩溃的例子:
-- 这段在Oracle中运行了5年的存储过程
CREATE OR REPLACE PROCEDURE batch_update_inventory IS
v_count NUMBER := 0;
BEGIN
FOR rec IN (
SELECT product_id, SUM(quantity) as total_qty
FROM orders
WHERE status = 'PENDING'
GROUP BY product_id
) LOOP
UPDATE inventory
SET qty = qty - rec.total_qty,
last_update = SYSDATE
WHERE product_id = rec.product_id;
v_count := v_count + 1;
END LOOP;
DBMS_OUTPUT.PUT_LINE('更新了 ' || v_count || ' 条记录');
COMMIT;
END;
迁移到其他数据库后,可能遇到的问题:
SYSDATE函数不识别DBMS_OUTPUT包不存在- 游标处理方式不兼容
- 隐式类型转换失败
KingbaseES的强大兼容性:
电科金仓提供了高达95%以上的Oracle PL/SQL兼容度,上述代码可以直接运行!具体支持包括:
-
完整的语法支持
- 存储过程、函数、触发器
- Package包结构
- 游标(显式和隐式)
- 异常处理机制
-
丰富的内置包
- DBMS_OUTPUT(调试输出)
- DBMS_SQL(动态SQL)
- DBMS_LOB(大对象处理)
- UTL_FILE(文件操作)
- 等30+常用包
-
高级特性支持
- %TYPE和%ROWTYPE属性
- BULK COLLECT批量操作
- FORALL批量DML
- 自治事务
痛点3:JSON处理报错——现代应用的"绊脚石"
典型场景:
某电商平台的订单系统,大量使用JSON存储商品属性、用户偏好等数据。迁移后发现:
-- Oracle中正常运行的查询
SELECT
order_id,
JSON_VALUE(order_detail, '$.customer.name') as customer_name,
JSON_QUERY(order_detail, '$.items[*].product_id') as product_ids
FROM orders
WHERE JSON_EXISTS(order_detail, '$.items[?(@.price > 100)]');
-- 迁移后可能出现:
-- ERROR: function json_value does not exist
-- ERROR: JSON path expression syntax error
-- 或者查询速度从毫秒级降到秒级
KingbaseES的JSON能力:
不仅实现了Oracle JSON函数的全面兼容,还在性能上做了优化:
- 支持JSON_VALUE、JSON_QUERY、JSON_TABLE等全套函数
- 兼容Oracle的JSON路径表达式语法
- 提供高效的JSON索引机制
- 查询性能达到甚至超越Oracle水平
痛点4:信创改造时间紧任务重——项目经理的"噩梦"
真实压力画像:
- 政策要求:2025年底前完成核心系统国产化
- 业务现状:200+个Oracle数据库实例,5000+个存储过程
- 资源限制:技术团队只有20人,还要维护日常业务
- 风险控制:不能影响生产系统,停机窗口只有4小时
这不是危言耸听,而是很多企业正在面临的真实困境。
二、KingbaseES迁移最佳实践:一套完整的"作战地图"
第一阶段:迁移评估——知己知彼,百战不殆
1. 确定迁移目标(不要盲目开始)
在动手之前,先回答这些问题:
业务层面:
- 迁移的紧迫性如何?是政策驱动还是成本优化?
- 业务能否接受短暂停机?停机窗口有多长?
- 迁移失败的容忍度如何?
技术层面:
- 数据库规模多大?(几GB、几十GB还是TB级?)
- 有多少复杂对象?(存储过程、触发器、包等)
- 是否使用了Oracle特有功能?(如RAC、DataGuard等)
资源层面:
- 技术团队的技能储备如何?
- 预算和工期的约束是什么?
- 是否需要外部专家支持?
2. 评估迁移任务(用数据说话)
使用下面的评估模板,建立清晰的迁移画像:
数据库概况评估表
| 评估项 | 具体信息 | 迁移影响 |
|---|---|---|
| Oracle版本 | 11g R2 | 兼容性较好 |
| 数据库大小 | 500GB | 需要4-6小时迁移时间 |
| 用户Schema数量 | 15个 | 需要逐个迁移 |
| 表数量 | 3,200张 | 中等规模 |
| 存储过程数量 | 856个 | 需要兼容性测试 |
| 触发器数量 | 123个 | 重点关注 |
| Package数量 | 45个 | 可能需要调整 |
| 物化视图 | 67个 | 需要重建 |
| 数据库链接 | 8个 | 需要重新配置 |
对象复杂度评估
简单对象(直接迁移):70%
- 普通表、视图、序列
- 简单存储过程和函数
中等复杂对象(需要测试):25%
- 带触发器的表
- 使用游标的存储过程
- 复杂视图
高复杂对象(需要改造):5%
- 使用Oracle特有功能的对象
- 深度嵌套的Package
- 使用高级特性的代码
3. 组建迁移团队(专业的事交给专业的人)
理想的团队配置:
- 项目经理(1人):统筹协调,风险控制
- DBA工程师(2-3人):熟悉Oracle和KingbaseES
- 应用开发工程师(3-5人):负责代码迁移和测试
- 测试工程师(2-3人):全面回归测试
- 运维工程师(1-2人):环境部署和监控
- 金仓技术支持(1-2人):提供专家级支持
团队技能要求:
- 熟悉Oracle和KingbaseES的SQL/PL-SQL语法差异
- 掌握KDTS、KFS等迁移工具的使用
- 具备性能调优和问题排查能力
- 了解应用系统的业务逻辑
第二阶段:迁移准备——磨刀不误砍柴工
1. 环境准备(硬件和软件)
硬件配置建议:
小型系统(<100GB):
- CPU: 8核
- 内存: 32GB
- 磁盘: SSD 500GB
中型系统(100GB-1TB):
- CPU: 16核
- 内存: 64GB
- 磁盘: SSD 2TB
大型系统(>1TB):
- CPU: 32核+
- 内存: 128GB+
- 磁盘: SSD RAID 5TB+
软件清单:
- KingbaseES V8/V9数据库系统
- KDTS数据迁移工具
- KFS数据同步工具(在线迁移需要)
- Ksql命令行工具
- KStudio图形化管理工具
- Oracle客户端(用于连接源库)
2. 获取源库信息(详细摸底)
必须收集的信息:
-- 1. 查看数据库版本和字符集
SELECT * FROM v$version;
SELECT value FROM nls_database_parameters
WHERE parameter = 'NLS_CHARACTERSET';
-- 2. 查看数据库大小
SELECT
SUM(bytes)/1024/1024/1024 as size_gb
FROM dba_segments;
-- 3. 查看表数据量(按大小排序)
SELECT
segment_name,
bytes/1024/1024/1024 as size_gb
FROM user_segments
WHERE segment_type='TABLE'
ORDER BY bytes DESC;
-- 4. 查看对象统计
SELECT object_type, COUNT(*) as count
FROM user_objects
GROUP BY object_type
ORDER BY count DESC;
-- 5. 查看日期格式
SELECT value FROM nls_session_parameters
WHERE parameter = 'NLS_DATE_FORMAT';
-- 6. 检查是否有特殊字符集数据
SELECT DISTINCT
DUMP(column_name) as encoding_info
FROM your_table
WHERE column_name IS NOT NULL;
3. 配置目标库(为迁移做好准备)
创建数据库和用户:
-- 1. 创建与Oracle同名的用户
CREATE USER scott WITH PASSWORD '123456' SUPERUSER;
-- 2. 创建与Oracle同名的数据库
CREATE DATABASE orcl
OWNER scott
ENCODING 'UTF8'
LC_COLLATE 'zh_CN.UTF-8'
LC_CTYPE 'zh_CN.UTF-8';
-- 3. 连接到新数据库
\c orcl scott
-- 4. 创建与Oracle用户同名的模式
CREATE SCHEMA scott AUTHORIZATION scott;
-- 5. 设置搜索路径
ALTER DATABASE orcl SET search_path TO scott, public;
配置Oracle兼容参数:
编辑kingbase.conf文件:
# 字符类型长度语义(与Oracle保持一致)
nls_length_semantics = 'BYTE' # 或 'CHAR',根据源库设置
# 启用OID伪列(兼容ROWID)
default_with_oids = on
# 日期格式(与Oracle保持一致)
datestyle = 'ISO, YMD'
# Oracle日期风格
ora_input_emulation = on
# 性能优化参数
shared_buffers = 8GB # 建议设置为内存的1/4
work_mem = 256MB
maintenance_work_mem = 1GB
effective_cache_size = 24GB # 建议设置为内存的3/4
# 连接参数
max_connections = 500
安装PostGIS插件(如果有GIS数据):
-- 创建必要的插件
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_raster;
CREATE EXTENSION postgis_topology;
CREATE EXTENSION fuzzystrmatch;
CREATE EXTENSION address_standardizer;
-- 验证安装
SELECT PostGIS_Version();
第三阶段:数据迁移——核心战役
方案一:离线迁移(适合可停机场景)
使用KDTS工具的完整流程:
Step 1: 配置源数据库连接
编辑conf/datasource-oracle.yml:
sources:
- dbType: oracle
dbVersion: 11g
url: jdbc:oracle:thin:@192.168.1.100:1521/ORCL
driver-class-name: oracle.jdbc.OracleDriver
username: scott
password: tiger
schemas: SCOTT
# 指定要迁移的表(可选)
table-includes: EMP,DEPT,SALGRADE
# 排除不需要迁移的表(可选)
table-excludes: TEMP_TABLE,LOG_TABLE
Step 2: 配置目标数据库连接
target:
dbType: KINGBASE
dbVersion: V9
url: jdbc:kingbase8://192.168.1.200:54321/orcl
driver-class-name: com.kingbase8.Driver
username: scott
password: 123456
schemas: SCOTT
Step 3: 配置迁移参数
migration:
# 表处理方式
drop-existing-object: true # 删除已存在的对象
truncate-table: false # 不清空表数据
# 数据读写参数
fetch-size: 1000 # 游标读取记录数
write-batch-size: 5000 # 批量写入记录数
write-batch-size-big-lob: 100 # 大对象批量写入记录数
# 大表拆分
large-table-split-threshold-rows: 10000000 # 1000万行
large-table-split-threshold-size: 10240 # 10GB
# 对象迁移开关
migrate-primary-key: true
migrate-foreign-key: true
migrate-index: true
migrate-trigger: true
migrate-view: true
migrate-sequence: true
migrate-procedure: true
migrate-function: true
migrate-package: true
# 数据类型映射
use-custom-type-mapping: true
# 连接池配置
maximum-pool-size: 20
Step 4: 配置数据类型映射
编辑conf/mapping_rule/data_type/oracle_to_kingbase.json:
[
{
"comment": "NUMBER(38,0)映射为BIGINT",
"sourceType": {
"name": "NUMBER",
"precisionMin": 0,
"precisionMax": 38,
"scaleMin": 0,
"scaleMax": 0
},
"targetType": {
"name": "BIGINT"
}
},
{
"comment": "VARCHAR2映射为VARCHAR",
"sourceType": {
"name": "VARCHAR2"
},
"targetType": {
"name": "VARCHAR"
}
},
{
"comment": "CLOB映射为TEXT",
"sourceType": {
"name": "CLOB"
},
"targetType": {
"name": "TEXT"
}
}
]
Step 5: 执行迁移
# 启动迁移任务
cd KDTS-CLI
./bin/startup.sh
# 查看迁移日志
tail -f logs/kdts_plus_*.log
# 迁移完成后查看报告
cd result/2024-12-08_12-00-00/SCOTT
# 打开index.html查看详细报告
Step 6: 验证迁移结果
-- 1. 检查表数量
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'scott';
-- 2. 检查数据量
SELECT
table_name,
sys_stat_get_live_tuples(oid) as row_count
FROM sys_class
WHERE relnamespace = (SELECT oid FROM sys_namespace WHERE nspname = 'scott')
AND relkind = 'r'
ORDER BY row_count DESC;
-- 3. 对比关键表的数据
-- 在源库执行
SELECT COUNT(*), SUM(sal), AVG(sal) FROM emp;
-- 在目标库执行
SELECT COUNT(*), SUM(sal), AVG(sal) FROM scott.emp;
-- 4. 检查约束
SELECT
conname as constraint_name,
contype as constraint_type
FROM sys_constraint
WHERE connamespace = (SELECT oid FROM sys_namespace WHERE nspname = 'scott');
-- 5. 检查索引
SELECT
indexname,
tablename,
indexdef
FROM sys_indexes
WHERE schemaname = 'scott';
方案二:在线迁移(适合不能停机场景)
在线迁移需要结合KDTS和KFS工具,分为三个步骤:
Step 1: 源库备份(获取一致性点)
-- 1. 创建一致性检查点
ALTER SYSTEM CHECKPOINT GLOBAL;
-- 2. 获取当前SCN号
SELECT checkpoint_change# FROM v$database;
-- 假设得到 SCN: 8523697
-- 3. 创建导出目录
CREATE DIRECTORY dump_dir AS '/data/oracle/dump';
GRANT READ, WRITE ON DIRECTORY dump_dir TO scott;
-- 4. 使用expdp导出(基于SCN)
expdp scott/tiger \
schemas=SCOTT \
directory=dump_dir \
flashback_scn=8523697 \
dumpfile=scott_20241208.dmp \
logfile=scott_20241208.log
Step 2: 中间库恢复和KDTS迁移
# 1. 在中间Oracle库导入数据
impdp scott/tiger \
directory=dump_dir \
dumpfile=scott_20241208.dmp \
remap_schema=SCOTT:SCOTT_NEW \
table_exists_action=replace
# 2. 使用KDTS将中间库数据迁移到KingbaseES
# (配置方法同离线迁移)
./bin/startup.sh
Step 3: 使用KFS追平增量数据
# 1. 配置KFS源端(Oracle)
cd KFS/conf
vi datasources.xml
<property name="replicator.datasource.global.url">
jdbc:oracle:thin:@192.168.1.100:1521/ORCL
</property>
<property name="replicator.datasource.global.user">scott</property>
<property name="replicator.datasource.global.password">tiger</property>
# 2. 配置KFS目标端(KingbaseES)
<property name="replicator.datasource.global.url">
jdbc:kingbase8://192.168.1.200:54321/orcl
</property>
# 3. 启动源端KFS(从指定SCN开始)
./bin/replicator start offline
./bin/fsrepctl -service oracle online -from-event ora:8523697:8523697
# 4. 启动目标端KFS
./bin/replicator start
# 5. 监控同步状态
./bin/fsrepctl services
# 输出示例:
# appliedLastSeqno: 8523850 # 当前同步到的序列号
# appliedLatency: 0.125 # 延迟时间(秒)
# state: ONLINE # 运行状态
数据追平判断标准:
# 当满足以下条件时,说明数据已追平:
# 1. appliedLastSeqno 与源库当前SCN接近
# 2. appliedLatency < 1秒
# 3. 连续观察5分钟,延迟保持稳定
# 此时可以进行业务切换
第四阶段:应用迁移——让系统跑起来
1. PL/SQL代码迁移
自动迁移(KDTS已完成):
- 存储过程
- 函数
- 包(Package)
- 触发器
手动处理(需要关注):
-- 匿名块中的代码需要手动迁移
-- Oracle代码
DECLARE
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM emp;
DBMS_OUTPUT.PUT_LINE('员工总数: ' || v_count);
END;
/
-- KingbaseES代码(完全兼容,无需修改)
DECLARE
v_count INTEGER;
BEGIN
SELECT COUNT(*) INTO v_count FROM emp;
RAISE NOTICE '员工总数: %', v_count;
END;
$$
需要注意的兼容性问题:
-- 1. Package中不允许同名同参数的过程和函数
-- Oracle允许:
CREATE OR REPLACE PACKAGE pkg_test AS
PROCEDURE proc_test(p_id NUMBER);
FUNCTION proc_test(p_id NUMBER) RETURN VARCHAR2;
END;
-- KingbaseES需要改名:
CREATE OR REPLACE PACKAGE pkg_test AS
PROCEDURE proc_test(p_id INTEGER);
FUNCTION func_test(p_id INTEGER) RETURN VARCHAR;
END;
-- 2. Object Type方法的连续调用
-- Oracle支持:
v_result := obj.method1().method2().method3();
-- KingbaseES需要改写:
v_temp1 := obj.method1();
v_temp2 := v_temp1.method2();
v_result := v_temp2.method3();
2. 应用程序连接迁移
JDBC连接迁移:
// Oracle连接
// String url = "jdbc:oracle:thin:@192.168.1.100:1521:ORCL";
// String driver = "oracle.jdbc.OracleDriver";
// 修改为KingbaseES连接
String url = "jdbc:kingbase8://192.168.1.200:54321/orcl";
String driver = "com.kingbase8.Driver";
String user = "scott";
String password = "123456";
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, password);
ODBC连接迁移(Windows):
- 打开"ODBC数据源管理器"
- 点击"添加",选择"KingbaseES ODBC Driver"
- 配置连接参数:
- 数据源名称:KingbaseES_ORCL
- 服务器:192.168.1.200
- 端口:54321
- 数据库:orcl
- 用户名:scott
- 密码:123456
- 测试连接成功后保存
应用程序中修改连接字符串:
// C# ADO.NET示例
// 原Oracle连接字符串
// string connStr = "Data Source=ORCL;User Id=scott;Password=tiger;";
// 修改为KingbaseES
string connStr = "Driver={KingbaseES ODBC Driver};" +
"Server=192.168.1.200;Port=54321;" +
"Database=orcl;UID=scott;PWD=123456;";
OCI应用迁移到DCI:
KingbaseES提供了DCI(Database Call Interface),兼容Oracle OCI的大部分接口:
// 原OCI代码
// #include <oci.h>
// OCIEnvCreate(&envhp, OCI_DEFAULT, ...);
// 修改为DCI
#include <dci.h>
DCIEnvCreate(&envhp, DCI_DEFAULT, ...);
// 其他API调用基本保持不变
第五阶段:测试与调优——确保万无一失
1. 功能测试清单
数据完整性测试:
-- 1. 表数量对比
-- 源库
SELECT COUNT(*) FROM all_tables WHERE owner = 'SCOTT';
-- 目标库
SELECT COUNT(*) FROM information_schema.tables
WHERE table_schema = 'scott';
-- 2. 数据量对比
-- 源库
SELECT table_name, num_rows
FROM all_tables
WHERE owner = 'SCOTT'
ORDER BY num_rows DESC;
-- 目标库
SELECT
schemaname || '.' || tablename as table_name,
n_live_tup as num_rows
FROM sys_stat_user_tables
WHERE schemaname = 'scott'
ORDER BY n_live_tup DESC;
-- 3. 数据一致性抽查
-- 对关键表进行MD5校验
-- 源库
SELECT MD5(
LISTAGG(emp_id || ',' || emp_name || ',' || salary, '|')
WITHIN GROUP (ORDER BY emp_id)
) FROM emp;
-- 目标库
SELECT MD5(
STRING_AGG(emp_id || ',' || emp_name || ',' || salary, '|'
ORDER BY emp_id)
) FROM scott.emp;
业务功能测试:
制作测试用例表:
| 测试模块 | 测试用例 | 预期结果 | 实际结果 | 状态 |
|---|---|---|---|---|
| 用户登录 | 正确用户名密码 | 登录成功 | 登录成功 | ✓ |
| 数据查询 | 查询员工列表 | 返回所有员工 | 返回所有员工 | ✓ |
| 数据新增 | 添加新员工 | 插入成功 | 插入成功 | ✓ |
| 数据修改 | 更新员工信息 | 更新成功 | 更新成功 | ✓ |
| 数据删除 | 删除员工记录 | 删除成功 | 删除成功 | ✓ |
| 批量处理 | 月末结算 | 处理成功 | 处理成功 | ✓ |
| 报表生成 | 生成月度报表 | 报表正确 | 报表正确 | ✓ |
2. 性能测试与调优
基准测试:
-- 1. 简单查询性能
EXPLAIN ANALYZE
SELECT * FROM emp WHERE deptno = 10;
-- 2. 复杂查询性能
EXPLAIN ANALYZE
SELECT
d.deptno,
d.dname,
COUNT(e.empno) as emp_count,
AVG(e.sal) as avg_salary
FROM dept d
LEFT JOIN emp e ON d.deptno = e.deptno
GROUP BY d.deptno, d.dname
ORDER BY emp_count DESC;
-- 3. 批量插入性能测试
DO $$
DECLARE
v_start_time TIMESTAMP;
v_end_time TIMESTAMP;
BEGIN
v_start_time := CLOCK_TIMESTAMP();
INSERT INTO test_table
SELECT
generate_series(1, 100000),
'Name_' || generate_series(1, 100000),
RANDOM() * 10000;
v_end_time := CLOCK_TIMESTAMP();
RAISE NOTICE '插入10万条记录耗时: %',
v_end_time - v_start_time;
END;
$$;
性能调优建议:
-- 1. 创建合适的索引
CREATE INDEX idx_emp_deptno ON emp(deptno);
CREATE INDEX idx_emp_sal ON emp(sal);
-- 2. 更新统计信息
ANALYZE emp;
ANALYZE dept;
-- 3. 调整查询计划
-- 如果发现查询计划不优,可以调整参数
SET enable_seqscan = off; -- 禁用顺序扫描
SET random_page_cost = 1.1; -- SSD磁盘建议值
-- 4. 使用物化视图
CREATE MATERIALIZED VIEW mv_dept_summary AS
SELECT
d.deptno,
d.dname,
COUNT(e.empno) as emp_count,
AVG(e.sal) as avg_salary
FROM dept d
LEFT JOIN emp e ON d.deptno = e.deptno
GROUP BY d.deptno, d.dname;
-- 定期刷新
REFRESH MATERIALIZED VIEW mv_dept_summary;
并发压力测试:
使用JMeter或LoadRunner进行压力测试:
测试场景1:高并发查询
- 并发用户数:500
- 持续时间:30分钟
- 目标TPS:1000
- 响应时间:<100ms
测试场景2:混合事务
- 并发用户数:200
- 查询:更新:插入 = 7:2:1
- 持续时间:1小时
- 目标TPS:500
- 响应时间:<200ms
三、特殊场景:GIS数据迁移
如果你的Oracle数据库中包含GIS数据(使用ArcGIS或GeoScene平台),需要额外的迁移步骤。
前置准备
1. 安装PostGIS插件
-- 连接到目标数据库
\c orcl
-- 创建必要的插件
CREATE EXTENSION postgis;
CREATE EXTENSION postgis_raster;
CREATE EXTENSION postgis_topology;
CREATE EXTENSION fuzzystrmatch;
CREATE EXTENSION address_standardizer;
-- 验证安装
SELECT PostGIS_Version();
2. 创建SDE用户和模式
-- 创建SDE用户(ArcGIS必需)
CREATE USER sde SUPERUSER PASSWORD '123456';
CREATE USER rds_superuser SUPERUSER PASSWORD '123456';
-- 创建SDE模式
CREATE SCHEMA sde AUTHORIZATION sde;
-- 设置参数
SET exclude_reserved_words = 'level';
3. 创建公共函数(仅Oracle源库需要)
-- 此函数用于处理SDE数据的SRID
CREATE OR REPLACE FUNCTION append_srid(
srid IN INTEGER,
kwb IN BLOB
) RETURN BLOB AS
re BLOB;
BEGIN
IF kwb IS NULL THEN
RETURN NULL;
END IF;
re := TO_BLOB(
UTL_RAW.CAST_FROM_BINARY_INTEGER(
srid,
UTL_RAW.LITTLE_ENDIAN
)
);
DBMS_LOB.APPEND(re, kwb);
RETURN re;
END;
$$
GIS数据迁移步骤
Step 1: 使用KDTS迁移非GIS数据
# 配置KDTS只迁移GIS相关的表
sources:
- dbType: oracle
username: SDE
password: sde123
schemas: SDE
table-includes: POINT,LINE,POLYGON,DLTB2
# 配置数据类型映射
# 将NUMBER(38,0)映射为INT
Step 2: 在ArcGIS中注册地理信息数据库
- 打开ArcMap软件
- 连接到KingbaseES数据库
- 右键点击数据库连接
- 选择"启用地理信息数据库"
Step 3: 执行Python脚本注册GIS对象
KDTS会在迁移结果目录生成acrpyRegisterWithGeodatabase.py脚本:
# 编辑脚本,修改数据库连接信息
arcpy.env.workspace = "Database Connections/KingbaseES_ORCL.sde"
# 执行脚本
python acrpyRegisterWithGeodatabase.py
Step 4: 验证GIS数据
在ArcMap中:
- 添加数据层
- 检查图层是否正常显示
- 测试空间查询功能
- 验证属性数据完整性
四、常见问题与解决方案
问题1:字符集乱码
现象:
中文数据显示为乱码或问号
原因分析:
- Oracle字符集为US7ASCII或WE8ISO8859P1
- KingbaseES字符集为UTF8
- 字符编码转换失败
解决方案:
# 在KDTS配置中添加字符解码参数
migration:
character-need-decoding: true
encoding-charset: "ISO-8859-1"
decoding-charset: "GB18030"
decoding-bytes: true # US7ASCII需要设为true
问题2:日期格式不一致
现象:
ERROR: date/time field value out of range
日期"99-09-30"被识别为"2099-09-30"而非"1999-09-30"
解决方案:
-- 在kingbase.conf中设置
datestyle = 'ISO, YMD'
-- 或在会话中设置
SET datestyle = 'ISO, YMD';
-- 启用Oracle日期风格
SET ora_input_emulation = on;
问题3:大对象迁移失败
现象:
LOB字段数据丢失或截断
迁移过程中内存溢出
解决方案:
# 调整KDTS配置
migration:
# 减小LOB字段预读取大小
lob-field-pre-fetch-size: 4000
# 减小大对象批量写入记录数
write-batch-size-big-lob: 50
# 增加读数据超时时长
read-data-timeout: 300000 # 5分钟
问题4:序列值不连续
现象:
迁移后序列的当前值与源库不一致
解决方案:
-- 迁移后手动调整序列值
-- 查询源库序列当前值
SELECT sequence_name, last_number
FROM all_sequences
WHERE sequence_owner = 'SCOTT';
-- 在目标库设置序列值
SELECT SETVAL('scott.seq_emp_id', 1000, false);
问题5:外键约束创建失败
现象:
ERROR: insert or update on table violates foreign key constraint
原因分析:
- 数据迁移顺序问题
- 主表数据未完全迁移
- 外键引用的数据不存在
解决方案:
# 方案1:先迁移数据,后创建约束
migration:
migrate-foreign-key: false # 第一次迁移时关闭
# 数据迁移完成后,手动创建外键
-- 方案2:临时禁用外键检查
SET session_replication_role = replica;
-- 执行数据迁移
-- ...
-- 恢复外键检查
SET session_replication_role = DEFAULT;
-- 验证数据完整性
SELECT * FROM emp WHERE deptno NOT IN (SELECT deptno FROM dept);
六、写在最后
Oracle到KingbaseES的迁移,不是简单的数据搬家,而是一次系统性的技术升级。它需要:
- 技术的准备:深入理解两个数据库的差异
- 工具的支持:善用KDTS、KFS等专业工具
- 团队的协作:DBA、开发、测试、运维紧密配合
- 时间的投入:给予充分的测试和调优时间
但请相信,这一切努力都是值得的。当你的系统成功运行在KingbaseES上时,你会发现:
- 成本降低了:不再需要支付高昂的Oracle许可费
- 性能提升了:针对性优化后的系统更加高效
- 自主可控了:关键数据掌握在自己手中
- 技术进步了:团队掌握了国产数据库的核心技能