购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.4 XTTS迁移升级技术

Oracle 8i引入了传输表空间特性(Transportable TableSpace,TTS),传输表空间是一种物理迁移数据库的方法,仅支持相同平台迁移,但在Oracle 10g中有所改进,可以支持跨平台迁移。由于在整个迁移过程中依然需要停机,而且停机时间长短与库的大小成正比,因此传输表空间并不是广大DBA的首选。

在小型机转X86的大趋势下,Oracle从11.2.0.4版本中开始支持跨平台增量传输表空间,XTTS(Cross Platform Transportable TableSpace)应运而生。TTS增强版的XTTS可以支持跨平台增量备份,使用增量备份的方式,可以在不中断业务的情况下进行前期的数据文件传输、数据文件转换等操作。然后通过多次增量备份恢复方式,使源端和目标端的数据差异降到最小,最终业务停机时间仅为最后一次增量备份和恢复所需的时间,整体停机时间稳定在1.5小时之内。下面就来具体演示如何使用XTTS完成跨平台迁移。

3.4.1 环境说明

源端采用AIX小型机单机架构,数据库版本为Oracle 11.2.0.4。目标端采用Linux X86 RAC架构,数据库版本为Oracle 19.3。

表3-3列举了前置条件检查的各个条目。

表3-3 前置条件检查列表

如果目标最终的数据库版本为Oracle 11.2.0.3或更低版本,则需要在目标系统上运行Oracle 11.2.0.4实例,用于执行增量备份转换。表3-4列举了当前环境的资源配置情况。

表3-4 当前环境资源配置情况

3.4.2 源端环境准备

生产库必须满足归档开启策略。

1.数据库版本检查

如果源端为Oracle 11.2.0.3的版本,那么为了避免Bug,需要安装p14192178_112030_Generic.zip补丁,解决Bug 14192178的问题,可参考文档Datapump Expdp and Impdp slow in 11.2.0.3 as a result of Queries on SYS.KU$_INDEX_VIEW KU$(文档ID:1459833.1)。

2.数据信息统计

以下是进行数据信息统计的步骤和内容。

1)检查数据库时区,命令如下:


SQL> select dbtimezone  from dual;
SQL> !date

2)检查数据库字符集,命令如下:


SQL> select *  from nls_database_parameters where parameter like '%CHARACTERSET%';

3)检查目标端补丁,命令如下:


SQL> select 'opatch',comments from dba_registry_history;

4)检查目标端数据库组件的安装情况,命令如下:


SQL> select comp_name from dba_registry;

5)检查源端是否使用了索引压缩(key compression),命令如下:


SQL> select index_name,table_name from dba_indexes where compression='ENABLE';
SQL> select owner,table_name from dba_tables where iot_type is not null;

6)检查源端是否存在同名数据文件,命令如下:


SQL> select substr(file_name,-6,2) from dba_data_files where tablespace_name=
    'TBS_NAME' order by 1;

7)检查源端compatible参数,命令如下:


SQL> show parameter compatible
<!--必须大于10.2-->

8)统计源端表空间,命令如下:


SQL> select distinct(tablespace_name) from dba_data_files;

9)统计源端需要传输的数据文件大小,命令如下:


SQL> SELECT d.FILE_ID,
d.TABLESPACE_NAME,
(SELECT (SUM(nb.BYTES/1024/1024))
FROM dba_data_files nb
WHERE nb.TABLESPACE_NAME = d.TABLESPACE_NAME) ts_size_m,
d.FILE_NAME,
(d.BYTES/1024/1024) file_size_m,
(d.USER_BYTES/1024/1024) file_use_size_m
FROM dba_data_files d
WHERE d.TABLESPACE_NAME  not in ('SYSTEM','SYSAUX','UNDOTBS1','UNDOTBS2')
ORDER BY  file_id;

10)统计需要迁移的用户,命令如下:


SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
SQL> SELECT d.username,
       d.default_tablespace,
       d.temporary_tablespace,
       d.account_status,
       d.created
  from dba_users d
 where d.account_status = 'OPEN' and d.username not like '%SYS%'
  order by d.CREATED desc;

SQL> select ''''||username||''',' from dba_users where username not like '%SYS%' and 
    account_status not like 'EXPIRED%';

11)用户权限收集,命令如下:


SQL> drop table t_tmp_user_lhr;     
SQL> create table   t_tmp_user_lhr( id number, username varchar2(50), exec_sql 
    varchar2(4000),create_type varchar2(20));
SQL> DROP  sequence   s_t_tmp_user_lhr;        
SQL> create sequence s_t_tmp_user_lhr;     
                                                       
SQL> begin                                                                              
  for cur in (SELECT d.username,        
                     d.default_tablespace, 
                     d.account_status,   
                     'create user ' || d.username || ' identified by ' ||
                     d.username || ' default tablespace ' ||
                     d.default_tablespace || '  TEMPORARY TABLESPACE  ' ||
                     D.temporary_tablespace || ';' CREATE_USER,
                     replace(to_char(DBMS_METADATA.GET_DDL('USER',
                                                   D.username)),
                             chr(10),   
                             '') create_USER1                            
                FROM dba_users d      
 WHERE d.username   in  ('业务用户名')) loop                                    
    INSERT INTO t_tmp_user_lhr         
      (id, username, exec_sql, create_type)   
    values      
      (s_t_tmp_user_lhr.nextval, cur.username, cur.CREATE_USER, 'USER');
            
    INSERT INTO t_tmp_user_lhr             
      (id, username, exec_sql, create_type)    
      SELECT s_t_tmp_user_lhr.nextval,  
             cur.username,     
             CASE            
               WHEN D.ADMIN_OPTION = 'YES' THEN     
                'GRANT ' || d.privilege || ' TO ' || d.GRANTEE ||
                ' WITH GRANT OPTION ;'   
               ELSE        
                'GRANT ' || d.privilege || ' TO ' || d.GRANTEE || ';'
             END priv,         
             'DBA_SYS_PRIVS'   
        FROM dba_sys_privs d   
       WHERE D.GRANTEE = CUR.USERNAME;   
                          
    INSERT INTO t_tmp_user_lhr   
      (id, username, exec_sql, create_type)     
      SELECT s_t_tmp_user_lhr.nextval,       
             cur.username,  
             CASE   
               WHEN D.ADMIN_OPTION = 'YES' THEN 
                'GRANT ' || d.GRANTED_ROLE || ' TO ' || d.GRANTEE ||
                ' WITH GRANT OPTION;'    
               ELSE       
                'GRANT ' || d.GRANTED_ROLE || ' TO ' || d.GRANTEE || ';'
             END priv,  
             'DBA_ROLE_PRIVS'   
        FROM DBA_ROLE_PRIVS d  
       WHERE D.GRANTEE = CUR.USERNAME;                                                                                                                                                                           
    INSERT INTO t_tmp_user_lhr     
      (id, username, exec_sql, create_type)   
      SELECT s_t_tmp_user_lhr.nextval,   
             cur.username,        
             CASE      
               WHEN d.grantable = 'YES' THEN   
                'GRANT ' || d.privilege || ' ON ' || d.owner || '.' ||   
                d.table_name || ' TO ' || d.GRANTEE || 
                '  WITH GRANT OPTION ;'  
               ELSE       
                'GRANT ' || d.privilege || ' ON ' || d.owner || '.' ||     
                d.table_name || ' TO ' || d.GRANTEE || ';'  
             END priv,           
             'DBA_TAB_PRIVS'    
        FROM DBA_TAB_PRIVS d   
       WHERE D.GRANTEE = CUR.USERNAME;    
  end loop;     
  COMMIT;   
end;          
/        
SQL> SELECT * FROM t_tmp_user_lhr; 
SQL> SELECT id,username,CREATE_TYPE,EXEC_SQL FROM t_tmp_user_lhr where 
    CREATE_TYPE not in ('USER');

12)统计用户表格的规模,命令如下:


SQL> select d.owner, (sum(bytes) / 1024 / 1024) sizes_m
  from dba_segments d
  where d.owner in ('业务用户名')
 AND NOT EXISTS (SELECT 1 FROM DBA_RECYCLEBIN B WHERE B.object_name=
     D.segment_name AND D.OWNER=B.owner)
 GROUP BY d.owner
 order by sum(bytes) desc;

13)统计用户对象的个数和类型,命令如下:


SQL> SELECT D.OWNER,COUNT(1)
  FROM dba_objects d
 WHERE d.OWNER   in ('业务用户')
 and d.OWNER not in ('PUBLIC') 
 AND NOT EXISTS (SELECT 1 FROM DBA_RECYCLEBIN B WHERE B.object_name=
     D.OBJECT_NAME AND D.OWNER=B.owner) 
 GROUP BY D.OWNER
 ORDER BY COUNT(1) desc;

SQL> SELECT D.OWNER, D.OBJECT_TYPE, COUNT(1)
   FROM dba_objects d
  WHERE d.OWNER   in ('业务用户')
    and d.OWNER not in ('PUBLIC')
    AND NOT EXISTS (SELECT 1
           FROM DBA_RECYCLEBIN B
          WHERE B.object_name = D.OBJECT_NAME
            AND D.OWNER = B.owner)
  GROUP BY D.OWNER, D.OBJECT_TYPE
  ORDER BY D.OWNER ,COUNT(1) desc;

14)备份对象信息,以方便与无效对象进行比对。

记录所有业务用户下的对象信息,命令如下:


SQL> spool invald.lst
SQL> select owner,object_name,object_type,status from dba_objects where status<>
    'VALID' and owner in ('业务用户');
SQL> select count(*),status from dba_objects where owner in ('业务用户') group by status;
SQL> spool off

创建对比表格,命令如下:


SQL> create table invalid_object_201911 as select * from dba_objects where 
    status<>'VALID';

查看业务用户的对象状态个数,命令如下:


SQL> select count(*),status from dba_objects where owner in ('业务用户') group by 
    status;

15)检查无效index,命令如下:


SQL> select owner, index_name, status from dba_indexes
where status= 'UNUSABLE' order by 1,2;
 
SQL> select i.owner, i.index_name, p.partition_name, p.status
from dba_ind_partitions p,dba_indexes i
where p.index_name=i.index_name and p.status= 'UNUSABLE'
order by 1,2,3;
 
SQL> select i.owner,i.index_name,s.subpartition_name,s.status from
dba_ind_subpartitions s,dba_indexes i where
s.index_name=i.index_name and s.status= 'UNUSABLE'
order by 1,2,3;

16)确定SYS及SYSTEM下是否存在业务对象。检查SYS和SYSTEM的重复对象,命令如下:


SQL> select object_name, object_type from dba_objects where (object_name,object_type) 
    in (select object_name,object_type from dba_objects where owner = 'SYS') and 
    owner = 'SYSTEM';

OBJECT_NAME                                    OBJECT_TYPE
--------------------------------------------   -------------------
AQ$_SCHEDULES                                  TABLE
DBMS_REPCAT_AUTH                               PACKAGE
AQ$_SCHEDULES_PRIMARY                          INDEX
DBMS_REPCAT_AUTH                               PACKAGE BODY
<!--若返回相同的内容,则表示正常-->

检查SYSTEM表空间下是否存在业务对象,命令如下:


SQL> select owner,segment_name,segment_type,tablespace_name from dba_segments 
    where tablespace_name in ('SYSTEM','SYSAUX') and owner in ('业务用户');

17)确定平台字节序,命令如下:


SQL> select tp.platform_name, tp.endian_format
  from v$transportable_platform tp
where tp.platform_name in ('Linux x86 64-bit', 'AIX-Based Systems (64-bit)');
PLATFORM_NAME                            ENDIAN_FORMAT
---------------------------------------- --------------
AIX-Based Systems (64-bit)               Big
Linux x86 64-bit                         Little

18)判断表空间是否具有自包含特性,命令如下:


SQL> execute sys.dbms_tts.transport_set_check('所有需要迁移的业务表空间',true);
SQL> select * from sys.transport_set_violations;

19)获取需要传输的表空间,命令如下:


SQL> set serveroutput on
SQL> declare 
  tsname varchar(30); 
  i number := 0; 
begin 
  dbms_output.put('tablespaces='); 
  for ts in  
    (select tablespace_name from dba_tablespaces 
     where tablespace_name not in ('SYSTEM','SYSAUX') 
       and contents = 'PERMANENT' 
     order by tablespace_name) 
  loop 
    if (i!=0) then 
      dbms_output.put_line(tsname||','); 
    end if; 
    i := 1; 
    tsname := ts.tablespace_name; 
  end loop; 
  dbms_output.put_line(tsname); 
  dbms_output.put_line(''); 
end; 
/

20)检查兼容的高级队列(Compatible Advanced Queues),命令如下:


SQL> select owner,queue_table,recipients,compatible from dba_queue_tables
where recipients= 'MULTIPLE' and compatible like '%8.0%' ;

21)检查基于XMLSchema的XMLType对象,命令如下:


SQL> SELECT distinct OWNER FROM DBA_XML_SCHEMAS;

SQL> select distinct p.tablespace_name
from dba_tablespaces p, dba_xml_tables x, dba_users u, all_all_tables t
where t.table_name=x.table_name and
      t.tablespace_name=p.tablespace_name and
      x.owner=u.username;

22)检查SPATIAL空间组件对象,命令如下:


SQL> select owner,index_name from dba_indexes
where ityp_name = 'SPATIAL_INDEX' ;

SQL> select owner, table_name, column_name
from dba_tab_columns
where data_type = 'SDO_GEOMETRY'
and owner != 'MDSYS'
order by 1,2,3;

23)检查外部表,命令如下:


SQL> select distinct owner from DBA_EXTERNAL_TABLES;

24)检查索引组织表(Index Organized Table,IOT),命令如下:


SQL> select distinct owner from dba_tables where IOT_TYPE is not null ;

25)检查临时表,命令如下:


SQL> SELECT owner,table_name FROM DBA_TABLES WHERE
TEMPORARY = 'Y' AND OWNER IN ('业务用户');

26)检查物化视图,命令如下:


SQL> select owner, count (*) from dba_mviews group by owner;

27)检查永久表空间,命令如下:


SQL> select t.TABLESPACE_NAME TABLESPACE_NAME, count (f.FILE_ID),
sum (f.bytes/1024/1024/1024) GB
FROM dba_tablespaces t, dba_data_files f
where t.TABLESPACE_NAME=f.TABLESPACE_NAME
     and t.tablespace_name not in (根据需求排除)
     and t.contents = 'PERMANENT'
group by t.TABLESPACE_NAME
order by 2;

28)检查回收站,命令如下:


SQL> select count (*) from dba_recyclebin;

29)检查是否存在用户使用TSTZ字段,命令如下:


SQL> select c.owner || '.' || c.table_name || '(' || c.column_name || ') -'
     || c.data_type || ' ' col
   from dba_tab_cols c, dba_objects o
  where c.data_type like '%WITH TIME ZONE'
     and c.owner=o.owner
    and c.table_name = o.object_name
    and o.object_type = 'TABLE'
order by col;

30)检查表空间是否加密,命令如下:


SQL> select tablespace_name,ENCRYPTED from dba_tablespaces;

31)检查是否存在加密字段,命令如下:


SQL> select * from DBA_ENCRYPTED_COLUMNS;

32)检查Opaque Types类型字段,命令如下:


SQL> select distinct owner ,DATA_TYPE from dba_tab_columns where
  owner in ('业务用户');

33)检查表空间和数据文件的状态,命令如下:


SQL> select tablespace_name,status from dba_tablespaces;
SQL> select STATUS,ONLINE_STATUS, count (*) from dba_data_files
group by STATUS,ONLINE_STATUS;

34)比对新旧环境中的profile是否一致,命令如下:


SQL> select distinct (t.pro) from
( select s.profile pro, l.profile pro2
from dba_profiles@ttslink s, dba_profiles l
where s.profile = l.profile(+)) t where t.pro2 is null
order by t.pro;

3.创建directory

在源端创建目录(directory),用于指向源端数据文件所在的位置,命令如下:


SQL> create directory sourcedir as '/dev';
SQL> grant all on directory sourcedir to public;

由于本案例中的数据文件是裸设备,所以代码中写的是/dev。

4.使用NFS配置共享文件夹

1)目标端配置。不同版本的系统开启NFS(Network File System,网络文件系统)的方法不同。

Linux 6中开启NFS的方法如下:


shell> service nfs start
shell> chkconfig nfs on

Linux 7中开启NFS的方法如下:


shell> systemctl start nfs.service
shell> systemctl enable nfs.service
shell> vi /etc/exports 
/backup 130.36.21.89(rw,sync,all_squash)
shell> exportfs –a

2)源端配置的命令如下:


shell> mount -o cio,rw,bg,hard,nointr,rsize=32768,wsize=32768,proto=tcp,noac,vers=3,
    timeo=600 132.151.59.16:/backup/bak /backup/bak

至此,源端和目标端均有/backup/bak目录了。

在源端挂载目标端网络文件系统时,在目标端/etc/exports中需要指定源端物理IP,否则会造成源端挂载失败,强烈建议挂载到二级目录,比如/backup/bak这种形式,否则可能会因为网络文件系统服务中断,而造成AIX生产端数据库服务异常。

5.准备XTTS介质

将介质“rman-xttconvert_3.0.zip”上传到生产源端的/backup/bak目录下。

6.编辑xtt.properties文件

编辑xtt.properties,添加如表3-5所示的参数内容。

表3-5 xtt.properties参数说明

对于表3-5中的第一条tablespaces参数,命令参考脚本如下:


SQL> set serveroutput on
SQL> declare 
  tsname varchar(30); 
  i number := 0; 
begin 
  dbms_output.put('tablespaces='); 
  for ts in  
    (select tablespace_name from dba_tablespaces 
     where tablespace_name not in ('SYSTEM','SYSAUX') 
       and contents = 'PERMANENT' 
     order by tablespace_name) 
  loop 
    if (i!=0) then 
      dbms_output.put_line(tsname||','); 
    end if; 
    i := 1; 
    tsname := ts.tablespace_name; 
  end loop; 
  dbms_output.put_line(tsname); 
  dbms_output.put_line(''); 
end; 
/

7.获取目标端所需创建的表空间语句

创建所有表空间语句,以用于从生产端导入所有权限及用户,相关脚本如下:


SQL> set heading off feedback off trimspool on linesize 500 
SQL> spool tts_create_ts.sql 
SQL> prompt /* ===================== */ 
SQL> prompt /* Create user tablespaces */ 
SQL> prompt /* ===================== */ 
SQL> select 'create TABLESPACE ' || tablespace_name || 
       ' DATAFILE ' ||'''+DATA/orajf/'||tablespace_name||'.dbf'''||' size 10M
           autoextend on;'
   from dba_tablespaces 
   where tablespace_name not in ('SYSTEM','SYSAUX',’USERS’) 
      and contents = 'PERMANENT'; 
SQL> prompt /* ===================== */ 
SQL> prompt /* Create user temporary tablespaces */ 
SQL> prompt /* ===================== */ 
SQL> select 'create TEMPORARY TABLESPACE ' || tablespace_name || 
       ' TEMPFILE ' ||'''+DATA/orajf/'||tablespace_name||'.dbf'''||' size 10M 
           autoextend on;'
   from dba_tablespaces 
   where tablespace_name not in ('TEMP’) 
      and contents = ''TEMPORARY''; 
SQL> spool off

3.4.3 目标端环境准备

1.安装集群创建数据库

安装Oracle 19.3集群及数据库软件。创建数据库时,原则上,数据库的名称应与生产保持一致,需要特别注意的是,字符集必须与生产保持一致,目标端同样必须满足归档开启策略。

源端和目标端数据库service_names参数设置需要保持一致,否则会造成应用连接失败的问题。

2.创建目标目录

创建目标端数据文件destdir最终所在的目录,命令如下:


SQL> create directory destdir as '+DATA/orajf/';
SQL> grant all on directory destdir to public;

3.创建DATA_PUMP_DIR

创建DATA_PUMP_DIR目录,用于导入元数据,命令如下:


SQL> create or replace directory DATA_PUMP_DIR as '/backup/bak';
SQL> grant all on directory DATA_PUMP_DIR to public;

4.创建DB_LINK

创建连接串,命令如下:


shell> vi /u01/app/oracle/product/19.3/db/network/admin/tnsnames.ora
XTTS =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 130.36.23.19)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orajf)
    )
  )

创建连接源端数据库的DBLINK,命令如下:


SQL> create public database link ttslink connect to system identified by zj130lt 
    using 'xtts';

5.创建所需的表空间

根据3.4.2节介绍的获取创建表空间文件的语句在目标端创建所需的表空间。

6.目标端导入生产库用户及权限

目标端导入生产库用户及权限的语句如下:


shell> impdp \'/ as sysdba\' DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp01.log
    NETWORK_LINK=TTSLINK FULL=y INCLUDE=USER,ROLE,ROLE_GRANT,PROFILE,function 

导入完成后,需要删除相应的表空间。需要明确的是,该操作是在目标端进行的,操作前请谨记,一定要再三确认。


SQL> set heading off feedback off trimspool on linesize 500 
SQL> spool tts_drop_ts.sql 
SQL> prompt /* ===================== */ 
SQL> prompt /* Drop user tablespaces */ 
SQL> prompt /* ===================== */ 
SQL> select 'DROP TABLESPACE ' || tablespace_name || 
       ' INCLUDING CONTENTS AND DATAFILES;' 
   from dba_tablespaces 
   where tablespace_name not in ('SYSTEM','SYSAUX',’USERS’) 
      and contents = 'PERMANENT'; 
SQL> prompt /* ===================== */ 
SQL> prompt /* Drop user temporary tablespaces */ 
SQL> prompt /* ===================== */ 
SQL> select 'DROP TABLESPACE ' || tablespace_name || 
       ' INCLUDING CONTENTS AND DATAFILES;' 
   from dba_tablespaces 
   where tablespace_name not in ('TEMP’) 
      and contents = ''TEMPORARY''; 
SQL> spool off

7.删除目标端的USERS表空间

为了保证源端的USERS表空间能够顺利传输过来,需要先删除目标端的USERS表空间,删除命令如下:


SQL> alter database default tablespace SYSAUX;
SQL> drop tablespace users including contents and datafiles;

8.设置TMPDIR

设置TMPDIR的语句如下:


源端(生产端):shell> export TMPDIR=/opt/oracle/tmp
目标端(新库):shell> export TMPDIR=/home/oracle/tmp

3.4.4 数据同步

1.数据全量传输阶段

数据全量传输可采用如下两种方式。

·Phase 2A-dbms_file_transfer Method。

·Phase 2B-RMAN Backup Method。

增量阶段应打开块跟踪,以加快速度,命令如下:


SQL> alter database enable block change tracking using file '/rman/trace.log';
SQL> select status from v$block_change_tracking;

1)生成增量所需的文件,命令如下:


shell> export TMPDIR=/opt/oracle/tmp
shell> export XTTDEBUG=1
shell> $ORACLE_HOME/perl/bin/perl xttdriver.pl -S
xttplan.txt              <!--记录数据文件SCN号-->
xttnewdatafiles.txt      <!--记录数据文件位置--> 

新生成文件需要提前备份!

2)以手动RMAN复制的方式传输文件。源端查询以下语句,复制源端数据文件至NFS共享目录/backup/bak中:


select 'copy datafile '||''''||file_name||''''||' to '||''''||'/backup/bak/'||substr
    (file_name,instr(file_name,'/',-1)+1)||'.dbf'''||';' from dba_data_files where 
    TABLESPACE_NAME  not in ('SYSTEM','SYSAUX','UNDOTBS1');

3)目标端手动修改数据文件。修改数据文件权限,命令如下:


shell> chown grid.oinstall *.dbf

查询语句在源端执行查询操作,在目标端执行convert操作,命令如下:


SQL> select 'CONVERT FROM PLATFORM '||''''||'AIX-Based Systems (64-bit)'||''''||' 
    PARALLELISM 10'||' datafile '||''''||'/backup/bak/'||SUBSTR(NAME,INSTR(NAME,
    '/',-1)+1)|| '.dbf'||''''||' format '||''''||'+DATA/orajf/'||SUBSTR(NAME,INSTR
    (NAME,'/',-1)+1)||'.dbf'''||';' from v$datafile;

2.增量恢复

1)源端执行。检查增量备份的路径,比如,xtt.properties文件的路径信息、权限等。

源端执行增量备份:


shell> export TMPDIR=/opt/oracle/tmp
shell> export XTTDEBUG=1
shell> $ORACLE_HOME/perl/bin/perl xttdriver.pl -i (nohup后台执行)

将以下源端文件复制或替换至目标端。


xttnewdatafiles.txt
xttplan.txt
tsbkupmap.txt
shell> scp  xttplan.txt 132.151.59.16:/home/oracle/tmp/
shell> scp  tsbkupmap.txt 132.151.59.16:/home/oracle/tmp/

2)目标端前滚。修改增量备份片权限,命令如下:


shell> chown grid.oinstall *_1_1
shell> chmod 775 *_1_1

目标端增量应用日志,命令如下:


shell> export TMPDIR=/home/oracle/tmp
shell> export XTTDEBUG=1
shell> $ORACLE_HOME/perl/bin/perl xttdriver.pl -r

可通过查看数据文件的时间来确定增量是否成功。

3)在源端确认下一个增量的SCN,命令如下:


shell> export TMPDIR=/opt/oracle/tmp
shell> export XTTDEBUG=1
shell> $ORACLE_HOME/perl/bin/perl xttdriver.pl -s

继续轮询增量恢复。

3.4.5 正式迁移

1.最后一次增量

1)将源端表空间设置为READ ONLY(只读)。在生产端运行如下命令,以获取READ ONLY脚本:


SQL> set heading off feedback off trimspool on linesize 500 
SQL> spool tts_tsro.sql 
SQL> prompt /* =================================== */ 
SQL> prompt /* Make all user tablespaces READ ONLY */ 
SQL> prompt /* =================================== */ 
SQL> select 'ALTER TABLESPACE ' || tablespace_name || ' READ ONLY;'
   from dba_tablespaces 
   where tablespace_name not in ('SYSTEM','SYSAUX','UNDOTBS1') 
      and contents = 'PERMANENT';
SQL> spool off

在源端执行以上获取到的命令。

检查表空间状态是否为只读(read only),命令如下:


SQL> select tablespace_name,status,contents from dba_tablespaces;

2)停止业务进行最后一次增量备份。在源端执行以下语句:


shell> export TMPDIR=/opt/oracle/tmp
shell> export XTTDEBUG=1
shell> $ORACLE_HOME/perl/bin/perl xttdriver.pl -i

最后一次增量结束之后关闭块跟踪,命令如下:


SQL> alter database disable block change tracking;

将以下源端文件复制或替换到目标端。

源端目录:/opt/oracle/tmp

目标端目录:/home/oracle/tmp/

命令如下:


xttnewdatafiles.txt
xttplan.txt
tsbkupmap.txt
shell> scp  xttplan.txt 132.151.59.16:/home/oracle/tmp/
shell> tsbkupmap.txt 132.151.59.16:/home/oracle/tmp/

3)目标端最后一次前滚。修改增量备份片权限,命令如下:


shell> chown grid.oinstall *_1_1
shell> chmod 775 *_1_1

目标端增量应用日志,命令如下:


shell> export TMPDIR=/home/oracle/tmp
shell> export XTTDEBUG=1
shell> $ORACLE_HOME/perl/bin/perl xttdriver.pl -r

2.元数据同步

1)确认生产是否新增数据文件,命令如下:


SQL> select name,CREATION_TIME from v$datafile order by CREATION_TIME asc;

2)元数据同步。目标端利用脚本生成元数据同步的导入语句(xttplugin.txt),命令如下:


shell> export TMPDIR=/home/oracle/tmp
shell> export XTTDEBUG=1
shell> $ORACLE_HOME/perl/bin/perl xttdriver.pl -e

备份生成的xttplugin.txt文件,并自定义修改,以下是笔者的修改项:


directory=DATA_PUMP_DIR 
exclude=STATISTICS
logfile=tts_imp_20191113.log
network_link=ttslink

transport_tablespaces和transport_datafiles信息可以通过以下脚本获取。

获取transport_tablespaces的命令如下:


SQL> set serveroutput on
SQL> declare 
  tsname varchar(30); 
  i number := 0; 
begin 
  dbms_output.put('transport_tablespaces='); 
  for ts in  
    (select tablespace_name from dba_tablespaces 
     where tablespace_name not in ('SYSTEM','SYSAUX') 
       and contents = 'PERMANENT' 
     order by tablespace_name) 
  loop 
    if (i!=0) then 
      dbms_output.put_line(tsname||', \'); 
    end if; 
    i := 1; 
    tsname := ts.tablespace_name; 
  end loop; 
  dbms_output.put_line(tsname); 
  dbms_output.put_line(''); 
end; 
/

获取transport_datafiles的命令如下:


SQL> set serveroutput on
SQL> declare 
  fname varchar(513); 
  i number := 0; 
begin 
  dbms_output.put('transport_datafiles='); 
  for df in 
    (select file_name from dba_tablespaces a, dba_data_files b 
     where a.tablespace_name = b.tablespace_name 
       and a.tablespace_name not in ('SYSTEM','SYSAUX') 
       and contents = 'PERMANENT' 
     order by a.tablespace_name) 
  loop 
    if (i!=0) then 
      dbms_output.put_line('''+DATA/zwhis/'||substr(fname,instr(fname,
          '/',-1)+1)||''', '); 
    end if; 
    i := 1; 
    fname := df.file_name; 
  end loop; 
  dbms_output.put_line('''+DATA/zwhis/'||substr(fname,instr(fname, 
      '/',-1)+1)||''''); 
  dbms_output.put_line(''); 
end; 
/

在目标端执行修改之后的脚本,结束后检查目标端的表空间和数据文件状态,命令如下:


SQL> select tablespace_name,file_name,status from dba_data_files;
SQL> select name,status from v$datafile;

3)验证传输的数据。使用RMAN验证传输过来的表空间是否存在物理或逻辑坏块,格式如下:


RMAN> validate tablespace 列出传输的表空间 check logical;

4)将目标端表空间设置成READ WRITE(读写)模式。在目标端运行如下命令以获取READ WRITE脚本:


SQL> set heading off feedback off trimspool on linesize 500 
SQL> spool tts_tsro.sql 
SQL> prompt /* ==================================== */ 
SQL> prompt /* Make all user tablespaces READ WRITE */ 
SQL> prompt /* ==================================== */ 
SQL> select 'ALTER TABLESPACE ' || tablespace_name || ' READ WRITE;'
   from dba_tablespaces 
   where tablespace_name not in ('SYSTEM','SYSAUX','UNDOTBS1') 
      and contents = 'PERMANENT';
SQL> spool off

最后检查表空间状态,执行如下命令:


SQL> select tablespace_name,status,contents from dba_tablespaces;

5)同步临时表。使用数据泵impdp的方式同步元数据时,临时表数据是不会自动同步的,需要在目标库中手动创建临时表。

在生产端查询临时表格,查询语句如下:


SQL> select TEMPORARY,table_name,owner  from dba_tables where owner in ('业务用户名');

获取生产端的建表语句,命令如下:


SQL> spool get_tmptable_ddl.sql
SQL> select dbms_metadata.get_ddl('TABLE','临时表格名','用户名') FROM dual;

以上语句可以直接合并为如下代码段:


SQL> select 'select dbms_metadata.get_ddl(' || '''' || 'TABLE' || '''' || ',' || '''' ||
       table_name || '''' || ',' || '''' || owner || '''' || ') FROM dual;'
  from dba_tables
 where owner in ('业务用户名')
   and TEMPORARY = 'Y';

6)导入源库的权限。

方法一,使用脚本导入:


SQL> spool grants.sql
SQL> SELECT EXEC_SQL FROM t_tmp_user_lhr where CREATE_TYPE not in ('USER');
SQL> spool off

方法二,使用impdp导入:


shell> impdp \'/ as sysdba\' DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp01.log 
    NETWORK_LINK=ttslink FULL=y INCLUDE=GRANT

7)导入DB_LINK对象,命令如下:


shell> impdp \'/ as sysdba\' DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp03.log 
    NETWORK_LINK=ttslink FULL=y INCLUDE=DB_LINK

在SYS用户下,对DB_LINK缺失问题的处理方法如下:


SQL> select dbms_metadata.get_ddl('DB_LINK','DBLINK_NAME','SYS') from dual;

8)导入其他对象,命令如下:


shell> impdp \'/ as sysdba\' DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp02.log 
    NETWORK_LINK=ttslink 
FULL=y INCLUDE=INDEX,FUNCTION,VIEW,SYNONYM,PACKAGE_BODY,SEQUENCE,PACKAGE,JOB,
TRIGGER,PROCEDURE,TPYE

9)编译无效对象,命令如下:


SQL> @?/rdbms/admin/utlrp.sql

10)修改默认表空间,命令如下:


SQL> alter database default tablespace USERS;

11)导入目标端的统计信息,命令如下:


shell> impdp \'/ as sysdba\' DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp02.log 
    NETWORK_LINK=ttslink 
FULL=y INCLUDE= STATISTICS

3.数据比对

1)对象数量的比对,命令如下:


SQL> SELECT D.OWNER,COUNT(1)
  FROM dba_objects d
 WHERE d.OWNER   in ('业务用户名')
 and d.OWNER not in ('PUBLIC') 
 AND NOT EXISTS (SELECT 1 FROM DBA_RECYCLEBIN B WHERE B.object_name=
     D.OBJECT_NAME AND D.OWNER=B.owner) 
 GROUP BY D.OWNER
 ORDER BY owner desc;

2)对象类型的比对,命令如下:


SQL> SELECT D.OWNER, D.OBJECT_TYPE, COUNT(1)
   FROM dba_objects d
  WHERE d.OWNER in ('业务用户名')
    and d.OWNER not in ('PUBLIC')
    AND NOT EXISTS (SELECT 1
           FROM DBA_RECYCLEBIN B
          WHERE B.object_name = D.OBJECT_NAME
            AND D.OWNER = B.owner)
  GROUP BY D.OWNER, D.OBJECT_TYPE
  ORDER BY D.OWNER ,COUNT(1) desc;

3)账号权限和同义词验证,命令如下:


SQL> select SYNONYM_NAME from dba_synonyms where owner in ('业务用户名');

4)检查数据文件头状态,命令如下:


SQL> select  STATUS,ERROR,TABLESPACE_NAME from V$DATAFILE_HEADER;

5)表空间校验。确认owner用户的DEFAULT_TABLESPACE、TEMPORARY_TABLESPACE,以及所有用户在相关表空间上的配额情况,将之前创建的owner用户的默认表空间修改为正确的默认表空间。

表3-6列举了验证结果比对项清单。

表3-6 比对项清单

3.4.6 迁移失败回退

迁移失败回退操作只需要将源生产数据库表空间置换为read write、源端JOB进程调整为原值,并启动源端监听即可,操作在5分钟之内即可完成。

3.4.7 迁移备忘录

为了避免在迁移过程中触发大量JOB,建议在迁移过程中禁用生产端和目标端JOB。禁用JOB的命令如下:


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

迁移和应用测试结束,且三方确认无误后,即可开启JOB。启用JOB的命令如下: QygEmKOGlypxpGzc2R4ifOzy3cCIH+yjR/VdflHX8qk+mL+/c1Vq7TWwPUXcOjvA


SQL> alter system set job_queue_processes=原值 scope=both sid='*';

点击中间区域
呼出菜单
上一章
目录
下一章
×