近期遇到一套windowsX64+Oracle11.2.0.1版本数据库,遇到一条使用了6个绑定变量值的插入sql出现了5000多个sql version,正常情况下此sql在早上8-9点要执行300-500次左右,当应用程序反应慢时,查看此sql version达到5000多;用户前一段时间在应用反应慢时,即通过重启数据库来解决此问题(用户并没有查找原因,单纯的用重启大法来试一次的),只是近期此问题出现频率较高,达到了隔一天需要重启一次。用户很着急,需要找到root cause并提出可靠的解决方案。
1.alert日志分析重启信息
接到此case后,首先远程获取了数据库的 alert日志,通过日志可以分析出近期数据库重启的时间点。通过搜索Starting ORACLE instance关键字,可以发现近期有如下重启记录:
2.重启前AWR/ASH报告分析
根据重启记录,来获取重启前的AWR/ASH报告信息,来辅助分析当时数据库的性能问题。
在数据库AWR中主要分析了多次重启前AWR中的如下信息,发现均是SQL_ID为22j335m33haq6的SQL在当时出现SQL版本多达5000多个,执行次数为0,同时占用较多的cpu time.与正常时刻同时段AWR对比,此SQL应该执行500次左右,与应用软件确认,此SQL确实是业务需要的,无法执行会导致业务执行不下去。对比重启后当天多个时间段的AWR,可以发现此SQL的version count不断上涨,上午重启的数据库,11-12点AWR中大约为1000多个version count,到16-17点已经增加到3000多个;基本确定是此问题导致应用反应慢,从而重启数据库。如下为AWR中的部分信息,相关库名、表名已经做处理。
DB Name | DB Id | Instance | Inst num | Startup Time | Release | RAC |
TEST1 | 1234563 | test1 | 1 | 02-5月 -17 09:05 | 11.2.0.1.0 | NO |
Host Name | Platform | CPUs | Cores | Sockets | Memory (GB) |
TEST | Microsoft Windows x86 64-bit | 16 | 8 | 1 | 127.91 |
| Snap Id | Snap Time | Sessions | Cursors/Session |
Begin Snap: | 4594 | 04-5月 -17 08:00:08 | 134 | 9.0 |
End Snap: | 4595 | 04-5月 -17 09:00:22 | 176 | 12.6 |
Elapsed: |
| 60.23 (mins) |
|
|
DB Time: |
| 66.89 (mins) |
|
|
SQL ordered by CPU Time部分信息:
CPU Time (s) | Executions | CPU per Exec (s) | %Total | Elapsed Time (s) | %CPU | %IO | SQL Id | SQL Module | SQL Text |
167.59 |
|
| 6.76 | 175.16 | 95.68 |
| 22j335m33haq6 |
| insert into TAB1... |
121.43 | 7 | 17.35 | 4.90 | 143.38 | 84.69 | 0.00 | 0cg9rcdhth5g1 | ORACLE.EXE | SELECT "A1".",... |
116.39 | 1 | 116.39 | 4.69 | 360.43 | 32.29 | 0.00 | 3acc5vt9hy5an |
| DECLARE job BINARY_INTEGER := ... |
SQL ordered by Sharable Memory部分信息:
Sharable Mem (b) | Executions | % Total | SQL Id | SQL Module | SQL Text |
107,972,000 |
| 1.09 | 22j335m33haq6 |
| insert into TAB1... |
94,107,328 |
| 0.95 | 934hswduksnzr |
| update TAB set B2,... |
SQL ordered by Version Count部分信息:
Version Count | Executions | SQL Id | SQL Module | SQL Text |
5,518 |
| 22j335m33haq6 |
| insert into TAB1... |
3,406 |
| 134q4yp2jdqh7 |
| insert into tab2... |
1,466 |
| 510d5hzgjw63d |
| update TAB3 set RE... |
1,369 |
| 4vs91dcv7u1p6 |
| insert into sys.aud$( sessioni... |
1,341 |
| d3cj1bqhzcfym |
| update tab4 set... |
1,060 |
| f711myt0q6cma |
| insert into sys.aud$( sessioni... |
3.解决方法:
1.建议协调应用软件开发商调整此INSERT SQL,改为不使用绑定变量插入数据(使用绑定变量的insert语句确实有较大概率出现SQL多版本的问题),来缓解此问题。
2.设置定时任务,每天在业务运行前刷新一次shared_pool(如早上6点),来缓解此问题。
3.当前数据库版本为11.2.0.1版本,这是11gR2的基础版本,存在着较多的软件bug等,建议升级到11.2.0.4版本。
这里最终使用的是定时刷共享池的方法,设置了定时任务每天早上6点刷共享池,同时多版本的SQL还有审计记录的语句也一并关闭audit参数等设置,目前已经正常运行一周多。
4.SQL多版本问题参考文档:
SQL多版本相对来说比较复杂,特别是在11.2.0.1版本,新特性与bug交织,如自适应游标共享等,不太方便问题排查,一般简单粗暴方法就是定时刷共享池(高并发生产环境需慎重做好评估)或找出容易出现多版本的语句由应用软件来配合做一些修改,当然在11gr2还有一个隐含参数_cursor_obsolete_threshold,此参数用来限制单个parent cursor下child cursor的数量,默认值为100。
如果child cursor的数量超过了这个阈值就会触发cursor obsolescence的特性,此时parent cursor会被废弃,同时新建parent cursor。 这样虽然mismatch会继续存在,但是一劳永逸的解决的high version count的问题。这个patch已经集成到11.2.0.3版本。如果低于11.2.0.3版本,除了需要应用这个patch(Bug 10187168),同时需要设置的相关参数在文档文档296377.1中也有说明,如有需要可以进行设置。
同时MOS上提供了判断SQL多版本原因的脚本,可以快速、全面的收集SQL出现多版本的原因(cursor不能共享的原因,上一篇blog里就在写cursor不能共享的事情)。
SQL多版本问排查可以参考如下MOS文档:
Troubleshooting: High Version Count Issues (文档 ID 296377.1)
SQL 版本数过高 – 原因判断脚本 (文档 ID 1985045.1)