在协助其他部门迁移数据库的过程中,在一台9201服务器上发现了这个错误。
查询METALINK,发现ORA-600(16515)错误对应两种情况,一种是分区执行了SPLIT操作以后,再次收集统计信息报错。这种情况受影响的版本是9206和9207,在9208被fixed。
另一种是由于表中以及存在了统计,导致收集列的统计信息报错,可能发生这种情况的版本就包括9201。从版本上怀疑是第二种情况,下面登陆问题数据库具体检查一下。
Errors in file d:\oracle\admin\newzb\udump\newzb_j000_772.trc:
ORA-00600: 内部错误代码,参数: [16515], [D], [21], [39643], [5], [0], [], []
ORA-06512: 在"SYS.DBMS_STATS", line 9136
ORA-06512: 在"SYS.DBMS_STATS", line 9616
ORA-06512: 在"SYS.DBMS_STATS", line 9800
ORA-06512: 在"SYS.DBMS_STATS", line 9854
ORA-06512: 在"SYS.DBMS_STATS", line 9831
ORA-06512: 在line 1
从服务器上alert文件中发现上面的错误,从对应的TRACE文件中找到出现问题JOB用户NI_JL013和JOB语句:
DECLARE job BINARY_INTEGER := :job; next_date DATE := :mydate; broken BOOLEAN := FALSE; BEGIN DBMS_STATS.GATHER_SCHEMA_STATS(USER, METHOD_OPT => 'FOR ALL INDEXED COLUMNS'); :mydate := next_date; IF broken THEN :b := 1; ELSE :b := 0; END IF; END;
用NI_JL013用户登陆,手工执行收集统计信息的操作:
SQL> EXEC DBMS_STATS.GATHER_SCHEMA_STATS(USER, METHOD_OPT=>'FOR ALL INDEXED COLU
MNS');
BEGIN DBMS_STATS.GATHER_SCHEMA_STATS(USER, METHOD_OPT=>'FOR ALL INDEXED COLUMNS'
); END;
*
ERROR 位于第 1 行:
ORA-00600: 内部错误代码,参数: [16515], [D], [40], [39643], [10], [0], [], []
ORA-06512: 在"SYS.DBMS_STATS", line 9136
ORA-06512: 在"SYS.DBMS_STATS", line 9616
ORA-06512: 在"SYS.DBMS_STATS", line 9800
ORA-06512: 在"SYS.DBMS_STATS", line 9854
ORA-06512: 在"SYS.DBMS_STATS", line 9831
ORA-06512: 在line 1
检测USER_TABLES的LAST_ANALYZED列,找出问题表T_INVITE_M_DIVIDE:
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T_INVITE_M_DIVIDE', METHOD_OPT =>
'FOR ALL INDEXED COLUMNS')
BEGIN DBMS_STATS.GATHER_TABLE_STATS(USER, 'T_INVITE_M_DIVIDE', METHOD_OPT => 'FO
R ALL INDEXED COLUMNS'); END;
*
ERROR 位于第 1 行:
ORA-00600: 内部错误代码,参数: [16515], [D], [40], [39643], [10], [0], [], []
ORA-06512: 在"SYS.DBMS_STATS", line 9136
ORA-06512: 在"SYS.DBMS_STATS", line 9150
ORA-06512: 在line 1
现在问题已经定位到表上了,根据metalink文档Note 2252824.8的描述,删除统计信息,然后重新收集,可以解决这个问题:
SQL> EXEC DBMS_STATS.DELETE_TABLE_STATS(USER, 'T_INVITE_M_DIVIDE')
PL/SQL 过程已成功完成。
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T_INVITE_M_DIVIDE', METHOD_OPT =>
'FOR ALL INDEXED COLUMNS')
PL/SQL 过程已成功完成。
想要重现问题也很简单,只需要使用ANALYZE语法收集一下统计信息就可以了:
SQL> ANALYZE TABLE T_INVITE_M_DIVIDE COMPUTE STATISTICS FOR ALL INDEXED COLUMNS;
表已分析。
SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T_INVITE_M_DIVIDE', METHOD_OPT =>
'FOR ALL INDEXED COLUMNS')
BEGIN DBMS_STATS.GATHER_TABLE_STATS(USER, 'T_INVITE_M_DIVIDE', METHOD_OPT => 'FO
R ALL INDEXED COLUMNS'); END;
*
ERROR 位于第 1 行:
ORA-00600: 内部错误代码,参数: [16515], [D], [40], [39643], [10], [0], [], []
ORA-06512: 在"SYS.DBMS_STATS", line 9136
ORA-06512: 在"SYS.DBMS_STATS", line 9150
ORA-06512: 在line 1
通过对问题的分析,除了将数据库版本升级到9202以上外,还可以通过修改统计信息脚本的方式来避免问题。
在每次收集统计信息前,可以先执行DBMS_STATS.DELETE_SCHEMA_STATS,这样随后的统计信息收集工作就不会报错了。
不过这要求统计信息统计的工作比较在夜里没有工作进行的时候运行,否则在DELETE_SCHEMA_STATS和GATHER_SCHEMA_STATS之间登陆的用户,很可能会使用RBO作为优化模式。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/4227/viewspace-217085/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/4227/viewspace-217085/