使用DTS迁移工具迁移oracle到DM
文章目录
- 1概述
- 2Oracle数据迁移
- 2.1迁移前准备
- 2.1.1源端信息统计
- 2.1.1.1确定迁移的用户和对象个数
- 2.1.1.2查看源端的字符集、大小写敏感参数
- 2.1.2目标端信息收集与设置
- 2.1.2.1数据库初始化信息查询
- 2.1.2.2设置oracle兼容性参数
- 2.2迁移前评估
- 2.3目标端创建表空间与用户
- 2.4迁移
- 2.4.1创建迁移并连接源端和目标端
- 2.4.2配置获取对象的方式和迁移策略
- 2.4.3进行表定义和注释迁移
- 2.4.4进行表数据迁移
- 2.4.5进行主键、索引和约束迁移
- 2.4.6非表对象迁移
- 2.5数据对比
- 2.5.1简单对比
- 2.5.2DTS对比
- 2.6更新统计信息
- 2.8迁移问题处理
- 2.8.1迁移表定义和注释阶段
- 2.8.1.1DEFAULT约束表达式无效
- 2.8.2迁移主键、索引和约束阶段
- 2.8.2.1表中已存在这样的唯一关键字或主键
- 2.8.3无效的链接名
1概述
使用在非DM数据库迁移到DM数据库可以使用DTS迁移工具进行迁移,迁移的总体思路就是在DM端初始化一个数据库初始化参数相同的实例,然后评估数据量如果数据量比较大(大于100G)的话建议分批进行迁移,迁移完成后处理迁移过程中遇到的错误问题,在完成全部错误问题处理后,进行数据比对并更新统计信息。
在迁移数据前需要确认源端源端是静止的,不然迁移后的数据比对可能对不上。接着是根据源端的数据库类型设置对应的数据库兼容参数,并且确定迁移的对象数量。
建议迁移顺序:(如果有大表也可以先迁移大表)
(1)表定义和注释的迁移
(2)表数据的迁移
(3)索引约束主键的迁移
(4)非表对象的迁移
2Oracle数据迁移
2.1迁移前准备
目标端数据库在迁移前已经初始化好了,在迁移前需要先明确以下信息。
2.1.1源端信息统计
2.1.1.1确定迁移的用户和对象个数
本次迁移以迁移TEST用户的数据。
通过以下SQL可以判断迁移的对象个数:
select owner,object_type,count(*)
from all_objects
where OWNER = 'TEST' -- oracle不限定用户的话执行不出来
group by owner,object_type
order by owner,object_type;-- 或者改查dba_objects:
select owner,object_type,count(*)
from dba_objects
group by owner,object_type
order by owner,object_type;

2.1.1.2查看源端的字符集、大小写敏感参数
本次迁移以迁移TEST用户的数据。
通过以下SQL可以判断迁移的对象个数:
-- 方法1:
select value from nls_database_parameters where PARAMETER='NLS_CHARACTERSET';
-- 方法2:
select userenv('language') from dual;

可以看到源端是GBK。
在Oracle中表名、字段名、函数名是不区分大小写的,但是表中的数据是区分大小写的,也就是说查某个字段为a的记录可以查出A和a两种记录。也可以通过以下SQL进行查询:
SELECT parameter, value
FROM nls_database_parameters
WHERE parameter IN ('NLS_SORT', 'NLS_COMP');

NLS_SORT参数:排序规则,BINARY:区分大小写;BINARY_CI:不区分大小写;
NLS_COMP参数:比较规则,BINARY:区分大小写;ANSI:不区分大小写;
2.1.2目标端信息收集与设置
2.1.2.1数据库初始化信息查询
目标端的达梦数据库在初始化的时候一般是参照源端oracle的字符集和大小写敏感参数进行初始化。在迁移前在目标端查一下数据库的初始化信息,因为如果源端和目标端的字符集不一样的话迁移的时候需要进行批量放大,否则字段会超长。
SELECT '页大小',cast(PAGE()/1024 as varchar) union all SELECT '簇大小',cast(SF_GET_EXTENT_SIZE() as varchar) union all
SELECT '字符集',CASE SF_GET_UNICODE_FLAG() WHEN '0' THEN 'GBK18030' WHEN '1' then 'UTF-8' when '2' then 'EUC-KR' end union all
SELECT '大小写敏感',cast(SF_GET_CASE_SENSITIVE_FLAG() as varchar) union all
select 'VARCHAR类型长度是否以字符为单位',para_value from v$dm_ini where para_name='LENGTH_IN_CHAR' union all
select '空格兼容模式',para_value from v$dm_ini where para_name='BLANK_PAD_MODE' union all
select '实例名称' 数据库选项,INSTANCE_NAME 数据库集群相关参数值 FROM v$instance union all
select '数据库名',name from v$database union all
select '端口号',para_value from v$dm_ini where para_name='PORT_NUM' union all
select '数据库版本1',substr(svr_version,instr(svr_version,'(')) FROM v$instance union all
select '数据库版本2', id_code from dual union all
select '数据库模式',MODE$ from v$instance union all
SELECT '数据库兼容模式', para_value FROM v$dm_ini WHERE para_name='COMPATIBLE_MODE' union all
select '唯一魔数',cast(permanent_magic as varchar) union all
select 'LSN',cast(cur_lsn as varchar) from v$rlog union all
select 'KEY文件属性', cluster_type from v$license union all
SELECT '日志文件大小',TO_CHAR(RLOG_SIZE/1024/1024) FROM V$RLOGFILE;

2.1.2.2设置oracle兼容性参数
修改参数前先查看参数值并进行备份:
select name,value from v$parameter where name in('USE_PLN_POOL','CALC_AS_DECIMAL','ORDER_BY_NULLS_FLAG','COMPATIBLE_MODE','NUMBER_MODE','VIEW_ACCESS_MODE','SUBQ_EXP_CVT_FLAG','DATETIME_FMT_MODE','DATETIME_FAST_RESTRICT','XA_COMPATIBLE_MODE','PL_SQLCODE_COMPATIBLE'
);

兼容Oracle数据库模式建议修改以下参数:
alter system set 'USE_PLN_POOL'=1 spfile;
alter system set 'CALC_AS_DECIMAL'=2 spfile; --科学计算法
alter system set 'ORDER_BY_NULLS_FLAG'=1 both;
alter system set 'COMPATIBLE_MODE' = 2 spfile;
alter system set 'NUMBER_MODE'=1 spfile;--解决float聚合SUM函数小数太长问题
alter system set 'VIEW_ACCESS_MODE'=1 spfile;--指定视图的自主访问控制机制。0:兼容 DM;1:兼容 ORACLE
alter system set 'SUBQ_EXP_CVT_FLAG'=201 both;
alter system set 'DATETIME_FMT_MODE'=0 both;-- 1:19-7月-22 12.09.23. 上午 0: 2022-06-18 00:09:11
alter system set 'DATETIME_FAST_RESTRICT'=0 both; --0的时候可以对时间做to_date
alter system set 'XA_COMPATIBLE_MODE'=1 both;
alter system set 'PL_SQLCODE_COMPATIBLE'=1 spfile;
修改参数后需要重启数据库实例服务。
2.2迁移前评估
如果源端是DM数据库的话大致是可以通过以下查询来判断数据量的:
-- 查询全库数据量:
select db_used_space/1024.0/1024/1024*page GB;
-- 对象个数
select owner,object_type,count(*)
from all_objects group by owner,object_type
order by owner,object_type;
其他数据库可以查表空间或者数据文件大小来评估,也可以使用DTS工具里面的评估功能,迁移前评估一下迁移的对象数和兼容情况。
新建评估:

输入源端信息和数据库版本、需要评估的模式:

然后选择一直点下一步就好了:

然后进行评估等待评估结果。
对于不兼容的可以双击查看并筛选:

上面的内容是oracle在DBMS_JOB创建的定时作业不支持迁移:

这些定时作业可以在迁移之后通过达梦的语法重新进行创建。
扩展:如果要指定oracle的驱动可以从oracle的安装目录下获取对应的jdbc驱动:
# 查询oracle安装目录
echo $ORACLE_HOME
# 也可以直接搜
find / -name "ojdbc*.jar" 2>/dev/null
2.3目标端创建表空间与用户
确定源端待迁移的用户和表空间大小。
在oracle可以通过以下查询判断表空间大小:
SELECT * FROM (
SELECT D.TABLESPACE_NAME,SPACE || 'M' "SUM_SPACE(M)",SPACE - NVL (FREE_SPACE, 0) || 'M' "USED_SPACE(M)",ROUND ( (1 - NVL (FREE_SPACE, 0) / SPACE) * 100, 2) || '%'"USED_RATE(%)",FREE_SPACE || 'M' "FREE_SPACE(M)"FROM ( SELECT TABLESPACE_NAME,ROUND (SUM (BYTES) / (1024 * 1024), 2) SPACEFROM DBA_DATA_FILESGROUP BY TABLESPACE_NAME) D,( SELECT TABLESPACE_NAME,ROUND (SUM (BYTES) / (1024 * 1024), 2) FREE_SPACEFROM DBA_FREE_SPACEGROUP BY TABLESPACE_NAME) FWHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME(+)
UNION ALL
SELECT D.TABLESPACE_NAME,SPACE || 'M' "SUM_SPACE(M)",USED_SPACE || 'M' "USED_SPACE(M)",ROUND (NVL (USED_SPACE, 0) / SPACE * 100, 2) || '%' "USED_RATE(%)",NVL (FREE_SPACE, 0) || 'M' "FREE_SPACE(M)"FROM ( SELECT TABLESPACE_NAME,ROUND (SUM (BYTES) / (1024 * 1024), 2) SPACEFROM DBA_TEMP_FILESGROUP BY TABLESPACE_NAME) D,( SELECT TABLESPACE_NAME,ROUND (SUM (BYTES_USED) / (1024 * 1024), 2) USED_SPACE,ROUND (SUM (BYTES_FREE) / (1024 * 1024), 2) FREE_SPACEFROM V$TEMP_SPACE_HEADERGROUP BY TABLESPACE_NAME) FWHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME(+)
ORDER BY 4 DESC)

可以看到待迁移的TEST的表空间总大小为500MB,只使用了5MB,所以可以按以下命令创建表空间:
create tablespace test datafile '/dmdata/dmdb/test01.dbf' size 512 autoextend on next 128 maxsize 1024;
创建用户并授权:
create user test identified by "密码" default tablespace test default index tablespace test;
grant resource,public,vti,soi,svi to test;
2.4迁移
DTS工具位于安装目录的tool目录下,Linux启动方式:(服务器需要支持图形化界面)
cd /home/dmdba/dmdbms/tool
./dts
迁移的时候建议分批迁移特别是数量比较大的情况下
2.4.1创建迁移并连接源端和目标端
新建工程后,右击【迁移】新建迁移:





2.4.2配置获取对象的方式和迁移策略
可以根据本机cpu设置并行度。如果源端和目标端字符集相同就不需要设置批量放大,字符串长度默认就好了,但是本次迁移源端oracle的字符集是GBK,达梦是UTF-8所以建议还是放大两倍;如果源端有非法的日期格式字符串这里也可以设置统一进行转换;

点击【更多】还可以设置字符集转换并发读取等设置:

2.4.3进行表定义和注释迁移
选择需要迁移的模式,再勾选“表”:

选择要迁移的表,之后点击转换:先不要勾选主键!

等待迁移完成:

迁移完成后查看是否有失败任务,处理完成后再进行下一步的迁移。

2.4.4进行表数据迁移
建议在表定义和注释迁移完成后,在同一个工程下创建一个新的迁移单独处理表数据的迁移,后续有问题也可以溯源和查看历史迁移情况。后续的迁移同样也是创建新的迁移。
迁移对象还是只勾选表:

迁移策略时只勾选迁移数据:

等待迁移完成:

2.4.5进行主键、索引和约束迁移
迁移对象还是只勾选表。
迁移策略时只勾选迁移数据:

等待迁移完成:

2.4.6非表对象迁移
迁移对象除了“创建模式”和“表”不勾选,其他都勾选:

选择转换的时候源库存在的类型不一样的话显示的设置内容也不一样,不要像以前一样设置一次就点下一步了。

一般不需要单独设置这些内容,所以勾选后点击下一步就好了。
如果是重新迁移的话就需要每类对象设置存在的时候先“先删除”;
等待迁移完成:

2.5数据对比
2.5.1简单对比
可以直接通过对象个数初步判断是否完成迁移:
源端(oracle)查询:
select owner,object_type,count(*)
from all_objects
where OWNER = 'TEST' -- TEST为迁移的用户
group by owner,object_type
order by owner,object_type;

目标端(DM)查询:
select owner,object_type,count(*)
from all_objects
where owner = 'TEST'
group by owner,object_type
order by owner,object_type;


发现索引对不上,是两倍,更新了统计信息也是。
其实是达梦数据库和Oracle在索引的组织方式上存在差异,Oracle:默认创建堆表。达梦默认是索引组织表,主键本身就是通过一个聚簇索引(DM默认是逻辑ROWID号创建聚集索引)。
SELECT owner, index_name, index_type, table_name, uniqueness
FROM all_indexes
WHERE owner = 'TEST'
ORDER BY table_name,index_name;
查询结果可以看到很多:index_type为CLUSTER的聚集性主键索引:

这些聚集性索引查dba_ind_columns表是查不到定义的,所以如果要对比迁移过来的索引数量可以剔除这些再查一遍就准确了:
SELECT count(*)
FROM all_indexes
WHERE owner = 'TEST'
and index_type != 'CLUSTER'
ORDER BY table_name,index_name;

2.5.2DTS对比
DTS自带数据比对功能,在迁移完成后,可以比对数据。
新建比对:

输入源端和目标端信息后,选择模式:

添加原表示是源库作为标准去对比目标库:

等待比对完成:

查看对比报告:

只有表定义不一致一般没有什么问题,因为前面批量放大过或者DM有些类型做了转换:

2.6更新统计信息
在迁移完成后需要在目标端更新统计信息,统计信息更新完成后数据库才可以使用:
DBMS_STATS.GATHER_SCHEMA_STATS('TEST',100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
2.7编译无效对象
迁移完成后虽然再DTS中没有报错,但是再目标端查看是有无效对象的:


然后再处理这些无效对象。
2.8迁移问题处理
2.8.1迁移表定义和注释阶段
2.8.1.1DEFAULT约束表达式无效
迁移报错:


双击查看详情:

因为源端是GBK,一个中文字符占2个字节,本质还是值超过定义的长度了,UTF-8字符集一个中文字符是3个字节导致的报错。

将这个表结构拿出来直接在目标端执行还是会报错的:

解决方式:重新迁移表结构,在迁移策略出指定字符放大倍数:

迁移过去后再目标端查看该表结构可以看到:

2.8.2迁移主键、索引和约束阶段
2.8.2.1表中已存在这样的唯一关键字或主键
解决:
前面迁移表定义和注释的时候勾选了主键导致的冲突:

查看一下是不是报错的同类型的问题,如果是的话就不需要处理了。
2.8.3无效的链接名
Oracle数据库有dblink用法,通过dblink就可以查全称数据库(即不是当前数据库中的对象),查询语法如下:
select * from 表名@数据库链接名;
其实和普通的select语句不一样的就是多了一个指定dblink的语法,然后就可以查远程数据库了。
扩展:
在oracle有两种方式创建dblink,方法一:配置tnsnames.ora并在里面编写对应远程数据库的别名等信息,然后使用以下命令创建dblink:
create public database link link_name
connect to username identified by password
using 'connect_string';
-- link_name是连接名字,可以自定义
-- username是登陆数据库的用户名
-- password是登陆数据库的用户密码
-- connect_string是数据库连接字符串,即配置在tnsnames.ora的定义的远程数据库别名
方法二:直接通过语法创建,比如创建一个到IP为192.168.30.18,实例名为orcl并且用户名为test密码为oracle的dblink:
create public database link link_local_orcl
connect to test identified by oracle
using '(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.30.181 )(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = orcl)
)
)';
如果迁移后有以下的无效对象:

说明是dblink失效了,要查看一下源库这个dblink是怎么定义的,如果那个远程的数据库可以连上则需要在目标端也创建相同的dblink到同一个数据库。
查询数据库的所有dblink:
select * from dba_db_links;
在目标端创建:
CREATE OR REPLACE PUBLIC LINK "LINK_LOCAL_ORCL"
CONNECT 'ORACLE' WITH TEST IDENTIFIED BY "oracle"
USING '(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.30.181 )(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = orcl)
)
)';
注意:用户名要大写且不能带引号,否则报错:“-6033: DBLINK连接丢失”!
验证:

方法一(推荐):到Oracle官网下载对应架构的instantclient客户端,上传服务器然后把后的解压路径加入到dmdba的LD_LIBRARY_PATH中;
(文件:instantclient-basic-linux.x64-19.28.0.0.0dbru.zip)
[dmdba@localhost.localdomain:/home/dmdba]$ cd /soft/
[dmdba@localhost.localdomain:/soft]$ mkdir /dmdata/oci
[dmdba@localhost.localdomain:/soft]$ unzip instantclient-basic-linux.x64-19.28.0.0.0dbru.zip -d /dmdata/oci[dmdba@localhost.localdomain:/soft]$ vi /home/dmdba/.bash_profile
在原有的LD_LIBRARY_PATH后面加上,注意前面有一个冒号
:/dmdata/oci/instantclient_19_28
[dmdba@localhost.localdomain:/soft]$ source /home/dmdba/.bash_profile
[dmdba@localhost.localdomain:/home/dmdba/dmdbms/bin]$ cp /dmdata/oci/instantclient_19_28/libclntsh.so.11.1 /home/dmdba/dmdbms/bin/libclntsh.so
[dmdba@localhost.localdomain:/home/dmdba/dmdbms/bin]$ ll libclntsh.so
-rwxr-xr-x 1 dmdba dinstall 82874352 10月 26 03:39 libclntsh.so
[dmdba@localhost.localdomain:/home/dmdba/dmdbms/bin]$ ldd libclntsh.so
# 然后重启数据库
方法二:把ORACLEHOME/lib目录的so文件拷贝到ORACLE_HOME/lib目录的so文件拷贝到ORACLEHOME/lib目录的so文件拷贝到DM_HOME/bin目录后再把需要的版本的libclntsh.so.11.1文件链接到libclntsh.so(Oracle 11g客户端:使用 libclntsh.so.11.1)重启达梦数据库:
[root@localhost ~]# mkdir /soft/oracle_so
[root@localhost ~]# chmod -R 755 /soft/oracle_so/
[root@localhost ~]# chown -R oracle:oinstall /soft/oracle_so/
[root@localhost ~]# su - oracle
[oracle@localhost ~]$ cd $ORACLE_HOME/lib
[oracle@localhost lib]$ pwd
/database/oracle/oracle/product/11g/db_1/lib
[oracle@localhost lib]$ cp *.so /soft/oracle_so/
[oracle@localhost lib]$ du -sh /soft/oracle_so/
270M /soft/oracle_so/
[oracle@localhost lib]$ scp -P 22 -r /soft/oracle_so/ root@192.168.30.175:/soft/
复制过去后到达梦数据库所在服务器175上执行:
[root@localhost.localdomain:/root]# chown -R dmdba:dinstall /soft/oracle_so/
[root@localhost.localdomain:/root]# chmod -R 755 /soft/oracle_so/
[root@localhost.localdomain:/root]# su - dmdba
[dmdba@localhost.localdomain:/home/dmdba]$ cd /soft/oracle_so/
[dmdba@localhost.localdomain:/soft/oracle_so]$ cp *.so $DM_HOME/bin
[dmdba@localhost.localdomain:/soft/oracle_so]$ cd $DM_HOME/bin/
[dmdba@localhost.localdomain:/home/dmdba/dmdbms/bin]$ chmod +x *.so
[dmdba@localhost.localdomain:/home/dmdba/dmdbms/bin]$ ldd libocci.so linux-vdso.so.1 => (0x00007ffefb08f000)libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00007fd69f4f8000)libm.so.6 => /usr/lib64/libm.so.6 (0x00007fd69f1f6000)libgcc_s.so.1 => /usr/lib64/libgcc_s.so.1 (0x00007fd69efe0000)libc.so.6 => /usr/lib64/libc.so.6 (0x00007fd69ec12000)/lib64/ld-linux-x86-64.so.2 (0x00007fd69fafc000)
[dmdba@localhost.localdomain:/home/dmdba/dmdbms/bin]$ ldd libclntsh.so linux-vdso.so.1 => (0x00007ffd067e3000)libnnz11.so (0x00007ff16dae1000)libdl.so.2 => /usr/lib64/libdl.so.2 (0x00007ff16d8dd000)libm.so.6 => /usr/lib64/libm.so.6 (0x00007ff16d5db000)libpthread.so.0 => /usr/lib64/libpthread.so.0 (0x00007ff16d3bf000)libnsl.so.1 => /usr/lib64/libnsl.so.1 (0x00007ff16d1a5000)libc.so.6 => /usr/lib64/libc.so.6 (0x00007ff16cdd7000)libaio.so.1 => /usr/lib64/libaio.so.1 (0x00007ff16cbd5000)/lib64/ld-linux-x86-64.so.2 (0x00007ff1704d4000)
[dmdba@localhost.localdomain:/home/dmdba/dmdbms/bin]$ ./DmServicedmdb restart
达梦社区地址:https://eco.dameng.com/
