一个SQL语句引发的ORA-00600错误排查(一)

最近有一个同事问我一个问题,说他运行一个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<to_date(:2 ,'yyyy-mm-dd="" hh24:mi:ss')                                AND PUT_DATE=TO_DATE(:3 ,'YYYY-MM-DD')) T
                   USING(SELECT
                           TO_CHAR(:4 ) AS SN,
                           TO_NUMBER(:5 ) AS GROUP_ID,
                           TO_NUMBER(:6 ) AS SERVER_IP,
                           TO_CHAR(:7 ) AS SERVER_NAME,
                           TO_NUMBER(:8 ) AS WORD,
                           TO_NUMBER(:9 ) AS SERVER,
                           TO_NUMBER(:10 ) AS SCENE,
                           TO_CHAR(:11 ) AS CN_GUID,
                           TO_DATE(:12 ,'YYYY-MM-DD HH24:MI:SS') AS BUY_TIME,
                           TO_NUMBER(:13 ) AS JEWEL_TOTAL,
                           TO_CHAR(:14 ) AS CN,
                           TO_CHAR(:15 ) AS CHARACTER_PUT,
                           TO_CHAR(:16 ) AS IP,
                           TO_NUMBER(:17 ) AS WEAPONID,
                           TO_DATE(:18 ,'YYYY-MM-DD') AS PUT_DATE,
                           TO_NUMBER(:19 ) AS WEAPONID_NEW,
                           TO_NUMBER(:20 ) AS COUNT,
                           TO_NUMBER(:21 ) AS USER_CLASS,
                           TO_CHAR(:22 ) AS CONSUME_WAY,
                           TO_NUMBER(:23 ) AS CLIENT_STYLE,
                           TO_CHAR(:24 ) AS GAME_TYPE
                         FROM DUAL) A
                   ON (T.SN=A.SN)
                   WHEN NOT MATCHED THEN
                   INSERT(T.SN,T.GROUP_ID,T.SERVER_IP,T.SERVER_NAME,T.WORD,T.SERVER,T.SCENE,T.CN_GUID,T.BUY_TIME,T.JEWEL_TOTAL,T.CN,T.CHARACTER_PUT,
                   T.IP,T.WEAPONID,T.PUT_DATE,T.WEAPONID_NEW,T.COUNT,T.USER_CLASS,T.CONSUME_WAY,T.CLIENT_STYLE,T.GAME_TYPE)
                   VALUES(A.SN,A.GROUP_ID,A.SERVER_IP,A.SERVER_NAME,A.WORD,A.SERVER,A.SCENE,A.CN_GUID,A.BUY_TIME,A.JEWEL_TOTAL,A.CN,A.CHARACTER_PUT,
                   A.IP,A.WEAPONID,A.PUT_DATE,A.WEAPONID_NEW,A.COUNT,A.USER_CLASS,A.CONSUME_WAY,A.CLIENT_STYLE,A.GAME_TYPE)
这样一个语句看起来结构挺复杂,细看逻辑其实倒不复杂。最近处理了几个性能问题,其实有不少都是和Merge的使用有关,这个语句有什么问题呢,目前来看没有直接的问题,唯一的感觉是绑定变量不少啊,另外需要补充一下,数据库版本是11.2.0.3
    拿到语句要分析的时候,能够复现问题是非常难得的机遇,有很多的ORA-00600错误要复现需要上下文环境触发一定的条件才可以复现,这个问题让我省了不少事,我在alert日志中也发现了对应的trace文件。当然这类的trace文件说实话还是蛮枯燥的,看起来基本都是朦朦胧胧。
    我没有花太多时间在这个trace上,转而尝试去复现这个问题,
首先我通过v$sql去数据库中查看这个SQL语句,结果查找的很仔细,竟然没有任何的信息,仿佛这个语句没有执行过一般。
然后我切换到属主用户下,尝试生成执行计划。庆幸的是这个时候问题可以复现出来了。
SQL> @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<2
       *
ERROR at line 1:
ORA-00904: "GAME_TYPE": invalid identifier
临时修复了这个问题,把这个字段先去掉,语句就可以正常解析了,但是问题的原因是什么呢,这个时候还是稀里糊涂。我尝试在using子句中再次添加一个绑定变量,问题再次出现。
ERROR at line 1:
ORA-00600: internal error code, arguments: [qcsfbdnp:1], [7], [], [2], [], [],
[], [], [], [], [], []
所以这个时候我的一个初步结论是,这个错误和绑定变量的个数没有关系,这个问题的直接原因还是因为语句中的一个字段不匹配导致。
那么这个问题是否和数据量有关呢,在咨询了开发的同事之后,发现字段不匹配的问题还是存在一些误解,因为开发提供的用户是另外一个,属主和我测试的也完全不一样。测试的用户中的这个TEST_SERVER_LOG的数据量情况如下:
SQL> 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]<-- Signaling
[09]: qcpibva []
[10]: qcpiapr []
[11]: qcpiafa []
[12]: qcpiaex []
[13]: qcpifn1 []
[14]: qcpifun []
[15]: qcpiapr []
[16]: qcpiafa []
[17]: qcpiaex []
[18]: qcpiexl []
报错编码是[qcsfbdnp:1], [7], [], [2], [], [],  这个代表的含义在这个日志中可以看到是熟悉SQL解析器的部分调用出现了问题。
而我们分析问题的时候就可以重新审视这个语句,看看是否存在一些隐患。后续我们继续补充。

时间: 2024-09-19 20:42:55

一个SQL语句引发的ORA-00600错误排查(一)的相关文章

一个SQL语句引发的ORA-00600错误排查

作者介绍 杨建荣,[DBAplus社群]联合发起人.现就职于搜狐畅游,Oracle ACE-A.YEP成员,超7年数据库开发和运维经验,擅长电信数据业务.数据库迁移和性能调优.持Oracle 10G OCP,OCM,MySQL OCP认证,<Oracle DBA工作笔记>作者.   Merge是从Oracle 9i就引入的功能,它是有别于其他DML中的一种特殊语句,类似于MySQL中的 insert into on duplicate key操作,而且Merge功能更丰富,可以同时对一个表中的

一个SQL语句引发的ORA-00600错误排查(二)

继昨天一个SQL语句导致的ORA-00600错误之后,我给出了背景和初步的分析结果,今天来给出我的结论,当然说明原因不是我的本意,还有反思. 首先语句类似这样的形式: MERGE INTO (SELECT * FROM TEST_SERVER_LOG WHERE BUY_TIME>=TO_DATE(:1 ,'YYYY-MM-DD HH24:MI:SS')                                AND BUY_TIME<to_date(:2 ,'yyyy-mm-dd=&q

在oracle 数据库中查看一个sql语句的执行时间和SP2-0027错误_oracle

进入sqlplus SQL> set timing on SQL> SQL> select count(*) from comm_human_role; COUNT(*) ---------- 866 Elapsed: 00:00:00.05 以上数字输出分别是:Hours:Minutes:Seconds.Milliseconds 即用了0.05秒的时间执行,相当于50毫秒. 时间如果是这样的表示:00: 03: 235.78 总共用的时间为235.78秒, 不到4分钟,所以显示的是3分

怎么写出一个sql语句来表示销售的配件的数量

问题描述 怎么写出一个sql语句来表示销售的配件的数量 String sql = "select '配件A' label,12 value " + "union all " + "select '配件B' label,10 value "; 来修改这个sql来表示表中的内容 解决方案 啥玩意,你这不是已经有这些数据了吗,还要改什么

需要写一个SQL语句,大神帮我吧!在线等

问题描述 需要写一个SQL语句,大神帮我吧!在线等 我有一张产品供货价的表ProductPrice,该表有五个字段,分别是id,ProductID(外键关联产品ID),ChannelID(外键关联渠道ID),CustomerTypeID(外键关联客户类型ID),PriceSupply(供货价), 该表有三个外键,我最终的目的是得到该外键对应的供货价,其中一个ID变了供货价肯定就变了.看一下该表的的结构和数据. 但是我页面上只有两个下拉框控件,一个是客户,一个是产品.我只能拿到这两个对应的ID,渠

sql语句-表T(A)包含正整数,可能有重复,构造一个SQL语句查询不在表T中的最小正整数

问题描述 表T(A)包含正整数,可能有重复,构造一个SQL语句查询不在表T中的最小正整数 表T(A)包含正整数,可能有重复,构造一个SQL语句查询不在表T中的最小正整数,需要考虑表T包含或不包含正整数1两种情况.不能编程实现.考虑了半天没有很好的思路,请大家指点则个 解决方案 DECLARE @minvalue INT = select min(A) from T IF minvalue > 1 return 1 ELSE DECLARE @maxvalue INT = select max(A

sql语句-请教一个SQL语句如何写?

问题描述 请教一个SQL语句如何写? 求助大侠:表A中有字段a,b,c,d,e,f,但并不是所有字段都一定有值,其中有值字段原值为'201xxxx'现在要将有值字段由'201xxxx'替换为'2001xxxx',无值字段保留为空,请问SQL语句如何写?(其中'201xxxx'中的xxxx代表数字,比如20101或201010101,位数不定,也可能只为201)请赐教. 解决方案 update [A] set [a] = left(a2)+'0'+right(alen(a)-2) [b] = le

求教这两张表有什么联系写一个sql语句呀!

问题描述 求教这两张表有什么联系写一个sql语句呀! ![ 解决方案 一个sql语句 怎么写比较好在同一个sql语句中写不同条件的count数量,和查询半年的数据自学数据库之一个自己写的SQL语句 解决方案二: 库存管理里面的商品product_id 和商品管理里的no,是同一个值么,如果不是的话,那商品管理表里面还有一部分看不到的字段呢? 解决方案三: 解决方案四: 两张表的第一个ID字段是不是同一个?

mysql 如何通过一个sql语句搜出比例关系

问题描述 mysql 如何通过一个sql语句搜出比例关系 例如 一个表格里有 商品,价格,日期 三个字段 a 10.2,20151008 a 9.2,20151009 a 7.2,20151010 b 11.2,20151008 b 10.2,20151008 我要搜 在历史上各个商品价格低于10¥的次数占该商品出现的总次数的百分比,应该如何写mysql语句呢? 谢谢了 搜出结果要类似 a 2/3 b 0/2 这样的sql语句怎么写呢? 解决方案 假设表名是ProductPrice, 商品,价格