當前位置:
首頁 > 最新 > 續:跨平台版本遷移之 XTTS 方案操作指南

續:跨平台版本遷移之 XTTS 方案操作指南

作者 | 羅貴林:雲和恩墨技術工程師,具有8年以上的 Oracle 資料庫工作經驗,曾任職於大型的國家電信、省級財政、省級公安的維護,性能調優等。精通 Oracle 資料庫管理,調優,問題診斷。擅長 SQL 調優,Oracle RAC 等維護,管理。

承接上篇:舉一反三:跨平台版本遷移之 XTTS 方案操作指南

7

XTTS 遷移後檢查

7.1 更改用戶默認表空間

更改用戶默認表空間,將用戶默認表空間設置與源資料庫保持一致:

@default_tablespace.sql

源端執行:

spool default_tablespace.sql

select "alter user "||username||" default tablespace "||default_tablespace||";" from dba_users where default_tablespace in(『DATATBS 』);

spool off

添加表空間配額許可權:

@unlimited_tablespace.sql

源庫:

select "alter user "||username||" quota unlimited on "|| default_tablespace||";" from dba_users where default_tablespace in (『DATATBS 』);

7.2 資料庫對象並行重編譯

exec utl_recomp.recomp_parallel(32);

set echo off feedback off timing off verify off

set pagesize 0 linesize 500 trimspool on trimout on

Set heading off;

set feedback off;

set echo off;

Set lines 999;

spool compile.sql

select "alter "||

decode(object_type,"SYNONYM",decode(owner,"PUBLIC","PUBLIC SYNONYM "||object_name,

"SYNONYM "||OWNER||"."||OBJECT_NAME)||" compile;",

decode(OBJECT_TYPE ,"PACKAGE BODY","PACKAGE",OBJECT_TYPE)||

" "||owner||"."||object_name||" compile "||

decode(OBJECT_TYPE ,"PACKAGE BODY","BODY;"," ;"))

from dba_objects where status"VALID"

order by owner,OBJECT_NAME;

spool off

@compile.sql

正式環境沒有無效對象。

7.3 資料庫對象數據比對

運行資料庫對比腳本,通過創建 dblink,運行相關的資料庫對象比對腳本。這裡我們主要比對了存儲過程,函數,觸發器,試圖,索引,表等等。

創建到生產環境 DB LINK

CREATE DATABASE LINK TEST_COMPARE CONNECT TO SYSTEM IDENTIFIED BY password xxx USING "xxxx:1521/xxxx";

使用如下腳本對比資料庫中對象個數:

SELECT OWNER, OBJECT_NAME, OBJECT_TYPE

FROM DBA_OBJECTS@TEST_COMPARE

WHERE OBJECT_NAME NOT LIKE "BIN%"

AND OBJECT_NAME NOT LIKE "SYS_%"

AND OWNER IN ("LUOKLE")

MINUS

SELECT OWNER, OBJECT_NAME, OBJECT_TYPE

FROM DBA_OBJECTS

WHERE OBJECT_NAME NOT LIKE "BIN%"

AND OBJECT_NAME NOT LIKE "SYS_%"

AND OWNER IN ("LUOKLE");

源庫:

select object_type,count(*) from dba_objects where owner

in (select username from 源庫) group by object_type;

目標:

select object_type,count(*) from dba_objects where owner

in (select username from 目標庫) group by object_type;

如果索引缺失可能是由於沒有存放在傳輸的表空間所以需要重新創建,而缺失的表可能是臨時表,需要手工創建。

使用如下腳本進行創建:

CREATE INDEX "LUOKLE"."IDX_XXX" ON "LUOKLE"."BI_XXXX" TABLESPACEDATATBS parallel 8;

Alter index "LUOKLE"."IDX_XX" noparallel;

CREATE GLOBAL TEMPORARY TABLE "LUOKLE"."TEMP_PAY_BATCH_CREATE_INSTR"

( "BATCH_ID" NUMBER,

"STATUS" CHAR(1)

) ON COMMIT PRESERVE ROWS ;

使用 hash 函數進行數據對比

兩邊分別創建存放 hash 數據的表

create table system.get_has_value (dbname varchar2(20),owner varchar2(30),table_name varchar2(100),value varchar2(100),error varchar2(2000));

創建需要驗證的表:

create sequence system.sequence_checkout_table start with 1 increment by 1 order cycle maxvalue 10 nocache;

CREATE TABLE SYSTEM.checkout_table as select sys_context("USERENV", "INSTANCE_NAME") dbnme,owner,table_name, system.sequence_checkout_table.NEXTVAL groupid from dba_tables where owner="LUOKLE"

結果顯示:

1 SELECT owner, groupid, COUNT (*)

2 FROM SYSTEM.checkout_table

3* GROUP BY owner, groupid,dbnme Order by owner,groupid

14:05:21 SQL> SELECT owner, groupid, COUNT (*)

14:05:31 2 FROM SYSTEM.checkout_table

14:05:32 3 GROUP BY owner, groupid,dbnme Order by owner,groupid;

OWNER GROUPID COUNT(*)

------------------------------ ---------- ----------

LUOKLE 1 32

LUOKLE 2 31

LUOKLE 3 31

LUOKLE 4 31

LUOKLE 5 31

LUOKLE 6 31

LUOKLE 7 31

LUOKLE 8 31

LUOKLE 9 31

LUOKLE 10 31

創建 hash 函數

grant select on sys.dba_tab_columns to system;

CREATE OR REPLACE PROCEDURE SYSTEM.get_hv_of_data (

avc_owner VARCHAR2,

avc_table VARCHAR2)

AS

lvc_sql_text VARCHAR2 (30000);

ln_hash_value NUMBER;

lvc_error VARCHAR2 (100);

BEGIN

SELECT "select /*+parallel(a,25)*/sum(dbms_utility.get_hash_value("

|| column_name_path

|| ",0,power(2,30)) ) from "

|| owner

|| "."

|| table_name

|| " a "

INTO LVC_SQL_TEXT

FROM (SELECT owner,

table_name,

column_name_path,

ROW_NUMBER ()

OVER (PARTITION BY table_name

ORDER BY table_name, curr_level DESC)

column_name_path_rank

FROM ( SELECT owner,

table_name,

column_name,

RANK,

LEVEL AS curr_level,

LTRIM (

SYS_CONNECT_BY_PATH (column_name, "||""|""||"),

"||""|""||")

column_name_path

FROM ( SELECT owner,

table_name,

""" || column_name || """ column_name,

ROW_NUMBER ()

OVER (PARTITION BY table_name

ORDER BY table_name, column_name)

RANK

FROM dba_tab_columns

WHERE owner = UPPER (avc_owner)

AND table_name = UPPER (avc_table)

AND DATA_TYPE IN ("TIMESTAMP(3)",

"INTERVAL DAY(3) TO SECOND(0)",

"TIMESTAMP(6)",

"NVARCHAR2",

"CHAR",

"BINARY_DOUBLE",

"NCHAR",

"DATE",

"RAW",

"TIMESTAMP(6)",

"VARCHAR2",

"NUMBER")

ORDER BY table_name, column_name)

CONNECT BY table_name = PRIOR table_name

AND RANK - 1 = PRIOR RANK))

WHERE column_name_path_rank = 1;

EXECUTE IMMEDIATE lvc_sql_text INTO ln_hash_value;

lvc_sql_text :=

"insert into system.get_has_value(owner,table_name,value) values(:x1,:x2,:x3)";

EXECUTE IMMEDIATE lvc_sql_text USING avc_owner, avc_table, ln_hash_value;

commit;

DBMS_OUTPUT.put_line (

avc_owner || "." || avc_table || " " || ln_hash_value);

EXCEPTION

WHEN NO_DATA_FOUND

THEN

lvc_error := "NO DATA FOUND";

lvc_sql_text :=

"insert into system.get_has_value(owner,table_name,error) values(:x1,:x2,:x3)";

EXECUTE IMMEDIATE lvc_sql_text USING avc_owner, avc_table, lvc_error;

commit;

WHEN OTHERS

THEN

lvc_sql_text :=

"insert into system.get_has_value(owner,table_name,value) values(:x1,:x2,:x3)";

EXECUTE IMMEDIATE lvc_sql_text USING avc_owner, avc_table, SQLERRM;

commit;

END;

/

sqlplus system/oracle

set heading off linesize 170 pagesize 0 feedback off echo off trimout on trimspool on termout off verify off

exit;

EOF

nohup ./check_source.sh LUOKLE 1 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 2 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 3 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 4 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 5 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 6 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 7 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 8 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 9 >./source_LUOKLE_cd_1.log 2>&1 &

nohup ./check_source.sh LUOKLE 10 >./source_LUOKLE_cd_1.log 2>&1 &

checkdata_source.sh

date

sqlplus system/oracle

set heading off linesize 170 pagesize 0 feedback off

spool source_check_$1_$2.sql

SELECT "exec system.get_hv_of_data("""

|| owner

|| ""","""

|| table_name

|| """)"

FROM system.checkout_table

WHERE owner = UPPER ("$1") and groupid=$2

AND table_name NOT IN (SELECT table_name

FROM dba_tables

WHERE owner = UPPER ("$1")

AND iot_type IS NOT NULL)

AND table_name IN (SELECT table_name

FROM ( SELECT table_name, COUNT (*)

FROM dba_tab_columns

WHERE owner = UPPER ("$1")

AND DATA_TYPE IN ("TIMESTAMP(3)",

"INTERVAL DAY(3) TO SECOND(0)",

"TIMESTAMP(6)",

"NVARCHAR2",

"CHAR",

"BINARY_DOUBLE",

"NCHAR",

"DATE",

"RAW",

"VARCHAR2",

"NUMBER")

GROUP BY table_name

HAVING COUNT (*) > 0))

ORDER BY table_name;

spool off

set serveroutput on

@source_check_$1_$2.sql

exit;

EOF

date

運行 hash 計算函數腳本,在LINUX環境對 LUOKLE 下所有表進行 hash 計算耗時30分鐘,總共311張表,有52張表沒有計算出 hash 經分析發現這些表為空表。

SQL> select count(*) from LUOKLE.XXXX;

COUNT(*)

----------

7.4 資料庫對象間許可權比對處理

對比源庫和目標庫資料庫的對象級別間許可權,如若許可權不一致建議將源庫跑出的 grant_tab_privs.log 到目標端執行。

複核對象上的 select 和 DML 許可權賦予給用戶

@grant_tab_privs.sql

源庫:

select "grant " || privilege || " on " || owner || "." || table_name || " to " || grantee || ";" from dba_tab_privs where (grantee in(select username from dba_users where default_tablespace in(『DATATBS 』)) or owner in(select username from dba_users where default_tablespace in(DATATBS ))) and privilege in("SELECT","DELETE","UPDATE","INSERT") and grantable="NO"

union

select "grant " || privilege || " on " || owner || "." || table_name || " to " || grantee || " with grant option;" from dba_tab_privs where (grantee in(select username from dba_users where default_tablespace in(DATATBS )) or owner in(select username from dba_users where default_tablespace in(DATATBS ))) and privilege in("SELECT","DELETE","UPDATE","INSERT") and grantable="YES";

7.5 收集統計信息

為了防止同時收集統計信息,造成系統資源的消耗,建議提前關閉後台自動收集統計信息的任務。

exec DBMS_AUTO_TASK_ADMIN.DISABLE(client_name => "auto optimizer stats collection",operation => NULL,window_name => NULL);

查看柱狀圖信息:

select count(*),owner,table_name,column_name from dba_tab_histograms

group by owner,table_name,column_name

having count(*) > 2;

手工運行收集腳本:

exec DBMS_STATS.SET_GLOBAL_PREFS("CONCURRENT","TRUE");設置並發收集模式

exec

dbms_stats.gather_database_stats(

estimate_percent =>dbms_stats.AUTO_SAMPLE_SIZE, ///// for all columns size repeat

METHOD_OPT=>"FOR ALL COLUMNS SIZE 1",

options=> "GATHER",degree=>8,

granularity =>』all』,

cascade=> TRUE

);

select * from dba_scheduler_jobs where schedule_type = "IMMEDIATE" and state = "RUNNING";

收集數據字典統計信息:

exec DBMS_STATS.GATHER_DICTIONARY_STATS(degree=>16);

固定對象的統計信息:

EXECUTE DBMS_STATS.GATHER_FIXED_OBJECTS_STATS;

開啟默認收集

exec DBMS_AUTO_TASK_ADMIN.ENABLE(client_name => "auto optimizer stats collection",operation => NULL,window_name => NULL);

exec DBMS_STATS.SET_GLOBAL_PREFS("CONCURRENT","false");

以下為測試過程:

13:23:41 SQL> select count(*),owner,table_name,column_name from dba_tab_histograms

13:23:45 2 where owner="LUOKLE"

13:23:46 3 group by owner,table_name,column_name

13:23:46 4 having count(*) > 2;

no rows selected

Elapsed: 00:00:00.10

13:28:06 SQL> exec dbms_stats.gather_database_stats(estimate_percent =>dbms_stats.AUTO_SAMPLE_SIZE,METHOD_OPT=>"FOR ALL COLUMNS SIZE 1",options=> "GATHER",degree=>8, granularity =>"all",cascade=> TRUE);

PL/SQL procedure successfully completed.

Elapsed: 00:26:51.34

13:55:05 SQL>

全庫統計信息收集耗時26分鐘

13:57:14 SQL> exec DBMS_STATS.GATHER_DICTIONARY_STATS(degree=>16);

PL/SQL procedure successfully completed.

Elapsed: 00:00:18.94

7.6 修改 job 參數

show parameter job_queue_processes;

alter system set job_queue_processes=100 scope=both;

8

XTTS 遷移測試耗時(20T)

9

XTTS 遷移測試問題記錄

expdp "/ as sysdba" directory=xtts dumpfile=expdp_LUOKLE_meta0822.dmp logfile=expdp_LUOKLE_meta0822.log CONTENT=metadata_only SCHEMAS=LUOKLE 15:06 開始到出

ORA-39014: One or more workers have prematurely exited.

ORA-39029: worker 1 with process name "DW00" prematurely terminated

ORA-31671: Worker process DW00 had an unhandled exception.

ORA-04030: out of process memory when trying to allocate 3704 bytes (kkoutlCreatePh,kkotbi : kkotbal)

ORA-06512: at "SYS.KUPW$WORKER", line 1887

ORA-06512: at line 2

在做元數據導出時候後台報大量 ORA-04030 錯誤,經過分析為 AMM 問題,通過關閉 AMM 手工管理內存解決。

10g 的 sga_target 設置為0

Errors in file /oracle/app/oracle/diag/rdbms/LUOKLE/orcl1/trace/orcl1_ora_13107324.trc (incident=28001):

ORA-04030: out of process memory when trying to allocate 32808 bytes (TCHK^cadd45dc,kggec.c.kggfa)

經過分析發現 AIX stack 設置偏小導致,修改限制解決。

ERROR IN CONVERSION ORA-19624: operation failed, retry possible

ORA-19505:

failed to identify file "/aix_xtts/oradata2/f8rdl6vi_1_1"

ORA-27037: unable to

obtain file status

Linux-x86_64 Error: 2: No such file or directory

Additional

information: 3

ORA-19600: input file is backup piece

(/aix_xtts/oradata2/f8rdl6vi_1_1)

ORA-19601: output file is backup piece

(/aix_xtts/incr/xib_f8rdl6vi_1_1_6_8_10_12_14_16_18_20_22_)

CONVERTED BACKUP PIECE/aix_xtts/incr/xib_f8rdl6vi_1_1_6_8_10_12_14_16_18_20_22_

PL/SQL procedure successfully completed.

ERROR IN CONVERSION ORA-19624: operation failed, retry possible

ORA-19505:

failed to identify file "/aix_xtts/oradata2/f9rdl70m_1_1"

ORA-27037: unable to

obtain file status

Linux-x86_64 Error: 2: No such file or directory

Additional

information: 3

ORA-19600: input file is backup piece

(/aix_xtts/oradata2/f9rdl70m_1_1)

ORA-19601: output file is backup piece

(/aix_xtts/incr/xib_f9rdl70m_1_1_7_9_11_13_15_17_19_21_23_)

CONVERTED BACKUP PIECE/aix_xtts/incr/xib_f9rdl70m_1_1_7_9_11_13_15_17_19_21_23_

經過分析發現增量備份沒有放在對應目錄導致。

failed to create file

"/xtts/incr/xib_f9rdl70m_1_1_7_9_11_13_15_17_19_21_23_"

ORA-27040: file create

error, unable to create file

Linux-x86_64 Error: 13: Permission

denied

Additional information: 1

ORA-19600: input file is backup piece

(/xtts/oradata2/f9rdl70m_1_1)

ORA-19601: output file is backup piece

(/xtts/incr/xib_f9rdl70m_1_1_7_9_11_13_15_17_19_21_23_)

CONVERTED BACKUP PIECE/xtts/incr/xib_f9rdl70m_1_1_7_9_11_13_15_17_19_21_23_

PL/SQL procedure successfully completed.

ERROR IN CONVERSION ORA-19624: operation failed, retry possible

ORA-19504:

failed to create file

"/xtts/incr/xib_f8rdl6vi_1_1_6_8_10_12_14_16_18_20_22_"

ORA-27040: file create

error, unable to create file

Linux-x86_64 Error: 13: Permission

denied

Additional information: 1

ORA-19600: input file is backup piece

(/xtts/oradata2/f8rdl6vi_1_1)

ORA-19601: output file is backup piece

(/xtts/incr/xib_f8rdl6vi_1_1_6_8_10_12_14_16_18_20_22_)

CONVERTED BACKUP PIECE/xtts/incr/xib_f8rdl6vi_1_1_6_8_10_12_14_16_18_20_22_

NFS 目錄許可權問題導致不行讀寫,修改許可權解決。

NFS 問題:

mount: 1831-008 giving up on:

192.168.1.100:/xtts

vmount: Operation not permitted.

# nfso -p -o nfs_use_reserved_ports=1

Setting nfs_use_reserved_ports to 1

Setting nfs_use_reserved_ports to 1 in nextboot file

# mount -o cio,rw,bg,hard,nointr,rsize=32768,wsize=32768,proto=tcp,noac,vers=3,timeo=600 10.20.28.21:/xtts /aix_xtts

10

總結

XTTS 支持跨平台跨版本遷移,操作起來比較方便,由於停機時間較短,可以較輕鬆完成遷移工作,在大數據量的跨平台跨版本遷移場景中,建議作為首選方案。

建議在做 XTTS 遷移的時候減少批次,批次越多,增量備份的數據越少,數據越少,最後停機時間越短,但是這個過程如果做太多就越容易出錯。一般使用一次增量備份再做一次正式遷移,甚至初始化後直接做正式遷移。

11

附錄 - xttdriver.pl 腳本使用說明

Description of Perl Script xttdriver.pl Options

The following table describes the options available for the main supporting script xttdriver.pl.

資源下載

關注公眾號:數據和雲(OraNews)回復關鍵字獲取

『2017DTC』,2017 DTC 大會 PPT

『DBALIFE』,「DBA 的一天」海報

『DBA04』,DBA 手記4 經典篇章電子書

『RACV1』, RAC 系列課程視頻及 PPT

『122ARCH』,Oracle 12.2 體系結構圖

『2017OOW』,Oracle OpenWorld 資料

『PRELECTION』,大講堂講師課程資料


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 雲和恩墨 的精彩文章:

新增視圖找出外部 SCN 跳變

TAG:雲和恩墨 |