抛出错误_如何找到抛出ORA00933错误的SQL
前幾天上線,凌晨3點多打車回來的路上,兄弟聯系我,提了一個問題,某核心系統,上線的時候,報了很多ORA-00933的錯誤,明顯是應用寫的SQL出現了錯誤導致的,但是因為未將出錯的SQL打印到日志中,所以不知道究竟是什么SQL出錯了,由于邏輯中涉及到很多的SQL,逐個排查,非常耗時。
ORA-00933,意思是“SQL command not properly ended”,明顯是SQL的語法出現錯誤,但是現在的問題,就是如何找到錯誤的SQL?
第一種考慮,能不能從數據字典視圖中找到?
我們執行如下這兩條SQL,第一條是錯誤的,提示ORA-00933,第二條是正確的,
SQL>?select?object_id?from?t?whereobject_id=1;select?object_id?from?t?whereobject_id=1
??????????????????????????????????????*
ERROR?at?line?1:
ORA-00933:?SQL?command?not?properly?ended
SQL>?select?object_id?from?t?where?object_id=1;
no?rows?selected
此時通過dba_hist_sqltext檢索不到任何SQL,
SQL>?select?sql_id,?sql_text?from?dba_hist_sqltext?where?sql_text?like?'%select?object%';no?rows?selected
dba_hist_sqltext是展示在AWR中采集到的屬于共享SQL游標的SQL語句,
究其原因,如果SQL語句沒有達到AWR的threshold值,是不會記錄到 dba_hist_sqltext中的。但是,我們在執行完SQL后手動創建快照,就可以在dba_hist_sqltext中看到,如下所示,但是,只出現執行正確的這條SQL,提示ORA-00933的SQL,并未采集到,
SQL>?exec?dbms_workload_repository.create_snapshot();PL/SQL?procedure?successfully?completed.
SQL>?select?sql_id,?sql_text?from?dba_hist_sqltext?where?sql_text?like?'%select?object%'
??2??and?sql_text?not?like?'%dba_hist_sqltext%';
SQL_ID??????????SQL_TEXT
-------------?--------------------------------------------------------------------------------
366bf1pphk8vp?select?object_id?from?t?where?object_id=1
我們知道,一條SQL在Oralce中執行的過程,會經過下圖中的幾個階段,在解析階段,會進行SQL的語法檢查、語義檢查以及共享池中查找是否存在執行過的SQL,如上ORA-00933錯誤,應該發生在語法解析階段,所以尚未到達執行階段,AWR未采集這條SQL,就可以解釋通了,
第二種考慮,使用Logminer能從日志中得到SQL?
我們知道Logminer是可以從在線/歸檔日志中解析出曾經執行過的SQL語句,其實從上面,我們已經知道,ORA-00933錯誤的SQL根本沒到執行階段,因此從原理上看,不可能寫入日志,就無從通過Logminer得到需要的SQL。
P.S.
關于Logminer的使用,可以參考我的好朋友老楊的文章《Logminer:oracle人為誤操作之恢復神器》。
當時沒想到其他的方法,唯一的做法就是讓應用改程序,打印出錯的SQL到日志中,這種方法其實很直接,但是畢竟涉及到了改動,還是帶來了不便。
后來看了惜分飛老師的文章,有了另外的考慮,SQL語句執行解析失敗最大的可能性就是SQL語句語法/權限錯誤,對于這類問題可以通過設置event 10035進行跟蹤,
http://www.xifenfei.com/2019/06/failed-parse-elapsed-time.html
打開10035事件,執行SQL,
SQL>?alter?system?set?events?'10035?trace?name?context?forever,?level?1';System?altered.
SQL>?select?object_id?from?t?whereobject_id=1;
select?object_id?from?t?whereobject_id=1
??????????????????????????????????????*
ERROR?at?line?1:
ORA-00933:?SQL?command?not?properly?ended
SQL>?alter?system?set?events?'10035?trace?name?context?off';
System?altered.
就可以在alert日志中,看到如下信息,error=933,就是ORA-00933,第二行的SQL,就是要找的,
PARSE?ERROR:?ospid=18911,?error=933?for?statement:select?object_id?from?t?whereobject_id=1^@
但是這種方法,需要注意,因為一旦打開10035,任何解析錯誤的SQL都會輸出到alert日志中,如果對并發量很高的系統,碰巧解析錯誤的會執行多次,可能瞬時導致磁盤空間壓力,因此Oracle中任何的event,我們在使用前,一定要知道他的副作用,避免帶來影響。
現在我們在做的一項工作,就是制定《軟件運維能力成熟度模型》,旨在通過設定一些通用的運維需求,采用分級的形式,從定量和定性,兩個維度,評估軟件的可運維能力,并給出提升指導。其中一項,就是應用執行錯誤的SQL語句需要打印到應用日志中,包括SQL原文、報錯信息、參數等,一方面為監控報警提供數據,另一方面便于問題的排查。
一般的開發人員只會關注系統的功能實現,對其他層面,例如性能、運維等,考慮的很有限,這就對系統運行和問題排查,會產生些影響,或者造成不便,此時,我們就可能需要其他的方法來解決,像上面介紹的10035,但歸根結底,一款軟件如果要運營的持久,除了系統架構要滿足功能,還需要為系統的可擴展性、可維護性等買單,當然,有人說過,“好的系統,不是設計出來的,而是演進來的”,不是說所有的問題都能在設計之初考慮到,但是當出現問題的時候,及時吸取教訓,在設計上完善,就算是一種改進,值得做。
總結
以上是生活随笔為你收集整理的抛出错误_如何找到抛出ORA00933错误的SQL的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: struts2找不到action_第一次
- 下一篇: 大一java期末考笔试_大学java期末