等待事件

数据库处理数据,只要有时间的消耗,就会有等待事件。

性能和等待是一个矛盾体。

理解出现某种等待的原因。结合业务主观的看待等待事件:

  • 制定基线(baseline),发现异常等待事件
  • 接受合理的等待事件

最简单的等待事件:SQL*Net message from client 空等待

SQL*Net是Oracle官方的客户端访问数据库协议,类似于ODBC、JDBC。

  1. -- 查看当前会话的sid
  2. select distinct sid from v$mystat;
  3. 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

  1. select sid, event, p1Text, p1, p1Raw, p2Text, p2, p2Raw, p3Text, p3, p3Raw
  2. 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花费的时间。

  1. 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

查找方式:

  1. -- 查看繁忙的对象编号
  2. select row_wait_obj#
  3. from v$session
  4. where event='buffer busy waits';
  5. -- 查看对象号对应的对象
  6. select owner, object_name, subobject_name, object_type
  7. from dba_objects
  8. 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区内存

其他相关视图

  1. -- v$session_wait只能查看当前正在等待的事件。
  2. -- v$session_evenet可以查看之前的等待事件
  3. select event, total_waits
  4. from v$session_event;
  5. -- 查看整个数据库的
  6. -- 可能会把很久以前的等待事件也显示出来,没有AWR报告只看一段时间方便
  7. select event, total_waits
  8. from v$system_event;