一次完整的expdp/impdp邏輯遷移

在前段時間,進行過一次expdp/impdp的邏輯遷移。但是也沒有進行過非常詳細的總結。這一次,終於想要把整個遷移過程和遇到的問題、解決方式都從頭到尾的總結一下,用來以後給以後的遷移過程做個參考模板。

一、明確遷移目標:

本次遷移是通過expdp/impdp的方式,將業務用戶數據用expdp導出到NFS上,然後再通過impdp導入到新數據庫中。

二、主機存儲操作

1.掛載NFS

將存儲劃分到其中1個節點,並製作爲文件系統,然後將該文件系統通過NFS配置共享出去:

vi /etc/exports
#NFS server share directories
/share XXX.XXX.XXX.XXX/24(rw,insecure,no_root_squash,sync)
/share XXX.XXX.XXX.XXX/24(rw,insecure,no_root_squash,sync)
/share XXX.XXX.XXX.XXX/24(rw,insecure,no_root_squash,sync)

注:需要注意,這裏將NFS的屬性掛在爲insecure,否則在導入的時候,可能會報錯。

三、源端數據庫調研:

1.確認需要遷移的用戶

select username from dba_users where username not in ('ANONYMOUS','DBSNMP','EXFSYS','MDDATA','MGMT_VIEW','ORDPLUGINS','OUTLN','SCOTT','SI_INFORMATN_SCHEMA','SYSMAN','WK_TEST','WKPROXY','WKSYS','XDB','APPQOSSYS','AUDSYS','CTXSYS','DVSYS','GGSYS','LBACSYS','MDSYS','OJVMSYS','OLAPSYS','ORDSYS','SYS','SYS$UMF','SYSBACKUP','SYSDG','SYSKM','SYSRAC','SYSTEM','WMSYS','XS$NULL','DBSFWUSER','SI_INFORMTN_SCHEMA','DVF','GSMADMIN_INTERNAL','ORDDATA','GSMCATUSER','REMOTE_SCHEDULER_AGENT','PDBADMIN','GSMUSER','DIP','ORACLE_OCM','SPATIAL_CSW_ADMIN_USR','APEX_040200','APEX_PUBLIC_USER','SPATIAL_WFS_ADMIN_USR','user_impdp','FLOWS_FILES','APEX_050000') and owner not like '%APEX%';

2.查看是否有非系統表在系統表空間下

set line 999
col owner format a10
col segment_name format a30
col tablespace_name format a30
select owner,segment_name,segment_type,tablespace_name from dba_segments where owner not in ('ANONYMOUS','DBSNMP','EXFSYS','MDDATA','MGMT_VIEW','ORDPLUGINS','OUTLN','SCOTT','SI_INFORMATN_SCHEMA','SYSMAN','WK_TEST','WKPROXY','WKSYS','XDB','APPQOSSYS','AUDSYS','CTXSYS','DVSYS','GGSYS','LBACSYS','MDSYS','OJVMSYS','OLAPSYS','ORDSYS','SYS','SYS$UMF','SYSBACKUP','SYSDG','SYSKM','SYSRAC','SYSTEM','WMSYS','XS$NULL','DBSFWUSER','SI_INFORMTN_SCHEMA','DVF','GSMADMIN_INTERNAL','ORDDATA','GSMCATUSER','REMOTE_SCHEDULER_AGENT','PDBADMIN','GSMUSER','DIP','ORACLE_OCM','SPATIAL_CSW_ADMIN_USR','APEX_040200','APEX_PUBLIC_USER','SPATIAL_WFS_ADMIN_USR','user_impdp','FLOWS_FILES','APEX_050000') and owner not like '%APEX%';

注:如果存在業務數據存放在系統表空間下的,則需要先對這些表進行move操作,將表移出系統表空間,因爲我們在遷移的時候是不會遷移系統表空間的,只能遷移業務表空間。

3.查看相應的表空間

select tablespace_name,sum(bytes)/1024/1024/1024 gb from dba_data_files where tablespace_name in
(select distinct tablespace_name from dba_segments where owner not in ('ANONYMOUS','DBSNMP','EXFSYS','MDDATA','MGMT_VIEW','ORDPLUGINS','OUTLN','SCOTT','SI_INFORMATN_SCHEMA','SYSMAN','WK_TEST','WKPROXY','WKSYS','XDB','APPQOSSYS','AUDSYS','CTXSYS','DVSYS','GGSYS','LBACSYS','MDSYS','OJVMSYS','OLAPSYS','ORDSYS','SYS','SYS$UMF','SYSBACKUP','SYSDG','SYSKM','SYSRAC','SYSTEM','WMSYS','XS$NULL','DBSFWUSER','SI_INFORMTN_SCHEMA','DVF','GSMADMIN_INTERNAL','ORDDATA','GSMCATUSER','REMOTE_SCHEDULER_AGENT','PDBADMIN','GSMUSER','DIP','ORACLE_OCM','SPATIAL_CSW_ADMIN_USR','APEX_040200','APEX_PUBLIC_USER','SPATIAL_WFS_ADMIN_USR','user_impdp','FLOWS_FILES','APEX_050000') and owner not like '%APEX%'group by tablespace_name;

四.創建表空間

1.根據業務實際要求,目標端創建表空間

create tablespace tablespace_name '+DISKGROUP_NAME' size 32767m autoextend off;
...
alter tablespace add tablespace_name add datafile '+DISKGROUP_NAME' size 32767m autoextend off;
...

2.查看臨時表空間,目標端創建臨時表空間

需要注意:,因爲要導入索引,所以可能就會有業務用戶的臨時表空間需要使用:

select distinct tablespace_name from dba_temp_files;

create temporary tablespace TEMP_XXX tempfile '+DISKGROUP_NAME' size 32767m autoextend off;
...
alter tablespace  TEMP_XXX add tempfile='+DISKGROUP_NAME' size 32767m autoextend off;
...

五.查看源庫是否有自己安裝的組件,如果有,則需要在目標端安裝:

col comp_id format a30
col comp_name format a40
col version format a40
select comp_id,comp_name,version from dba_registry;

六.在源端和目標端創建導出和導入用戶,目錄,授權:

如果用impdp+dblink,則直接在目標端創建即可,因爲數據不用落地。這裏,我們拿數據落地舉例子。

源端:

創建用戶:

create user user_impdp identified by oracle;
create directory dir_impdp as '/share/xxx';

賦權限:

根據現場賦權限,有些地方不能賦予dba權限,就賦予需要使用的權限

grant dba to user_impdp;
(grant connect,resource,unilimited tablespace to user_impdp)
grant read,write on directory dir_impdp to user_impdp;

目標端:

創建用戶:

create user user_impdp identified by oracle;
create directory dir_impdp as '/share/xxx';

賦權限:

根據現場賦權限,有些地方不能賦予dba權限,就賦予需要使用的權限

grant dba to user_impdp;
(grant connect,resource,unilimited tablespace to user_impdp)
grant read,write on directory dir_impdp to user_impdp;

七.從源端導出全庫數據

1.設置parfile:

vi expdp_full.par

directory=user_impdp
DUMPFILE=full_database_%U.dmp
LOGFILE=full_database.log
PARALLEL=32			 #根據cpu數量,設置並行
#version=11.2.0.4    #根據目標端要求來導出版本
SCHEMAS=AAA,BBB,CCC,DDD,EEE
#query=AAA.TABLE_1:"where 1=2"  #這種方式可以在引號中寫條件,從而導出滿足條件的內容,這裏表示只導出表結構

2.導出數據

nohup expdp user_impdp/oracle PARFILE=expdp_full.par &

八.導入數據

1.創建用戶parfile,方便導入使用

vi schema.par
schemas=AAAA,
BBBB,
CCCC,
DDDD,
EEEE

2.修改共享目錄權限

chmod -R 777 /share

3.清除測試用戶

操作前務必覈對好機器,不要在生產庫操作,且這步操作是在經歷多次測試後才做的,新環境下不用做。

drop user AAAA cascade;
drop user BBBB cascade;
drop user CCCC cascade;
drop user DDDD cascade;
drop user EEEE cascade;

注:如果刪除用戶比較慢,則可以先刪除其中的大表或者大對象後,在刪除用戶,就會很快。

4.導入profile

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp include=profile content=metadata_only logfile=impdp_profile.log &

5.導入角色

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp include=ROLE content=metadata_only logfile=impdp_role.log &

6.導入用戶

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp include=USER,SYSTEM_GRANT,ROLE_GRANT,DEFAULT_ROLE parfile=schema.par content=metadata_only logfile=impdp_user.log &

7.導入元數據(只導入表結構)

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp exclude=type,package,user,index,trigger,procedure,CONSTRAINT,INDEX_STATISTICS,TABLE_STATISTICS parfile=schema.par content=metadata_only logfile=impdp_table.log &

8.導入數據

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp PARALLEL=32 parfile=schema.par content=data_only logfile=impdp_data_only.log &

9.重建索引:

重建索引分爲兩種方式:
1)通過impdp生成sqlfile,然後手動修改索引中的index的並行度,直接執行修改後的sqlfile,創建索引;

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp include=index sqlfile=index.sql parfile=schema.par content=metadata_only full=y logfile=create_index_sql.log &

修改sqlfile:

vi index.sql

create index AAA.index_1 on AAA.TABLE_1(COL_1) parallel 10;
alter index AAA.index_1 no parallel;
.... 

2)直接通過Impdp導入索引,同時加入parallel參數,對索引開啓並行導入。

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp include=index parallel=32 parfile=schema.par content=metadata_only full=y logfile=create_index_sql.log &

兩種導入的方式不同點在於:
通過sqlfile的方式,可以手動修改單獨索引的parallel,從而加快單個索引的創建速度,但是創建索引還是逐個創建(當然,我們也可以通過手動對sqlfile進行分片,分成n個片,那麼也可以等效爲同時並行創建n個索引,且每個索引都是已parallel的並行度創建);
(12.2以後)直接通過impdp+parallel參數的方式,一條命令即可實現。且可以有parallel個索引同時創建,但是每個索引的創建,並不會使用並行。

10.重建約束:

對於約束,我們則可以直接通過impdp的方式直接導入,因爲約束無法開啓並行:

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp include=container parallel=32 content=metadata_only full=y logfile=create_constraint_sql.log &

而在12C以後,同樣導入constraint,開啓PARALLEL是會開啓多個進程,同時導入多個constraint的,所以效率還是比較高。

在索引和約束導入過程中,需要注意以下幾個問題,也是可以提前必坑的:
1)在導入索引後,發現索引的數量和原來的數量無法匹配上;
2)在創建約束的時候,發現有些約束會非常慢;
3)約束創建完以後,發現約束也有非常多的數量無法和源庫匹配上;

對於問題一和問題二,我們可以生成約束的sql語句看一下約束創建語句:

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp include=container parallel=32 sqlfile=constraint.sql content=metadata_only full=y logfile=create_constraint_sql.log &

發現其中的constraint的創建方法,對於主鍵均是使用以下方式創建的:

alter table add constraint pk_xxxxx using (create unique index on table_name(col_1));

通過這種方式創建,數據庫會先創建唯一索引,再增加約束,而在創建索引的時候,並不會開啓並行,所以真正慢的地方不是導入約束,而是創建索引;同時,這些索引是不會在導入索引的時候生成到sqlfile中的,這也就解釋了爲什麼在導入索引後,索引的數量與源端不一致(我們在導入這部分約束後,發現索引數量與源端完全一致);

對於問題三,導入約束後,對比發現目標端約束的數量遠小於源端。
篩選幾張表,對目標端和源端的表上的約束進行比對,發現在源端的約束中,有很多以SYS_開頭的約束名字,但目標端卻沒有。

select * from dba_constraints;

這是因爲,以SYS開頭的約束,在創建的時候都沒有指定約束名字,而在不同的系統中,沒有指定名字的約束,數據庫會自動給該約束生成一個SYS+編號名字。
對於這種約束,我們只能通過獲取這些約束的DDL,並在目標庫上執行才能成功創建。
具體方法如下:

select 
'select dbms_metadata.get_ddl('||''''||'CONSTRAINT'||''''||','||''''||CONSTRAINT_NAME||''''||','||''''||owner||''''||')'||' from dual;' 
from dba_constraints 
where owner='AAA' 
and CONSTRAINT_NAME like 'SYS%';

這樣的約束大部分都是非空約束,所以執行起來還是比較快。

其實,從這裏也可以看到,我們在應用程序開發的時候,開發標準的重要性:
1)如果我們創建主鍵約束的方式是先創建唯一索引,然後再通過唯一索引添加主鍵索引,那麼索引則可以一次性全部創建好;
2)如果我們創建約束全部制定了名字,那麼也可以一次性將約束全部導入,而不用單獨創建。

11.最後導入除了統計信息以外的其他元數據(已經存在的會報錯存在,並跳過)

nohup impdp user_impdp/[email protected]:1521/pdb directory=dir_impdp DUMPFILE=full_database_%U.dmp exclude=STATISTICS content=metadata_only logfile=impdp_metadata_last.log &

十.收集全庫統計信息:

vi gather_static.sh

sqlplus / as sysdba<<EOF
alter session set container=pdb;
set timing on
alter system set resource_manager_plan = 'DEFAULT_PLAN' scope=both
exec dbms_stats.set_global_prefs('CONCURRENT','TRUE');
	begin
	dbms_stats.gather_database_stats(
	ESTIMATE_PERCENT=>DBMS_STATS.AUTO_SAMPLE_SIZE, method_opt => 'for all indexed columns', cascade=>true, degree=>120);
	end;
	/
exec dbms_stats.set_global_prefs('CONCURRENT','FALSE');
alter system set resource_manager_plan = 'FORCE:' scope=both
exit;
EOF

執行這個語句,收集全庫統計信息:

nohup gather_static.sh &

十一.對比對象
這一步,分別對錶、索引、約束、過程、觸發器等數量進行比對即可。

select count(*) from dba_objects where owner not in ('ANONYMOUS','DBSNMP','EXFSYS','MDDATA','MGMT_VIEW','ORDPLUGINS','OUTLN','SCOTT','SI_INFORMATN_SCHEMA','SYSMAN','WK_TEST','WKPROXY','WKSYS','XDB','APPQOSSYS','AUDSYS','CTXSYS','DVSYS','GGSYS','LBACSYS','MDSYS','OJVMSYS','OLAPSYS','ORDSYS','SYS','SYS$UMF','SYSBACKUP','SYSDG','SYSKM','SYSRAC','SYSTEM','WMSYS','XS$NULL','DBSFWUSER','SI_INFORMTN_SCHEMA','DVF','GSMADMIN_INTERNAL','ORDDATA','GSMCATUSER','REMOTE_SCHEDULER_AGENT','PDBADMIN','GSMUSER','DIP','ORACLE_OCM','SPATIAL_CSW_ADMIN_USR','APEX_040200','APEX_PUBLIC_USER','SPATIAL_WFS_ADMIN_USR','user_impdp','FLOWS_FILES','APEX_050000') and owner not like '%APEX%') and object_type=&object_type;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章