Oracle 12c PDB遷移及ORA-00600錯誤分析和解決(r10筆記第72天)
最近遷移一臺測試環境,準備整合到12c的PDB,常規的思路是用Datapump匯出匯入,對於資料較大的環境來說這個時間會比較長,為此自己也嘗試先升級這個測試庫,然後加入到CDB中去。
升級的過程就不多說了,其實對於大多數常規的業務來說,本身不是難點。
把升級後的NON-CDB加入到CDB中,基本是下面的思路,先把資料啟動到只讀模式,然後到處一個配置檔案,載入到CDB的重要地方就是使用這個配置檔案。先做檢查。
sqlplus / as sysdba SQL> select name, CDB from v$database; NAME CDB --------- --- TESTDB YES SET SERVEROUTPUT ON DECLARE compatible CONSTANT VARCHAR2(3) := CASE DBMS_PDB.CHECK_PLUG_COMPATIBILITY( pdb_descr_file => '/tmp/ncdb12c_actvdb.xml', pdb_name => 'NCDB12C') WHEN TRUE THEN 'YES' ELSE 'NO' END; BEGIN DBMS_OUTPUT.PUT_LINE(compatible); END; / NO PL/SQL procedure successfully completed.
仔細一看這個地方竟然輸出了NO,對於這種情況需要檢視下面的資料字典來得到更多的資訊。
select name,cause,type,message,status from PDB_PLUG_IN_VIOLATIONS where name='NCDB12C';
比如會有下面的資訊:
NAME CAUSE TYPE MESSAGE STATUS ---------- ------------------------------ --------- -------------------------------------------------- --------- NCDB12C Parameter WARNING CDB parameter optimizer_index_caching mismatch: PENDING Previous 90 Current 0 NCDB12C Parameter WARNING CDB parameter pga_aggregate_target mismatch: PENDING Previous 788M Current 6440M NCDB12C SQL patch error ERROR (PSU bundle patch 160719 (Database Patch Set PENDING Update : 12.1.0.2.160719 (23054246)): APPLY SUCCESS): with status in the PDB.
警告的資訊沒有大的影響,關鍵就在於ERROR
但是這個地方我就比較奇怪了,使用opatch lsinventory檢視,補丁是有的。而且其他的資料庫已經都部署多套了。這個為什麼就丟擲了這個問題呢。
為了儘快修復這個問題,我開啟生成的配置檔案,把SQL Patch的這一段資訊刪除了,然後再次執行上面的檢查指令碼就沒有問題了。
SQL> @a.sql
YES
PL/SQL procedure successfully completed.
基本的準備工作做完了,也算是有驚又險。
我們建立PDB,注意檔案路徑的對映。
SQL> CREATE PLUGGABLE DATABASE actvdb using '/tmp/ncdb12c_actvdb.xml' copy file_name_convert=('/U01/app/oracle/oradata/actvdb','/home/U01/app/oracle/oradata/testdb/pdb/actvdb'); Pluggable database created.
這個過程時間會持續稍長一些,不過因為是在本地,所以影響不大,建立好之後,嘗試open這個PDB,發現不大對勁。
SQL> alter pluggable database actvdb open; Warning: PDB altered with errors.
檢查這個PDB的狀態,發現是受限的會話連線。
SQL> show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
。。。
8 ACTVDB READ WRITE YES
突然醒悟,還有一個重要的指令碼沒跑,那就是
@$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql
一遍感嘆粗心大意,一邊趕緊執行指令碼。
執行的過程中檢視PDB的狀態是MIGRATE
SQL> SQL> show pdbs
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
。。。
8 ACTVDB MIGRATE YES
但是讓我有些意外的是這個指令碼執行失敗了,而且丟擲了ORA-00600的錯誤。
SQL> DECLARE
2 threads pls_integer := &&1;
3 BEGIN
4 utl_recomp.recomp_parallel(threads);
5 END;
6 /
DECLARE
*
ERROR at line 1:
ORA-04045: errors during recompilation/revalidation of SYS.DBMS_QOPATCH
ORA-00600: internal error code, arguments: [kql_tab_diana:new dep],
[0x4C7382A68], [0x7F97536569A0], [1], [2], [], [], [], [], [], [], []
ORA-06512: at "SYS.DBMS_UTILITY", line 1294
ORA-06512: at line 1
因為也不大確定這個的影響範圍,檢視PDB的狀態,發現是受限的會話連線。
SQL> show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
。。。
8 ACTVDB READ WRITE YES
嘗試反覆啟停,還是同樣的錯誤,眼看升級遷移的時間越來越緊,儘管是測試環境,還是不能麻痺大意。
對於這個問題,真是讓我一頭霧水,檢視MOS也沒有找到直接的解答,而檢視OTN的問答,發現有些朋友也確實碰到了。有人找到了根上,那就是編譯一個包的時候會丟擲ORA-00600的錯誤。
我試了下,確實如此。
SQL> ALTER PACKAGE "SYS"."DBMS_QOPATCH" COMPILE BODY REUSE SETTINGS ;
ALTER PACKAGE "SYS"."DBMS_QOPATCH" COMPILE BODY REUSE SETTINGS
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [kql_tab_diana:new dep],
[0x149CF37C0], [0x7F9BEA79DBD0], [1], [2], [], [], [], [], [], [], []
有些人嘗試重新建立編譯這個包,我在本地嘗試,發現還是丟擲了ORA-00600的錯誤。
SQL> @?/rdbms/admin/prvtqopi.plb
Session altered.
CREATE OR REPLACE PACKAGE BODY DBMS_QOPATCH wrapped
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [kql_tab_diana:new dep],
[0x149CF37C0], [0x7F9BEAB683B8], [1], [2], [], [], [], [], [], [], []
這個問題越發嚴峻,而我似乎只能找到一個有些相關的bug
Bug 20981713 : ORA-600 [KQL_TAB_DIANA:NEW DEP] DURING NONCDB_TO_PDB.SQL 過了一會兒之後,我再次嘗試停庫,然後重新啟動,發現竟然可以了。
當然我的內心是忐忑的,我深深知道很可能這個庫再停了之後就無法正常open了。
但是應用的連線能夠正常進來,也算是躲過了一劫,而馬上我就發現這個問題不是一般的糾結。因為我碰到了另外一個棘手的問題,那就是主庫雖然可以正常open了,忽略了裡面的警告,但是備庫的這個PDB卻偏偏無法正常open到read only狀態。
SQL> alter pluggable database all open;
alter pluggable database all open
*
ERROR at line 1:
ORA-01109: database not open
對於災備而言,這是極為嚴重,而且不合格的。但是問題的原因是什麼呢。
為了進一步實驗,我在備庫開啟了snapshot Standby,這樣備庫可讀可寫,就能夠模擬測試了,但是我發現問題是接二連三。
馬上發現這個PDB在open的時候報出了其它的ORA-00600錯誤。
Errors in file /home/U01/app/oracle/diag/rdbms/testdb2/testdb/trace/testdb_p005_24365.trc (incident=140313) (PDBNAME=ACTVDB):
ORA-00600: internal error code, arguments: [kqlobjlod-no-result-from-proc$], [1403], [888], [], [], [], [], [], [], [], [], []
Incident details in: /home/U01/app/oracle/diag/rdbms/testdb2/testdb/incident/incdir_140313/testdb_p005_24365_i140313.trc
Use ADRCI or Support Workbench to package the incident.
See Note 411.1 at My Oracle Support for error and packaging details.
檢視MOS 找到了文章,但是還是沒有解決的方法。
ORA-600 [kqlobjlod-no-result-from-proc$] (Doc ID 1613402.1)
在查看了不少的文章之後,隱隱發現是在這個Patch上。
因為我在Snapshot Standby中測試了下面的命令,發現似乎容器的Patch沒有生效。
$ ./datapatch -verbose
....
Installing patches...
Patch installation complete. Total patches installed: 7
所以在做了一個艱難的決定之後,我決定在主庫重新給這個PDB部署Patch,然後執行noncdb_to_pdb.sql
但是這樣做的風險就是這個PDB如果還是無法正常open,很可能的情況就是受限的會話連線,這樣的話我只能重新修復了,為此我花了些時間做了一個完整的邏輯備份,然後開始嘗試修復。
再次執行noncdb_to_pdb.sql的指令碼。
SQL> alter session set container=actvdb;
Session altered.
SQL> @$ORACLE_HOME/rdbms/admin/noncdb_to_pdb.sql
看到上次丟擲ORA-00600的地方會快就順利完成了,心裡總算鬆了口氣。然後嘗試open的時候發現這次丟擲了SQLPatch的Error
我在主庫端$ORACLE_HOME/OPatch下執行dbpach -verbose 短暫的等待之後,可以看到PDB已經部署了新的補丁。
Current state of SQL patches:
Bundle series PSU:
ID 160719 in the binary registry and ID 160719 in PDB ACTVDB
然後重啟PDB,就恢復了正常。
SQL> alter session set container=actvdb;
Session altered.
SQL> shutdown immediate
Pluggable Database closed.
SQL> startup
Pluggable Database opened.
SQL> show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
8 ACTVDB READ WRITE NO
而這個問題在備庫就立竿見影,再次嘗試啟動備庫的PDB。
使用alter pluggable database all open就沒有問題了。
SQL> show pdbs;
CON_ID CON_NAME OPEN MODE RESTRICTED
---------- ------------------------------ ---------- ----------
2 PDB$SEED READ ONLY NO
。。。
8 ACTVDB READ ONLY NO
SQL> select open_mode from v$database;
OPEN_MODE
--------------------
READ ONLY WITH APPLY
這個問題總算告一段落,而對於SQL Patch也有了更深一層的理解。