[轉]ORA-00979: not a GROUP BY expression報錯處理


本文轉自:http://blog.itpub.net/29154652/viewspace-772504/

環境:Oracle Database 11gR2(11.2.0.2) on Linux 
故障現象: 執行Group By語句報錯ORA-00979。
具體的SQL如下:
SQL> select  a.d1,a.EXIT_type,round(a.cnt1/b.cnt2*100,2) from 
  2  (select substr(LOGIN_DATE,1,8) d1,EXIT_type,count(*) cnt1 from xxx_connect_log group by substr(LOGIN_DATE,1,8),EXIT_type) a,
  3  (select substr(LOGIN_DATE,1,8) d2 ,count(*) cnt2 from xxx_connect_log group by substr(LOGIN_DATE,1,8) ) b   4  where A.d1=B.d2 order by a.d1,a.EXIT_type; (select substr(LOGIN_DATE,1,8) d2 ,count(*) cnt2 from xxx_connect_log group by substr(LOGIN_DATE,1,8) ) b                                                                    * ERROR at line 3: ORA-00979: not a GROUP BY expression
 
這條語句在其他大區的DB上執行均OK,在體驗服DB上執行報錯。從語法上看,確實是完全沒問題的。
 
碰到這種ORA-報錯的情況,我們可以通過設置ErrorStack對錯誤堆棧進行跟蹤,將錯誤的后台信息比較詳盡的轉儲到跟蹤文件,供分析研究。
 
ErrorStack的四個級別及說明:
0 Error stack only 
1 Error stack and function call stack 
2 As level 1 plus the process state 
3 As level 2 plus the context area 
 
ErrorStack僅在特定的錯誤出現的時候才被觸發。可以在實例或者會話級別進行設置。
 
下面我們進行979的ErrorStack跟蹤:
SQL> alter system set events='979 trace name errorstack forever,level 3';
System altered.
SQL> select  a.d1,a.EXIT_type,round(a.cnt1/b.cnt2*100,2) from    2  (select substr(LOGIN_DATE,1,8) d1,EXIT_type,count(*) cnt1 from xxx_connect_log group by substr(LOGIN_DATE,1,8),EXIT_type) a,   3  (select substr(LOGIN_DATE,1,8) d2 ,count(*) cnt2 from xxx_connect_log group by substr(LOGIN_DATE,1,8) ) b   4  where A.d1=B.d2 order by a.d1,a.EXIT_type; (select substr(LOGIN_DATE,1,8) d2 ,count(*) cnt2 from xxx_connect_log group by substr(LOGIN_DATE,1,8) ) b                                                                    * ERROR at line 3: ORA-00979: not a GROUP BY expression 
 
SQL> alter system set events='979 trace name errorstack off';
System altered. 
 
alert日志中的內容:
Fri May 31 13:19:20 2013
OS Pid: 29652 executed alter system set events '979 trace name errorstack forever,level 3'
Errors in file /u/ora11g/diag/rdbms/xxxtest/xxxtest/trace/xxxtest_ora_29652.trc:
ORA-00979: not a GROUP BY expression
Fri May 31 13:19:27 2013
Dumping diagnostic data in directory=[cdmp_20130531131927], requested by (instance=1, sid=29652), summary=[abnormal process termination].
Fri May 31 13:19:52 2013
OS Pid: 29652 executed alter system set events '979 trace name errorstack off'
 
對應的跟蹤文件是: /u/ora11g/diag/rdbms/xxxtest/xxxtest/trace/xxxtest_ora_29652.trc
我們來查看跟蹤文件中具體的信息:
dbkedDefDump(): Starting a non-incident diagnostic dump (flags=0x0, level=12, mask=0x0)
----- Error Stack Dump -----
ORA-00979: not a GROUP BY expression
----- Current SQL Statement for this session (sql_id=d2ccw741whuh0) -----
select  a.d1,a.EXIT_type,round(a.cnt1/b.cnt2*:"SYS_B_0",:"SYS_B_1") from
(select substr(LOGIN_DATE,:"SYS_B_2",:"SYS_B_3") d1,EXIT_type,count(*) cnt1 from xxx_connect_log group by substr(LOGIN_DATE,:"SYS_B_4
",:"SYS_B_5"),EXIT_type) a,
(select substr(LOGIN_DATE,:"SYS_B_6",:"SYS_B_7") d2 ,count(*) cnt2 from xxx_connect_log group by substr(LOGIN_DATE,:"SYS_B_8",:"SYS_B
_9") ) b
where A.d1=B.d2 order by a.d1,a.EXIT_type
 
----- Call Stack Trace -----
calling              call     entry                argument values in hex      
location             type     point                (? means dubious value)     
-------------------- -------- -------------------- ----------------------------
skdstdst()+36        call     kgdsdst()            000000000 ? 000000000 ?
                                                   7FFFA7A0B468 ? 000000001 ?
                                                   000000001 ? 
                                                   
...
 
在跟蹤文件中,我們看到針對我們發出的SQL,在Oracle底層已經將一些數據替換成了綁定變量,這個是因為我們設置了cursor_sharing=FORCE的。
 
那么對於這個SQL,是否是因為cursor_sharing這個設置導致group by報錯了呢?
查詢了metalink,Cursor_sharing確實有對應的Bug會導致這個報錯:
 
8913729 11.2.0.2, 12.1.0.0 ORA-979 with CURSOR_SHARING=SIMILAR or FORCE
 
文檔上宣稱是11.2.0.2中是修復了此Bug的。但我們的環境就是11.2.0.2的哦。搞毛?
 
通過Oracle的堆棧信息確認了是bug 8913729。
類似的堆棧信息如下:
kgesev <- kgesec0="" -="" qcuerroer="" qcuerroep="" erroep="" em=""> <- qecgoc="" -="" qecsel="" qecpqbcheck="" qecdrv="" em="">  <- kkqcttcalo="" -="" kkqctdrvit="" apadrv="" pitca="" em="">
 
解決方法:
以下幾種都可以解決:
1:通過設置CURSOR_SHARING=EXACT;
2:在SQL語句中使用hint  /*+ CURSOR_SHARING_EXACT */;
3:設置optimizer_features_enable參數為10.2.0.5或者11.1.0.7(現在的值是11.2.0.2)。
 
我們選擇第2種方式來解決:
修改后的SQL如下:
select  /*+ CURSOR_SHARING_EXACT */ a.d1,a.EXIT_type,round(a.cnt1/b.cnt2*100,2) from 
(select substr(LOGIN_DATE,1,8) d1,EXIT_type,count(*) cnt1 from xxx_connect_log group by substr(LOGIN_DATE,1,8),EXIT_type) a,
(select substr(LOGIN_DATE,1,8) d2 ,count(*) cnt2 from xxx_connect_log group by substr(LOGIN_DATE,1,8) ) b
where A.d1=B.d2 order by a.d1,a.EXIT_type;
 
已證實可行。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM