1、环境描述
2、DTS概述
1.支持视图、存储过程/函数、包、类、同义词、触发器等对象迁移;
2.支持数据类型的自动映射,编码转换;
3.支持根据条件自定义迁移部分数据;
4.向导式迁移步骤,上手简单;
5.支持 web 端操作、监控;
6.支持迁移评估。
3、DTS典型应用场景
1.支持全量静态数据迁移,无法实现数据增量迁移方式;
2.为保障迁移全量数据的一致性,需要充足的业务系统停机窗口;
3.迁移过程中,源端数据库不能有数据变更以及对象变更。
4、数据库调研
4.1源端Oracle数据库调研
4.1.1迁移对象统计
select a.username, (select count(1) from dba_tables b where b.owner = a.username) table_num,
( SELECT COUNT(1) FROM DBA_INDEXES I WHERE UNIQUENESS = 'UNIQUE' AND OWNER =A.USERNAME OR INDEX_NAME NOT LIKE 'SYS_%' AND OWNER =A.USERNAME) index_num,
(select count(distinct c.table_name)
from dba_tab_partitions c
where c.table_owner = a.username) part_num,
(select count(1)
from dba_tab_cols d
where d.OWNER = a.username
and d.DATA_TYPE like '%LOB%') lob_num,
(select sum(e.bytes) / 1024 / 1024 / 1024
from dba_extents e
where exists (select 1
from dba_lobs f
where f.owner = a.username
and f.segment_name = e.segment_name)) lob_space,
(select count(1) from dba_views g where g.OWNER = a.username) view_num,
(select count(1) from dba_triggers h where h.owner = a.username) trig_num,
(select count(DISTINCT I.NAME)
from DBA_SOURCE I
WHERE I.OWNER = A.username
AND I.TYPE = 'FUNCTION') fun_num,
(select COUNT(1)
FROM DBA_SEQUENCES j
WHERE j.sequence_owner = A.username) seq_num,
(select count(1) from dba_synonyms where owner= A.username) syn,
(select COUNT(1) FROM DBA_MVIEWS K WHERE K.owner = A.username) mv_num,
(select count(DISTINCT l.NAME)
from DBA_SOURCE L
WHERE L.OWNER = A.username
AND L.TYPE = 'PROCEDURE') stor_num,
(select COUNT(1) FROM DBA_DB_LINKS M WHERE M.owner = A.username) dblink_num,
(select max(n.DATA_LENGTH)
from dba_tab_cols n
where n.OWNER = a.username) max_length,
(select SUM(O.DATA_LENGTH)
from dba_tab_cols o
where o.OWNER = a.username
and o.DATA_TYPE not like '%LOB%') max_row_wide
from dba_users a where username in ('HR');
4.1.2迁移数据量统计
select distinct segment_type,sum(BYTES)/1024 /1024 /1024 , COUNT(*)
FROM DBA_SEGMENTS
where owner = 'HR' group by segment_type order by 2 desc;
4.1.3字符集信息统计
SQL> SELECT value FROM NLS_Database_Parameters WHERE PARAMETER='NLS_NCHAR_CHARACTERSET';
VALUE
-------------------------
AL16UTF16
SQL> select userenv('language') from dual;
USERENV('LANGUAGE')
----------------------------------------------------
AMERICAN_AMERICA.AL32UTF8
4.1.4是否已字节为单位
SQL> Show parameter NLS_LENGTH_SEMANTICS;
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
nls_length_semantics string BYTE
SQL> select PRIVILEGE from dba_sys_privs WHERE GRANTEE='HR';
PRIVILEGE
----------------------------------------
CREATE DATABASE LINK
ALTER SESSION
CREATE VIEW
UNLIMITED TABLESPACE
CREATE SESSION
CREATE SEQUENCE
CREATE SYNONYM
7 rows selected.
4.1.5对象权限调研
SQL> select * from dba_tab_privs WHERE GRANTEE='HR';
GRANTEE OWNER TABLE_NAME GRANTOR PRIVILEGE GRA HIE COM TYPE INH
--------------- --------------- --------------- --------------- --------------- --- --- --- --------------- ---
HR SYS DBMS_STATS SYS EXECUTE NO NO NO PACKAGE NO
4.1.6表空间信息调研
select ee.username,dd.* from (select aa.*, bb.file_name, cc.NEXT_EXTENT
from (select tbs_used_info.tablespace_name,
tbs_used_info.alloc_mb,
tbs_used_info.used_mb,
tbs_used_info.max_mb,
tbs_used_info.free_of_max_mb,
tbs_used_info.used_of_max || '%' used_of_max_pct
from (select a.tablespace_name,
round(a.bytes_alloc / 1024 / 1024) alloc_mb,
round((a.bytes_alloc - nvl(b.bytes_free, 0)) / 1024 / 1024) used_mb,
round((a.bytes_alloc - nvl(b.bytes_free, 0)) * 100 /
a.maxbytes) used_of_max,
round((a.maxbytes - a.bytes_alloc +
nvl(b.bytes_free, 0)) / 1048576) free_of_max_mb,
round(a.maxbytes / 1048576) max_mb
from (select f.tablespace_name,
sum(f.bytes) bytes_alloc,
sum(decode(f.autoextensible,
'YES',
f.maxbytes,
'NO',
f.bytes)) maxbytes
from dba_data_files f
group by tablespace_name) a,
(select f.tablespace_name, sum(f.bytes) bytes_free
from dba_free_space f
group by tablespace_name) b
where a.tablespace_name = b.tablespace_name(+)) tbs_used_info
order by tbs_used_info.used_of_max desc) aa,
dba_data_files bb,
dba_tablespaces cc
where aa.tablespace_name = bb.tablespace_name
and aa.tablespace_name = cc.tablespace_name) dd
right join dba_users ee on dd.tablespace_name=ee.default_tablespace
where ee.username in ('HR');
select *
from (select owner, tablespace_name, sum(b) KB
from (select owner,
t.segment_name,t.partition_name,round(bytes / 1024 , 2) b,tablespace_name
from dba_segments t)
where owner in ('HR')
group by owner,tablespace_name);
4.2目标端DM数据库调研
根据实际需求安装部署相应的DM数据库版本。
5、迁移评估
[dmdba@lei2 ~]$ cd /dmdba/dmdbms/tool/
[dmdba@lei2 tool]$ export DISPLAY=192.168.0.200:0.0
[dmdba@lei2 tool]$ ./dts
Xlib: extension "RANDR" missing on display "192.168.0.200:0.0".
6、制定迁移计划
根据待移植的 Oracle 系统信息分析的情况,制定迁移计划:先对整库进行一次性迁移,再对迁移失败的或不兼容的对象进行手动迁移。
先在目标端DM数据库创建相应的表空间、用户并赋权。
SQL> create user hr identified by hrhrhrhrhr default tablespace dmhr;
操作已执行
已用时间: 4.317(毫秒). 执行号:604.
SQL> grant resource,VTI to hr;
操作已执行
已用时间: 1.490(毫秒). 执行号:605.
7、迁移数据库
将ORACLE中的HR用户迁移至DM数据库中的HR用户。
8、数据验证
8.1源端对象及数据统计
create table table_count (owner varchar(100),table_name varchar(100),cnt int);
declare
v_owner VARCHAR2(100);
v_tabname VARCHAR2(100);
stmt VARCHAR2(200);
num_rows number;
begin
for rec in (select owner,table_name from dba_tables where owner='HR' order by 1, 2)
loop
select rec.owner,rec.table_name into v_owner,v_tabname from dual;
stmt := 'select count(*) from "' || v_owner || '"."' || v_tabname || '"';
EXECUTE IMMEDIATE stmt INTO num_rows;
EXECUTE IMMEDIATE 'insert into table_count values('''||v_owner||''','''||v_tabname||''','''||to_number(num_rows)||''')';
end loop;
end;
/
SQL> select * from table_count;
OWNER TABLE_NAME CNT
--------------- --------------- ----------
HR COUNTRIES 25
HR DEPARTMENTS 27
HR EMPLOYEES 107
HR JOBS 19
HR JOB_HISTORY 10
HR LOCATIONS 23
HR REGIONS 4
7 rows selected.
8.2源端各对象的数量统计
SELECT
A.USERNAME ,
(SELECT COUNT(1) FROM DBA_TABLES B WHERE B.OWNER = A.USERNAME) table_num,
( SELECT COUNT(1) FROM DBA_VIEWS G WHERE G.OWNER = A.USERNAME ) view_num,
(SELECT COUNT(1) FROM DBA_MVIEWS K WHERE K.OWNER = A.USERNAME) mv_num,
( SELECT COUNT(1) FROM DBA_TRIGGERS H WHERE H.OWNER = A.USERNAME ) tri_num,
( SELECT COUNT(DISTINCT I.NAME) FROM DBA_SOURCE I WHERE I.OWNER = A.USERNAME AND I.TYPE = 'FUNCTION' ) fun_num,
( SELECT COUNT(1) FROM DBA_SEQUENCES J WHERE J.SEQUENCE_OWNER = A.USERNAME ) seq_num,
( SELECT COUNT(DISTINCT L.NAME) FROM DBA_SOURCE L WHERE L.OWNER = A.USERNAME AND L.TYPE = 'PROCEDURE' ) stor_num,
( SELECT COUNT(1) FROM DBA_DB_LINKS M WHERE M.OWNER = A.USERNAME ) link_num,
( SELECT COUNT(1) FROM DBA_INDEXES I WHERE UNIQUENESS = 'UNIQUE' AND OWNER =A.USERNAME OR INDEX_NAME NOT LIKE 'SYS_%' AND OWNER =A.USERNAME) idx_num,
( SELECT COUNT(1) FROM DBA_OBJECTS WHERE OBJECT_TYPE='TYPE' AND OWNER =A.USERNAME ) other,
( SELECT COUNT(1) FROM DBA_OBJECTS WHERE OBJECT_TYPE='PACKAGE' AND OWNER =A.USERNAME) pkg_num
FROM
DBA_USERS A WHERE A.USERNAME IN ('HR');
8.3目标端对象及数据统计
create table table_count (owner varchar(100),table_name varchar(100),cnt int);
declare
v_owner VARCHAR2(100);
v_tabname VARCHAR2(100);
stmt VARCHAR2(200);
num_rows number;
begin
for rec in (select owner,table_name from dba_tables where owner='HR' order by 1, 2)
loop
select rec.owner,rec.table_name into v_owner,v_tabname from dual;
stmt := 'select count(*) from "' || v_owner || '"."' || v_tabname || '"';
EXECUTE IMMEDIATE stmt INTO num_rows;
EXECUTE IMMEDIATE 'insert into table_count values('''||v_owner||''','''||v_tabname||''','''||to_number(num_rows)||''')';
end loop;
end;
/
SQL> select * from table_count;
行号 OWNER TABLE_NAME CNT
---------- ----- ----------- -----------
1 HR COUNTRIES 25
2 HR DEPARTMENTS 27
3 HR EMPLOYEES 107
4 HR JOBS 19
5 HR JOB_HISTORY 10
6 HR LOCATIONS 23
7 HR REGIONS 4
7 rows got
已用时间: 0.372(毫秒). 执行号:610.
SQL> select * from table_count;
行号 OWNER TABLE_NAME CNT
---------- ----- ----------- -----------
1 HR COUNTRIES 25
2 HR DEPARTMENTS 27
3 HR EMPLOYEES 107
4 HR JOBS 19
5 HR JOB_HISTORY 10
6 HR LOCATIONS 23
7 HR REGIONS 4
7 rows got
已用时间: 0.372(毫秒). 执行号:610.
8.4目标端各对象的数量统计
SELECT
A.USERNAME "用户名",
(SELECT COUNT(1) FROM DBA_TABLES B WHERE B.OWNER = A.USERNAME) "表数量",
( SELECT COUNT(1) FROM DBA_VIEWS G WHERE G.OWNER = A.USERNAME ) "视图数量",
( SELECT COUNT(1) FROM DBA_TRIGGERS H WHERE H.OWNER = A.USERNAME ) "触发器数量",
( SELECT COUNT(DISTINCT I.NAME) FROM DBA_SOURCE I WHERE I.OWNER = A.USERNAME AND I.TYPE = 'FUNCTION' ) "函数数量",
( SELECT COUNT(1) FROM DBA_SEQUENCES J WHERE J.SEQUENCE_OWNER = A.USERNAME ) "序列数量",
( SELECT COUNT(DISTINCT L.NAME) FROM DBA_SOURCE L WHERE L.OWNER = A.USERNAME AND L.TYPE = 'PROCEDURE' ) "存储过程数量",
( SELECT COUNT(1) FROM DBA_DB_LINKS M WHERE M.OWNER = A.USERNAME ) "DBLINK数量",
( SELECT COUNT(1) FROM DBA_INDEXES I WHERE UNIQUENESS = 'UNIQUE' AND OWNER =A.USERNAME OR INDEX_NAME NOT LIKE 'INDEX335%' AND OWNER =A.USERNAME) "索引数量",
( SELECT COUNT(1) FROM DBA_OBJECTS WHERE OBJECT_TYPE='TYPE' AND OWNER =A.USERNAME OR OBJECT_TYPE='CLASS' AND OWNER =A.USERNAME ) "自定义类型",
( SELECT COUNT(1) FROM DBA_OBJECTS WHERE OBJECT_TYPE='PACKAGE' AND OWNER =A.USERNAME) "PKG数量"
FROM
DBA_USERS A WHERE A.USERNAME IN ('HR');
9、迁移完成后续工作
9.1统计信息收集
SQL> DBMS_STATS.GATHER_SCHEMA_STATS( 'HR',100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
DMSQL 过程已成功完成
已用时间: 164.834(毫秒). 执行号:612.
9.2数据库备份
迁移完成后,建议对数据库做一次全量备份。
9.3应用迁移
应用迁移、连接串修改、驱动修改等。
更多内容请参考:https://eco.dameng.com