朋友一套12.2的RAC一节点CRASH, 发我一份alert log让帮着看看,crash的原因以后有时间再写,但是alert log中出现了大量的”WARNING: too many parse errors”,是以前的版本中从未见过,这也是12.2的新特性,自动生成解析失败的信息写入db alert log, 即使没有在数据库启用event 10035, 以前版本可以通过启用10035 event分析解决失败信息写入alert log.
一段db alert log
2017-11-21T04:22:55.526449+08:00 XXHCPDB(12):WARNING: too many parse errors, count=2996 SQL hash=0x117d3781 XXHCPDB(12):PARSE ERROR: ospid=56905, error=1446 for statement: 2017-11-21T04:22:55.526595+08:00 XXHCPDB(12):select rowid as "__Oracle_JDBC_internal_ROWID__", inv_objs from (select count(*) as inv_objs from dba_objects where status='INVALID') XXHCPDB(12):Additional information: hd=0x43f493be0 phd=0x4368401a0 flg=0x20 cisid=0 sid=0 ciuid=0 uid=0 XXHCPDB(12):WARNING: too many parse errors, count=2996 SQL hash=0x92a117b7 XXHCPDB(12):PARSE ERROR: ospid=56905, error=918 for statement: 2017-11-21T04:22:55.563449+08:00 XXHCPDB(12):select rowid as "__Oracle_JDBC_internal_ROWID__", ses,ac_ses,waits,ofn_files,fai_jobs,inv_objs,lck_objs from (select count(*) as ses from v$session),(select count(*) as ac_ses from v$session where status='ACTIVE'),(select count(*) as waits from v$session_wait),(select count(*) as ofn_files from v$datafile where status = 'OFFLINE'),(select count(*) as fai_jobs from dba_jobs where failures > 0),(select count(*) as lck_objs from v$locked_object),(select count(*) as inv_objs from dba_objects where status='INVALID') XXHCPDB(12):Additional information: hd=0x479b14608 phd=0xfc3e4728 flg=0x20 cisid=0 sid=0 ciuid=0 uid=0
Note:
从以上信息中可以看到的信息:
1, WARNING: too many parse errors
2, SQL HASH
3, SQL TEXT
4, SQL ERROR CODE
5, __Oracle_JDBC_internal_ROWID__
[oracle@anbob ~]$ oerr ora 1446
01446, 00000, “cannot select ROWID from, or sample, a view with DISTINCT, GROUP BY, etc.”
// *Cause:
// *Action:
[oracle@anbob ~]$ oerr ora 918
00918, 00000, “column ambiguously defined”
// *Cause:
SQL解析失败是一种常见现象,但是同一SQL频繁的解析失败会给数据库带来性能问题, 从AWR中的时间模型中同样可以发现parse, failed parse 占用较高的DB TIME, 以上DB Alert log中的输出是一种诊断信息的增强,可以默认把经常解决失败的信息写入db alert, 多数都是应用程序问题,解决方法自然是调整应用或SQL.
WARNING: too many parse errors 并不是每次解析都提示,默认是在同一SQL在60分钟内每出现100次就会提示一次worning到DB ALERT LOG. 对于这个阀值应该是有隐藏参数”_kks_parse_error_warning” 控制的。
SQL> @pd parse_error
Show all parameters and session values from x$ksppi/x$ksppcv...
NUM N_HEX NAME VALUE DESCRIPTION
---------- ----- ---------------------------- ------------- -------------------------
3080 C08 _kks_cached_parse_errors 0 KKS cached parse errors
3082 C0A _kks_parse_error_warning 100 Parse error warning
对于SQL文本是可以手动执行还原问题,ERROR 就是解析的错误ORACE的提示编号,这里的1446 是提示rowid 不能用于count这类汇总操作中。
对于SQL文本中的ROWID 和“__Oracle_JDBC_internal_ROWID__”应该不是程序员人为加入,ALERT中提示中出现了大量__Oracle_JDBC_internal_ROWID__字样,判断应该是ORACLE JDBC驱动自动附加的。
当JDBC 中scroll sensitive resultset 启用时,JDBC驱动就会在用户SQL中自动增加ROWID ,但是并不是所有的查询都适合附加rowid, 该功能是JDBC中对于结果集是否在数据改变后自动刷新,有TYPE_SCROLL_SENSITIVE和TYPE_SCROLL_INSENSITIVE两种,区别可以看这里。
–JAVA CODE Demo
try { Class.forName(driverName).newInstance(); connection = DriverManager.getConnection(url+dbName, userName, password); Statement stmt = connection.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY); ... if (res.getType() == ResultSet.TYPE_SCROLL_SENSITIVE) { System.out.println("ResultSet TYPE_SCROLL_SENSITIVE."); } ''' }
解决该类问题需要程序员了解TYPE_SCROLL_SENSITIVE的限制,修改SQL解析失败处代码ResultSet型的类