迁移需求
由于非信创到信创环境的割接,需要将一套Oracle RAC迁移至金仓读写分离集群。由于二者之间存在网闸、VPN和堡垒机频繁掉线、请求超时,使用KDTS停机迁移、使用KDTS+KFS不停机迁移的两种方式均失败,协调云上和网闸方面的技术人员更改后依然没改善,最后只能采用中转迁移方案:将Oracle RAC 通过KDTS停机迁移至同网段金仓单点临时服务器(Centos79、x86架构),金仓单点临时服务器上的金仓库冷迁移至金仓读写分离集群中的主节点上(Kylin V10,Kunpeng920),最后单点转集群。
说明:
- 冷迁移:关库,拷贝数据目录
- 网闸方:启明星辰 该现场的网闸存在超时 会话不定时端口的情况,若遇到该情况,不要坚持不停机迁移。
环境说明
操作系统 | 内存 | cpu | ip地址 | 数据库名 | 业务用户密码 | 备注 | |
源端Oracle RAC | Centos7.9 | 128G | 64核 | 172.20.111.11 172.20.111.12 172.20.111.13 | icpsp1 | icpsp/icpsp | |
金仓单点临时服务器 | Centos7.9 | 64G | 64核 | 172.20.111.32 | icpsp1 | icpsp/icpsp | 迁移至public模式下 |
目标端金仓RWC | KylinV10 SP3 | 512G | 64核 | 172.21.142.105 主 172.21.142.104 备 | 已部署好集群 | ||
KDTS工具位置 | 172.21.142.104 | web版本kdts-plus-bs-V009R001C002 放于备节点避免影响主节点写入 |
特别注意:金仓单点临时服务器的数据库版本必须和目标端金仓RWC版本保持一致
迁移前准备
硬件方面
申请和源端Oracle RAC同网段的临时服务器
由于云上最高配置是内存64G 64核CPU,所以只能申请到一台内存64G CPU64核 10T的临时服务器172.20.111.32
网络方面
申请云上开通金仓临时服务器访问源端RAC节点1的端口 :172.20.111.11
堡垒机界面增加KDTS WEB页面访问入口
软件方面
源端库
数据库信息统计
查字符集
-- 查看数据库字符集
set linesize 999
col value for a60
select * from nls_database_parameters where PARAMETER in ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');
PARAMETER VALUE
------------------------------ ----------------------------------------------------------------------------
NLS_CHARACTERSET AL32UTF8
NLS_NCHAR_CHARACTERSET UTF8
select userenv('language') from dual;查数据量
--查看总大小
select round(sum(bytes) / 1024 / 1024 / 1024, 2) || 'G'
from dba_segments
where owner in ('TOPICIS') ;
ROUND(SUM(BYTES)/1024/1024/1024,2)||'G'
-----------------------------------------
3578.66G统计表大小
统计大于500G的表,该步骤是为了实现后面KDTS分批迁移。
--查看表大小超过10G的大表
col owner for a40
col TABLE_NAME for a60
set linesize 999 pagesize 999
select * from (SELECT OWNER,TABLE_NAME,SUM(tabsize) table_size from (
SELECT owner,SEGMENT_NAME as table_name,SUM(BYTES)/1024/1024/1024 as tabsize FROM DBA_SEGMENTS WHERE (OWNER,SEGMENT_NAME) IN (
SELECT OWNER,TABLE_NAME FROM DBA_TABLES WHERE OWNER NOT IN ('SYS','SYSTEM','DBSNMP'))
GROUP BY SEGMENT_NAME,owner
union ALL
select lob.owner,lob.table_name,sum(seg.bytes)/1024/1024/1024 as tabsize from dba_lobs lob,dba_segments seg
where lob.segment_name=seg.segment_name and lob.OWNER NOT IN ('SYS','SYSTEM','DBSNMP') group by lob.owner,lob.table_name
)
GROUP BY OWNER,TABLE_NAME ORDER BY 3 DESC)
where table_size>=500 ;
--统计大字段
SELECT
l.owner,
l.TABLE_NAME,
s.segment_name,
s.segment_type,
SUM(s.bytes / 1024 / 1024 / 1024)
FROM
dba_lobs l
JOIN
dba_segments s
ON
l.segment_name = s.segment_name
GROUP BY
l.owner,
s.segment_name,
s.segment_type,
l.TABLE_NAME
ORDER BY
5 DESC;金仓单点临时服务器
部署金仓库
在金仓单点临时服务器部署金仓数据库,记得配置环境变量,方便启停库。
注意:字符集、数据库模式、大小写敏感保持一致。
字符集:UTF8
数据库模式:Oracle
大小写敏感:敏感
部署金仓库后查看以上参数值:
test=# show encoding;
encoding
---------------
UTF8
(1 行记录)
test=# show database_mode;
database_mode
---------------
oracle
(1 行记录)
test=# show enable_ci; --默认off:区分大小写
enable_ci
-----------
off
(1 行记录)创建数据库和用户
创建数据库和用户,保持和源端库业务数据库和业务用户一致。迁移至topicis用户的public模式下。
create user topicis with password 'oracle';
create database topicis owner topicis;
grant all privileges on database topicis to topicis;参数更改
--更改参数
vi kingbase.conf
ignore_char_null_check=on
ora_input_emptystr_isnull=on
shared_preload_libraries = 'dbms_lob' # (change requires restart)
--重启库生效
sys_ctl restart
--创建相关扩展 如果未用到大字段可忽略
--超级管理员连到业务库
ksql -Usystem icpsp
--创建kdb_raw扩展
create extension kdb_raw;
--创建dbms_lob扩展
create extension dbms_lob;停止业务
联系业务方停止业务,更改源端Oracle RAC中业务用户密码,防止新的会话进入。
查看源库会话,确保业务会话已消失,若未消失进行手动杀会话。
--查看不同用户的连接数
select username,count(username) from v$session where username is not null group by username;
--查询用户会话
select username,serial#, sid ,status from v$session where username is not null;
select username,status,schemaname,osuser,process,machine,port,program,serial#, sid from v$session where username is not null;
--删除相关用户会话
alter system kill session 'sid,serial#';
补充:
--源库杀用户连接 不建议 该步骤慎重 该文档未进行该操作 该方法迫不得已不用
ps -ef|grep LOCAL=NO|awk '{print $2}'|xargs kill -9迁移步骤
KDTS工具将Oracle RAC中的业务数据迁移至金仓单点临时服务器
更改以下参数

迁移数据有utf8 0x00报错的时候,删除空白字符选是,一般一开始就选删除空白字符
Caused by: com.kingbase8.util.KSQLException: ERROR: invalid byte sequence for encoding "UTF8": 0x00 Where: COPY PUB_CERTIFICATION_HISTORY, line 574, column PAPERNUMBER at
创建迁移任务
根据CPU核数而定,如果CPU核数很充裕,大于等于500G且含有大字段的表分别创建独立的迁移任务,不然进行表组合创建迁移任务,剩余的表独立创建迁移任务
启动所有的迁移任务
启动所有的迁移任务,注意实时观察。如果有表组合的迁移任务,遇到某个表迁移失败要及时对失败的表创建独立的迁移任务。
速度很快,3.5T的数据量耗时约10小时,平均359G/h。
传输金仓临时服务器数据目录至金仓集群主节点
关闭金仓临时库
sys_ctl stop -D /oracle/kingbase/data分片压缩数据目录
由于金仓临时库数据目录下小文件较多,scp直接传输时间耗时很长不可控,传输前将数据目录进行分片压缩。
该现场数据目录3.1T,分片压缩耗时47小时,平均68G/h;这是不得不面对的一大硬伤,逻辑备份耗时太长、物理备份也有很多小文件,压缩数据目录遇到服务器性能差的服务器真是很牺牲时间。期待未来拷贝数据文件冷迁移能不压缩直接传避免耗时长的问题。
由于VPN和堡垒机频繁掉线、请求超时,只能通过脚本后台分片压缩
--创建存放压缩文件的目录
mkdir -p /oracle/kingbase/kesdbtar
chown -R kingbase:kingbase /oracle/kingbase/kesdbtar
chmod -R 775 /oracle/kingbase/kesdbtar
--编写tar压缩脚本 进入数据目录再压缩不然回级联压缩
cat tar.sh
#/bin/bash
cd /oracle/kingbase
tar -czf - data | split -b 50G - /oracle/kingbase/kesdbtar/data.tar.gz.
--后台执行压缩
nohup ./tar.sh &配置ssh互相
由于VPN和堡垒机频繁掉线、请求超时,只能通过ssh免密访问来 实现文件传输。
本文档采用的是rsync脚本传输
#1.本地生成密钥文件(172.20.111.32上操作)
ssh-keygen --全程敲回车
#2.将本地公钥传输到远程主机(172.20.111.32上操作)
--如果网络通的情况下是这样操作,如果ip通过映射,需要将172.21.142.105改成映射后的ip
ssh-copy-id -i ~/.ssh/id_ed25519.pub root@172.21.142.105
--如果网络不通 本文档属于该场景
查看~/.ssh/id_ed25519.pub内容 cat ~/.ssh/id_ed25519.pub
将id_ed25519.pub内容追加到远程主机172.21.142.105上 ~/.ssh/authorized_keys文件中
#3.测试本地免密登录到远程主机(172.20.111.32上操作,ssh 目标服务器ip)
ssh 172.21.142.105
不提示输入密码即免密配置成功传输数据目录至目标金仓集群
--编写rsync脚本 一定要指定ssh协议,不然速度龟慢龟慢
cat rsync.sh
#/bin/bash
/usr/bin/rsync -P --rsh=ssh /oracle/kingbase/kesdbtar/* root@172.21.142.105:/data/20250502/kesdbtar/ > /tmp/load.log 2>&1 &
--后台执行文件传输
nohup ./rsync.sh &越是复杂的场景越是激发技能盲区,终于明白那些大佬们在大数据量场景下迁移能忙里偷闲睡觉的诀窍了。
目标端金仓RWC用已存在的数据目录重部署
重部署前准备工作
目标端金仓RWC关闭集群
查看集群状态(任意一个节点操作)
--查看集群状态 任意一个节点操作均可
[kingbase@02 ~]$ repmgr cluster show
ID | Name | Role | Status | Upstream | Location | Priority | Timeline | LSN_Lag | Connection string
----+-------+---------+-----------+----------+----------+----------+----------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 | node1 | primary | * running | | default | 100 | 7 | | host=172.21.142.105 user=esrep dbname=esrep port=54321 connect_timeout=10 keepalives=1 keepalives_idle=2 keepalives_interval=2 keepalives_count=3 tcp_user_timeout=9000
2 | node2 | standby | running | node1 | default | 100 | 7 | 0 bytes | host=172.21.142.104 user=esrep dbname=esrep port=54321 connect_timeout=10 keepalives=1 keepalives_idle=2 keepalives_interval=2 keepalives_count=3 tcp_user_timeout=9000停止集群(任意一个节点操作)
--停止集群 任意一个节点操作均可
sys_monitor.sh stop停止sys_securecmdd进程(所有节点都需要操作)
V8R6需要在root用户下操作,V9R1已经可以在kingbase用户下操作
--停止sys_securecmdd进程 所有节点都需要操作 不要kill,kill会很快复活
su - root
cd /home/kingbase/cluster/install/bin
./sys_HAscmdd.sh stop问题处理
--问题描述sys_securecmdd进程提示securecmdd_config文件不存在
备节点停止
[kingbase@02 ~]$ ./sys_HAscmdd.sh stop
the file "/etc/.kes/kingbase/securecmdd_config" is not exists
--分析过程
文件存在,但是sys_securecmdd进程调用的securecmdd_config文件和sys_HAscmdd.sh调用的securecmdd_config文件路径不匹配
[kingbase@02 ~]$ ps -ef | grep kingbase
root 2519659 1 0 May02 ? 00:00:00 sys_securecmdd: /home/kingbase/cluster/install/kingbase/bin/sys_securecmdd -f /etc/.kes/securecmdd_config [listener] 0 of 128-256 startups
--解决办法
1.删除/etc/.kes/目录下文件
cd /etc/.kes/
rm -rf *
2.kill 掉sys_securecmdd进程
[kingbase@02 ~]$ ps -ef | grep kingbase
root 2519659 1 0 May02 ? 00:00:00 sys_securecmdd: /home/kingbase/cluster/install/kingbase/bin/sys_securecmdd -f /etc/.kes/securecmdd_config [listener] 0 of 128-256 startups
[kingbase@02 ~]$ kill -9 2519659删除集群安装目录(所有节点)
--删除集群安装目录 由于磁盘空间很充裕,未选择rm -rf方式,建议条件允许的场景下mv而不是rm -rf
cd /home/kingbase/cluster/install/
mv kingbase kingbase_bak_20250504
--创建集群安装目录
mkdir -p kingbase删除集群数据目录(注意:主节点和备节点操作有所区别)
删除集群数据目录,所有节点都需要操作,但是注意:主节点和备节点操作有所区别
--主节点
cd /data/kingbase
mv data data_bak_20250504
--备节点
cd /data/kingbase
mv data data_bak_20250504
mkdir -p data解压临时金仓库的数据目录至集群数据目录
cat /data/20250502/kesdbtar/data.tar.gz* | tar -xzvf - -C /data/kingbase/修改集群安装配置文件install.conf
su - kingbase
cd /data/kesclusterinstall/ClientTools/guitools/DeployTools/zip
cp install.conf install.conf_20250504bak
vi install.conf- [install]组下面的数据目录参数,需要更改
## Will or not use the data directory which is already exists on one node.
# 0: there is no data, will generate the data directory by initdb.
# 1: there is only one data, use it as the primary node. (In TPTC, the data directory must on any node of produtcion_ip.)
use_exist_data=1 会跳过初始化数据目录的步骤
## the path of data directory, BMJ defaults to "/opt/Kingbase/ES/V8/data", the general machine defaults to "install_dir/kingbase/data"
data_directory="/data/kingbase/data"
# database initializes user configuration
db_user="system" # the user name of database
db_password="kingbase" # the password of database.
db_port="54321" # the port of database, defaults is 54321
db_mode="oracle" # database mode: pg, oracle, mysql
db_auth="scram-sha-256" # database authority: scram-sha-256, md5, scram-sm3, sm4, default is scram-sha-256
db_case_sensitive="yes" # database case sensitive settings: yes, no. default is yes - case sensitive; no - case insensitive
encoding="UTF8" # set default encoding for new databases. must be one of ('default' 'UTF8' 'GBK' 'GB2312' 'GB18030')- use_exist_data=1 会跳过初始化数据目录的步骤
- db_password 需要改成金仓临时库的密码
- db_port 需要改成金仓临时库的端口
- db_mode 需要改成金仓临时库的模式
- db_case_sensitive 需要改成金仓临时库的大小写模式
- encoding 需要改成金仓临时库的数据库 编码
如果system用户密码、端口和数据库模式采用默认则忽视上面红色内容。另外其他信息不用更改
修改集群安装配置文件cluster_install.sh
仅需要在密码、端口、数据库模式、大小写敏感、数据库编码不采用默认时更改,若采用默认参数,则跳过该步骤
vi cluster_install.sh
# db configuration
db_user="system"
db_password="kingbase"
db_port="54321"
db_mode="oracle"
db_case_sensitive=""数据库集群安装
最后输出[INSTALL] start up the whole cluster ... OK 说明集群部署完成
su - kingbase
cd /data/kesclusterinstall/ClientTools/guitools/DeployTools/zip
./cluster_install.sh查询集群状态
[kingbase@02 ~]$ repmgr cluster show
ID | Name | Role | Status | Upstream | Location | Priority | Timeline | LSN_Lag | Connection string
----+-------+---------+-----------+----------+----------+----------+----------+---------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1 | node1 | primary | * running | | default | 100 | 7 | | host=172.21.142.105 user=esrep dbname=esrep port=54321 connect_timeout=10 keepalives=1 keepalives_idle=2 keepalives_interval=2 keepalives_count=3 tcp_user_timeout=9000
2 | node2 | standby | running | node1 | default | 100 | 7 | 0 bytes | host=172.21.142.104 user=esrep dbname=esrep port=54321 connect_timeout=10 keepalives=1 keepalives_idle=2 keepalives_interval=2 keepalives_count=3 tcp_user_timeout=9000数据校验
源端
查看对象数量
--每个业务用户下的各个对象类别的数量校验
SQL> select OWNER,OBJECT_TYPE,count(OBJECT_NAME) from dba_objects where owner in ('ICPSP') group by OBJECT_TYPE,owner order by 1,3,2;查看表记录数
--新增count_rows 函数
CREATE OR REPLACE FUNCTION count_rows (
table_name IN varchar2,
owner IN varchar2 := NULL
)
RETURN number AUTHID current_user
AS
num_rows number;
stmt varchar2(2000);
BEGIN
IF owner IS NULL THEN
stmt := 'select count(*) from "' || table_name || '"';
ELSE
stmt := 'select count(*) from "' || owner || '"."' || table_name || '"';
END IF;
EXECUTE IMMEDIATE stmt INTO num_rows;
RETURN num_rows;
END;
/
--调用count_rows 函数,统计各种表的记录数
select table_name, count_rows(table_name) nrows from user_tables where tablespace_name='ICPSP'
order by nrows desc;目标端
对象数量和表记录数可在KDTS迁移任务查看,新版统计准确率很高。
时间允许可通过sql两种方式比对。
查看对象数量
SELECT
object_type,
count
FROM (
SELECT 'tablename' AS object_type, COUNT(*) FROM pg_tables where schemaname = 'public'
UNION ALL
SELECT 'viewname', COUNT(*) FROM pg_views where schemaname = 'public'
UNION ALL
SELECT 'matviewname', COUNT(*) from pg_matviews where schemaname = 'public'
UNION ALL
SELECT 'indexname', COUNT(*) from pg_indexes where schemaname = 'public'
UNION ALL
SELECT 'sequencename', COUNT(*) from pg_sequences where schemaname = 'pubic'
UNION ALL
SELECT 'function', COUNT(*) FROM pg_proc WHERE pronamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
UNION ALL
SELECT 'type', COUNT(*) FROM pg_type WHERE typnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
UNION ALL
SELECT 'constraint', COUNT(*) FROM pg_constraint WHERE connamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public')
UNION ALL
SELECT 'trigger', COUNT(*) FROM pg_trigger WHERE tgrelid IN (SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = 'public'))
) AS objects;查看表记录数
执行以下sql,由于表名的排序和Oracle不一样,需要再通过excel表进行下比对。
cat tablecount.sh
#!/bin/bash
# 需要统计的表名数组
TABLES=(
"t2"
"public.t3" # 支持带schema的表
)
# 遍历统计
for TABLE in "${TABLES[@]}"; do
# 执行查询并提取结果
COUNT=$(ksql -d test -U system -c "SELECT COUNT(*) FROM $TABLE;" | awk '/^[[:space:]]*[0-9]+[[:space:]]*$/{print $1}')
# 结果格式化输出
echo "${TABLE}:" "$COUNT"
done总结
至此,单点到集群迁移完成。非信创到信创迁移在网络条件不达标的情况下可以采用非常规办法:直接迁移数据目录,Centos7.9 X86架构上的文件是可以直接迁移到不同国产操作系统arm架构上直接使用的,银河麒麟和统信都已操作过。但是需要注意的是不要直接传输数据目录,因为小文件比较多存在时长不好预估的情况。




