2021/1/27日上午,某客户反映业务系统反映卡顿,通过查询操作系统性能,未有明显异常。通过v$session中查看active状态的会话以及对应等待事件及blocking session,可以发现数据库中存在大量的热块等等,在Oracle数据库的早期版本,热块等待的典型等待事件是buffer busy wait,后来又有了新的等待事件read by other session以及集群等待事件gc buffer busy等,关于read by other session?参考文档:文档 ID 732891.1解释如下:
This wait event occurs when we are trying to access a buffer in the buffer cache but we find that the buffer is currently being read from disk by another user so we need to wait for that to complete before we can access it.  In previous versions, this wait was classified under the "buffer busy waits" event. However, in Oracle 10.1 and higher, the wait time is now broken out into the "read by other session" wait event.
Excessive waits for this event are typically due to several processes repeatedly reading the same blocks, e.g. many sessions scanning the same index or performing full table scans on the same table. Tuning this issue is a matter of finding and eliminating this contention.

1.本次问题,初步来看是由于TOP SQL引起的热块问题,因此一开始集中精力查看TOP SQL。通过收集AWR及v$session中查看active状态的会话SQL_ID,很快就定位到了SQL语句。对此SQL使用awrsqrpt.sql进行信息收集,可以发现SQL的执行计划有多个,当前的确实不是最优。

一次非典型的SQL效率问题分析-read by other session_执行计划

2.于是通过coe_load_sql_profile脚本进行执行计划绑定,这是个12C使用PDB的数据库环境,绑定动作完成后,检查v$session中查看active状态的会话,等待事件仍然为read by other session以及集群等待事件gc buffer busy等,而SQL执行计划也使用了绑定的最优执行计划。

一次非典型的SQL效率问题分析-read by other session_oracle_02

继续问题排查…………

3.在上述绑定动作后,SQL执行计划效率依然较低,通过排查,SQL已经使用最优执行计划,但是read by other session与gc buffer busy依然存在。

一次非典型的SQL效率问题分析-read by other session_执行计划_03

4.其实问题排查到这里,如果对于read by other session的定义很熟悉,这个问题一下子就能找到。而这些年随着主机的大内存普及,由于buffer cache内存不足导致SQL物理读多、buffer cache 命中率低等情况基本很少出现,对于buffer busy wait、latch:cache buffers chain等buffer cache相关等待事件,出现频率已经变少。遇到这类问题通常第一反应就是SQL性能问题,如用了全表扫描等情况并且高并发的查询,极少考虑buffer cache过小问题。这次我按照SQL优化思路,发现了SQL执行计划变化,做了绑定,性能依然不理想;我当时的反应是还有其它未被发现的问题,继续分析AWR报告,并很快在AWR中发现了问题:数据库的内存设置不合理,主机内存252GB,只给数据库SGA分配49GB,而SGA中shared_pool 29GB,buffer cache只有7G多;

一次非典型的SQL效率问题分析-read by other session_oracle_04

 

5.问题的处理

发现此问题后,检查发现数据库参数中未指定buffer cache的最小值,即完全使用了SGA自动内存管理。我通过人工修改buffer cache(分多次每次增加400M左右,最终buffer cache大约10GB,已经无法再扩大),此SQL的性能逐渐恢复正常。

6.问题总结:

整个问题的逻辑是:1.数据库SGA内存设置没有结合操作系统 的内存来设置,与OS内存相比SGA过小。 

2. SGA自动内存管理情况下,应用程序的SQL写法不够好带来了shared_pool的不断增长,buffer cache不断shrik并最终导致SQL需要大量物理读。

3.SQL执行计划变化(较大可能与buffer cache变小后CBO计算的COST有关),导致性能问题进一步严重,出现大量read by other session、gc buffer busy,平均读取时间达到10ms以上。

因此后续人工临时设置buffer cache到10GB左右,问题就得到了解决。后续很快在晚上停机时间进行了内存调整,后续数据库运行稳定。

此次问题排查不足之处:这次性能问题,一开始排查思路还是正常的,找到问题SQL后,基于此业务已经稳定运行很久,因此第一反应是SQL执行计划、执行频率等方面排查问题。而发现SQL执行计划变化并绑定为正确的后,问题并未解决,此时基于等待事件的排查未进行,而是从AWR中仔细分析找问题,虽然最终也找到了问题,但是这次如果从等待事件及其原因来分析,会更快。还是有点经验主义,并且太久没遇到过buffer cache过小的问题,脑子中未第一时间排查此种可能………,而排查和描述此类热块问题,在2014年初的blog中已经有写过

一次非典型的SQL效率问题分析-read by other session_执行计划_05

一次非典型的SQL效率问题分析-read by other session_oracle_06

相关的参考MOS文档:

Resolving Issues Where 'read by other session' Waits When I/O is Slow (Doc ID 1477229.1)
Resolving Issues Where 'read by other session' Waits Occur When I/O is NOT Slow and Cause is Unknown (Doc ID 1476081.1)
WAITEVENT: "read by other session" Reference Note (Doc ID 732891.1)