【迁移】使用XTTS-V3(DBMS_FILE_TRANSFER)数据迁移

2021-04-22 17:20:40 浏览数 (1)

生产上遇到一个迁移场景,大概1T数据量左右,由于没用XTTS做过迁移,所以准备尝试一下,本次迁移采用XTTS(增强传输表空间) V3版本的DBMS_FILE_TRANSFER方式。

一、源库及目标库情况

从目标库及源库情况来看,选用XTTS并不是个好选择。XTTS主要还是用在跨平台、跨版本且数据量大的场景下,当前的场景:服务器间网络传输速率高用DataPump的netlink方式最简单,用DG停机时间可以做到最短。

源库

目标库

IP地址

10.0.11.XXX

10.0.14.XXX

系统版本

CentOS 5.7

CentOS Linux release 7.6.1810 (Core)

数据库版本

11.2.0.3.0

11.2.0.4.181016 (28204707)

字符集

AL32UTF8

AL32UTF8

实例名

XKORG

XKORG

CPU

16

16

内存(GB)

32

32

数据量GB

1000

要迁移的表空间:USERS、ORCLTBS

二、文档及脚本

mos 1389592.1

使用rman_xttconvert_v3.zip脚本

文档及脚本放到网盘中,公众号回复XTTS获取网盘地址

三、迁移流程

3.1 前置条件检查

XTTS使用限制较多,V3版本按照本节逐项检查

3.1.1 目标库操作系统不能为Window

源库:CentOS 5.7 目标库:CentOS Linux 7.6.1810

3.1.2 源库必须在10.2.0.3 版本或以上

代码语言:javascript复制
sqlplus -v

源库版本:Release 11.2.0.3.0 Production

3.1.3 源库的compatible 兼容性参数在 10.2.0 或以上

代码语言:javascript复制
show parameter compatible

检查结果:11.2.0.0.0

3.1.4 源库的compatible 参数必须不能比目标库大(向下兼容)

代码语言:javascript复制
show parameter compatible

源库:11.2.0.0.0 目标库:11.2.0.4.0

3.1.5 源库必须处于归档模式

代码语言:javascript复制
archive log list

检查结果:已在归档模式下

3.1.6 目标库必须是11.2.0.4或以上

代码语言:javascript复制
sqlplus -v

检查结果:11.2.0.4.0

3.1.7 rman备份策略应该是备份到disk

检查结果:

3.1.8 rman备份不能启用压缩

代码语言:javascript复制
show all

检查结果:

代码语言:javascript复制
CONFIGURE DEVICE TYPE DISK PARALLELISM 1 BACKUP TYPE TO BACKUPSET; # default

3.1.9 要被传输的表空间必须是online不能包含离线的数据文件

代码语言:javascript复制
select file_name,online_status from dba_data_files t where t.online_status not in ('ONLINE','SYSTEM');
代码语言:javascript复制
select tablespace_name,status from dba_tablespaces t where t.status<> 'ONLINE';

检查结果:均为online状态

3.1.10 源库和目标库字符集需要保持一致(包括国家字符集)

代码语言:javascript复制
select * from nls_database_parameters t where t.parameter in ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');

检查结果:源库、目标库均为:

3.1.11 目标库db_files参数必须大于源库

代码语言:javascript复制
show parameter  db_files

源库:200 目标库:200 目标库不符合要求,修改

代码语言:javascript复制
alter system set db_files=500 scope=spfile;

3.1.12 确定SYS及SYSTEM下是否存在业务对象

见3.2.2

3.1.13 SYS、SYSTEM 用户是否有对象存在于业务表空间

见3.2.2

3.1.14 检查是否存在外部表

代码语言:javascript复制
SELECT DISTINCT owner FROM DBA_EXTERNAL_TABLES;
select owner, TABLE_NAME, DEFAULT_DIRECTORY_OWNER, DEFAULT_DIRECTORY_NAME from DBA_EXTERNAL_TABLES;

检查结果:

3.1.15 检查表加密列信息加密表空间

代码语言:javascript复制
SELECT owner, table_name, COUNT(*) FROM DBA_ENCRYPTED_COLUMNS GROUP BY owner, table_name;
SELECT tablespace_name, ENCRYPTED FROM dba_tablespaces WHERE ENCRYPTED = 'YES';

检查结果:

3.1.16 检测数据库时区、TIMEZONE,保证源库目标库一致

代码语言:javascript复制
select dbtimezone from dual;
select name,value$ from props$ where name ='DST_PRIMARY_TT_VERSION';

检查结果:源库、目标库均为

3.1.17 源库开启块跟踪,并修改bct隐藏参数

代码语言:javascript复制
alter database enable block change tracking using file '/u02/data/XKORG/trace.log';
select status, filename from v$block_change_tracking;
alter system set "_bct_bitmaps_per_file"=100;

启动BCT后,XTTS使用tracking file里的信息,只需要读取改变的数据块信息,而不用再对全部数据文件进行扫描,从而提高了XTTS增量备份的性能。

3.1.18 目标库UNDO表空间配置

搞大点

代码语言:javascript复制
select * from v$dbfile;
alter database  datafile 3  resize 32766m;

3.1.19 目标库TEMP表空间配置

代码语言:javascript复制
alter tablespace TEMP add tempfile '/oradata/datafile/XKORG/temp02.dbf' size 20G autoextend on;

3.1.20 目标库USER表空间配置··

需要传输的表空间中包含USER,需要将目标库USER替换为users_back

代码语言:javascript复制
create tablespace users_back datafile '/oradata/datafile/XKORG/users_back.dbf' size 10m;
alter database default tablespace users_back;
drop tablespace users;

3.1.21 源库创建用户表

创建一个单独的用户表,这个表里面存放的是要迁移的用户,在checkobject(迁移完检查源库目标库对象是否一致)脚本与导入临时表的脚本中都会用到这个表create_migrate_useranme.sql

代码语言:javascript复制
@/home/oracle/xtts_scripts/create_migrate_username.sql
代码语言:javascript复制
--脚本内容
CREATE TABLE SYSTEM.migrate_username
AS
   SELECT username
     FROM dba_users
    WHERE username NOT IN ('ANONYMOUS',
                           'APEX_030200',
                           'APEX_PUBLIC_USER',
                           'APPQOSSYS',
                           'CTXSYS',
                           'DBSNMP',
                           'DIP',
                           'EXFSYS',
                           'FLOWS_FILES',
                           'MDDATA',
                           'MDSYS',
                           'MGMT_VIEW',
                           'OLAPSYS',
                           'ORACLE_OCM',
                           'ORDDATA',
                           'ORDPLUGINS',
                           'ORDSYS',
                           'OUTLN',
                           'OWBSYS',
                           'OWBSYS_AUDIT',
                           'SCOTT',
                           'SI_INFORMTN_SCHEMA',
                           'SPATIAL_CSW_ADMIN_USR',
                           'SPATIAL_WFS_ADMIN_USR',
                           'SYS',
                           'SYSMAN',
                           'SYSTEM',
                           'WMSYS',
                           'XDB',
                           'XS$NULL',
                           'GGADM',
                           'SPA');

3.1.22 主机hosts文件配置

将源库/ete/hosts文件内容复制到目标环境中

以上条件全部满足,则具备迁移的前置条件

3.2 初始化设置阶段

3.2.1 目标库安装数据库软件并创建数据库,软件版本不小于源库

检查结果:已按要求安装软件并创建数据库,实例名同源库

3.2.2 检查表空间是否自包含

代码语言:javascript复制
execute dbms_tts.transport_set_check('USERS,ORCLTBS',true);
select * from transport_set_violations;

我在迁移时候出现非自包含情况,检查发现有分区表及索引存储在SYSTEM表空间中,需要将这部分数据首先移动到业务表空间,详见:【迁移】Oracle分区表及索引迁移表空间(https://www.modb.pro/db/42030) 迁移完成后,检查结果如下:

3.2.3 创建以下对象

  1. 源端创建复制数据库对象的目录(源库被传输的数据文件存放位置)
代码语言:javascript复制
create directory source_dir as '/u02/data/XKORG/';
  1. 目标端创建存放数据库对象的目录(目标库最终数据文件存放位置)
代码语言:javascript复制
create directory dest_dir as '/oradata/datafile/XKORG/';

3.2.4 目标库创建DBLINK

代码语言:javascript复制
create public database link to_old connect to system identified by oracle using '(DESCRIPTION =
(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = 10.0.11.XXX)(PORT = 1521)))
(CONNECT_DATA = (SERVICE_NAME = XKORG))
)';

验证是否创建成功

代码语言:javascript复制
select * from dual@to_old;

3.2.5 源库目录创建

代码语言:javascript复制
mkdir /home/oracle/xtts
chown -R oracle:dba /home/oracle/xtts/

上传官方脚本 rman_xttconvert_v3.zip 文件到xtts目录下,并授权

代码语言:javascript复制
cd /home/oracle/xtts/
unzip rman_xttconvert_v3.zip

3.2.6 编辑xtt.properties配置文件

修改如下参数

代码语言:javascript复制
tablespaces= USERS,ORCLTBS              --要迁移的表空间名称
platformid=13                             --select platform_id from v$database;
srcdir = SOURCE_DIR                       --dft时使用,源库存放数据文件的路径
dstdir = DEST_DIR                         --dft时使用,目标库存放数据文件的路径
srclink=to_old                            --目标库创建的DBLINK
backupformat=/home/oracle/xtts/bakincr    --源端用于存放增量备份的路径
stageondest=/home/oracle/xtts/bak         --目标端存放数据文件副本目录,和存放增量备份目录     
backupondest=/home/oracle/xtts/bak        --目标端增量备份的最终存放目录
parallel= 8
rollparallel= 8                           --增量备份的并行度
getfileparallel= 8                        --获取文件的并行度

说明:在v$transportable_platform视图中标记了platformid对应的platformname及字节序

源端创建目录

代码语言:javascript复制
mkdir -p /home/oracle/xtts/bakincr
mkdir -p /home/oracle/xtts/bak

chown oracle:dba /home/oracle/xtts/bakincr
chown oracle:dba /home/oracle/xtts/bak

目标端创建目录

代码语言:javascript复制
mkdir -p /home/oracle/xtts/bak

3.2.7 源端和目标端设置TMPDIR

Oracle用户环境变量

代码语言:javascript复制
$export TMPDIR=/home/oracle/xtts

3.2.8 源端将/home/oracle/xtts 下所有文件传给目标端

代码语言:javascript复制
scp -P 10011 /home/oracle/xtts/*  10.0.14.XXX:/home/oracle/xtts/

3.3 准备阶段

在这个阶段,表空间数据文件会从源库传输到目标库,并且会做一个自动的字节格式的转换。这个步骤只需要做一次。在此阶段,源端数据库可以正常进行访问。

下图为官方脚本功能说明:

3.3.1 源库执行以下命令

代码语言:javascript复制
[oracle@source]$ nohup $ORACLE_HOME/perl/bin/perl xttdriver.pl -S &

这个命令会执行以下动作:

  • 确认表空间是 online,read write 模式,不包含 offline 数据文件
  • 创建两个文件:xttnewdatafiles.txt,getfile.sql

3.3.2 将第一步产生的两个文件传到目标端

代码语言:javascript复制
scp -P 10011 xttnewdatafiles.txt getfile.sql 10.0.14.XXX:/home/oracle/xtts/

3.3.3 目标端执行以下命令

代码语言:javascript复制
[oracle@dest]$ nohup $ORACLE_HOME/perl/bin/perl xttdriver.pl -G &

当这一步完成,数据文件将会被传输到目标端最终位置,并且被目标库使用,可见数据文件出现在目标库数据文件存放目录下,相当于将一份全备应用到了目标库。

3.4 前滚阶段

在这个阶段中,源库会创建一个增量备份,传输到备库。并且会转换为目标库字节格式,并应用于目标库。这个阶段可以运行多次,每一个成功的增量备份所花的时间应该比之前的要少,并且使目标库的数据与源库更接近。

3.4.1 源库创建表空间的增量备份集

代码语言:javascript复制
nohup perl xttdriver.pl -i &

这个命令会对传输的表空间产生一个增量备份集。备份集位于 backupformat 目录下。并且会产生两个文件:tsbkupmap.txt,incrbackups.txt

3.4.2 传输增量备份集到目标端

代码语言:javascript复制
scp -P 10011 'cat incrbackups.txt'  10.0.14.XXX:/home/oracle/xtts/bak/

3.4.3 转换增量备份集并应用到目标库

源端复制xttplan.txt,tsbkupmap.txt 到目标端

代码语言:javascript复制
scp -P 10011 xttplan.txt tsbkupmap.txt 10.0.14.XXX:/home/oracle/xtts/

目标端执行以下命令,应用增量备份

代码语言:javascript复制
nohup perl xttdriver.pl -r &

3.4.4 确定下次增量备份的scn

源库运行下面脚本, 确定一个新的scn, 记录在 xttplan.txt 文件中

代码语言:javascript复制
nohup perl xttdriver.pl -s &

3.4.5 重复前滚阶段(可选)

如果你需要使目标库更接近源库,则需要重复进行1-4 步骤;如果目标库已经足够接近源库,那就直接进行传输阶段。

3.5 传输阶段

在传输阶段,源库需要被设置为read only 模式,目标库会被应用最后一次增量备份。在目标数据文件一致后,将执行一次普通的传输表空间的步骤,从源库导出元数据对象并导入目标库。在此阶段结束之前,源库只能通过 read only 方式访问数据。

3.5.1 目标库导入profile

将资源控制文件profile,通过network_link方式导入目标库

代码语言:javascript复制
nohup impdp "/as sysdba"  metrics=yes network_link=to_old  include=profile  full=y content=metadata_only > profile.log 2>&1 &

3.5.2 目标库导入role

将角色通过network_link方式导入目标库

代码语言:javascript复制
nohup impdp "/as sysdba"   metrics=yes network_link=to_old include=role full=y content=metadata_only > role.log 2>&1 &

3.5.3 确认是否有新用户添加

代码语言:javascript复制
select username,created from dba_users where created in (select max(CREATED) from dba_users);

3.5.4 确认是否有新的数据文件添加

代码语言:javascript复制
select file#,name,creation_time from v$datafile where creation_time in (select max(creation_time) from v$datafile);

3.5.5 通知客户停业务

从这里开始计算停机时间

3.5.6 源库清理回收站数据

代码语言:javascript复制
purge dba_recyclebin;

3.5.7 导出统计信息及DBLINK

关于统计信息有两种处理方式:导出再倒入 或者 目标库重新收集。这里选择重新收集更合理一些,所以可以不导出统计信息,更节省时间。

代码语言:javascript复制
nohup expdp "/as sysdba" directory=DUMPDIR dumpfile=stat_dblink.dmp logfile=stat_dblink.log include=statistics,DB_LINK full=y &

这里的directory=DUMPDIR指向一个NAS,该NAS挂载到了源库与目标库。

3.5.8 停服务与修改JOB参数(源库/目标库)

代码语言:javascript复制
alter system set job_queue_processes=0;
show parameter job_queue_processes;

3.5.9 源库处理进程

确认无活动事务与死事务,包括分布式事务

代码语言:javascript复制
ps -ef| grep LOCAL=NO| grep -v grep| awk '{print $2}'| xargs kill -9
select local_tran_id,state from dba_2pc_pending;

3.5.10 源库创建用户与测试表,插入数据

代码语言:javascript复制
create user TEST identified by oracle default tablespace USERS;
grant connect,resource to TEST;

--create_test_table.sql 内容就是创建两个测试表,用于迁移完验证是否在目标库也能查询到
@/home/oracle/xtts_scripts/create_test_table.sql

3.5.11 多次切换归档

代码语言:javascript复制
alter system switch logfile;

3.5.12 再次清空回收站

代码语言:javascript复制
purge dba_recyclebin;

3.5.13 源库将表空间设置read only

代码语言:javascript复制
alter tablespace USERS read only;
alter tablespace ORCLTBS read only;

3.5.14 源库创建最后一次增量备份集,传输、转换、应用到目标库

建议通知客户停业务之前再做一次增量备份应用,以减少数据差异,缩短停业务后的这次增量备时间

代码语言:javascript复制
nohup perl xttdriver.pl -i &
scp 'cat incrbackups.txt' 10.0.14.XXX:/home/oracle/xtts/bak/
scp xttplan.txt tsbkupmap.txt 10.0.14.XXX:/home/oracle/xtts/

3.5.15 目标端最后一次应用

代码语言:javascript复制
nohup perl xttdriver.pl -r &

3.5.16 创建用户

目标库执行脚本,通过之间创建的dblink,在目标端创建用户,脚本不是自己写的就不放出来了

代码语言:javascript复制
@/home/oracle/xtts_scripts/create_user.sql

3.5.17 给create database link权限

给上一步创建的用户加权限 grant create database link to X

代码语言:javascript复制
@/home/oracle/xtts_scripts/drm_grant_create_link.sql

3.5.18 开启数据库flashback功能

脚本内容就是开启闪回,创建restore point

代码语言:javascript复制
@/home/oracle/xtts_scripts/drm_enable_flashback.sql

3.5.19 导入对象数据到目标库

目标端执行以下命令

代码语言:javascript复制
nohup perl xttdriver.pl -e &

这个命令会产生一个DataPump 导入模板文件 xttplugin.txt 。该文件里是impdp的导入模板,编辑并执行导入 注意:

  1. 可以在impdp语句中加入exclude=TABLE_STATISTICS,INDEX_STATISTICS,排除统计信息,我们后面收集
  2. 语句中transport_datafiles可能比较多,建议放到par文件中执行
  3. 查看日志发现触发器警告,可先忽略后续编译处理
  4. 指定的dump目录第一次执行失败,查询为权限问题 给dump目录加777后解决

3.5.20 禁用FLASHBACK功能

这一步应该放到应用最终测试完成后再执行

代码语言:javascript复制
@/home/oracle/xtts_scripts/drm_disable_flashback.sql

3.5.21 查询测试表是否有数据

代码语言:javascript复制
@/home/oracle/xtts_scripts/query_test_table_data.sql

查询结果:

3.5.22 目标库设置表空间read write

代码语言:javascript复制
select tablespace_name,file_name from dba_data_files;
alter tablespace USERS read write;
alter tablespace ORCLTBS read write;
select TABLESPACE_NAME,status,CONTENTS from dba_tablespaces;

3.5.23 检查物理和逻辑块损坏,并验证数据

该步骤执行时间较长

代码语言:javascript复制
RMAN> validate tablespace USERS, ORCLTBS check logical;

3.5.24 导入数据库的元对象

代码语言:javascript复制
nohup impdp "/ as sysdba" network_link=to_old SCHEMAS='XXX','XXX' content=metadata_only TABLE_EXISTS_ACTION=SKIP exclude=table,index parallel=8 metrics=y directory=DUMPDIR > imp_meta.log 2>&1 &

3.5.25 导入临时表

代码语言:javascript复制
--源库查询无用户自定义临时表
select owner,table_name from dba_tables where TEMPORARY='Y';

如果有的话按下面语句导入
nohup impdp "/ as sysdba"  metrics=yes network_link=to_old logfile=temp_table.log schemas='XXX','XXX' include=TABLE:"" in (select table_name from dba_tables where TEMPORARY='Y')"" > imp_tmp.log 2>&1 &"

3.5.26 回收create database link权限

代码语言:javascript复制
@/home/oracle/xtts_scripts/drm_revoke_database_link.sql

3.5.27 修改用户默认表空间

还是通过dblink获取

代码语言:javascript复制
@/home/oracle/xtts_scripts/alter_user_default_tablespace.sql

Select username,default_tablespace from dba_users;

3.5.28 给角色及对象授权

代码语言:javascript复制
select 'grant '||GRANTED_ROLE||' to '||grantee||';' from dba_role_privs where grantee in(select username from dba_users where default_tablespace in ('USERS','ORCLTBS') and user_id >='84');

源库查询后,在目标库执行 对象权限、角色权限、DDL权限 后续执行checkobject.sql脚本时生成后在目标库执行即可

3.5.29 编译无效对象

代码语言:javascript复制
DECLARE 
   threads pls_integer := 150;
BEGIN 
   utl_recomp.recomp_parallel(threads); 
END;
/

3.5.30 对比对象

代码语言:javascript复制
@/home/oracle/xtts_scripts/checkobject.sql

select object_type,count(*) as num from dba_objects where owner='MAOTAI' group by object_type order by num desc;

3.5.31 收集(或导入)统计信息及DBLINK

方式1:导入统计信息及dblink 如果在3.5.7小节导出了统计信息,那么这里可以选择导入,但是时间会很长

代码语言:javascript复制
nohup impdp "/as sysdba" directory=DUMPDIR dumpfile=stat_dblink.dmp logfile=stat_dblink_i.log include=statistics,DB_LINK full=y &

方式2:手工统计

代码语言:javascript复制
select 'EXEC DBMS_STATS.GATHER_TABLE_STATS('''||owner||''','''||table_name||''',estimate_percent=>10,method_opt=>''FOR ALL COLUMNS SIZE AUTO'',degree=>12,cascade=>TRUE);' from dba_tables where owner in('schema1','schema2') ;

源库执行生成语句,编辑一个static.sql文件在目标库执行,此处是按表统计也可选择按schema统计GATHER_SCHEMA_STATS;

代码语言:javascript复制
@/home/oracle/xtts_scripts/static.sql

注意:这次迁移最占用时间的步骤来了,一开始estimate 设置为80,但是特别慢,后续改为10,也跑了3个小时才完成,后来咨询大拿,这里其实收集个0.01就可以了,也就是收集0.01%的统计信息。注意并行度16个cpu开到12。

代码语言:javascript复制
select sql_id,program,status,state,LAST_CALL_ET from v$session where program like '%P0%' and sql_id is not null order by 3

通过上述语句查询开启的并行进程,LAST_CALL_ET为该进程执行的时间 执行过程中可到v$lock 视图查询是否有锁 TM TX 如果执行过慢,可查询dba_segments bytes字段查询大小

3.5.32 收集字典表统计信息

代码语言:javascript复制
EXEC DBMS_STATS.GATHER_DICTIONARY_STATS;
EXEC DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;

3.5.33 源库查询失效对象

迁移后与目标库对比

代码语言:javascript复制
set line 1000 pages 500
col owner for a20
col object_name for a50
col object_type for a15

SELECT owner, object_name, object_type,status 
FROM dba_objects
WHERE status = 'INVALID' and owner in('schema1','schema2');

select owner,object_name,object_type,status from dba_objects@to_old where  object_name in(select object_name from dba_objects where status='INVALID' and owner!='PUBLIC');

3.5.34 目标库打开JOB

代码语言:javascript复制
alter system set job_queue_processes=1000;

3.5.35 通知切换IP

3.5.36 启动应用测试

3.5.37 防火墙策略添加

四、应急处置

XTTS迁移方式对源库变动主要是设置要迁移表空间read only,如迁移发现异常,按照如下步骤恢复:

  1. 假设服务器IP已替换,则首先需要将10.0.13.31IP重新切换到原服务器;
  2. 设置USERS、ORCLTBS表空间 read write;
代码语言:javascript复制
alter tablespace USERS read write;
alter tablespace ORCLTBS read write;
  1. 检查监听状态
  2. 通知应用启动测试

五、总结

1、实际迁移花费6个小时,消耗时间最多的是收集统计信息耗费3小时,其次是最后一次增量备占用1小时,再次是坏块检查; 2、收集统计信息部分,事后咨询专家后知道其实收集0.01%就可以; 3、设置源库表空间为read only后的增量备时间有点长,现在看应该在停业务前再应用一次增量,应该能再减少这部分时间; 4、检查物理和逻辑块损坏,并验证数据,虽然是极小概率的情况,我觉得还是不要省为好 5、脚本很强大,能省很多时间,有专家用自己写的脚本不用官方脚本

0 人点赞