Oracle Wait Interface Note

Oracle Wait Interface学习笔记

博客分类: Oracle
OracleSQLSQL ServerCacheOS
1.Introduction

以往性能调整常用的一些指标:

  • Buffer cache>90%
  • Data dictionary misses<10%
  • Sqlarea gethitratio and pinhitratio>90% (ratio of reloads<1%)
  • willing-to-wait latch hit ratios shalt be close to 1

但是光靠这些指标是不够的,在现实中,高缓存命中率并不总是意味着性能良好。在Oracle数据库10g第1版性能调优指南规定:
When tuning, it is common to compute a ratio that helps determine whether there is a problem. Such ratios include the buffer cache-hit ratio, the soft-parse ratio, and the latch-hit ratio. These ratios should not be used as‘hard and fast’identifiers of whether there is or is not a performance bottleneck. Rather, they should be used as indicators. In order to identify whether there is a bottleneck, other related evidence should be examined.

Oracle从7.0.12开始推出OWI,当时有104个等待事件,到9i发展到400个,到10g已发展到800个。事实上,10g的Enterprise Manager Performance中已经不再有buffer cache hit ratio。

OWI是一种用于定位process bottlenecks(即wait evennts)的方式,包括I/O,locks,latches,bk process activities,network latencies等等。它记录了所有这些事件的等待次数和总的等待时间。解除或者降低这些等待都会使系统性能得到提高。这些数据都被记录在动态视图中。

有了OWI可以快速的定位问题,而在OWI之前,要定位问题必须将checklist上的所有项目都执行一遍,再根据经验判断问题所在,这往往浪费大量的时间而且容易产生错误。

Database Response Time Tuning Model
Response Time = Service Time + WaitTime
The service time is the amount of time a process spends on the CPU. The wait time is the amount of time a process waits for specific resources to be available before continuing with processing.
Response Time = CPU used when call started + S TIME_WAITED

可使用如下SQL来获取用户进程的response time,将得到的结果累加得到的就是该用户进程的response time:
Sql代码
select event, time_waited as time_spent
from v$session_event
where sid = &&sid
and event not in (
'Null event',
'client message',
'KXFX: Execution Message Dequeue - Slave',
'PX Deq: Execution Msg',
'KXFQ: kxfqdeq - normal deqeue',
'PX Deq: Table Q Normal',
'Wait for credit - send blocked',
'PX Deq Credit: send blkd',
'Wait for credit - need buffer to send',
'PX Deq Credit: need buffer',
'Wait for credit - free buffer',
'PX Deq Credit: free buffer',
'parallel query dequeue wait',
'PX Deque wait',
'Parallel Query Idle Wait - Slaves',
'PX Idle Wait',
'slave wait',
'dispatcher timer',
'virtual circuit status',
'pipe get',
'rdbms ipc message',
'rdbms ipc reply',
'pmon timer',
'smon timer',
'PL/SQL lock timer',
'SQL*Net message from client',
'WMON goes to sleep')
union all
select b.name, a.value
from v$sesstat a, v$statname b
where a.statistic# = b.statistic#
and b.name ='CPU used when call started'
and a.sid = &sid;

There are three key behavioral changes that need to happen before you can master the OWI method:

  • You must stop measuring performance using non-throughput related ratios, such as the BCHR, sorts-to-disk ratio, and so on.
  • You need to start measuring process response time and/or throughput.
  • You must look at resource consumption from the response time perspective.

原来的方式教DBA如何去查找消耗了大量CPU,IO以及buffer的SQL,但是这样的SQL调整事先并不清楚调整后会带来多大的改善,因为之前的统计都没有时间信息。而使用OWI则可以预测所作的改动将对SQL带来多大的影响。

2.OWI Componets

Oracle能做到self-monitoring但是做不到self-tuning,oracle收集了大量的性能数据,包括instance级和session级。

WAIT EVENT

Session连接到oracle instance后需要获取某些资源来完成它的任务,这里所说的资源可能是databuffer, latch, enqueue(lock),pin或者db object. 当一个Session处于等待状态时,其等待时间被记录到对应的wait event中。
例1:session需要一个不存在于SGA中的index block,等待这个数据块的时间被记录到db file sequential read event.
例2:session完成了任务正处于idle状态,等待用户的输入,此时,等待时间被记入SQL*Net message from client。
简要地说,当session不使用CPU时,它一定是在等待某一个资源、或等待用户操作。因此,events往往被称之为wait events.

OWI Components

OWI是由一系列的动态性能视图和一个扩展SQL Trace文件组成的。
OWI提供了对wait events的统计信息,如等待的某个资源的次数以及等待某个资源的总的时间。获取等待累计等待时间的前提是将TIMED_STATISTICS参数设为TRUE,现在设置这个参数已经不会带来系统压力,因为绝大多数的服务器都提供硬件级的fast timer支持。
OWI主要包括以下动态性能试图:
V$EVENT_NAME
V$SESSION_WAIT(*)
V$SESSION_EVENT(*)
V$SYSTEM_EVENT(*)
V$SYSTEM_WAIT_CLASS(10G新增)
V$SESSION_WAIT_CLASS(10G新增)
V$SESSION_WAIT_HISTORY(10G新增)
V$EVENT_HISTOGRAM(10G新增)
V$ACTIVE_SESSION_HISTORY(10G新增)
对这些视图的查询往往是反复的,可以使用扩展SQL Trace功能将这些信息抓取到trace文件中,然后用tkprof工具分析。

2.1.V$EVENT_NAME

视图定义如下,其中打*是10G新增的列:
Sql代码
SQL> desc v$event_name
Name Type
---- ------
EVENT# NUMBER
*EVENT_ID NUMBER
NAME VARCHAR2(64)
PARAMETER1 VARCHAR2(64)
PARAMETER2 VARCHAR2(64)
PARAMETER3 VARCHAR2(64)
*WAIT_CLASS_ID NUMBER
*WAIT_CLASS# NUMBER
*WAIT_CLASS VARCHAR2(64)

NAME列各版本基本一致,EVENT#列各版本并不同,10g新增的EVENT_ID是一个hash列,不随版本变更而变更。
每一个event可以由最多3个属性,被记录在PARAMETER1-3中。这三列在v$session_wait中对应的是P1TEXT、P2TEXT和P3TEXT,而3个属性的值则纪录在P1,P2和P3。
10G开始对event做了分类,目前共有12个分类:
Sql代码
SQL> select wait_class#, wait_class_id, wait_class
from v$event_name
group by wait_class#, wait_class_id, wait_class;

WAIT_CLASS# WAIT_CLASS_ID WAIT_CLASS
--- --- ------
10 2396326234 Scheduler
4 3875070507 Concurrency
8 1740759767 User I/O
0 1893977003 Other
6 2723168908 Idle
1 4217450380 Application
2 3290255840 Configuration
11 3871361733 Cluster
3 4166625743 Administrative
9 4108307767 System I/O
7 2000153315 Network
5 3386400367 Commit

12 rows selected.

2.2.V$SYSTEM_EVENT
Sql代码
SQL> desc v$system_event
Name Type
---- -----
EVENT VARCHAR2(64)
TOTAL_WAITS NUMBER 等待总次数
TOTAL_TIMEOUTS NUMBER
TIME_WAITED NUMBER 等待总时间=time_waited_micro/10000
AVERAGE_WAIT NUMBER =time_waited/total_waits
TIME_WAITED_MICRO NUMBER (单位:microseconds,1/1,000,000秒)
*EVENT_ID NUMBER
*WAIT_CLASS_ID NUMBER
*WAIT_CLASS# NUMBER
*WAIT_CLASS VARCHAR2(64)

有些event有timeout属性(哪里可以查询到?v$session_wait中的P1-3?),例如free buffer waits有一个Timeout的时间为100centisecond,当一个session处于free buffer waits事件超过100centisecond后,total_timeouts列会+1,同时,该Session开始第二个free buffer waits等待。而有一些event,特别是I/O相关的,都没有timeout的属性,这意味着session会一直处于等待状态知道获取所需要的资源。

V$system_event使用时注意:

  • V$system_event提供的是instance级的事件统计信息,没有session级的信息;instance启动的时间越长,其累计的time_waited列值越大;
  • 我们需要关注time_waited列,而非total_waits列。有些event如latch free会有非常高的total_waits,但是每一次的等待时间都非常短,而有些event如enqueue虽然total_waits很小,但是每一次的等待时间却很长;

Sql代码
set lines 160
set numwidth 18
col class for a15
col event for a30
col total_waits for 999,999,999
col total_timeouts for 999,999,999
col time_waited for 999,999,999,999
col average_wait for 999,999,999,999
select b.wait_class, a.*, c.startup_time
from v$system_event a,
v$event_name b,
v$instance c
where a.event = b.name
order by b.wait_class, a.time_waited desc;

WAIT_CLASS EVENT TOTAL_WAITSTIME_WAITEDAVERAGE_WAIT STARTUP_TIME
User I/Odb file sequential read195100 50336 0.26 2008-7-16 11:17:16
User I/Odb file scattered read 32096 16345 0.51 2008-7-16 11:17:16

特别注意和User I/O及System I/O相关的event,这些event反映了你系统的速度和IO Cost。
Sql代码
SQL> SELECT NAME FROM V$EVENT_NAME
2 WHERE WAIT_CLASS='User I/O' or WAIT_CLASS='System I/O';

获取阶段数据:可以使用statspack获取,也可以通过脚本来获取:
Sql代码
— Assumption is that you have TOOLS tablespace in your database.
— Create Begin and End tables to store V$SYSTEM_EVENT contents for
— time T1 and T2 to compute delta.
— ===================================
— You only need to create these tables once.
— ===================================
create table begin_system_event tablespace tools
as select * from v$system_event where 1=2;

create table end_system_event tablespace tools
as select * from v$system_event where 1=2;

— Take a snapshot of V$SYSTEM_EVENT information at time T1
truncate table begin_system_event;
insert into begin_system_event
select * from v$system_event;

— Wait n seconds or n minutes, and then take another snapshot
— of V$SYSTEM_EVENT at time T2
truncate table end_system_event;

select * from v$system_event;

— Report the ‘delta’ numbers for wait events between times T2 and T1
select t1.event,
(t2.total_waits - nvl(t1.total_waits,0)) "Delta_Waits",
(t2.total_timeouts - nvl(t1.total_timeouts,0)) "Delta_Timeouts",
(t2.time_waited - nvl(t1.time_waited,0)) "Delta_Time_Waited"
from begin_system_event t1,
end_system_event t2
where t2.event = t1.event(+)
order by (t2.time_waited - nvl(t1.time_waited,0)) desc;

2.3.V$SESSION_EVENT
Sql代码
SQL> desc v$session_event
Name Type
---------——
SID NUMBER
EVENT VARCHAR2(64)
TOTAL_WAITS NUMBER
TOTAL_TIMEOUTS NUMBER
TIME_WAITED NUMBER
AVERAGE_WAIT NUMBER
MAX_WAIT NUMBER
TIME_WAITED_MICRO NUMBER
EVENT_ID NUMBER
WAIT_CLASS_ID NUMBER
WAIT_CLASS# NUMBER
WAIT_CLASS VARCHAR2(64)

V$session_event对于查找某一个session的主要瓶颈非常有用,但是它对于查找根源并不很有帮助:

  • V$session_event不跟踪产生瓶颈的SQL,例如你发现db file scattered read事件是你主要的瓶颈,但是不抓住执行全表扫描的SQL,一切还是徒劳;
  • 还不能提供足够的证据来定位性能问题的根源。例如,所有的latch wait都会记入latch free事件,你并不清楚session所等待的究竟是什么latch。

MAX_WAIT纪录的是该Session对某一个时间的最大等待时间,即high-water mark of this wait event,不过oracle并不记录这个高点产生的时间。Oracle提供了一个内部过程dbms_system.kcfrms()可以reset所有session的MAX_WAIT列,另外,它也会reset v$filestat视图的maxiortm和maxiowtm。

2.4.V$SESSION_WAIT
Sql代码
SQL> desc v$session_wait
Name Type
---------—-
SID NUMBER
SEQ# NUMBER
EVENT VARCHAR2(64)
P1TEXT VARCHAR2(64)
P1 NUMBER
P1RAW RAW(8)
P2TEXT VARCHAR2(64)
P2 NUMBER
P2RAW RAW(8)
P3TEXT VARCHAR2(64)
P3 NUMBER
P3RAW RAW(8)
WAIT_CLASS_ID NUMBER
WAIT_CLASS# NUMBER
WAIT_CLASS VARCHAR2(64)
WAIT_TIME NUMBER
SECONDS_IN_WAIT NUMBER
STATE VARCHAR2(19)

当得知某个正在运行的应用有问题时查询v$session_wait最有用,由于这个视图是实施刷新的,你只需要重复查询这个视图,如果查询结果不停的变换,用户一直都在经历不同的wait event,说明应用正在运行,如果应用持续的等候同一个事件,那就意味着这个session处于idle状态或者正在等待某个资源,如lock、latch等。
V$session_wait提供的是实时地数据,10g开始,历史数据可以从v$session_wait_history获取。

STATE字段共有4个状态:
STATE状态 状态说明 WAIT_TIME值
WAITED UNKNOWN TIME TIMED_STATISTICS为FALSE -2
WAITED SHORT TIME 前一个等待的时间<1 centisecond -1
WAITING
正处于等待状态,实际的等待时间在SECONDS_IN_WAIT中有记录;
等待的时间(单位:centisecond)

2.5.Trace Event 10046—The Extended SQL Trace

前面说的,要跟踪某个session的运行状况,找到其瓶颈,最好的方式就是定期的获取wait event的数据,将这些数据写入trace文件是一个很好的选择。我们可以设置session级的参数SQL_TRACE=TRUE,也可以使用trace event 10046获取更多的信息,这是SQL trace的扩展。

Trace level:

  • Level 0 Tracing is disabled. This is the same as setting SQL_TRACE = FALSE.
  • Level 1 Standard SQL trace information (SQL_TRACE = TRUE). This is the default level.
  • Level 4 SQL trace information plus bind variable values.
  • Level 8 SQL trace information plus wait event information.
  • Level 12 SQL trace information, wait event information, and bind variable values.

2.5.1. 启动trace event 10046
INSTANCE级:更改init.ora,添加EVENT参数后重启,不建议!
Java代码
<pre>

  1. This enables the trace event 10046 at level 8 for the instance.
  2. Restart the instance after this change is made to the init.ora file.

EVENT = "10046 trace name context forever, level 8"
</pre>

推荐使用Session级的trace event 10046
2.5.2. Trace your own session
方法1
Sql代码
alter session settimed_statistics= true;
alter session setmax_dump_file_size= unlimited;
— To enable the trace event 10046 in Oracle 7.3 onwards
alter session setevents ‘10046 trace name context forever, level 8’;
— Run your SQL script. or program to trace wait event information
— To turn off the tracing:
alter session setevents ‘10046 trace name context off’;

方法2
Sql代码
$sqlplus '/ as sysdba'
SQL>start $ORACLE_HOME/rdbms/admin/dbmssupp.sql
Package created.
Package body created.
SQL> grant execute on DBMS_SUPPORT to username;
Grant succeeded.
SQL> connect username/pwd
SQL> — To include Wait Event data with SQL trace (default option)
SQL>exec sys.dbms_support.start_trace;
PL/SQL procedure successfully completed.
SQL> — To include Bind variable values, Wait Event data with SQL trace
SQL>exec sys.dbms_support.start_trace(waits => TRUE, binds=> TRUE)
PL/SQL procedure successfully completed.
SQL> — Run your SQL script. or program to trace wait event information
SQL> — To turn off the tracing:
SQL>exec sys.dbms_support.stop_trace;
PL/SQL procedure successfully completed.

2.5.3. Trace Someone Else’s Session
先调整参数
Sql代码
— Set TIME_STATISTICS to TRUE for SID 1234, Serial# 56789
execsys.dbms_system.set_bool_param_in_session( -
sid => 1234, -
serial# => 56789, -
parnam => ‘TIMED_STATISTICS’, -
bval => true);
— Set MAX_DUMP_FILE_SIZE to 2147483647
— for SID 1234, Serial# 56789
execsys.dbms_system.set_int_param_in_session( -
sid => 1234, -
serial# => 56789, -
parnam => ‘MAX_DUMP_FILE_SIZE’, -
intval => 2147483647);

** 方法1:Use the DBMS_SUPPORT package procedures:
Sql代码
— Enable ‘level 12’ trace in session 1234 with serial# 56789
exec dbms_support.start_trace_in_session( -
sid => 1234, -
serial# => 56789, -
waits => true, -
binds => true);

— Let the session execute SQL script. or
— program for some amount of time

— To turn off the tracing:
exec dbms_support.stop_trace_in_session( -
sid => 1234, -
serial# => 56789);

** 方法2:Use the DBMS_SYSTEM package procedure(oracle不建议此用法)
Sql代码
— Enable trace at level 8 for session 1234 with serial# 56789
exec dbms_system.set_ev( 1234, 56789, 10046, 8, ‘’);
— Let the session execute SQL script. or
— program for some amount of time

— To turn off the tracing:
exec dbms_system.set_ev( 1234, 56789, 10046, 0, ‘’);

** 方法3:Use the oradebug facility.
You need to know the session's OS process ID (SPID) or Oracle process ID (PID). You can look them up in the V$PROCESS view. Assuming you know the name of the user you want to trace:
Sql代码
select s.username,
p.spid os_process_id,
p.pid oracle_process_id
from v$session s, v$process p
where s.paddr = p.addr
and s.username = upper(‘&user_name’);

Now use SQL*Plus to connect as sysdba and issue following commands:
Sql代码
alter system set timed_statistics = true;
oradebug setospid 12345;
— 12345 is the OS process id for the session
oradebug unlimit;
oradebug event 10046 trace name context forever, level 8;
— Let the session execute SQL script.
— or program for some amount of time

— To turn off the tracing:
oradebug event 10046 trace name context off;

10g you can use DBMS_MONITOR package procedures to enable tracing based on the SID, service name, module, or action. The action-based tracing empowers a DBA to trace a specific business function. There is a little catch to this: the procedure requires that the DBA know the module and action names.
** 方法4:Use the DBMS_MONITOR package to enable tracing for session 1234 and serial# 56789 as shown below:
这个方法和dbms_support很相像,在10g下,建议用dbms_monitor
Sql代码
exec dbms_monitor.session_trace_enable( -
session_id => 1234, -
serial_num => 56789, -
waits => true, -
binds => true);
— Let the session execute SQL script. or
— program for some amount of time

— To turn off the tracing:
exec dbms_monitor.session_trace_disable( -
session_id => 1234, -
serial_num => 56789);

** 方法5:Use the DBMS_MONITOR package for service, module, and action-based tracing:
Sql代码
— Enable Level 12 trace for known Service,
— Module and Action
exec dbms_monitor.serv_mod_act_trace_enable( -
service_name => ‘APPS1’, -
module_name => ‘GLEDGER’, -
action_name => ‘DEBIT_ENTRY’, -
waits => true, -
binds => true, -
instance_name => null);

— Let the session execute SQL script. or
— program for some amount of time

— To turn off the tracing:
exec dbms_monitor.serv_mod_act_trace_disable( -
service_name => ‘APPS1’, -
module_name => ‘GLEDGER’, -
action_name => ‘DEBIT_ENTRY’);

使用以上方法获取的trace文件在USER_DUMP_FILE目录下,可以使用以下方式来为trace文件添加前缀:
Sql代码
alter session set tracefile_identifier = ‘MyTrace’;

如果是使用oradebug来获取trace文件的,还可以通过以下方式知道trace文件名:
Sql代码
SQL> oradebug setmypid
Statement processed.
SQL> oradebug event 10046 trace name context forever,level 8
Statement processed.
SQL> oradebug tracefile_name
d:\oracle\admin\or92\udump\or92_ora_171.trc

trace文件格式非常难懂,可以使用tkprof工具整理后查看。
Metalink关于trace文件格式的解释:Note:39817.1 Interpreting Raw SQL_TRACE and DBMS_SUPPORT.START_TRACE output

3.Common Wait Events

3.1.Buffer busy waits

当一个session要获取buffer cache中的数据块,而该数据块正在被其他session所使用时这一event就会出现。
两种情况下会产生这一事件:

  • 另一Sesssion正在buffer cache中修改该数据块,修改数据块时session会修改该数据块头的标记,以防止其他session冲突;
  • 另一Session正在从datafile将此数据块读入buffer cache。这一情况在10g之前会产生buffer busy waits事件,从10g开始由read by other session事件替代。

不要混淆buffer busy waits和buffer busy,buffer busy是由于session要通过ASM使用cached metadata所产生的。
常见的可能产生buffer busy waits事件的buffer类型包括:data blocks,segment header,undo blocks和undo header。

参数:
P1-file number,
P2-block number,
P3-10g之前是一个代表wait原因的数值,10g之后是wait class.
Timeout: 100cs or 1 second.

3.2.Control file parallel write

Session等待写控制文件的竞争。需要写控制文件主要有以下几种情况:

  • CKPT每3秒向控制文件写入redo logs的checkpoint位置,用于recovery;
  • NOLOGGING或者UNRECOVERABLE的DML操作时,oracle会将这些SCN写入控制文件;
  • RMAN将备份和恢复信息写入控制文件。

Control file parallel write等待的是OS和IO,而并非其他session.当一个session在写控制文件时,会hold CF enqueue,这样其他Session就会等待这个enqueue。
如果这一等待时间很多,说明系统写控制文件的操作过多,或者写控制文件的性能过低。

参数:
P1-number of control file;
P2-total number of blocks to write to control file;
P3- number of IO requests

3.3.Db file parallel read

以下两种情况会出现该事件:

  • 在数据库recovery的时候出现,从Datafile并行读取恢复所需数据块;
  • 用户进程从一个或者和多个数据文件读取很多非连续的single block.

参数:
P1-读取的文件编号;
P2-total number of blocks to read;
P3-total numbe of IO requests

3.4.Db file parallel write

DBWR向数据文件写入脏数据块时产生,产生的原因是系统IO. Dbwr将一系列的脏数据块整理到”write batch”,并向IO请求将Batch写入数据文件的资源,并一直等待到IO完成写入为止。如果使用的是异步IO,则DBWR不等待IO写入完成就直接将free buffer放回LRU chain供用户使用。

参数:
P1-number of file to write to ;
P2-total number of blocks to write;
p3-timeout value

3.5.Db file scattered read

当session提交一个IO请求,要求读取很多数据块时会出现该事件。这些被读取的数据块被scattered into the buffer cache,他们在buffer cache中并不连续。这一事件往往出现在全表扫描和index fast full scans。参数db_file_multiblock_read_count定义了每次读取的最大block数量。

数据文件的IO等待是正常的现象,这一事件本身并不代表数据库有问题。但是如果用于等待该事件的时间明显高于其他等待事件,那就需要进一步查找原因了。

参数:
P1-file number to read the blocks from;
P2-starting block number to begin reading;
P3-number of blocks to read

3.6.Db file sequential read

(摘自原文,理解不深刻,怕翻错了)The db file sequential read wait event occurs when the process waits foran I/O completion for a sequential read. The name is a bit misleading, suggesting a multiblock operation, butthis is a single block read operation. The event gets posted whenreading from an index, rollback or undo segments,table access by rowid, rebuilding control files, dumping datafile headers, or the datafile headers.
同样,这一事件本身并不代表数据库有问题。但是如果用于等待该事件的时间明显高于其他等待事件,那就需要进一步查找原因了。

参数:P1-file number to read the blocks from; P2-starting block number to begin reading; P3-number of blocks to read,绝大多数情况下是1

3.7.Db file single write

由dbwr发起,往往发生在oracle更新数据文件头时,最常见的就是checkpoint的时候。这一事件往往出现在数据文件比较混乱的情况下。

参数:
P1-file number to write to,
P2-starting block number,
P3-number to write,往往是1

3.8.Direct path read

当session直接将数据读入PGA而不是SGA的buffer cache时会产生direct path read事件。根据硬件平台的不同和DISK_ASYNCH_IO参数的不同,direct path read有同步和异步两种方式。Direct path read一般是排序、并行查询、hash joins等需要使用到磁盘的temporary segments的操作所引起所使用到的。

这个事件的等待次数和时间在同步和异步的情况下是不同的:

  • 同步的情况下session提交一个请求以后会等待IO结束,但这个等待的时间并不计入direct path read事件。在IO完成,session获取到自己所需要的数据以后会提交direct path read事件。这样,应该是每有一个read request,就会有一个对应的等待时间,但是等待时间却是相当短的。
  • 异步的情况下,session持续提交多个读取数据的请求,之后就对已经被读取到PGA的数据进行处理。只有在发现所需要的数据还没有被读入PGA,才会提交direct path read等待事件。因此,在异步的情况下,read request的数量和等待的数量是不同的。

因此,我们在v$system_event和v$session_event中看到关于这一等待事件的统计并不可靠。

3.9.Direct path write

同direct path read相对应,是由于direct data loads(inserts with APPEND hint OR CATS)或并行的DML操作需要写入temporary segments引起的。

3.10.Enqueue

某一个Session需要使用数据库的某项资源时,由于有其他的session正在使用这一资源,就会产生enqueue等待事件。
Enqueue的种类是由两位字符表示的,常见的有:

  • ST Enqueue for Space Management Transaction
  • SQ Enqueue for Sequence Numbers
  • TX Enqueue for a Transaction

从10g开始,每种enqueue都由单独的等待事件来表示,而不再是合并在enqueue中由不同的种类区分了。
看个例子,在9i和10g分别实验,两个Session同时对同一张表作dml操作时,9i显示有”enqueue”事件,类型为“TX”,而10g报告的等待事件则为“enq: TX - row lock contention”。
Sql代码
—以下为9i的输出
select sid,event,p1text,p1,p2text,p2,p3text,p3,wait_time,state
from v$session_wait
where event='enqueue';

SID EVENT P1TEXT P1 P2TEXT P2 P3TEXT P3 WAIT_TIME STATE
22 enqueuename|mode 1415053318 id1131073 id2597156 0 WAITING

select sid,
chr(bitand(p1, -16777216)/16777215)||chr(bitand(p1,16711680)/65535) "Name",
(bitand(p1, 65535)) "Mode"
from v$session_wait where event = 'enqueue';

SID Name Mode
22 TX 6

—以下为10g的输出

SQL> select sid,event,p1text,p1,p2text,p2,p3text,p3,wait_time,state from v$session_wait where sid in (144);

SID EVENT P1TEXT P1 P2TEXT P2 P3TEXT P3 WAIT_TIME STATE
144 enq: TX - row lock contention name|mode 1415053318 usn«16 | slot 655364 sequence 1619 0 WAITING

参数:
P1-enqueue name and mode,encoded in ASCII format;
P2- Resource identifier ID1 for the requested lock, same as V$LOCK.ID1
P3- Resource identifier ID1 for the requested lock, same as V$LOCK.ID2

3.11.Free buffer waits

当session在buffer cache中找不到足够的free buffer用于read in data blocks或者build a consistent read(CR) image of data block时就会提交Free buffer waits。产生这个等待事件的原因可能是buffer cache过小,或者将脏块写入磁盘的速度过慢,一旦出现这个等待事件,用户进程就会向DBWR发送信号,要求其尽快将脏数据块写入磁盘。

参数:
P1-用户读取的数据块的所在文件,
P2-用户读取的数据块的所在block号,
P3-10g才开始启动,用于记录BUFFER CACHE中LRU和LRUW的SET_ID#

3.12.Latch free

进程想要获取latch的时候发现该latch正被其他进程所占用,此时就会出现latch free wait事件。和enqueue不同的是,latch不使用queue,process在获取不到latch的情况下不进入queue等待而是等待一段时间以后再获取。

常见的latch包括cache buffer chains, library chache以及shared pool等,详见第六章。

参数:
P1-进程所等待的latch address,
P2-latch number,可以通过v$latchname查询到对应的latch name,
P3-尝试获取latch的次数

3.13.Library cache pin

当一个Session要更改library cache中的对象,它必须先获取pin,在这个session编译或者分析PL/SQL存储过程和视图的过程中oracle会提交library cache pin事件。
(这段不太明白)What actions to take to reduce these waits depend heavily on what blocking scenario is occurring. A common problem scenario is the use of DYNAMIC SQL from within a PL/SQL procedure where the PL/SQL code is recompiled and the DYNAMIC SQL calls something that depends on the calling procedure.
如果出现blocking的情况,可以使用如下方法找到requesting pin的对象:
Sql代码
Select P1 from v$session_wait where event='library cache pin';

select s.sid, kglpnmod "Mode", kglpnreq "Req"
from x$kglpn p, v$session s
where p.kglpnuse=s.saddr
kglpnhdl='&P1RAW' ;

3.14.x$kglpn——[K]ernel [G]eneric [L]ibrary Cache Manager object [P]i[N]s
Sql代码
sys@ORALOCAL(192.168.0.22)> desc x$kglpn
##主要用来处理library cache pin holder
Name Null? Type
----------- -- --
ADDR RAW(4)
INDX NUMBER
INST_ID NUMBER
KGLPNADR RAW(4)
KGLPNUSE RAW(4)
KGLPNSES RAW(4)
KGLPNHDL RAW(4)
##关联v$session_wait中event为library cache pin的P1RAW,再关联v$session,可以查出sid和serial#
KGLPNLCK RAW(4)
KGLPNCNT NUMBER
KGLPNMOD NUMBER
##如果值为3,表示为library cache pin的holder;如果值为0,表示为waiter
KGLPNREQ NUMBER
##如果值为0,表示为library cache pin的holder;如果值为2,表示为waiter
KGLPNDMK NUMBER
KGLPNSPN NUMBER

参数:
P1-被pin对象地址,
P2-address of load lock,
P3 Contains the mode plus the namespace (mode indicates which data pieces of the object are to be loaded; namespace is the object namespace as displayed in V$DB_OBJECT_CACHE view)

3.15.Library cache lock

A session must acquire a library cache lock on an object handle to prevent other sessions from accessing it at the same time, or to maintain a dependency for a long time, or to locate an object in the library cache.

与library cache pin有何区别呢?

3.16.Log buffer space

Session向log buffer中写入数据时发现没有足够的空间就会产生log buffer space,这一事件说明LGWR向redo log写入的速度没有应用产生redo日志的速度快。可能的原因:log buffer过小或者redo log file存在IO竞争。

3.17.Log file parallel write

由LGWR进程提交该事件,when the session waits for LGWR process to write redo from log buffer to all the log members of the redo log group,就会出现这个事件。
在异步IO情况下,LGWR进程同时向所有log file member写入,否则,顺序写入。
有该事件出现时说明磁盘设备速度比较慢或者redo log所在的盘有IO竞争。

参数:
P1-number of log files to write to,
P2-number of OS blocks to write to,
P3-number of IO requests.

3.18.Log file sequential read

当Arch进程从online redo log file读取数据块有等待时就会产生log file sequential read事件。

参数:
P1-Relative sequence number of the redo log file within the redo log group,
P2-block number to start reading from,
P3- number of os blocks to read

3.19.Log file switch(archiving needed)

当LGWR要切换到下一个redo log group时发现arch进程尚未将该日志组写道archived log file destination,此时就会出现该等待事件。

3.20.Log file switch(checkpoint incomplete)

LGWR试图切换日志文件时由于checkpoint尚未完成导致的等待。这一事件一般是在redo log files过小的情况下出现。

3.21.Log file switch completion

进程等待log file switch to complete.

3.22.Log file sync

用户完成一个事物后commit或者rollback都会触发LGWR将redo log写入online redo log。用户进程等待LGWR进程完成写入redo log的IO过程就会产生该等待事件。
如果一个用户遇到log file sync等待事件,通过v$session_wait查看发现它一直在等待同一个buffer#(P1),那么v$session_wait表中该Session对应的log file sync等待事件的SEQ#会不断增长(否则的话timeout可能存在问题),此时的瓶颈就在LGWR进程,就需要查找堵塞LGWR进程的原因了。
调优LGWR的关键是磁盘IO,例如,redo logs不应该放在RAID5的磁盘阵列上。另外,将分散的事务合并成大事务也有助于减少该等待事件。

参数:
P1-The number of the buffer in the log buffer that needs to be synchronized

3.23.SQL*Net message from client

Session在等待client的输入。

参数:
P1-Prior to Oracle8i release, the value in this parameter was not of much use. Since Oracle8i, the P1RAW column contains an ASCII value to show what type of network driver is in use by the client connections; for example, bequeath, and TCP.
P2-The number of bytes received by the session from the client—generally one, even though the received packet will contain more than 1 byte.

3.24.SQL*Net message to client

This wait event is posted by the session when it is sending a message to the client. The client process may be too busy to accept the delivery of the message, causing the server session to wait, or the network latency delays may be causing the message delivery to take longer.

参数:
P1-Prior to Oracle8i Database, the value in this parameter was not of much use. Since Oracle8i, the P1RAW column contains an ASCII value to show what type of network driver is in use by the client connections, for example, bequeath and TCP.
P2-Number of bytes sent to client. This is generally one even though the sent packet will contain more than 1 byte.

3.25.Global cache cr request

Common wait Events in RAC

When a session is looking for a consistent read (CR) copy of the buffer cached by the remote instance, it waits on the global cache cr request event till the buffer is available in the local instance. Normally the holder constructs the CR version of the buffer and ships it to the requesting instance through the high speed interconnect.

从10g开始,global cache cr request更名为gc cr request waits.

该事件可能存在以下几种情况:

  • 所需buffer的CR copy被发送到提交request的instance, v$sysstat中的”globalcache cr blocks received”统计数量增1;
  • If the buffer is not cached by the remote instance (but mastered by the remote instance),远程instance将该buffer的权限赋予request instance. Session就能够从磁盘直接读取该数据块,”global cache gets”统计数量增1;
  • 如果该buffer的cr copy数量达到了_fairness_threshold参数的限制,the remote instance downgrades the lock to null mode and flushes the redo to the disk. The session can do the disk I/O to get the block from the disk.

关于参数_FAIRNESS_THRESHOLD的解释:
The behavior. of the write-to-read transfer is determined by the _FAIRNESS_THRESHOLD parameter,which was introduced in Oracle 8.1.5 and defaults to 4. Prior to the introduction of this parameter,when Instance A held a block in exclusive mode and Instance B requested a read-only copy of that block, Instance A would downgrade its exclusive lock to a shared lock and send the block to Instance B,which would also set a shared lock on the block. However, if Instance A is performing frequent updates on the block, it will need to reacquire the block and set an exclusive lock again. If this process is repeated frequently, then Instance A will be continually interrupted, as it has to downgrade the exclusive lock to a shared lock and wait until Instance B has finished reading the block before it can convert the shared lock back into an exclusive lock.
The _FAIRNESS_THRESHOLD parameter modifies this behavior. When this parameter is set,Instance A will no longer downgrade the exclusive lock. Instead, it sends a null lock to Instance B,and then it can continue processing. However, if instance B requests the block _FAIRNESS_THRESHOLD times, by default 4, then Instance A will revert to the original behavior—it will downgrade the exclusive lock to a shared lock and ship the block to Instance B, which will also set a shared lock on the block.

如果遇到RAC中的global cache cr request等待事件过长的情况,可以考虑

alter system set "_fairness_threshold" = 3
or even lower, like 1, or 0 to disable downgrading the lock.
Record the data_requests and fairness_down_converts in v$cr_block_server before and after the change. (After the change, let the database run for a while and record the numbers.)
Note:181489.1 Tuning Inter-Instance Performance in RAC and OPS

后两种情况,在global cache cr requtest事件后一般会出现db file sequential reads and/or db file scattered read waits.

参数:P1-file number,P2-block number,P3-lock element number

查看内部参数的方法:
Sql代码
select
x.ksppinm name,
y.ksppstvl value,
y.ksppstdf isdefault,
decode(bitand(y.ksppstvf,7),1,'MODIFIED',4,'SYSTEM_MOD','FALSE') ismod,
decode(bitand(y.ksppstvf,2),2,'TRUE','FALSE') isadj
from
sys.x$ksppi x, sys.x$ksppcv y
where
x.inst_id = userenv('Instance') and
y.inst_id = userenv('Instance') and
x.indx = y.indx and
x.ksppinm like '%_&par%'
order by
translate(x.ksppinm, ' _', ' ');