代码改变世界

XTTS系列之一:U2L迁移解决方案之XTTS的使用

2019-07-28 18:27 AlfredZhao 阅读(...) 评论(...) 编辑 收藏

本系列的定位是对XTTS及相关技术进行深入的学习研究。作为本系列的开篇,本着实用性的原则,我先把一次实际生产环境U2L的迁移实战实施方案进行提炼简化,旨在能清楚说明该如何使用XTTS这种解决方案来进行U2L迁移,先达到可以跟着做下来的初级目标,如果有兴趣再去深入研究相关细节。

1.XTTS概述

采用XTTS(Cross Platform Transportable Tablespaces)迁移方式,准确说这里指的是加强版XTTS,具备跨平台字节序转换、全量初始化、多次增量前滚的功能,从而有效缩短正式迁移阶段的生产停机时间,顺利完成U2L的迁移工作。比如本次需求如下:

源端 目标端
IP地址 10.6.xx.xx 10.5.xx.xx
操作系统 AIX 5.3 RHEL 6.7
是否RAC
数据库名称 sourcedb targetdb
迁移业务用户 JINGYU JINGYU

2.迁移准备阶段

2.1 校验自包含

本次只迁移 JINGYU 用户,只检查 JINGYU 用户所在表空间的自包含验证即可:

SQL> select distinct tablespace_name from dba_segments where owner='JINGYU' order by 1; 

TABLESPACE_NAME 
------------------------------ 
DBS_D_JINGYU 
DBS_I_JINGYU

SQL> execute dbms_tts.transport_set_check('DBS_D_JINGYU, DBS_I_JINGYU');
PL/SQL procedure successfully completed. 

SQL> select * from TRANSPORT_SET_VIOLATIONS; 
no rows selected

上述查询若没有结果行返回,说明自包含校验通过。

2.2 创建XTTS工作目录
本次我设置的XTTS的工作目录是/exp/newxx,在源端和目标端都创建相关目录,上传并解压MOS(文档 ID 1389592.1)提供的xttconvert脚本。

--源端AIX创建相关目录
mkdir -p  /exp/newxx
mkdir -p  /exp/newxx/src_backup
mkdir -p  /exp/newxx/tmp
mkdir -p  /exp/newxx/dump
mkdir -p  /exp/newxx/backup_incre
chown -R ora103:dba /exp/newxx

--源端AIX上传rman-xttconvert_2.0.zip至/exp/newxx
cd /exp/newxx
unzip rman-xttconvert_2.0.zip

--目标端Linux创建相关目录
mkdir -p  /exp/newxx
mkdir -p  /exp/newxx/src_backup
mkdir -p  /exp/newxx/tmp
mkdir -p  /exp/newxx/dump
mkdir -p  /exp/newxx/backup_incre
chown -R ora11g:dba /exp/newxx

--目标端Linux上传rman-xttconvert_2.0.zip至/exp/newxx
cd /exp/newxx
unzip rman-xttconvert_2.0.zip

2.3 源端开启 bct
源端开启bct(block change tracking)

SQL> alter database enable block change tracking using file '/exp/newxx/bct2'; 
Database altered.

如果测试阶段发现bct无法生效(增量备份时间很长),可考虑手工进行一次表空间的0级备份:

--手动以level 0进行备份待迁移的表空间(只是为了增量可读bct,不做其他恢复操作)
RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 16 BACKUP TYPE TO BACKUPSET;
RMAN> backup incremental level 0 tablespace DBS_D_JINGYU, DBS_I_JINGYU format '/exp/test/%U.bck';

注:这是特殊情况,不一定会遇到,根据你的实际测试情况选择是否要做。本次大概2T的表空间0级备份时间:2h。

2.4 配置 xtt.properties

配置源端AIX xtt.properties属性文件:

cd /exp/newxx
vi xtt.properties

#增加如下配置信息:
tablespaces=DBS_D_JINGYU,DBS_I_JINGYU
platformid=6
dfcopydir=/exp/newxx/src_backup
backupformat=/exp/newxx/backup_incre
backupondest=/exp/newxx/backup_incre
stageondest=/exp/newxx/src_backup
storageondest=+DG_DATA/targetdb/datafile
parallel=16
rollparallel=16
getfileparallel=6

配置目标端Linux xtt.properties属性文件:

cd /exp/newxx
vi xtt.properties

#增加如下配置信息:
tablespaces=DBS_D_JINGYU,DBS_I_JINGYU
platformid=6
dfcopydir=/exp/newxx/src_backup
backupformat=/exp/newxx/backup_incre
backupondest=/exp/newxx/backup_incre
stageondest=/exp/newxx/backup_incre
storageondest=+DG_DATA/targetdb/datafile
parallel=16
rollparallel=16
getfileparallel=6
asm_home=/opt/app/11.2.0/grid
asm_sid=+ASM1

注:这里的platformid=6是根据源端的OS平台决定的,可以通过查询v$database的platform_id字段进行确认,也可参照v$transportable_platform中的平台对应。

2.5 目标端提前建立用户角色
目标端创建JINGYU用户,完成元数据导入后才可修改默认表空间。
以下是在源端执行获取创建用户和对应角色、权限的语句后,在目标端对应创建(如果你很清楚要迁移业务用户的用户密码和权限等信息,也可以选择直接创建):

--源端执行:
--create user
sqlplus -S / as sysdba
set pages 0
set feedback off
spool /exp/newxx/scripts/create_user.sql
select 'create user '||name||' identified by values '''||password||''';' from user$ where name = 'JINGYU' and type#=1;
spool off
exit

--create role
sqlplus -S / as sysdba
set pages 0
set feedback off
spool /exp/newxx/scripts/create_role.sql
select 'grant '||GRANTED_ROLE||' to '||grantee||';' from dba_role_privs where grantee = 'JINGYU';
spool off
exit

--owner为sys的表的权限需要手动赋予
sqlplus -S / as sysdba
set pages 0
set feedback off
spool /exp/newxx/scripts/grant_sys_privs.sql
select 'grant '||PRIVILEGE||' on '||owner||'.'||table_name||' to '||GRANTEE||';' from dba_tab_privs where owner='SYS'  and GRANTEE = 'JINGYU';
spool off
exit

--源端验证SQL正确与否:
cat /exp/newxx/scripts/create_user.sql
cat /exp/newxx/scripts/create_role.sql
cat /exp/newxx/scripts/grant_sys_privs.sql

--目标端执行:
@/exp/newxx/scripts/create_user.sql
@/exp/newxx/scripts/create_role.sql
@/exp/newxx/scripts/grant_sys_privs.sql

2.6 表空间全量备份
源端AIX执行被传输业务表空间全量备份创建xtts表空间全量备份脚本执行过程中产生的配置文件,用于数据文件转换及每次增量备份及恢复,同时每次执行增量备份过程中,配置文件内容会发生变化,用于新的增量恢复,主要是SCN的变化。
增加rman备份并行度:

RMAN> CONFIGURE DEVICE TYPE DISK PARALLELISM 16 BACKUP TYPE TO BACKUPSET;

编辑备份文件,每次备份失败会在/exp/newxx/tmp产生fails文件需要删除后方可再次运行

cd /exp/newxx
--full_backup.sh脚本内容如下
export ORACLE_SID=sourcedb
export TMPDIR=/exp/newxx/tmp
export PERL5LIB=/opt/app/ora103/10.2.0/product/perl/lib
/opt/app/ora103/10.2.0/product/perl/bin/perl /exp/newxx/xttdriver.pl -p –d

在后台执行全量备份:

cd /exp/newxx
nohup sh full_backup.sh > full_backup.log &

查看/exp/newxx/src_backup产生的全量备份大小(本次测试大小为 2T,备份耗时 4小时34分钟)

2.7 表空间全量恢复及转换
将文件传输至目标端

cd /exp/newxx/src_backup
scp * ora11g@10.5.xx.xx:/exp/newxx/src_backup
--scp拷贝耗时10小时
cd /exp/newxx/tmp
scp * ora11g@10.5.xx.xx:/exp/newxx/tmp

目标端 Linux 执行表空间恢复并将数据文件转换至 ASM 磁盘组中,每次恢复失败时会在/exp/newxx/tmp 产生 fails 文件需要删除后方可再次运行(详见下面3.2节的特别说明)。

cd /exp/newxx
--full_restore.sh脚本内容如下
export TMPDIR=/exp/newxx/tmp
export ORACLE_SID=targetdb1
/opt/app/ora11g/product/11.2.0/perl/bin/perl /exp/newxx/xttdriver.pl -c –d

在后台执行全量恢复及转换:

nohup sh full_restore.sh > full_restore.log &

本次恢复及转换耗时:4 小时15分钟。

3.增量前滚阶段

3.1 表空间增量备份
源端进行增量备份:

cd /exp/newxx
--增量备份脚本incre_backup.sh内容如下
export ORACLE_SID=sourcedb
export TMPDIR=/exp/newxx/tmp
export PERL5LIB=/opt/app/ora103/10.2.0/product/perl/lib
/opt/app/ora103/10.2.0/product/perl/bin/perl /exp/newxx/xttdriver.pl -i –d

在后台执行增量备份:

cd /exp/newxx
nohup sh incre_backup.sh > incre_backup.log &

增量备份前确认xtt.properties文件配置正确,增量备份耗时几分钟,说明bct起作用了。

--(选做)第二次做一个测试验证表:
SQL> create table JINGYU.xttstest tablespace DBS_D_JINGYUas SELECT * FROM DBA_objects;
Select count(1) from JINGYU.xttstest;

将文件传输至目标端:

cd /exp/newxx/backup_incre
scp *_1_1 ora11g@10.5.xx.xx:/exp/newxx/backup_incre
cd /exp/newxx/tmp
scp * ora11g@10.5.xx.xx:/exp/newxx/tmp

3.2 表空间增量恢复
目标端进行增量恢复:

cd /exp/newxx
--incre_recover.sh脚本内容如下
export TMPDIR=/exp/newxx/tmp
export ORACLE_SID=targetdb1
/opt/app/ora11g/product/11.2.0/perl/bin/perl /exp/newxx/xttdriver.pl -r –d

在后台执行增量恢复:

nohup sh incre_recover.sh > incre_recover.log &

特别说明:
1.以上增量前滚的步骤在正式迁移前可重复执行多次,用于对目标库进行多次表空间增量恢复,使目标端数据库在正式迁移前与生产数据库近乎一致,大幅减少迁移停机时间。
2.每次备份(全量和增量)成功后,源端/exp/newxx/tmp目录中会生成文件,需要将此目录下的所有文件传输到/exp/newxx/tmp下(每次覆盖即可)
3.每次备份(全量和增量)后,/exp/newxx/tmp目录中会生成最新的xttplan.txt.new文件,该文件中记录了各表空间最新的scn,需要将旧的xttplan.txt文件在每次增量恢复前linux端进行如下改名操作:
cd /exp/newxx/tmp
mv xttplan.txt xttplan.old1.txt
mv xttplan.txt.new xttplan.txt

4.正式迁移阶段

4.1 表空间read only
应用侧停止业务后,数据库层面复查确认没有用户会话连接;
源端AIX将被传输业务表空间修改为READ ONLY状态:

sqlplus -S / as sysdba
set pages 0
set feedback off
spool /exp/newxx/scripts/read_only.sql
select 'alter tablespace '||name||' read only;' from v$tablespace where name in ('DBS_D_JINGYU','DBS_I_JINGYU') order by 1;
spool off
exit

cat /exp/newxx/scripts/read_only.sql 
@/exp/newxx/scripts/read_only.sql

4.2 最后一次增量操作
按照前面 增量前滚阶段的方法,完成最后一次增量备份与恢复。
本次测试,最后一次增量备份时间用时 21 分钟。

4.3 目标端开启闪回
目标端Linux开启在导入元数据前开启闪回

SQL> alter system set db_recovery_file_dest_size=100g scope=both;
System altered.

SQL> alter system set db_recovery_file_dest='+DG_DATA' scope=both;
System altered.

SQL> alter database flashback on;
Database altered.

SQL> select flashback_on from v$database;
FLASHBACK_ON
------------------
YES

SQL> create restore point before_imp_xtts guarantee flashback database;
Restore point created.

SQL> select name from v$restore_point;
确认有刚建立的restore point。

4.4 导入XTTS元数据
4.4.1 AIX源端导出XTTS元数据:

create directory dump as '/exp/newxx/dump';

导出表空间、用户元数据:

--导出表空间元数据(vi expdp_xtts.sh)
expdp system/oracle parfile=expdp_xtts.par
--expdp_xtts.par内容如下:
directory=dump
dumpfile=tbs_xtts.dmp
logfile=expdp_xtts.log
transport_tablespaces=('DBS_D_JINGYU','DBS_I_JINGYU')
transport_full_check=y
metrics=yes

--导出用户元数据(vi expdp_xtts_other.sh)
expdp system/oracle parfile=expdp_xtts_other.par
--expdp_xtts_other.par内容如下
directory=dump
dumpfile=tbs_xtts_other.dmp
logfile=expdp_xtts_other.log
content=metadata_only
schemas=JINGYU
metrics=yes

执行导出表空间、用户元数据的脚本:

cd /exp/newxx/dump
./expdp_xtts.sh
./expdp_xtts_other.sh

导出完成后将dump文件传输到目标端/exp/newxx/dump目录

cd /exp/newxx/dump
scp *.dmp ora11g@10.5.108.28:/exp/newxx/dump

4.4.2 LINUX目标端导入XTTS元数据:
创建directory:

create or replace directory dump as '/exp/newxx/dump';

导入XTTS元数据:

--导入XTTS元数据(vi impdp_xtts.sh)
impdp system/oracle parfile=impdp_xtts.par
--impdp_xtts.par内容如下:
directory=dump
logfile=impdp_xtts.log
dumpfile=tbs_xtts.dmp
cluster=n
metrics=yes
transport_datafiles='+DG_DATA/targetdb/DATAFILE/DBS_D_JINGYU.290.976290433',
'+DG_DATA/targetdb/DATAFILE/DBS_I_JINGYU.286.976290433'

注意:上面数据文件路径需要根据实际导入情况更改。

执行导入XTTS元数据的脚本:

cd /exp/newxx/dump
./impdp_xtts.sh
SQL> select count(1) from JINGYU.xttstest;
正常返回结果.

执行完成后,同时验证成功。

4.5 表空间read write
LINUX目标端表空间read write:

sqlplus -S / as sysdba
set pages 0
set feedback off
spool /exp/newxx/scripts/read_write.sql
select 'alter tablespace '||name||' read write;' from v$tablespace where name in ('DBS_D_JINGYU','DBS_I_JINGYU') order by 1;
spool off
exit 

cat /exp/newxx/scripts/read_write.sql
@/exp/newxx/scripts/read_write.sql

4.6 第二次开启闪回
目标端Linux在其他元数据导入前再次开启闪回

sqlplus / as sysdba
select flashback_on from v$database;
create restore point before_imp_other guarantee flashback database;
select name from v$restore_point;

4.7 导入其他元数据
导入其他元数据

--导入其他元数据(vi impdp_xtts_other.sh)
impdp system/oracle parfile=impdp_xtts_other.par 
--impdp_xtts_other.par 内容如下
directory=dump 
dumpfile=tbs_xtts_other.dmp
logfile=impdp_xtts_other.log 
content=metadata_only
schemas=JINGYU
cluster=n
metrics=yes

执行导入其他元数据的脚本:

cd /exp/newxx/dump
./impdp_xtts_other.sh

4.8 检查public dblink
原生产环境查询public dblink,若有结果,到新生产环境创建:

--原生产环境查询:
select * from dba_db_links;
OWNER                          DB_LINK                        USERNAME                       HOST                           CREATED
------------------------------ ------------------------------ ------------------------------ ------------------------------ -------------------
JINGYU                          XXX_TMP                        JINGYU                          xxdb                          2008-05-20 09:51:14

select dbms_metadata.get_ddl('DB_LINK',DB_LINK,'JINGYU') FROM DBA_DB_LINKS where owner='JINGYU';

CREATE DATABASE LINK "XXX_TMP"
   CONNECT TO "JINGYU" IDENTIFIED BY VALUES '056414CFC01C4F42E2E496B913FDC0212A'
   USING 'xxdb';

--连接到JINGYU用户创建即可,开始没有权限:
grant create database link to JINGYU;

4.9 检查public synonyms
原生产环境查询public synonyms,若有结果,到新生产环境创建:

select owner,SYNONYM_NAME,TABLE_OWNER,TABLE_NAME from dba_synonyms where owner='PUBLIC' and table_owner in ('JINGYU');

本次无结果。

4.10 检查外部表
原生产环境查询外部表信息,若有结果,到新生产环境创建:

SQL> select * from dba_external_tables;

本次无结果。

4.11 数据比对
源环境和目标环境分别查询比对:

set linesize 200
set pagesize 9999
col owner format a15
col object_type format a15
select owner, object_type, count(*)
  from dba_objects
 where object_name not like 'BIN%'
   and owner in ('JINGYU')
 group by owner, object_type
 order by 1,2 desc;

OWNER           OBJECT_TYPE       COUNT(*)
--------------- --------------- ----------
JINGYU           VIEW                     2
JINGYU           TABLE PARTITION         25
JINGYU           TABLE                   49
JINGYU           SEQUENCE                 4
JINGYU           PROCEDURE                5
JINGYU           INDEX PARTITION        225
JINGYU           INDEX                   55
JINGYU           FUNCTION                 3
JINGYU           DATABASE LINK            1

9 rows selected.

4.12 编译失效对象
查询失效对象数量,按对象类型分组统计:

sqlplus / as sysdba
set timing on
select owner, object_type, count(*)
  from dba_objects
 where status <> 'VALID'
   and owner in ('JINGYU')
 group by owner, object_type
 order by 1, 2 desc;

OWNER           OBJECT_TYPE       COUNT(*)
--------------- --------------- ----------
JINGYU           PROCEDURE                1
JINGYU           FUNCTION                 1

--查看具体失效对象,比对源端、目标端:
set linesize 200
set pagesize 9999
col owner format a15
col object_type format a15
col OBJECT_NAME for a32
select owner,object_name, object_type, status
  from dba_objects
 where status <> 'VALID'
   and owner in ('JINGYU') order by 2;

OWNER           OBJECT_NAME                      OBJECT_TYPE     STATUS
--------------- -------------------------------- --------------- -------
JINGYU           XXXXCITY                         FUNCTION        INVALID
JINGYU           TAB_MAINTAIN_XXX                 PROCEDURE       INVALID

编译失效对象(若两边失效对象一致可不做)
exec utl_recomp.recomp_parallel(64);

4.13 更改用户默认表空间
由于表空间比用户晚创建,需要手动更改默认表空间:

alter user JINGYU default tablespace DBS_D_JINGYU;
select username,default_tablespace,temporary_tablespace from dba_users where username='JINGYU';

4.14 删除闪回点

确认本次迁移成功后,手动删除闪回点

--(选做)此时可以先删除之前的测试表:
drop table JINGYU.xttstest;

--手动删除闪回点:
drop restore point BEFORE_IMP_XTTS;
drop restore point before_imp_other;
select name from v$restore_point;

--关闭闪回数据库的功能:
SQL> alter database flashback off;

Database altered.

SQL> select flashback_on from v$database;

FLASHBACK_ON
------------------
NO

SQL> alter system set db_recovery_file_dest='' sid='*' scope=both;

System altered.

4.15 修改service参数
手动修改和用户同名的service参数:

--service_names参数保持和源端一致:
show parameter service_names
alter system set service_names ='dbaas','targetdb','jingyursv', 'jingyu' sid='*' scope=both;
alter system register;

检查监听注册情况:

--本次环境使用的非默认监听,名字是targetdb:
lsnrctl status targetdb

5.其他注意事项

收集了公司同事在其他项目实际进行XTTS迁移项目的经验,再结合本次自己实施过程中遇到的情况,列举了XTTS相关的其他注意事项(欢迎大家继续补充自己做XTTS时踩过的坑和对应的经验分享):

  • 1.使用XTTS迁移所需时间根据情况不同所花费时间也不同,每次都需要评估好停机时间;
  • 2.XTTS迁移速度主要在于元数据的导出导入时间(无法使用并行),对象数越多导入导出越慢;
  • 3.导入过程中检查是否有其他用户建在导出用户表空间上的索引,此种索引无法在自包含检查中检测出来,所以应在全量备份前进行检查。提前处理此种对象,我这次没有遇到:
  /*查询表空间中对象的详细信息*/
  SELECT OWNER                  AS OWNER
       ,SEGMENT_NAME           AS SEGMENT_NAME
       ,SEGMENT_TYPE           AS SEGMENT_TYPE
     ,SUM(BYTES)/1024/1024   AS SEGMENT_SIZE
  FROM DBA_SEGMENTS
  WHERE TABLESPACE_NAME in ('DBS_D_JINGYU','DBS_I_JINGYU') and owner <> 'JINGYU'
  GROUP BY OWNER,SEGMENT_NAME,SEGMENT_TYPE
  ORDER BY 4;
  • 4.使用XTTS迁移数据库必须每套数据库都进行测试,并生成细致操作文档(由于每个数据库每个用户对象之间的关联关系不同,再倒入元数据的时候相互依赖关系可能比较难梳理。必须提前做测试进行梳理);
  • 5.XTTS目标段必须有11.2.0.4的软件进行数据文件转换,源端最低为10G数据库;
  • 6.XTTS在目标段做全量以及增量恢复时,会重启运行恢复脚本的实例(如果目标端数据库还有其他业务用户属于生产运行,尤其要注意这点);
  • 7.本次测试遇到因源库数据文件名称包含特殊字符导致表空间全量备份缺失文件且日志不报任何错误,在恢复阶段才发现缺少文件,所以建议以后准备工作多加一项数据文件数量的检查比对:
  select count(1) from dba_data_files where tablespace_name in ('DBS_D_JINGYU','DBS_I_JINGYU');
  --本次迁移数据文件数量135,与表空间全量备份出来的文件数量进行对比确认一致。

关于第7项,我实际遇到并在测试环境进行了重现,具体可参考之前的随笔: