等待事件
数据库处理数据,只要有时间的消耗,就会有等待事件。
性能和等待是一个矛盾体。
理解出现某种等待的原因。结合业务主观的看待等待事件:
- 制定基线(baseline),发现异常等待事件
- 接受合理的等待事件
最简单的等待事件:SQL*Net message from client 空等待
SQL*Net是Oracle官方的客户端访问数据库协议,类似于ODBC、JDBC。
-- 查看当前会话的sid
select distinct sid from v$mystat;
select sid,event,state from v$session where sid=7;
使用sqlplus连接数据库后,数据库服务器等待客户端发送指令,此时就会产生一个空等待。
通常情况下,这个空等待是个可以忽略的等待事件。
造成Oracle等待的三种情况:
- 请求的资源太忙,需要等待资源释放
- 会话处于空闲状态,等待新的任务
- 会话被阻塞,需要等待阻塞解除
等待的定位方式
SQL级别:使用 10046事件,level放到12。
会话级别:查看会话的等待视图v$session_wait
。
系统级别:查看视图v$system_event
,查看AWR报告
等待事件分类
类别 | 描述 |
---|---|
Administrative | Waits resulting from DBA commands that cause user to wait(例如索引重建) |
Application | Wait resulting from user application code(例如行锁等) |
Cluster | Wait related to RAC resource(例如 gc cr block busy,通常以gc开头,global cache) |
commit | This wait class only comprises one wait event - wait for redo log write confirmation after a commit(例如 log file sync) |
Concurrency | Waits for internal database resources(例如Lathes) |
Configuration | Wait caused by inadequate configuration of database or instance resource(例如logfile尺寸、shared pool尺寸) |
Idle | Waits that sisgnify the session is inactive , waiting for work(例如SQL*Net message from client) |
Network | Waits related to network messaging(例如SQL*Net more data to dblink) |
Queue | Contains events that signify delays in obtaining additional data in a pipelined environment. The time spent on these wait events indicates inefficiency or other porblems in the pipeline. It affects features such as Oracle Streams,parallel queries |
Scheduler | Resource Manager related waits(例如resmgr: bcome active) |
System I/O | Waits for background process I/O(例如DBWR等待db file parallel write) |
User I/O | Waits for user I/O (例如 db file sequential read) |
Other | Waits which should not typically occur on a system(例如 wait for EMON to spawn) |
查看等待事件
使用v$session_wait
的event、p1、p2、p3
select sid, event, p1Text, p1, p1Raw, p2Text, p2, p2Raw, p3Text, p3, p3Raw
from v$session_wait;
p1/p2/p3表示三个参数,不同类型的等待事件中,这三个参数的值的含义不同。
例如,event为SQL*Net message from client
时,p1表示协议号,p2表示传输的字节数,p3为0;
event为db file sequential read
时,p1表示文件id,p2表示数据块号,p3表示读取的数据块数量。
常见等待事件
idle wait events
进程由于无事可做,等待分派任务。
空等待意味着当前会话空闲。但又意味着数据库的空闲,也可能是因为数据库太繁忙了,导致了当前会话的空闲。
比如很多辆车堵在收费站,此时对于每辆车的司机来说是空闲的,但是对于收费员来说是处于繁忙状态。
空闲等待:
- client message
- dispatcher timer
- null event
- smon timer
- PX idle wait
- pipe get
- PL/SQL lock timer
- pmon timer
- parallel query dequeue
- rdbms ipc message
- SQL*Net message from client
- SQL*Net message to client
- SQL*Net more data from client
- wakeup time manager
- virtual circuit status
- lock manager wait for remote message
CPU
CPU不属于等待事件,但是通常也要分析cpu花费的时间。
select name,value from v$sysstat where name like '%CPU%';
db file scattered read
当数据块以multiblock read的行式被读取到SGA中时,这种通过散列读的方式读取到内存产生的等待事件。
通常以下情况下会发生多数据块读:
- FTS(full table scan)
- IFFS(index fast full scan)
一次读取的数据块数量通过db_file_multiblock_read_count
参数配置。
参数说明:
- P1:读取的文件ID
- P2:当前读取的数据块ID
- P3:读取的数据块数量
出现了这种等待,不需要解决这个问题,因为这个等待不可避免,这个等待是正常的现象。
如果这个等待事件真的影响到效率了,可以考虑是否应该添加索引。
如果也不是索引的问题,而是真的需要多数据块读取且比较慢,可以考虑开启并行。
db file sequential read
数据文件的顺序读。当把一个数据块读入SGA时,会发生这种等待事件。
这种单数据块的顺序读,通常是指索引的读取,但是也不绝对:
- 有些索引读取会发生
db file scattered read
等待 - 有时候表的读取会发生
db file sequential
等待 - undo的读取,会使用
db file sequential
参数说明:
- P1:读取的文件ID
- P2:当前读取的数据块ID
- P3:读取的数据块数量
这个等待是一种正常的等待,无需解决这个问题。
如果严重影响到性能,检查是否SQL语句写的有效率问题、索引的方式是否正确、是否可以使用全表扫描+并行的方式替代索引扫描、改善磁盘的I/O。
direct path read
直接路径的数据读。数据被直接读取到PGA内存中发生的等待。
通常发生在:
- 排序数据由于内存不足,被写到磁盘上(temp表空间数据文件),然后重新读取时
- 并行操作的slave进程的数据读取
- 其他的属于某个会话私有数据的读取操作
参数说明:
- P1:读取的文件ID
- P2:读取开始的数据块ID
- P3:读取的数据块数量
这种等待是一种正常等待,无需解决这个问题。
如果影响了效率,可以考虑增大PGA内存排序区、调整操作的并行度、改善磁盘的I/O。
direct path write
数据从PGA内存中直接写到磁盘上发生的等待。
通常发生在:
- 排序数据由于内存不足,被写到磁盘上(temp表空间数据文件)
- 并行操作的slave进程向磁盘上写数据
- 其他的属于某个会话私有数据的读取操作
log file sync
log文件同步的等待事件。用户commit/rollback时,LGWR需要将log buffer的数据写到 log file 上面发生的等待。
参数说明:
- P1,写入文件的数据块数
- P2,无
- P3,无
AWR报告中出现了很多这种等待事件时,可以考虑减少commit的频率(错误的频繁提交)、提交I/O性能。
buffer busy waits
内存中的数据块的繁忙等待。内存中对相同数据块又多个并发请求时,导致这个等待。
参数说明:
- P1,读取数据块所在的文件ID
- P2,读取的数据块ID
- P3,等待类型(class id)
oracle 10g把数据库繁忙的类型单独成了一个等待事件read by other session
。
查找方式:
-- 查看繁忙的对象编号
select row_wait_obj#
from v$session
where event='buffer busy waits';
-- 查看对象号对应的对象
select owner, object_name, subobject_name, object_type
from dba_objects
where data_object_id='';
热块的解决方式:
- 如果发生在segment header —-使用 ASSM(默认)
- 如果发生在data block — 使用ASSM 反向索引(不推荐,失去了索引应有的意义)
- 如果发生在undo header — 使用automatic undo management(默认)
- 如果发生在undo block — 增大回滚段
free buffer waits
等待申请空闲buffer。server process 无法找到一个可用的内存空间。
常见情况:
- 系统I/O称为瓶颈(或者性能不够)
- 等待资源latch争用
- SGA太小
- SGA太大,DBWR无法快速的把脏数据刷到磁盘上
参数说明:
- P1,读取数据块所在的文件ID
- P2,读取的数据块ID
- P3,无
优化I/O:
异步I/O
增加督导各DBWR进程
提高I/O通道的性能
SGA区太小则增大SGA区内存
其他相关视图
-- v$session_wait只能查看当前正在等待的事件。
-- v$session_evenet可以查看之前的等待事件
select event, total_waits
from v$session_event;
-- 查看整个数据库的
-- 可能会把很久以前的等待事件也显示出来,没有AWR报告只看一段时间方便
select event, total_waits
from v$system_event;