一 说明
该文档为 XTTS 数据库跨平台迁移方案
环境说明
源端数据库采用AIX 小机RAC 架构,数据库版本11.2.0.4 目标端采用LINUX X86 RAC 架构,数据库版本为11.2.0.4+ 最新PSU
硬件环境检查
对于一套RAC 的实施,我们需要确保基本的硬件环境已经达到要求,具体如下:
1. 主机操作系统安装,版本在RHEL 6 以上( 本文档针对的版本)
2. 存储已经挂载,并且所有的存储LUN 已经两两映射到对应的两台主机
3. LUN 要求:需要1G LUN 3 块 1T LUN 若干(具体视数据库空间) 并且互相映射
4. 网线已经正常接驳,心跳建议采用交换机模式连接
前置条件检查
|
条目 |
是否满足 |
备注 |
|
源端不能是windows |
是 |
|
|
源库的版本必须大于10.2 |
是 |
|
|
源库的compatible 参数不能大于目标端 |
是 |
|
|
源库和目标库字符集需要保持一致 |
是 |
|
|
目标端db_files 参数必须大于源端 |
是 |
|
|
源库必须处于归档模式 |
是 |
|
|
源库的rman 配置中DEVICE TYPE DISK 不能设置为COMPRESSED |
是 |
|
|
要迁移的表空间数据文件必须都是online 的或者不包括offline 数据文件 |
是 |
|
|
排除系统表空间,避免冲突并检查业务表空间是否自包含 |
是 |
资源配置情况
|
配置类型 |
源 库 |
目标库 |
|
数据库版本 |
11.2.0.4 |
11.2.0.4.161018 |
|
数据库名称 |
XXX |
XXX |
|
数据库字符集 |
AMERICAN_AMERICA.ZHS16GBK |
AMERICAN_AMERICA.ZHS16GBK |
|
数据库节点 |
RAC 1 节点 |
RAC 1 节点 |
|
操作系统版本 |
AIX6 |
Linux6.8 |
|
磁盘组大小 |
||
|
数据库大小 |
||
|
Block size |
8192 |
8192 |
二 生产基本数据统计
2.1 表空间统计
|
set linesize 200 col file_name for a50 set pagesize 0 select file_id,tablespace_name,file_name,status from dba_data_files; |
需要传输的数据文件大小
|
set linesize 1000 col file_name for a50 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; |
需要迁移的用户统计
|
alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss'; set line 200 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; |
|
select ‘‘‘‘||username||’’’,’ from dba_users where to_char(created,’yyyy-mm-dd’) > ‘2013-10-01’; |
用户权限收集
|
drop table t_tmp_user_lhr; create table t_tmp_user_lhr( id number, username varchar2(50), exec_sql varchar2(4000),create_type varchar2(20)); DROP sequence s_t_tmp_user_lhr; create sequence s_t_tmp_user_lhr;
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 (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’)) 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; / SELECT * FROM t_tmp_user_lhr; col username for a17 col CREATE_TYPE for a17 col EXEC_SQL for a110 set line 200 SELECT id,username,CREATE_TYPE,EXEC_SQL FROM t_tmp_user_lhr where CREATE_TYPE not in (‘USER’); |
用户表格规模统计
|
select d.owner, (sum(bytes) / 1024 / 1024) sizes_m from dba_segments d where d.owner in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’) 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; |
用户对象个数统计
基于用户对象统计
|
FROM dba_objects d WHERE d.OWNER in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’) 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; |
基于用户对象类型统计
|
FROM dba_objects d WHERE d.OWNER in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’) 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; |
2.7 备份对象信息,方便无效对象比对
无效对象统计
|
spool invald.lst select owner,object_name,object_type,status from dba_objects where status<>‘VALID’ ; select count(*),status from dba_objects group by status; select owner,object_name,object_type,status from dba_objects where status<>‘VALID’ and owner in ; select count(*),status from dba_objects where owner in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’) group by status; spool off create table invalid_object_201702 as select * from dba_objects where status<>‘VALID’; |
|
select count(*),status from dba_objects where owner in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’) group by status;
select count(*),status from dba_objects where owner in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’) and object_type like ‘PACKAGE%’ group by status; |
2.8 确定 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’; |
SYSTEM 表空间下是否存在对象
|
select owner,segment_name,segment_type,tablespace_name from dba_segments where tablespace_name in (‘SYSTEM’,’SYSAUX’) and owner in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’,’ZJJBUNI2REP’,’ZJJBUNI2’,’QMCB_NEW’,’JBGC’); |
确定平台字节序
|
col platform_name for a40 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)’); |
判断表空间是否自包含
当检测到表空间不是自包含时,需要迁移跨表空间对象至同一表空间。 详见附录一:
|
execute sys.dbms_tts.transport_set_check(‘CURRY,CURRY1,CURRY2,CURRY3,CURRY4,CURRY5,USERS’,true);col violations for a150select * from sys.transport_set_violations; |
获取需传输的表空间
|
set serveroutput on 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; / |
三 LINUX 端环境准备( 目标端)
配置到生产的NFS
LINUX 端准备 开启NFS :service nfs startchkconfig nfs onvi /etc/exports/backup 192.168.200.*(rw,sync,all_squash)exportfs –ashowmount -e AIX 源端配置: 检查aix 是否启用自定义端口# nfso -a|grep nfs_use_reserved_ports 启用aix 自定义端口
nfso -p -o nfs_use_reserved_ports=1
# showmount -e
# mount -o cio,rw,bg,hard,nointr,rsize=32768,wsize=32768,proto=tcp,noac,vers=3,timeo=600 192.168.200.90:/backup /backup 至此,源端和目标端均有/backup 目录 注意:在源端挂载目标端 NFS 文件系统时,在目标端 /etc/exports 中需指定源端物理 IP ,否则会造成源端挂载失败
安装集群创建数据库
安装最新11.2.0.4 集群+ 最新PSU 创建数据库,原则上和生产保持一致名称,特别注意字符集,需要和生产保持一致。 注意:需保持源端和目标端数据库 service_names 参数设置一致,否则会造成应用连接失败
准备XTTS 介质
上传介质到生产源端环境/backup 目录下
四 生产端操作
生产库必须满足归档开启策略
创建directory
源端创建directory 指向源端数据文件所在的位置create directory sourcedir as ‘+DATA/XXX/datafile’;grant all on directory sourcedir to public;
编辑xtt.properties 文件
$ mv xtt.properties xtt.properties.bak$ touch xtt.propertiesvi xtt.properties 填写以下内容
|
tablespaces=CURRY,CURRY1,CURRY2,CURRY3,CURRY4,CURRY5,USERSplatformid=6srcdir=SOURCEDIRdstdir=DESTDIRsrclink=TTSLINKdfcopydir=/backupbackupformat=/backupstageondest=/backupstorageondest=+DATAbackupondest=+DATAasm_home=/oracle/grid/crs_1asm_sid=+ASM1 |
需要迁移的表空间 |
|
源端数据库平台参数, V$DATABASE.PLATFORM_ID | |
|
源端根据数据文件所在目录 | |
|
目标端最终数据文件所在的目录 | |
|
目标端连接源端创建的db link | |
|
源端rman 备份目录 | |
|
源端增量备份目录 | |
|
目标端存放备份目录 | |
|
目标端rman 恢复目录 | |
|
目标端增量恢复目录 | |
|
目标端asm home 目录 | |
|
目标端asm 实例名 |
第一条tablespaces 参数,命令参考脚本:
|
set serveroutput ondeclare 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; / |
由于是NFS 挂载的,所以所有文件都不需要拷贝到目标端
五 目标端操作
创建目标directory
destdir 目标端数据文件最终所在的目录:
|
create directory destdir as ‘+DATA/XXX’; grant all on directory destdir to public; |
创建DATA_PUMP_DIR
DATA_PUMP_DIR 目录创建用于元数据导入
|
create or replace directory as ‘/backup’;grant all on directory DATA_PUMP_DIR to public; |
创建DB_LINK
xtts = (DESCRIPTION = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.200.71)(PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XXX) ) ) 创建连接源端数据库的dblink create public database link ttslink connect to system identified by oracle using ‘xtts’; 备注:
如果users 表空间已经存在了,这里把target 端的users 表空间重命名一下就可以了: alter tablespace users rename to users01;
临时创建所有表空间语句
临时创建所有表空间语句,用于从生产导入所有的权限及用户 相关脚本如下:(在生产端运行并生产文件)
|
set heading off feedback off trimspool on linesize 500spool tts_create_ts.sqlprompt /* ===================== */prompt /* Create user tablespaces */prompt /* ===================== */select ‘create TABLESPACE ‘ || tablespace_name || ‘ DATAFILE ‘ ||’’’+DATA/XXX/’||tablespace_name||’.dbf’’’||’ size 10M autoextend on;’ from dba_tablespaces where tablespace_name not in (‘SYSTEM’,’SYSAUX’) and contents = ‘PERMANENT’;spool off |
导入生产库用户及权限
同步用户和权限
|
impdp \’/ as sysdba\’ DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp01.log NETWORK_LINK=ttslink FULL=y INCLUDE=USER,ROLE,ROLE_GRANT,PROFILE |
删除表空间:该操作要明确,是在目标端操作的,即新环境端,操作前谨记,再三确认,操作前必须关闭生产库所有界面,只保留目标端,并且操作完后清理掉 tts_drop_ts.sql
|
set heading off feedback off trimspool on linesize 500 spool tts_drop_ts.sql prompt /* ===================== */ prompt /* Drop user tablespaces */ prompt /* ===================== */ select ‘DROP TABLESPACE ‘ || tablespace_name || ‘ INCLUDING CONTENTS AND DATAFILES;’ from dba_tablespaces where tablespace_name not in (‘SYSTEM’,’SYSAUX’) and contents = ‘PERMANENT’; spool off |
删除$ rm tts_drop_ts.sql 脚本
删除目标端USERS 表空间
为使得源端USERS 表空间顺利传输过来,删除USERS 表空间:alter database default tablespace SYSAUX;SQL> drop tablespace users including contents and datafiles;
设置 TMPDIR
源端(生产端):export TMPDIR=/home/oracle/tmp 目标端(新库):export TMPDIR=/home/oracle/tmp
六 数据全量传输阶段
数据全量传输采用两种方式:Phase 2A - dbms_file_transfer MethodPhase 2B - RMAN Backup Method 增量阶段发现还是应该打开块跟踪会比较好,加快速度,应该在全同步之前打开 alter database enable block change tracking using file ‘+DATA/trace.log’;alter database disable block change tracking;
生成增量所需文件
[oracle@source]$ export XTTDEBUG=1 [oracle@source]$ $ORACLE_HOME/perl/bin/perl xttdriver.pl -S
|
xttplan.txt # 记录数据文件 SCN 号 xttnewdatafiles.txt # 记录数据文件位置 |
手动 rman 拷贝方式传输文件
查询语句源端查询,拷贝source 端数据文件至NFS 共享目录/backup
|
select ‘copy datafile ‘||’’’’||file_name||’’’’||’ to ‘||’’’’||’/backup/’||substr(file_name,instr(file_name,’/’,-1)+1)||’’’;’ from dba_data_files;
copy datafile ‘+DATA/XXX/users01.dbf’ to ‘/backup/users01.dbf’; copy datafile ‘+DATA/XXX/curry01.dbf’ to ‘/backup/curry01.dbf’; copy datafile ‘+DATA/XXX/curry1.dbf’ to ‘/backup/curry1.dbf’; copy datafile ‘+DATA/XXX/curry2.dbf’ to ‘/backup/curry2.dbf’; copy datafile ‘+DATA/XXX/curry3.dbf’ to ‘/backup/curry3.dbf’; copy datafile ‘+DATA/XXX/curry4.dbf’ to ‘/backup/curry4.dbf’;copy datafile ‘+DATA/XXX/curry5.dbf’ to ‘/backup/curry5.dbf’; |
目标端手动 convert 数据文件
修改数据文件权限
|
chown grid.oinstall *.dbf |
查询语句源端查询,在目标端执行convert 操作
|
select ‘CONVERT FROM PLATFORM ‘||’’’’||’AIX-Based Systems (64-bit)’||’’’’||’ PARALLELISM 10’||’ datafile ‘||’’’’||’/backup/’||SUBSTR(NAME,INSTR(NAME,’/’,-1)+1)||’’’’||’ format ‘||’’’’||’+DATA/XXX/’||SUBSTR(NAME,INSTR(NAME,’/’,-1)+1)||’’’;’ from v$datafile;
CONVERT FROM PLATFORM ‘AIX-Based Systems (64-bit)’ PARALLELISM 10 datafile ‘/backup/users01.dbf’ format ‘+DATA/XXX/users01.dbf’; CONVERT FROM PLATFORM ‘AIX-Based Systems (64-bit)’ PARALLELISM 10 datafile ‘/backup/curry01.dbf’ format ‘+DATA/XXX/curry01.dbf’; CONVERT FROM PLATFORM ‘AIX-Based Systems (64-bit)’ PARALLELISM 10 datafile ‘/backup/curry1.dbf’ format ‘+DATA/XXX/curry1.dbf’; CONVERT FROM PLATFORM ‘AIX-Based Systems (64-bit)’ PARALLELISM 10 datafile ‘/backup/curry2.dbf’ format ‘+DATA/XXX/curry2.dbf’; CONVERT FROM PLATFORM ‘AIX-Based Systems (64-bit)’ PARALLELISM 10 datafile ‘/backup/curry3.dbf’ format ‘+DATA/XXX/curry3.dbf’; CONVERT FROM PLATFORM ‘AIX-Based Systems (64-bit)’ PARALLELISM 10 datafile ‘/backup/curry4.dbf’ format ‘+DATA/XXX/curry4.dbf’; CONVERT FROM PLATFORM ‘AIX-Based Systems (64-bit)’ PARALLELISM 10 datafile ‘/backup/curry5.dbf’ format ‘+DATA/XXX/curry5.dbf’; |
七 前滚阶段(增量恢复阶段)
7.1 源端执行
检查增量备份的路径,比如 xtt.properties 文件的路径信息权限等 源端增量备份阶段:
|
$export XTTDEBUG=1$ $ORACLE_HOME/perl/bin/perl xttdriver.pl -i |
拷贝或替换源端以下文件至目标端
|
xttnewdatafiles.txt xttplan.txt tsbkupmap.txt |
目标端执行
修改增量备份片权限
|
chown grid.oinstall *_1_1 |
目标端增量应用日志:
|
$export XTTDEBUG=1$ $ORACLE_HOME/perl/bin/perl xttdriver.pl -r |
源端确认下一个增量的SCN
源端执行:
|
[oracle@source]$ $ORACLE_HOME/perl/bin/perl xttdriver.pl -s |
继续轮询增量恢复
如果还需要增量恢复,重复执行7.1~7.3
八 最后一次增量前滚
源端表空间READ ONLY
生产端运行如下脚本,获取READ ONLY 脚本 脚本如下:
|
set heading off feedback off trimspool on linesize 500spool tts_tsro.sqlprompt /* =================================== */prompt /* Make all user tablespaces READ ONLY */prompt /* =================================== */select ‘ALTER TABLESPACE ‘ || tablespace_name || ‘ READ ONLY;’ from dba_tablespaces where tablespace_name not in (‘SYSTEM’,’SYSAUX’) and contents = ‘PERMANENT’;spool off |
检查状态:SQL> select tablespace_name,status,contents from dba_tablespaces;
最后一次增量备份
生产端执行:
|
[oracle@source]$ $ORACLE_HOME/perl/bin/perl xttdriver.pl -i |
最后一次增量结束关闭块跟踪alter database disable block change tracking; 目标端执行:
|
[oracle@dest]$ $ORACLE_HOME/perl/bin/perl xttdriver.pl -r |
九 数据同步
元数据同步
|
[oracle@dest]$ $ORACLE_HOME/perl/bin/perl xttdriver.pl -e |
相关语句如下:(transport_tablespaces 和transport_datafiles 根据实际情况修改)
|
impdp "‘"/ as sysdba"‘" directory=DATA_PUMP_DIR logfile=tts_imp.log \ network_link=ttslink transport_full_check=no \ transport_tablespaces=CURRY,CURRY1,CURRY2,CURRY3,CURRY4,CURRY5,USERS \ transport_datafiles=‘+DATA/XXX/curry01.dbf’,’+DATA/XXX/curry1.dbf’,’+DATA/XXX/curry2.dbf’,’+DATA/XXX/curry3.dbf’,’+DATA/XXX/curry4.dbf’,’+DATA/XXX/curry5.dbf’,’+DATA /nocdb/users01.dbf’ |
测试过程由于各种原因导致时间不够,因此为了加快进度, 没有将统计信息导入,采用后续手工统计 获取transport_tablespaces :
|
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 :
|
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/XXX/’||substr(fname,instr(fname,’/’,-1)+1)||’’’, \’); end if; i := 1; fname := df.file_name; end loop; dbms_output.put_line(‘‘‘+DATA/XXX/’||substr(fname,instr(fname,’/’,-1)+1)||’’’’); dbms_output.put_line(‘‘);end;/ |
转换结束,检查目标端表空间、数据文件状态:
|
col file_name for a40set linesize 1000select tablespace_name,file_name,status from dba_data_files; col name for a40select name,status from v$datafile; |
目标库表空间置成 READ WRITE 模式
目标端运行如下脚本,获取READ WRITE 脚本 脚本如下:
|
set heading off feedback off trimspool on linesize 500spool tts_tsro.sqlprompt /* ==================================== */prompt /* Make all user tablespaces READ WRITE */prompt /* ==================================== */select ‘ALTER TABLESPACE ‘ || tablespace_name || ‘ READ WRITE;’ from dba_tablespaces where tablespace_name not in (‘SYSTEM’,’SYSAUX’) and contents = ‘PERMANENT’;spool off |
检查状态:SQL> select tablespace_name,status,contents from dba_tablespaces;
临时表同步& 数据同步
生产端临时表格处理:
|
select TEMPORARY,table_name,owner from dba_tables where owner in (‘TPCC’,’CURRY4’,’TEST24’,’JJF’,’CURRY3’,’CURRY2’,’CURRY1’,’HR’,’TEST’,’HZMCMEMAUDIT’,’CURRY’,’CURRY5’,’TEST1’,’JTEST’,’TEST02’) and TEMPORARY=‘Y’; |
生产端获取建表语句
|
set heading off;set echo off;Set pages 999;set long 90000;spool get_tmptable_ddl.sqlselect dbms_metadata.get_ddl(‘TABLE’,’TMPTAB’,’BUDGET’) FROM dual; . . . . |
此时手动授权 GRANT 语句,会发现很多对象不存在,在元数据同步之后还是有 部分对象缺失,所以再导一次相关对象: 进行缺失对象导入时,优先导入DB_LINK
|
impdp \’/ as sysdba\’ DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp.log NETWORK_LINK=ttslink FULL=y INCLUDE=DB_LINK |
|
grant create database link to xxx; |
确认DB_LINK 导入无误后,再导入其他对象
|
impdp \’/ as sysdba\’ DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp.log NETWORK_LINK=ttslink FULL=y INCLUDE=INDEX,FUNCTION,VIEW,SYNONYM,PACKAGE BODY,SEQUENCE,PACKAGE,JOB,TRIGGER,PROCEDURE |
确认缺少对象导入之后,进行权限GRANT 导入
|
impdp \’/ as sysdba\’ DIRECTORY=DATA_PUMP_DIR LOGFILE=dp_userimp01.log NETWORK_LINK=ttslink FULL=y INCLUDE= GRANT |
在测试迁移阶段,发现即使进行权限 GRANT 完全导入之后,还是有部分基于 sys 下一些数据字典权限没有同步至目标库。此时需要手动执行 grant 语句授权。 @user_privs_collect.sql 待相关对象同步好之后,再开始进行数据校验。
目标库统计信息收集
数据校验完全一致后,收集目标库统计信息
|
exec dbms_stats.gather_database_stats(estimate_percent=>10,Degree=>8,Cascade=>TRUE,Granularity=>‘ALL’);exec dbms_stats.gather_dictionary_stats(estimate_percent=>100,Degree=>8,Cascade=>TRUE,Granularity=>‘ALL’);exec dbms_stats.gather_fixed_objects_stats; |
十 备忘录
源库禁用块跟踪
测试迁移结束之后,源库禁用块跟踪。正式迁移跳过此步。select * from v$block_change_tracking;alter database disable block change tracking;
源端表空间READ WRITE
测试迁移结束之后,源库表空间置回读写模式。正式迁移跳过此步。READ WRITE 脚本如下:
|
set heading off feedback off trimspool on linesize 500 spool tts_tsro.sqlprompt /* ==================================== */prompt /* Make all user tablespaces READ WRITE */prompt /* ==================================== */select ‘ALTER TABLESPACE ‘ || tablespace_name || ‘ READ WRITE;’ from dba_tablespaces where tablespace_name not in (‘SYSTEM’,’SYSAUX’) and contents = ‘PERMANENT’;spool off |
检查状态:SQL> select tablespace_name,status,contents from dba_tablespaces;
源库JOB 禁用& 启用
由于迁移时间是月初,时间比较敏感,大量JOB 可能都在该时段触发,与客户和应用确认是否要禁用生产库JOBalter system set job_queue_processes=0 scope=both sid=‘*’;
目标库JOB 禁用& 启用
为了防止JOB 调度而引起的数据校验不一致,在迁移前禁用所有JOBalter system set job_queue_processes=0 scope=both sid=‘*’; 迁移结束,应用测试结束,三方确认无误后,开启JOBalter system set job_queue_processes=1000 scope=both sid=‘*’;
