等待事件统计信息--Wait Events Statistics
视图v$session,v$session_wait,v$session_wait_history,v$session_event,v$system_event提供了等待哪些资源以及每种资源等待的时间(timed_statistics参数为TRUE)等信息。
进行性能调优时,调查等待事件以及相关的计时数据,占用最多时间的事件常常是性能瓶颈的标志。
下面介绍常用的等待事件:
buffer busy waits
1、描述
该等待事件显示多个进程试图同时访问缓冲区缓存中的一些缓冲区。查询V$waitstat可得到每个缓冲区的等待统计信息。具有缓冲区繁忙等待的公共缓冲区类包括数据块、段头、撤销头和撤销块。
SQL> SELECT t.name,
t.parameter1,
t.parameter2,
t.parameter3,
t.wait_class
FROM v$event_name t
WHERE t.name = 'buffer busy waits';
NAME PARAMETER1 PARAMETER2 PARAMETER3 WAIT_CLASS
-------------------- ---------- ---------- ---------- ---------------
buffer busy waits file# block# class# Concurrency
查看v$session_wait视图,参数P1、P2、P3分别对应File ID、Block ID和Class ID。
2、原因
当buffer busy waits出现时,查询V$session视图识别Row_wait_obj#,例如:
SQL> select row_wait_obj#
2 from v$session
3 where event='buffer busy waits';
查询dba_objects识别争用的对象及类型,例如:
SQL> select owner,object_name,subobject_name,object_type
2 from dba_objects
3 where data_object_id=&row_wait_obj;
3、解决办法
所需要的操作依赖于争用的数据块和实际的段。
1)段头(segment header)
如果争用发生在段头,那么很可能是free list争用。
在本地管理的表空间中,自动段空间管理消除了指定pctused、freelists和freelist groups参数,如果需要,切换手动空间管理为自动段空间管理(ASSM)。
如果不使用ASSM(例如,表空间使用字典空间管理),可参考下面信息:
free list是一个空闲数据块的列表,通常包括在段内的几个不同区中的数据块。free lists是由空闲空间内尚未达到pctfree的数据块或者已经收缩到pctused下的使用过的空间组成。使用freelists参数指定处理空闲列表的数量,默认值是1,最大值取决于数据块大小。
可利用下面的SQL查看当前freelist的设置:
SQL> select segment_name,freelists
2 from dba_segments
3 where segment_name=&segment_name
4 and segment_type=&segment_type;
然后设置free lists,或者增大free lists的值。
2)数据块(data block)
如果争用发生在表或者索引(不是段头):
- 检查右索引,这些是被许多进程在同一点插入的索引,例如:使用序列生成的值;
- 考虑使用ASSM、全局哈希分区索引,或者增加freelists避免多个进程视图插入同一数据块。
3)撤销头(undo header)
对于争用发生在回滚段头,如果没有使用自动UNDO管理,那么就增加更多的回滚段。
4)撤销块(undo block)
对于争用发生在回滚段数据块,如果没有使用自动UNDO管理,那么考虑增大回滚段的大小。
db file scattered read
1、描述
该等待事件显示用户进程正在将缓冲区读取到SGA缓冲区缓存中,并等待物理I/O调用返回。db file scattered read进行离散读将数据读入多个不连续的内存位置。离散读是一个多数据块读,通常发生在索引快速全扫描和全表扫描。
db file scattered read等待事件显示发生了全表扫描,当执行全扫描到缓冲区缓存,数据块被读取到物理位置不相邻的内存区域中,这种读取称为离散读调用,因为数据块在整个内存中是离散存放的。多块读(取决于DB_FILE_MULTIBLOCK_READ_COUNT数据块)由于全扫描到缓冲区缓存显示为等待‘db file scattered read’。
SQL> SELECT t.name,
t.parameter1,
t.parameter2,
t.parameter3,
t.wait_class
FROM v$event_name t
WHERE t.name = 'db file scattered read';
NAME PARAMETER1 PARAMETER2 PARAMETER3 WAIT_CLASS
------------------------------ ---------- ---------- ---------- ---------------
db file scattered read file# block# blocks User I/O
2、原因
在一个健康的系统上,物理读等待是继空闲等待之后最大的等待事件,然而,也应该考虑应该做小量索引访问的OLTP系统是否有直接读等待或者db file scattered read等待。
系统显示过量I/O负载的事情包括:
- 过低的缓冲区缓存命中率
- 因为用户的相应时间差,这些等待事件增加了用户的等待时间。
3、管理过多的I/O
有几种方法可以处理过多的I/O等待,按照有效性排列如下:
- 通过SQL调优减少I/O活动;
- 通过管理工作负载减少对I/O的需求;
- 使用DBMS_STATS收集系统统计信息,使查询优化器能准确地使用可能的访问路径;
- 使用ASM;
- 增加更多的磁盘以减少每个磁盘I/O的数量;
- 通过在现有磁盘上重新分配I/O来减少I/O热点。
对于处理过度I/O的情况,首先应该找到减少I/O的机会,通过对于这些事件的会话等待检查运行的SQL语句和引起v$sqlarea高物理I/O的语句,导致过度I/O的对执行计划产生负面影响的因素包括:
- 优化SQL不当
- 索引丢失
- 表的高度并行性
- 缺少精确的优化器统计信息
- 将有利于全扫描的DB_FILE_MULTIBLOCK_READ_COUNT初始化参数设置过高。
4)I/O分配不足
除了减少I/O之外,还可以检查磁盘上文件的I/O分布。
5)查找等待I/O的会话执行的SQL语句
SQL> SELECT SQL_ADDRESS, SQL_HASH_VALUE
FROM V$SESSION
WHERE EVENT LIKE 'db file%read';
6)查找需要I/O的对象
SQL> select row_wait_obj#
2 from v$session
3 where event='db file scattered read';
查询dba_objects识别争用的对象及类型,例如:
SQL> select owner,object_name,subobject_name,object_type
2 from dba_objects
3 where data_object_id=&row_wait_obj;
db file sequential read
1、描述
该等待事件显示用户进程正在将缓冲区读取到SGA缓冲区缓存中,并等待物理I/O调用返回。顺序读取是一个单块读取操作。单数据块I/O通常是使用索引的结果,极小情况下,全表扫描由于区边界或缓冲区缓存中存在的缓冲区而被截断到单数据块调用,这些等待也会显示为db file sequential read 。
SQL> select name,parameter1,parameter2,parameter3,wait_class
2 from v$event_name
3 where name='db file sequential read';
NAME PARAMETER1 PARAMETER2 PARAMETER3 WAIT_CLASS
------------------------------ ---------- ---------- ---------- --------------------
db file sequential read file# block# blocks User I/O
如下展示了下面等待事件的不同之处:
- db file sequential read(将单个数据块读到一个SGA缓冲区)
- db file scattered read(将多个数据块读到许多不连续的SGA缓冲区)
- direct read(将单个或者多个数据块读到PGA,绕过SGA)
direct path read & direct path read temp
1、描述
当会话从磁盘直接将缓冲区读取到PGA(相对于SGA的缓冲区缓存),它将在这个事件上发生等待。如果I/O子系统不支持异步I/O,那么每个等待都对应于一个物理读请求。
如果I/O子系统支持异步I/O,则该进程能够通过处理PGA中已存在的数据块来重复发出读请求。当进程尝试访问PGA中尚未从磁盘读取的数据块时,那么它将发出一个等待调用,并更新该事件的统计信息。因此,等待的数量不一定与读请求的数量相同(不像db file scattered read 和 db file sequential read)。
可以从v$session_wait查看下面三个参数具体的值:
SQL> select name,parameter1,parameter2,parameter3,wait_class
2 from v$event_name
3 where name in('direct path read temp','direct path read');
NAME PARAMETER1 PARAMETER2 PARAMETER3 WAIT_CLASS
------------------------- --------------- ---------- ---------- --------------------
direct path read file number first dba block cnt User I/O
direct path read temp file number first dba block cnt User I/O
2、原因
该等待事件发生在下面几种情况:
- 排序太大,无法装入内存,有些排序数据直接写入磁盘,这些数据稍后会使用直接读来读取;
- 并行slaves用来扫描数据;
- 服务器进程处理缓冲区的速度比I/O系统能够返回到缓冲区的速度更快,这可以指示过载的I/O系统。
3、解决办法
file_id显示读是否是Temp表空间的对象或者是通过并行slaves的全表扫描。数据仓库环境中,该等待是最大的等待,然而,如果该负载不是DSS系统的负载,那么需要检查为何会发生该种等待。
1)磁盘排序(Sorts to Disk)
检查当前正在运行的SQL语句,查看什么原因导致了排序,可以通过视图v$tempseg_usage找出产生排序操作的SQL语句,同时从视图v$sesstat查询统计信息以确定排序的大小,然后查看是否有可能通过优化SQL语句来减少排序。如果workarea_size_policy设置为manual,那么考虑为系统或单个进程增加sort_area_size大小;如果workarea_size_policy设置为auto,那么检查是否增加pga_aggregate_target参数的值。
2)全表扫描(Full Tables Scans)
3)哈希区大小(Hash Area Size)
对于调用hash join的查询计划,过多的I/O会导致hash_area_size太小。如果workarea_size_policy设置为manual,那么考虑为系统或者单个进程增加hash_area_size的大小;如果workarea_size_policy设置为auto,那么检查是否增加pga_aggregate_target参数的值。
direct path write & direct path write temp
1、描述
当一个进程直接从PGA写入缓冲区,在该事件进程等待写调用完成。执行direct path write的操作包括:磁盘排序,并行DML操作,直接路径插入、并行create table as select和一些LOB操作。
像direct path read一样,如果I/O子系统支持异步写,等待的数量和执行写调用的数量不相同。如果会话处理了PGA中的所有缓冲区,并且不能继续工作,则会话等待,直到I/O请求完成。
可以从v$session_wait查看下面三个参数具体的值:
SQL> select name,parameter1,parameter2,parameter3,wait_class
2 from v$event_name
3 where name in('direct path write temp','direct path write');
NAME PARAMETER1 PARAMETER2 PARAMETER3 WAIT_CLASS
------------------------- --------------- ---------- ---------- --------------------
direct path write file number first dba block cnt User I/O
direct path write temp file number first dba block cnt User I/O
2)原因
该等待事件发生在下面几种情况:
- 排序太大,无法装入内存;
- 并行DML用来创建/填充对象;
- 直接路径加载。
3)解决
对于大的排序操作,见磁盘排序;
对于并行DML,检查跨磁盘的I/O分布,并确保I/O子系统配置合适的并行度。
free buffer waits
1、描述
该等待事件显示服务器进程不能找到空闲的缓冲区,数据库写入器通过将脏缓冲区的内容写到磁盘以获得空闲的缓冲区。脏缓冲区是内容被修改的缓冲区,当数据库写将数据块写到磁盘上后,脏缓冲区被释放以重用。
SQL> select name,parameter1,parameter2,parameter3,wait_class
2 from v$event_name
3 where name ='free buffer waits';
NAME PARAMETER1 PARAMETER2 PARAMETER3 WAIT_CLASS
-------------------- --------------- --------------- --------------- --------------------
free buffer waits file# block# set-id# Configuration
2、原因
在以下情况下,DBWR可能无法继续写脏缓冲区:
- I/O系统运行缓慢;
- 有资源正在等待,比如latches;
- 缓冲区缓存太小,DBWR大部分事件都在清理服务器进程的缓冲区;
- 缓冲区缓存太大,以至于一个DBWR进程不足以释放足够的缓冲区来满足请求;
3、解决办法
如果该事件经常发生,那么检查会话等待以确定释放有任何延迟的DBWR。
1)写(Writes)
如果正在等待写,那么确定什么因素导致延迟写,并修复它,检查以下几点:
- 检查v$filestat确定大部分写操作发生在哪里;
- 检查I/O系统的主机操作系统统计信息,写操作时间是否可接受?
如果I/O比较慢,
- 考虑使用更快的I/O来提高写入次数;
- 在更多的磁盘和控制器上传播I/O活动;
2)缓存太小(Cache is Too Small)
缓存太小可能会使DBWR变得非常活跃,如果缓冲区缓存命中率低,查看这是否是一个可能的原因,也可以使用v$db_cache_advice来确定合适的缓存大小。
3)对于DBWR而言,缓存过大
如果缓存大小足够,且I/O分布均匀,那么可以通过使用异步I/O或使用多个数据库写入器来修改DBWR的行为。
4、考虑多个数据库写进程或者I/O Slaves
当事务率高或者缓冲区缓存过大以至于单个DBWn进程无法跟上负载时,配置多个数据库写入器进程或使用I/O Slaves很有用处。
1)DB_WRITER_PROCESSES
2)DBWR_IO_SLAVES
3)Choose Between Multiple DBWR Processes and I/O Slaves
Idle Wait Events
这些事件属于Idle wait类,表明服务器进程正在等待,因为它没有工作。这通常意味着如果存在瓶颈,那么瓶颈不是因为数据库资源引起。在调优时,大多数空闲等待事件应该被忽略,因为它们没有显示出性能瓶颈的本质。一些等待事件有助于说明瓶颈并不存在,此类型事件的一个例子是最经常遇到的空闲等待事件SQL Net message from client 。
latch events
latch是一个低级别的内部锁,用来保护内存结构,当服务器进程尝试获取一个latch时,latch free event会被更新,并且在第一次尝试时,latch是不可用的。
对于那些经常产生重大争用的latch,有一个专用的latch相关的等待事件,那就是latch的名字出现在等待事件中,比如:latch:library cache 或者 latch:cache buffers chains 。如果多数与latch相关的争用是由特定类型的latch引起的话,这种名称可以快速识别。所有其他latch的等待归在通用的latch free 等待事件中。
1 latch: shared pool
共享池或库缓存争用的一个主要原因是解析。
2 latch: cache buffers chains
cache buffers chains latches用于保护buffer cache的buffer list 。这些latches在搜索、增加或者从buffer cache移除buffer时使用,这个latch的争用通常意味着有一个被极大争用的数据块(称为热块)。
查找热块的逻辑:
首先从v$latch_children找出gets、misses和sleep的最大值的addr,然后从x$bh根据hladdr=v$latch_children.addr,最后在dba_objects根据data_object_id=x$bh.obj找出对应的对象。
3 latch: row cache objects
row cache objects latches用于保护数据字典。
log file parallel write
该事件包括将redo记录从log buffer写到redo log file 。
library cache pin
该事件管理库缓存的并发性。pin一个对象会使这些heaps加载到内存中,如果客户端想要修改或者检查这个对象,那么客户端必须在lock之后获得一个pin 。
library cache lock
该事件控制库缓存的客户端之间的并发性。该锁也可用于在库缓存中定位对象。
log buffer space
该事件发生在服务器进程正在log buffer等待空闲空间,因为所有的redo产生速度比LGWR写到日志文件的速度更快。在确保online redo logs所在的磁盘不存在I/O争用的情况下可以通过增加log buffer size解决。
log file switch
该事件是LGWR不能切换到下一个online redo log file ,所有的commit请求在等待这个事件。通常会遇到两种情况:
1 log file switch(archiving needed)
archiver不能及时归档,可能出自以下原因:
- 归档目的地正在耗尽空闲空间;
- archiver不能快速的读取redo logs(与LGWR争用);
- archiver不能快速写(归档目的地争用,或者没有足够的ARCH进程),如果排除了其他可能性(比如慢磁盘或者归档目的地空间用完),可以考虑增加ARCn进程,默认是2;
- 如果强制远程传输归档日志,检查是否因为网络延迟或者由于错误导致写入没有完成,该归档进程是否正在减慢。
2 log file switch(checkpoint incomplete)
- 检查DBWR是否慢,可能由于负载过重,或者I/O系统慢;检查DBWR写入次数、I/O系统,如果必要,重新分配I/O;
- 检查redo logs数量是否太少,或者redo logs文件太小。如果在DBWR能够完成检查点之前系统产生足够多的redo遍历所有的logs,并且redo logs数量太少,或者尺寸太小,那么增加redo log的大小或者增加redo log的数量。
log file sync
当用户会话commit(或rollback)时,该会话的redo信息必须通过LGWR刷新到重做日志文件。执行提交或回滚的服务器进程在该事件下等待写重做日志文件完成。如果等待的平均时间比较短,但是等待的次数比较高时,可能应用程序在每次insert后执行commit,而不是批量提交,此时应用程序可以采取批量提交的方式解决,比如每次提交500行。
rdbms ipc reply
该事件用于等待一个后台进程的回复。
SQL *Net Events
下面的等待事件表示数据库进程正在等待dblink或者客户端进程的确认:
1 SQL*Net break/reset to client
2 SQL*Net break/reset to dblink
3 SQL*Net message from client
4 SQL*Net message from dblink
5 SQL*Net meaasge to client
6 SQL*Net message to dblink
7 SQL*Net more data from client
8 SQL*Net more data from dblink
9 SQL*Net more data to client
10 SQL*Net more data to dblink
如果以上等待占据了等待时间中很大一部分比例,或者用户正经历响应时间的问题,那么瓶颈很可能出现在网络或者中间层。
与client相关的事件应被诊断为SQL*Net message from client;与dblink相关的事件应该被诊断为SQL*Net message from dblink 。
参考:https://docs.oracle.com/cd/E11882_01/server.112/e41573/instance_tune.htm#PFGRF02410