oracle dba手記-02dba工作網名Yangtingkun_第1頁
oracle dba手記-02dba工作網名Yangtingkun_第2頁
oracle dba手記-02dba工作網名Yangtingkun_第3頁
oracle dba手記-02dba工作網名Yangtingkun_第4頁
oracle dba手記-02dba工作網名Yangtingkun_第5頁
免費預覽已結束,剩余21頁可下載查看

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

(網(網現任云和恩墨CTO,ITPUB論壇Oracle數據庫管理版版主。2004年曾參與編寫《Oracle數據庫性能優化》一書,2007年被Oracle公司授予OracleACE稱號,喜歡研究Oracle相積累了1500多篇Oracle相關的技術文章。tingkunDBA工作編者按:老楊在網絡上的博客數年來一直維持著頻繁更新的記DBADBA的工作可以苦中作樂,也可以樂在其中,讓首先來看看老楊如何用SQL來為解釋一個魔術——利用SQL解釋一個一個偶然的機會在電視上看到一個有關牌的魔術,覺得很有意思。這個魔術明顯不是靠手快或者做來實現的,奧妙在于魔術中包含了數學原理。 的目標牌。讓觀眾牢記后將其放回到其余20張牌中,然后任意洗牌。下面開始進行發牌的工作,發牌和普通的發牌規則一樣。將牌發成3疊,每疊7張。將每疊牌依次示給觀眾,要求觀眾確認目標牌在3之后 3疊。讓對方確認目標牌所在的一疊,將這疊牌放到另外下面神奇的時刻到來了:從這疊牌的上面每次拿起一張,每拿起一張牌的同時要說一句話“你要相信魔術你的牌是。說完這句話,下一張牌就是目標牌了。位置,只要按照這個規則最后都一定會來到這個指定的位置。看了這個魔術,不禁有點手癢,既然是DBA出身,就用SQLSQL>WITHA(SELECTROWNUMPFROMDUALCONNECTBYLEVEL<=7+(7+(7+FROM21簡單地解釋一下這個SQL:設WITH查詢中的P表示這張牌的初始位置,這個位置的取值范圍是從1到21。而后將牌按照發牌的順序分成3份,于是這張牌的位置變為CEIL(P/3)。由于在魔術表演的過程中,目標牌7。魔術中上面的步驟重復了3次,因此在SQL中這個過程也重復3次,最終SQL返回的結果就是目標牌21根據計算結果可以看到,無論這張牌在哪里,最終都會達到第11張的位置。這也就是這個魔術的奧秘之不過SQL只是演示了結果,并沒有給出為什么會出現這種結果的答案,下面通過數學簡單分析一下:目標牌的那一份放到中間的位置。所以可以認為這張牌在中間位置第1到7的任何一個位置上,因此這張牌的位置就是7p。下面將牌分成三份,然后將目標牌堆放到中間,這時這張牌的位置變為77+p)/3。最后再重復一次這個動作,最終結果變為:7+(7+(7+p)/3)/3。對上面的表達式進行通分計算后,結果變成(7*97*37p)/9,進一步簡化變成(91p)/9,最后變成了10+(1+p)/9,而p的位置是1到7,也就是說無論取何值,(1+p)/9都不會大于1,所以最終的結果是11。最后,應該修改一下魔術中語:“你要相信數學你的牌是ORA-600(17069)錯誤的解決過FriFeb2008:16:44ErrorsinfileORA-00600:internalerrorcode,arguments:[17069],[0x6A5DEE1E0],[],[],[],[],[],[]FriFeb2008:16:472009ErrorsinfileORA-00600:internalerrorcode,arguments:[17069],[0x6A5DEE1E0],[],[],[],[],[],進一步檢查對應的trace文件bash-2.03$moreOracle9iEnterpriseEditionRelease9.2.0.4.0-64bitProductionWiththePartitioning,OLAPandOracleDataMiningoptionsJServerRelease9.2.0.4.0–ProductionORACLE_HOME=/data/oracle/product/920Systemname: Node Generic_117350- Instancename:repdb01Redothreadmountedbythisinstance:1Oracleprocessnumber:35Unixprocesspid:5099,image:oracle@newreport***SESSIONID:(12.28191)2009-02-20***2009-02-20ksedmp:internalorfatalORA-00600:internalerrorcode,arguments:[17069],[0x6A5DEE1E0],[],[],[],[],[],[]CurrentSQLstatementforthissession:DECLAREjobBINARY_INTEGER:=:job;next_dateDATE:=:mydate;brokenBOOLEAN:=FALSE;BEGIN0000032');:mydate:=next_date;IFbrokenTHEN:b:=1;ELSE:b:=0;ENDIF;-----CallStackTrace----argumentvaluesinhex(?meansdubiousvalue)FFFFFFFF7FFF6430000000000?00000000000000003EFFFFFFFF7FFF6CC81031D56C8000000000?0001034000001035D9?000102C001035D9000?1035D9C28從trace文件包含的進程名稱j015來看,導致問題是一個JOB。從trace文件中包含的錯誤語句則更加證實了JOB在數據庫中已經運行了很長時間,一直沒有出現過錯誤。現在運行報錯,肯定是由于其他的外部原因導致JOB運行的異常。大部分的ORA-600錯誤在Metalink上都有詳細的描述,于是查詢了Metalink:文檔DocID:39616.1中匯總了ORA-600(17069)錯誤的已知Bug,不過這些Bug的描述都與當前問題的現象并不太相符。不過文檔中還是包含了一些有價值的信息。文檔中描述ORA-600(17069)錯誤的第二個參數代表LibraryCacheObjectHandle,這里的值為0x6A5DEE1E0。看起來問題可能和LATCHV$LATCH和 JOB。根據的特性,在運行失敗后這個JOB會自動再次JOB運行時的V$LOCKSQL>SELECTADDR,TYPE,ID1,ID2,LMODE,REQUEST,2FROMV$LOCKWHERESID= 0000000690342780CU-6600 600在V$LOCK中沒有什么特別的信息,接著檢查V$SESSION_WAIT,看看這個JOBSQL>SQL>SELECTEVENT,P1TEXT,P1RAW,P2TEXT,P2RAW,2FROMV$SESSION_WAITWHERESID= librarycachepinhandleaddress00000006A5DEE1E0pinaddress00000006B1A971A8很明顯,查詢結果中P1RAW的值就是ORA-600(17069)錯誤的第二個參數,配合等待事件信息基本上可以確定問題就是出現在LIBRARYCACHEPIN的過程中。再次查看Metalink信息,Oracle這個錯誤的原因PROCEDURE在執行過程中,所依賴的對象被編譯或者刪除了。檢查出錯JOB所調用過程的狀態:SQL>SELECTOWNER,OBJECT_NAME,OBJECT_TYPE,FROMWHEREOWNER=ANDOBJECT_NAME=SQL>EXECDBMS_JOB.BROKEN(63,PL/SQLproceduresuccessfullycompleted.SQL>COMMIT;Commit果然,出錯過程的狀態是不正常的。在修正錯誤前SQL>EXECDBMS_JOB.BROKEN(63,PL/SQLproceduresuccessfullycompleted.SQL>COMMIT;Commit在操作系統級殺掉JOB對應SQL>SQL>SELECTSPIDFROMV$PROCESSWHEREADDRIN(SELECTPADDRFROMV$SESSIONWHERESID=75);SQL>HOSTkill-9SQL>ALTERPROCEDUREP_GENERATE_REPD ALTERPROCEDUREP_GENERATE_REPD *ERRORSQL>ALTERPROCEDUREP_GENERATE_REPD ALTERPROCEDUREP_GENERATE_REPD *ERRORatlineORA-04021:timeoutoccurredwhilewaitingtolockobject由于從V$LOCK和V$LATCH視圖中都P_GENERATE_REPDATASQL>SELECT*FROMWHERE(OWNER,OBJECT)(SELECTREFERENCED_OWNER,REFERENCED_NAMEFROMWHEREOWNER='FUJIANREP'ANDNAME=SID 545451rowsSQL>SELECTSID,SERIAL#,2FROMV$SESSIONWHERESID=54; SERIAL#USERNAME 26216PlSqlDev.exe沒想到是同事通過pldevelopSQL>SQL>SELECTSQL_TEXTFROM2WHEREADDRESSIN(SELECTSQL_ADDRESSFROMV$SESSIONWHERESID=54);ALTERALTER _S_MO_ENTRUNCATEPARTITION居然是TRUNCATE分區的操作,難怪會導致過程處于INVALID狀態,不過TRUNCATE操作應該不會持SQL>SELECTEVENT,P1TEXT,P1,P2TEXT,P2,P3TEXT,P3,2FROMV$SESSION_WAITWHERESID= P1 P2 P3dbfilesequential11701581這個TRUNCATE的等待時間已經超過10天了,很顯然這是一個僵死的會話。應從Kill掉對應的SQL>SELECTSQL>SELECTSPIDFROMV$PROCESSWHEREADDRIN(SELECTPADDRFROMV$SESSIONWHERESID=54);SQL>HOSTkill-9切換為FUJIANREPSQL>SQL>ALTERPROCEDUREProcedure至此問題解決。將JOB重新設置BROKENSQL>SQL>EXECDBMS_JOB.BROKEN(63,PL/SQLproceduresuccessfullycompleted.SQL>COMMIT;Commit問題解決后再次檢查過程,發現TRUNCATE語句居然就是這個過程的一部分。這個過程會先執行TRUNCATE,然后執行等DML語句系,數據庫中的會話變成僵死狀態停在了TRUNCATETABLE語句處。而執行者只是中止了客戶端的請求,并沒有進程的問題。JOB的運LOCK和LATCH,于是了上面的ORA-600(17079)錯誤。這也是隨后手工編譯PROCEDURE報錯ORA-4021的原V$SQL視圖顯示結果異常有一次碰到一個很奇怪的問題,在檢查會話所執行的SQL時,發現V$SQL視圖中SQL_TEXT列中的數由于V$SQL是動態性能視圖,里面保存的是當前共享池中加載的SQL語句,所以如果這個SQL不是執行很頻繁的話,那么它很可能會被替換出共享池。或者數據庫意外重啟,也會導致這個SQL徹底丟失。那么將顯示異常的V$SQL記錄備份到了BAK_V$SQL表中,首先看一下異常的SQLSQL>SELECTSQL_TEXTFROMinfo.CONTRACT_ITEM_ID,info.BUYER_ el未承諾'DISCOUNT_STEPisnullorINC.NUM_STEPisnullthento_char(INC.DISCOUNT_STEP*100,'0.0')||'%'劭勐?'||'未CASH.CASHisnullandCASH.CASH_THIRTYisnullthen'現款:'||to_char(CASH.CASH*100,'0.0''30日結款:'SH_THIRTYisnotnullcasewhendendasCASH_DISCOUNT,0,'0.0')||eninfo.modify_date>inc.modify_dateandinfo.modify_date>cash.modify_datethen顯然這個SQL語句是不正常的,語句中甚至連select、insert、update、delete命令都不包括。但是這個觀察這個SQL,第一感覺像是V$SQL視圖中顯示了部分SQL,而沒有從SQL語句的開頭部分開始顯示。而且即使是部分SQL,也不是連續顯示的,因為連續的兩行并不連貫。首先想到的就是Oracle的Bug,因為除了這一點,暫時沒有想到其他的原因來解釋這個現象。那么如果確實是由于Bug,導致V$SQLSQL又是什么呢,是否完整的SQL也會存在問題呢。剛才一直在查詢V$SQL視圖,下面不妨查詢一下V$SQLTEXT_WITH_NEWLINES視圖,看看這個視圖中的結SQL>SELECTSQL_TEXTFROM2WHEREHASH_VALUEIN(SELECTHASH_VALUEFROMBAK_V$SQL)ORDERBYPIECE;SELECT*FROMSELECTROWNUMasnumrow,yy.*from(WHEREnumrow>=32rows出乎意料的是,從V$SQLTEXT_WITH_NEWLINES中查詢,發現SQL的結果是正常的,而且V$SQL中顯示的內容在V$SQLTEXT_WITH_NEWLINES中都可以找到,只不過不是連續的。從這一點上看,似乎更可以肯定是Bug了。不過還存在幾個疑點:首先在Metalink上沒有發現類似的描述,難道存在一個還沒有發現的Bug其次對比兩個視圖的結果,二者的差異完全沒法解釋。V$SQL視圖中的SQL_TEXT截取了全部SQL語句的前1000個字節,而V_SQLTEXT_WITH_NEWLINES視圖則包含全部的SQL內容,但是查詢結果是分行顯示的。沒有道理顯示結果是完全正常的,事實上前1000個字節就出現了錯誤。而且錯誤出現得那么,很關鍵是找不到這個Bug的原因。如果確實是顯示問題,那么應該所有的SQL都會有問題。如果僅僅是這個SQL有問題,那么多半問題出在這個SQL本身。V$SQL中的SQL_TEXT字段長度為1000,對于長度大于1000的SQL,會顯示前面1000個字符。從V$SQLTEXT_WITH_NEWLINES視圖的結果看,SQL的長度肯定超過了1000,但從V$SQL中的查詢結果來看,長度應該遠遠小于1000。查詢一下V$SQLSQL_TEXT的具體長度SQL>SQL>SELECTLENGTH(SQL_TEXT)FROMBAK_V$SQL;長度 SQL>SELECTLENGTH(SQL_TEXT),SQL_TEXTFROMBAK_V$SQL;info.CONTRACT_ITEM_ID,info.BUYER_ el未承諾'DISCOUNT_STEPisnullorINC.NUM_STEPisnullthento_char(INC.DISCOUNT_STEP*100,'0.0')||'%'劭勐?'||'未CASH.CASHisnullandCASH.CASH_THIRTYisnullthen'現款:'||to_char(CASH.CASH*100,'0.0''30日結款:'SH_THIRTYisnotnullthencasewhendendasCASH_DISCOUNT,0,'0.0')||eninfo.modify_date>inc.modify_dateandinfo.modify_date>cash.modify_datethen這個格式不是很美觀,設置COLSQL>COLSQL_TEXTFORMATA70SQL>SELECTLENGTH(SQL_TEXT),SQL_TEXTFROMLENGTH(SQL_TEXT)info.TROWNUMasnumrow,yy.*from(selectinfo.CONTRACT_ITEM_ID,info.BUYER__IDasBUYER_ORwhenINC.DISCOUNT_STEPisnullorINC.NUM_'起付諾'EPisnullthento_char(額||to_char(INC.NUM_STEP||萬,折扣率||endasNUM_DISCOUNT,T_STEP*100,'0.0')||'%'whenCASH.CASHisnullandCASH.CASH_THIRcase信?isnullthen'現款||to_char(CSH.CASHisnotnullthenend''eASH.CASH*100,'0.0')||'%;''enCASH.CASH_THIRTYisnotnull30日結款||to_char(CASH.CASH_THIRTY*100,'0.0||casewhendendasCASH_DISCOUNT,eninfo.modify_date>inc.modify_dateandinfo.modify_date>cash.modify_datetheninfo.mo奇怪的事情出現了,不僅SQL_TEXT的長度內容被覆蓋掉了,而且SQL_TEXT的內容并沒有從到這里已經可以確定問題的原因了,為了更加精確的定位問題,將SQL_TEXT中的內容進行DUMP:SQL>SELECTDUMP(SUBSTR(SQL_TEXT,1,100),16)FROMBAK_V$SQL; SQL>SELECTSUBSTR(SQL_TEXT,1,100)FROMBAK_V$SQL;info.CONTRAumrow,yy.*from(從DUMP文件中已經可以清晰地看到問題的原因了,SQL語句中僅使用了ASCII(0XD)回車符,而沒有使用ASCII(0XA)換行。這會導致在Unix和Linux環境下,第二行的數據仍然從第一行的第一列位置開始輸出,SQL>SELECT'AB'||CHR(13)||'C'FROMDUAL;rowSQL>SELECT'AB'||CHR(10)||CHR(13)||'C'FROMDUAL;rowV$SQL中顯示不正常,而V$SQLTEXT_WITH_NEWLINES64個字SQL>SELECTREPLACE(SQL_TEXT,CHR(13),CHR(10)||CHR(13))FROMBAK_V$SQL;SELECT*FROMSELECTROWNUMasnumrow,yy.*from(selectinfo.CONTRACT_ITEM_ID,info.BUYER__IDasBUYER_ID,...endendascasewheninfo.modify_date>inc.modify_dateandinfo.modify_date>cash.modify_datethenBug的問Bug引起的,而是不同操作系統的差異導致了這個問題。在Windows環境中,一個回車符就足夠了,但是對于Unix和Linux環境,還需過程ORA-4068之錯誤解在運行一個過程了一 誤產生的原因,還要對概念有比較清晰的理解。下面用一個簡單的例子來重現錯誤:SQL>CREATETABLETASSELECT*FROM表已創SQL>CREATEORREPLACEPROCEDUREP_RECREATEEXECUTEIMMEDIATE'DROPTABLEEXECUTEIMMEDIATE'CREATETABLETASSELECT*FROM/過程已SQL>CREATEORREPLACEPROCEDUREP_INSERT_TINSERTINTOTSELECT*FROM/過程已SQL>/*第1行出現錯誤ORA-04068:已丟棄程序包的當前狀ORA-04065:未執行,已更改或刪除storedprocedure"TK.P_INSERT_T"ORA-06508:PL/SQL:無法找到正在調用:"TK.P_INSERT_T"的程序單元ORA-06512:在line3上面建立了兩個過程,在第一個過程P_RECREATE中,通過動態語句DROPTABLET,然后通過動態語句CREATETABLEASSELECT來重建T表。第二個過程P_INSERT_T則更簡單,就是根據T表的內容實現SQL>EXECPL/SQL過程已成功完成SQL>EXECPL/SQL過程已成功完成SQL>EXECPL/SQL過程已成功完成SQL>EXECPL/SQL過程已成功完成看到這個ORA-4068錯誤,首P_RECREATE過程對表進行刪除并重建的操作,這會導致所有和這個T表相關的過程變為INVALID狀態。由于T表結構在重建前面沒有發生變化,因此通過簡單的編譯,就可以使得P_INSERT_T因此,嘗試在調用過程之前重編譯P_INSERT_TSQL>EXECUTEIMMEDIATE'ALTERPROCEDUREP_INSERT_T/*第1行出現錯誤ORA-04068:已丟棄程序包的當前狀ORA-04065:未執行,已更改或刪除storedprocedure"TK.P_INSERT_T"ORA-06508:PL/SQL:無法找到正在調用:"TK.P_INSERT_T"的程序單元ORA-06512:在line4錯誤依舊。而且有趣的是,由于錯誤發生在調用P_INSERT_T過程中,所以alterprocedure命令顯然已經執行完成,而且已經成功了。而這個命令的執行成功說明P_INSERT_T過程的狀態已經恢復為VALID狀態了,SQL>EXECUTEIMMEDIATE'BEGINP_INSERT_T;/PL/SQL過程已成功完成如果使用動態SQL的方式調用P_INSERT_T過程,則不會報錯。過程在編譯時,會自動檢查語法錯誤、權限及所有對象的依賴性。而等到執行的時候,Oracle則不會當過程所依賴的對象發生了變化,Oracle會自動將過程的狀態置為INVALID,而過程的狀態如果為INVALID,則會在下次執行時嘗試重新編譯,如果編譯通過則繼續執行;如果編譯失敗則報錯。這就是上面例子中兩個過程單獨執行并不會報錯的原因。雖然P_RECREATE過程會重建T表,并導致P_INSERT_T過程失效,但是P_INSERT_T在調用時會嘗試重新編譯,而由于T的結構保持不變,所以編譯不會報錯,因此P_INSERT_T的調用就不會報錯。那么為什么兩個過程放到一起執行就會報錯且嘗試重新編譯也不起作用呢。這是由于導致P_INSERT_T失效的過程就在調用P_INSERT_T過程的塊中。在將塊提交給Oracle時,Oracle對里面每個過程的狀態進行了檢查,由于導致P_INSERT_T失效的P_RECREATE過程還沒有執行,因此這時所有過程的狀態都是正常的。于是Oracle記錄了過程的狀態信息并開始調用過程。在調用P_RECREATE過程后,由于T表被刪除重建,P_INSERT_T的狀態發生變化,但此時Oracle對過程P_INSERT_T的檢查已經完成,因此在嘗試直接運行P_INSERT_T的代碼時發現P_INSERT_T的狀態已經發生變化,所以這里報錯ORA-4068。同樣的道理,即使對P_INSERT_T進行了重新編譯,Oracle在執行時發現檢查時的代碼已經發生了變化,當前的P_INSERT_T和調用時的P_INSERT_T已經發生了變化,因此仍然會報錯,即使這時過程的狀態已而采用動態SQL不會報錯的原因就更容易理解了。采用動態SQL語句,Oracle將編譯時進行的操作推遲到運行時進行。也就是說Oracle會在調用P_RECREATE之后,在調用P_INSERT_T過程之前對P_INSERT_T進行檢查并重新編譯,所以采用動態SQL不會報錯。一次網絡連接錯誤的教,還是在網絡上搜索結果,這兩點同樣也是關鍵信息。當前這個錯誤簡單的描述就是:在通過9i的客戶端連接10g的rac環境時出現了ORA12054錯誤。E:\>sqlplusSQL*Plus:Release10.2.0.1.0Productionon星期二5月818:40:182007Copyright(c)1982,2005,Oracle.s.輸令ORA-12504:TNS:程序在CONNECT_DATA中未獲得有了錯誤信息就可以根據線索進行進一步的檢查;也可以通過進一步的檢查來縮小錯誤可能發生的范圍。比如隨后進行的tns檢查,就發現當前TNS配置正常: Utilityfor32-bitWindows:Version10.2.0.1.0Productionon08-5月-200718:42:00Copyright(c)1997,2005,Oracle.s.已使用TNSNAMESAttemptingtocontact(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.25.198.224)(PORT1521(CONNECT_DATA(SERVERDEDICATED)(SERVER_NAMEtestrac)))OK(10毫秒)tns正常,說明檢查主機名和端口是正常的,這就縮小了查找錯誤的范圍繼續進行檢查,嘗試在TESTRAC服務名的配置中添加(SID=TESTRAC1)信息,這時SQLPLUS可以問題可能發生的范圍被進一步縮小了。現在多半由于SERVICE_NAME的配置出現了錯誤。不過當前的錯誤和普通SERVICE_NAME出錯時的錯誤又有所不同。再次仔細檢查,最終發現在手工編輯tnsnames.ora時出現了拼寫錯誤,將SERVICE_NAME拼寫為SERVER_NAME,由此導致了上面錯誤的產生。將其改正后,錯誤。TESTRAC=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=172.25.198.224)(PORT=1521))(CONNECT_DATA=(SERVER=(SERVICE_NAME=))E:\>sqlplusSQL*Plus:Release10.2.0.1.0Productionon星期二5月818:52:522007Copyright(c)1982,2005,Oracle.s.輸令連接到OracleDatabase10gEnterpriseEditionRelease10.2.0.3.0-64bitProductionWiththePartitioning,RealApplicationClusters,OLAPandDataMiningoptionsTESTRAC的配置中SID也沒有設置SERVICE_NAME,從而導致了這個ORA-12504錯誤的產生。同時,這個錯誤也說明Oracle并不對tnsnames.ora淺談JOB和DatabaseLink的一個特曾經遇到一個比較“奇怪”的錯誤,JOB自動運行報錯,但是手工執行不會出錯,而且手工執行job運行的仔細研究后發現問題是JOBDatabaseLink二者特性的共同作用造成的。SQL>conntk/SQL>select*fromSQL>select*from21-10月-在當前用戶下沒有建立數據庫鏈,但是建有一個到rep.tingkun的公用數據庫鏈。在當前用戶下執行select*fromtab@rep.tingkun會找到并使用這個公用數據庫鏈。注意一點,這個數據庫鏈的USERNAME為空,也就是說,在建立數據庫鏈的時候沒有指定CONNECTCREATEPUBLICDATABASELINKREP.TINGKUNUSING 如果沒有給出CONNECTTO語句,在調用數據庫鏈的時候,會用當前session的用戶名、去遠端SQL>createorreplaceprocedurep_test 3forcin(select*fromtingkun)45end67/過程已SQL>execPL/SQL過程已成功完成SQL>v_jobdbms_job.submit(v_job,'p_test;',sysdate,'sysdate+/PL/SQL過程已成功完SQL>selectjob,what,next_date,interval,failures,brokenfromuser_jobs;JOBWHAT NEXT_DATEINTERVAL FAILURESB-6 01-12月-04sysdate+ 0將過程加入JOB中SQL>SQL>selectjob,failures,brokenfromuser_jobs; FAILURESB- 8經過一段時間檢查JOB,發現已經出現了8次錯誤SQLexecdbms_job.run(6);PL/SQL過程已成功完成。SQL>selectjob,failures,brokenfromuser_jobs; FAILURESB-0手工執行JOB等待一段時間后,再次查看。發現JOBSQL>SQL>selectjob,failures,brokenfromuser_jobs; FAILURESB - 16這時檢查alert_test.logWedDec0119:16:51ErrorsinfileORA-12012自動執行作業6ORA-01005nullpasswordgiven;logondeniedORA-06512:在"TK.P_TEST",line3ORA-06512line根據上面這些信息可以判斷:JOB在自動執行的時候,雖然是以當前用戶執行,但是并不包含當前用戶的信息。而手工執行JOB時,由于運行在當前用戶的session中,帶有當前用戶的用戶名和信息,所以如果比較清晰地了解Oracle數據庫鏈和JOB一次ORA-01041錯就是在數據庫時出現了ORA-01041錯誤。2006-7-32006-7-3ORA-錯誤,hostdefSELECT*FROM(SELECTROWNUMasnumrow,zz.*from(SELECTID,URL,MEMBER_TYPE, HH24:mi:ss')>0)zzWHEREROWNUM<=2000)WHEREnumrow>=1這個錯誤倒是不陌生。在一個SQLPLUS客戶端連接到Oracle的過程中,Oracle數據庫執行了關閉和啟動的操作,且在關閉數據庫時這個SQLPLUS的連接并沒有退出。那么這個SQLPLUS客戶端有很大的可能性會碰到這個ORA-1041錯誤。一旦出現了這個錯誤,無論使用什么用戶進行重新連接都沒有作用,必須退出SQLPLUS,再重新啟動SQLPLUS才行。這說明SQLPLUS工具的狀態已經不正確了。僅這錯誤息是夠的判問的原還要相的息比如據的本、臺以及是在何種情況下出現了上面的錯誤。因此我提出需要數據庫的版本和操作系統的信息,最好將數據庫的alert在等待回復的過程中,我在Metalink上查詢了一些有關ORA-1041錯誤的信息。看看是否有其他未知的Bug會導致這個錯誤的產生。不過缺少數據庫版本信息和平臺信息,無法確定Oracle描述的Bug與當前的問題是否相符,因為絕大部分Bug都是在特定的版本、特定的平臺上出現的。直到我得到完整的錯誤日志文件才發現做了很多的無用功:根本沒有必要去查詢Metalink首先,這個錯誤信息不是記錄在Orace的aert文件中,而是在應用程序打印的日志信息里。其次,提供給錯誤只是整個錯誤文件中次數最多的錯誤,而并不是所有的錯誤信息。不但漏掉了其中的幾個關鍵錯誤信息,而且導致問題產生的第一個錯誤也沒有提及。ORA-12571TNS:包寫入程序失ORA-03114:未連接到OralceORA-03113:通信通道的文件結束只須通過上面的這3個錯誤信息,馬上就可以定位到問題。由于會話連接到Oracle的時間超過了交換器上空閑時間的設置,導致這個連接直接被交換器切斷,使得應用程序處于不正常的狀態,最終導致了上面的那個ORA-01041錯誤。如果一開始就把完整的錯誤日志發送過來,問題可以很快解決。很多時候能否準確地定位問題完全取決于信息提供的是否準確和完整。其實找出問題的最好方式是通過自己的提煉,能用一個簡單的例子重現問題。如果這點無法做到或者很難做到,那么最起碼應該提供充足的信息。這是定位、分析和解決問題的基礎。如果錯誤日志中報了30多個錯誤,而你對其中一個進行分析,顯然得到的結果也是片面的、確的。在MetalinkOracle的技一個ORA-604錯誤的分同事遇到一ORA-604錯誤,分析一下感覺還比較有趣。出錯的SQL大致如下:SQL>CREATETABLET_604SELECT*(SELECTOBJECT_TYPE,TO_CHAR(AVG(OBJECT_ID),'999999.999')FROMGROUPBYORDERBY2WHEREROWNUM<(SELECTOBJECT_TYPE,TO_CHAR(AVG(OBJECT_ID),'999999.999')FROM*第3行出現錯誤ORA-00604遞歸SQL層1ORA-01401:的值對于列過DBA,因此對這個錯誤比較困惑,不清楚為什么SELECT語句直接執行沒有任何的問題,而根據SELECT的查詢結果去創建表卻出現了錯誤,因此同事認為可能是空間分配上出現了問題。SQL>SELECT*(SELECTOBJECT_TYPE,TO_CHAR(AVG(OBJECT_ID),'999999.999')FROMGROUPBYORDERBY2WHEREROWNUM< DATABASELINKRULEEVALUATIONXML9一般來說,ORA-604錯誤很少直接出現在用戶調用的SQL中。對于本例的情況,后面的那個錯誤信息才是真正錯誤的原因。也就是說真正的錯誤是后面的那個ORA-1401錯誤。這個ORA-1401錯誤很好理解的值比表中列的定義值要大不過CREATETABLEASSELECT 其實問題很簡單,導致錯誤的真正原因是列名長度太長了,因此只需將上面的CREATETABLE語句改變SQL>CREATETABLET_604(OBJECT_TYPE,AVG_OBJECT_ID)SELECT*(SELECTOBJECT_TYPE,TO_CHAR(AVG(OBJECT_ID),'999999.999')FROMGROUPBYORDERBY2WHEREROWNUM<表已創SQL>DROPTABLE表已刪SQL>CREATETABLET_604SELECT*(SELECTOBJECT_TYPE,TO_CHAR(AVG(OBJECT_ID),'999999.999')FROMGROUPBYORDERBY2WHEREROWNUM<表已創當用戶執行ddl操作時,Oracle通過大量的遞歸調用來數據字典。比如這個CREATETABLE語句,Oracle就會或更新TAB$、COL$等表。這些操作都是遞歸調用操作,而在遞歸調用過程中出現的錯誤就會報錯ORA-604。出錯的SQL語句由于沒有指定別名,Oracle會將查詢語句中的字段名稱作為CREATETABLE語句的列名。也就是說,Oracle試圖將TO_CHAR(AVG(OBJECT_ID),'999999.99')作為列名,而這個列名的長度顯然超過了列長度30個字符的限制,因此Oracle在數據字典表時出現ORA-1401錯誤。SQL,一個是CREATETABLE時就指定SELECT時為超長的列指定了別名。因此這兩個SQL都不會出現列名超長的問題。當然這個錯誤的產生還有一定的條件:如果是TO_CHAR(AVG(OBJECT_ID),999999.999')直接出現在SELECT的外層,在CREATETABLE的時候,Oracle會明確要求用戶提供別名。SQL>CREATETABLET_604SELECTOBJECT_TYPE,TO_CHAR(AVG(OBJECT_ID),FROMGROUPBYORDERBY2SELECTOBJECT_TYPE,TO_CHAR(AVG(OBJECT_ID),*第2行出現錯誤ORA-00998:必須使用列別名命名此表達而這個錯誤就要比前面的ORA-604和ORA-1401錯誤直觀ORA-7445(kdodpm)錯在進行LogMiner操作時碰到了這個錯誤。下面描述一下錯誤的起因及解決的過程由于要查看被程序刪除的一些記錄,因此對重做日志進行了LogMiner的操作:SQL>altersessionsetnls_date_format='yyyy-mm-ddhh24:mi:ss';會話已SQL>select*fromGROUP#THREAD# BYTESMEMBERSARC _CHANGE#1132852YES-07-282132862YES-07-283132872NO-07-284132842YES-07-275214572NO-07-276214542YES-07-267214552YES-07-2688214562YES-07-26SQL>selectmemberfromv$logfilewheregroup#in(3,5); PL/SQL過程已成功完 PL/SQL過程已成功完SQLexecdbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog)PL/SQL過程已成功完成。SQL>createtablet_logminertablespace asselect*fromv$logmnr_contentswhereseg_owner=''andseg_name=createtablet_logminertablespace*第1行出現錯誤ORA-03113:通信通道的文件SQL>execdbms_logmnr.end_logmnrORA-03114未連接到O本來一個很簡單的操作,沒想到遇到了錯誤。一般前臺出現ORA-3113錯誤 多半出現ORA-7445ORA-600錯誤alertTueTueJul2816:04:24ErrorsinfileORA-07445:出現異常錯誤: 轉儲[kdodpm() [0xFFFFFFFF79270002][][]在alert文件中果然出現了ORA-7445錯誤,錯誤參數為kdodpm。檢查這個錯誤對應的trace***2009-07-28***SERVICENAME:(SYS$USERS)2009-07-28***SESSIONID:(282.47827)2009-07-28*kjdrpkey2hv:calledwithpkey207480,options***2009-07-28Exceptionsignal:11(SIGSEGV),code:2(Invalidpermissionsformappedobject),addr:0xffffffff79270002,PC:[0x10285aa34,kdodpm( ***2009-07-28ksedmp:internalorfatalORA-07445:出現異常錯誤:轉儲[kdodpm() ][SIGSEGV][Invalidpermissionsformappedobject][0xFFFFFFFF79270002][][]CurrentSQLstatementforthiscreatetablet_logminertablespaceasselect*fromv$logmnr_contentswhereseg_owner=''andseg_name=-----CallStackTrace----

argumentvaluesinhex(?meansdubiousvalue) 000000300?1066DE17C000000000?1066DAC701066D99D8?1066DA3D8顯然問題是LogMiner操作造成的。Oracle從9i開始就提供了LogMiner功能,到10g已經比較穩定了,再加上平時使用LogMiner很少出現錯誤,那么此次出錯應是由于一些特殊的操作或配置導致的。如果說當前這個LogMiner操作與其他普通的操作有什么不同的話,那么主要是兩點:一個是當前為RAC環境,LogMiner要同時對兩個實例的日志進行分析;另一個就是當前分析的日志是ONLINE日志。由于RAC環境的日志對于任何一個實例都是可以的,理論上不大可能出現上面的問題,可見多半是SQL>conn/asSQL>altersessionsetnls_date_format='yyyy-mm-dd會話已SQL>selectgroup#,statusfromv$logwherestatus='CURRENT';GROUP#STATUS352SQL>selectmemberfromv$logfilewheregroup#in(3,5);4SQL>altersystemarchivelog系統已SQL>selectgroup#,statusfromv$logwherestatus='CURRENT';GROUP#STATUS462PL/SQL過程已成功完成SQLexecdbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog)PL/SQL過程已成功完成。SQL>createtablet_logminertablespaceasselect*fromwhereseg_owner='andseg_name=表已創切換日志后LogMiner分析的日志不再是ONLINE函數索引產生隱藏發現這個問題其實比較偶然,在一次執行LOGMNR操作時發現了空的列名。由于這個現象很奇怪且以前有一次,由于需要撤銷一些已經提交的數據,且提交時間超過了可閃回的時間范圍,因此只能采用LOGMNR進行處理。而處理過程中,發現得到的SQLSQL>CONNSYS@YTK102AS會話已SQL>SELECTGROUP#,_TIMEFROMV$LOG;GROUP#_TIME12008-01-1822008-01-2032008-01-16SQL>SELECTMEMBERFROMV$LOGFILEWHEREGROUP#=2;SQL>ALTERSYSTEMSWITCHLOGFILE;系統已PL/SQL過程已成功完SQL>EXECDBMS_LOGMNR.START_LOGMNR(OPTIONS=>PL/SQL過程已成功完SQL>SELECTSQL_UNDOFROMV$LOGMNR_CONTENTSWHERESEG_NAME=insertinto"TK"."T_LOGMNR"("ID","NAME","")valuesinsertinto"TK"."T_LOGMNR"("ID","NAME","")valuesinsertinto"TK"."T_LOGMNR"("ID","NAME","")values可以看到T_LOGMNR表的最后一列是一個空列,而這個列所對應的值也是NULL。SQL>名是否為空?NOTNULLSQL>SELECTTABLE_NAME,COLUMN_NAMEFROM2WHERETABLE_NAME='T_LOGMNR'ANDOWNER='TK'; 從數據字典中找不到這個空列的信息。根據經驗,有些用戶無須關心的輔助列在Oracle顯示的,想要查詢隱藏列只能直接查詢COL$表:SQL>SELECTOBJECT_IDFROM WHEREOBJECT_NAME='T_LOGMNR'ANDOWNER='TK';SQL>SELECTNAMEFROMCOL$WHEREOBJ#=53636;通過查詢DBA_OBJECTS視圖得到OBJECT_ID的值。COL$表中可以根據這個值找到表現在 SQL>SELECTNAME,DEFAULT$FROMCOL$WHEREOBJ#=53636; 由于是自動生成的列,Oracle也會自動來,因此這個列擁有DEFAULT$值。根據這個DEFAULT值可SQL>SELECTINDEX_NAME,INDEX_TYPE,UNIQUENESSFROMWHERETABLE_NAME=ANDTABLE_OWNER=' SQL>SELECT

FUNCTION-BASEDNORMAL

WHERETABLE_NAME=ANDTABLE_OWNER='ANDINDEX_NAME='IND_T_LOGMNR_NAME';用SQL解決一道有趣的Oracle的SQL的數學方法進行手工分析將會十分麻煩,而使用SQL來求解則要簡單得多。Gauss和Poincare在相遇了,上帝說:都是人間最偉大的數學家,那我來出道題考考誰更聰明11001100的數,然后把他們的和Gauss手上,把積寫在Poincare手上,看看能不能猜出這兩個數字是幾。Gauss看了手上的數字,說:“我不知道這兩個數字是幾,可我保證Poincare也不知道。”Poincare看了手上的數字,說:“我原來的確不知道那兩個數字是幾,可我現在知道了。”Gauss說:“那我也知道了。”1和100之間。題目中明確說明的條件僅此而已,剩下的條件就要依靠分析才能得出了。對于Gauss來說他知道兩個數之和,而不知道兩個數的積,但是Gauss卻肯定的說,他保證Poincare也不知道這兩個數是什么。這句話就很有深意。舉個例子,如果兩個數分別是3和7,那么這兩個數之積就是21。由于這兩個數都是大于1的,因此兩個數乘積為21的只有3和7這一種可能。如果Poincare手中的值是21,那么Poincare肯定可以確定這兩個數是什么,因此對于Gauss

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論