最近有一个同事问我一个问题,说他运行一个SQL语句抛出了ORA-00600的错误,想让我帮忙分析一下,这种问题听了确实有兴趣,了解了问题的大体情况之后,发现这个问题还是值得分析分析的,因为只是客户端调用抛出异常,没有给服务器端带来什么致命的影响,这样的问题还是很耐人寻味的。
简单沟通后,我得到了同事提供的SQL语句和执行环境,语句类似下面的形式:
MERGE INTO (SELECT * FROM TEST_SERVER_LOG WHERE BUY_TIME>=TO_DATE(:1 ,'YYYY-MM-DD HH24:MI:SS')
AND BUY_TIME @600.sql
explain plan for MERGE INTO (SELECT * FROM TEST_SERVER_LOG WHERE BUY_TIME>=TO_DATE(:1 ,'YYYY-MM-DD HH24:MI:SS')
*
ERROR at line 1:
ORA-00600: internal error code, arguments: [qcsfbdnp:1], [4], [], [25], [], [],
[], [], [], [], [], []
由此可见,这个语句在SQL解析的时候就会抛出问题。对于这个报错,在MetaLink上进行一番查找,发现相关的bug还真不少,锁定了一个较为符合的bug.
Bug 13496884 ORA-600 [qcsfbdnp:1] from Merge Statement with Bind Variables
是和执行Merge相关的,但是查看里面的解释,就是打补丁,没有其它的解决方法。
其实对于ORA-00600的错误,就类似开发中的NULLPointerException,这类问题的边界比较模糊,排查需要花费一些精力。
我的初步感觉就是问题可能出现在两个方面。
1.一个是TEST_SERVER_LOG这个表数据量非常大,是否在Merge中有一定的影响导致
2.语句中含有大量的绑定变量,是否绑定变量数过多导致了Merge的支持出现了问题
于是我朝着这个方向进行了分析和排查。我逐个替换了绑定变量,把它暂时替换为常量,发现错误依旧出现,只是错误的参数部分会有下标的变化。
直到我把整个using部分的绑定变量全部替换掉,最后竟然抛出了一个看起来不大相关的错误。
T.IP,T.WEAPONID,T.PUT_DATE,T.WEAPONID_NEW,T.COUNT,T.USER_CLASS,T.CONSUME_WAY,T.CLIENT_STYLE,T.GAME_TYPE)
*
ERROR at line 30:
ORA-00904: "T"."GAME_TYPE": invalid identifier
看这个问题,是字段不存在,仔细查看源表中的字段信息,发现这个字段还真是不存在,我是如获至宝,好像找到了问题的原因。
select game_type from TEST_SERVER_LOG where rownum select count(*)from dystat_bg.TEST_SERVER_LOG ;
COUNT(*)
----------
1
所以可以证明,这个bug和TEST_SERVER_LOG的数据量无关,和绑定变量的个数无关。
明白了这两点我们再来看看trace文件中的内容:
看到了这么一段,对我们分析这个ORA-00600的错误还是有一些帮助的。
----- Incident Context Dump -----
Address: 0x7fff07bebbc0
Incident ID: 324423
Problem Key: ORA 600 [qcsfbdnp:1]
Error: ORA-600 [qcsfbdnp:1] [4] [] [7] [] [] [] [] [] [] [] []
[00]: dbgexProcessError [diag_dde]
[01]: dbgeExecuteForError [diag_dde]
[02]: dbgePostErrorKGE [diag_dde]
[03]: dbkePostKGE_kgsf [rdbms_dde]
[04]: kgeadse []
[05]: kgerinv_internal []
[06]: kgerinv []
[07]: kgeasnmierr []
[08]: qcsfbdnp [SQL_Parser]