分享

深入浅出Oracle学习笔记(8)

 cinnamon 2011-10-09

8等待事件

当一个进程连接到event, '%CA%FD%BE%DD%BF%E2');" target="_self">数据库之后,进程所经历的种种等待就开始被记录,并且通过一系列的动态性能视图进行展现。通过等待事件用户可以很快地发现数据库的性能瓶颈,从而进行针对性能的优化和分析。

等待事件可以通过v$event_name视图获得,该视图记录着当前数据库支持的等待事件及其基本信息。

Oracle的等待事件主要可以分为两类,即空闲等待事件和非空闲等待事件。空闲事件指Oracle正等待某种工作,在诊断和优化数据库的时候不用过多注意这部分事件。非空闲等待事件专门针对Oracle的活动,指数据库任务或应用运行过程中发生的等待,这些等待事件是在调整数据库的时候应该关注与研究的。

v$event_name视图中的parameter1parameter2parameter3非常重要,对于不同的等待事件参数的意义各不相同。

SQL> select name,parameter1,parameter2,parameter3 from v$event_name

 2 where name='db file scattered read';

 

NAME

----------------------------------------------------------------

PARAMETER1

----------------------------------------------------------------

PARAMETER2

----------------------------------------------------------------

PARAMETER3

----------------------------------------------------------------

db file scattered read

file#

block#

blocks

 

V$SESSION视图记录的是数据库当前连接的session信息。V$SESSION_WAIT视图记录的是当前数据库连接的活动session正在等待的资源或事件信息。由于V$SESSION记录的是动态信息,和session的生命周期相关,而并不记录历史信息,所以Oracle提供另外一个视图V$SYSTEM_EVENT来记录数据库自启动以来所有等待事件的汇总信息。通过V$SYSTEM_EVENT视图,用户可以迅速地获得数据库运行的总体概况。

 

以下是Oracle 9iR2v$session_wait视图的结构:

SQL> desc v$session_wait

 名称                                     是否为空?类型

 ----------------------------------------- -------- ----------------------------

 SID                                               NUMBER

 SEQ#                                              NUMBER

 EVENT                                             VARCHAR2(64)

 P1TEXT                                            VARCHAR2(64)

 P1                                                NUMBER

 P1RAW                                             RAW(4)

 P2TEXT                                            VARCHAR2(64)

 P2                                                NUMBER

 P2RAW                                             RAW(4)

 P3TEXT                                            VARCHAR2(64)

 P3                                                NUMBER

 P3RAW                                             RAW(4)

 WAIT_TIME                                         NUMBER

 SECONDS_IN_WAIT                                   NUMBER

 STATE                                             VARCHAR2(19)

其中Event代表等待事件的名称,p<n>text用以描述具体的参数,p<n>分别代表以十进制定义参数的参数值,p<n>raw是以十六进制表示的参数值。

 

在数据库出现瓶颈时,通常可以从v$session_wait找到那些正在等待的session,通过sessionsid,联合v$sessionv$sqltext视图就可以捕获这些session正在执行的sql语句。

 

数据库运行缓慢,可以判断数据库可能经历了等待,那么可以通过v$session_wait视图入手。查询v$session_wait获取各进程等待信息:

Select sid,event,p1,p1text from v$session_wait;

 

Db file scattered read(DB文件分散读取):这种情况通常显示与全表扫描相关的等待。当数据库进行全表扫描时,基于性能的考虑,数据会分散读入buffer cache。如果这个等待事件比较显著,可能说明对于谋略写全表扫描的表没有创建索引或者没有创建合适的索引,可能需要检查这些数据表是否进行了正确的设置。然而这个等待事件不一定意味着性能低下,在某些条件下Oracle会主动使用全表扫描来替换索引扫描以提高性能,这和访问的数据量有关,在CBOOracle会进行更为智能的选择,在RBOOracle更倾向于使用索引。

 

确定了进程等待事件之后,考虑捕获这些SQL以发现问题:

Select sql_text from v$sqltext a

Where a.hash_value=(select sql_hash_value from v$session b where b.sid=’&sid’)

Order by piece asc

 

获得了产生等待的sql语句之后,可以使用应用用户连接数据库,检查以上事件的执行计划。

检查表的索引和索引键值:

Select index_name,index_type from user_indexes where table_name=’EMP’;.

Select index_name,column_name from user_ind_columns where table_name=’EMP’;

可以考虑在区分度高的字段上创建索引以消除全表扫描。

 

Oracle10g的增强

虽然V$SESSION_WAIT记录的信息如此重要,但是这些重要的信息是随session而消失的,如果希望获得数据库的历史状态及session的历史等待信息等数据,那是不可得的。

 

 

Top等待事件

V$SYSTEM_EVENT视图记录的是数据库自启动以来等待事件的汇总。通过查询该视图,可以快速获得数据库等待事件的总体概况,了解数据库的基本状态(Top 10 wait event):

Select * from (

Select event,time_waited from v$system_event order by time_waited desc)

Where rownum<10;

 

Statspack ReportTop sql部分导致的Buffer Gets非常高,这使我们有理由怀疑索引存在问题,甚至缺少必要的索引。Statspack中记录的是SQL片段,通过hash value值再结合V$SQL_TEXT,可以获得完整的SQL语句。

接着分组查询V$SESSION_LONGOPS视图:

Select target,count(*) from v$session_longops group by target;

 

V$SESSION_LONGOPS

This view displays the status of various operations that run for longer than 6 seconds (in absolute time). These operations currently include many backup and recovery functions, statistics gathering, and query execution, and more operations are added for every Oracle release.

To monitor query execution progress, you must be using the cost-based optimizer and you must:

Set the TIMED_STATISTICS or SQL_TRACE parameter to true

Gather statistics for your objects with the ANALYZE statement or the DBMS_STATS package

 

重要等待事件

Db file sequential read(数据文件顺序读取)

Db file sequential read是个非常常见的I/O相关的等待事件,通常显示与单个数据块相关的读取操作,在大多数情况下,读取一个索引块或者通过索引读取一个数据块时,都会记录这个等待。

这个等待事件有3个参数P1P2P3,其中P1代表Oracle要读取的文件的绝对文件号,P2代表Oracle从这个文件中开始读取的起始数据块块号,P3代表读取的Block数量,通常这个值为1,表明是单个Block被读取。

SQL> select name,parameter1,parameter2,parameter3

 2 from v$event_name where name='db file sequential read';

NAME

----------------------------------------------------------------

PARAMETER1

----------------------------------------------------------------

PARAMETER2

----------------------------------------------------------------

PARAMETER3

----------------------------------------------------------------

db file sequential read

file#

block#

blocks

 

如果这个等待事件比较显著,可能表示在多表连接中,表的连接顺序存在问题,可能没有正确的使用驱动表;或者可能索引的使用存在问题,并非索引总是最好的选择。

在大多数情况下,通过索引可以更为快速地获取记录,所以对于一个编码规范、调整良好的数据库,这个等待事件很大通常是正常的。但是在很多情况下,使用索引并不是最佳的选择,比如读取较大表中大量的数据,全表扫描可能会明显快于索引扫描,所以在开发中就应该注意,对于这样的查询应该避免使用索引扫描。

Oracle 9iR2开始,Oracle引入了段级统计信息收集的新特性,收集的统计信息共有11类:

Select * from v$segstat_name;

Oracle 10gR2中,这类统计信息增加为15个。

对于CBO模式下的数据库,应当及时收集统计信息,使SQL可以选择正确的执行计划,避免因为统计信息陈旧而导致的执行错误等。

 

Db file scattered read(数据文件离散读取)

SQL> select * from v$event_name where name='db file scattered read';

   EVENT# NAME

---------- ----------------------------------------------------------------

PARAMETER1

----------------------------------------------------------------

PARAMETER2

----------------------------------------------------------------

PARAMETER3

----------------------------------------------------------------

      188 db file scattered read

file#

block#

blocks

V$EVENT_NAME视图可以看到,该事件有3个参数,分别代表文件号、起始数据块号、数据块的数量。

起始数据块号加上数据块的数量,这意味着Oracle session正在等待多块连续读操作的完成。这个操作可能与全表扫描(Full table scan)或者快速全索引扫描(Index Fast Full Scan)的连续读取相关。根据经验,通常大量的db file scattered read等待可能意味着应用问题或者索引缺失。

在实际环境的诊断过程中,可以通过v$session_wait视图发现session的等待,再结合其他视图找到存在问题的SQL等根本原因,从而从根本上解决问题。当这个等待事件比较显著时,也可结合v$session_longops动态性能视图来进行诊断,该视图记录了长时间(运行时间超过6秒的)运行的事务。

Oracle 9i开始,Oracle新增加了一个视图V$SQL_PLAN用于记录当前系统Library CacheSQL语句的执行计划,可以通过这个视图找到存在问题的SQL语句。

通过V$SQL_PLAN视图,可以获得大量有用的信息:

获得全表扫描的对象

Select distinct object_name,object_owner from v$sql_plan p

Where p.operation=’TABLE ACCESS’and p.options=’FULL’ and object_owner=’SCOTT’;

获得全索引扫描的对象

Select distinct object_name,object_owner from v$sql_plan p

Where p.operation=’INDEX’ and p.options=’FULL SCAN’ and object_owner=’SCOTT’;

通过V$SQL_PLANV$SQLTEXT联合,获得全表扫描的SQL语句

Select sql_text from v$sqltext t,v$sql_plan p

Where t.hash_value=p.hash_value

And p.operation=’TABLE ACCESS’

And p.options=’FULL’

Order by p.hash_value,t.piece;

 

Direct path read/write(直接路径读/写)

直接路径读通常发生在Oracle直接读取数据到PGA时,这个读取不需要经过SGA。直接路径读等待事件的3个参数分别是:file#(指绝对文件号)、first block#block数量。

这类读取通常在以下情况被使用:

磁盘排序IO操作

并行查询从属进程

预读操作

最常见的是第一种情况。在DSS系统中,存在大量的Direct path read是很正常的,但是在OLTP系统中,通常显著的直接路径读都意味着系统应用存在问题,从而导致大量的磁盘排序读取操作。

直接路径写通常发生在Oracle直接从PGA写数据到数据文件或临时文件,这个写操作可以绕过SGA。直接路径写等待事件的3个参数分别是:file#(指绝对文件号)、first block#block数量。

这类读取通常在以下情况被使用:

直接路径加载

并行DML操作

磁盘排序

对未缓存的“LOB”段的写入,随后会记录为direct path write(lob)等待

最常见的直接路径写,多数因为磁盘排序导致。对于这一写入等待,应该找到I/O操作最为频繁的数据文件(如果有过多的排序操作,很有可能就是临时文件),分散负载,加快其写入操作。

如果系统存在过多的磁盘排序,会导致临时表空间操作频繁,对于这种情况,可以考虑为不同用户分配不同的临时表空间,使用多个临时文件,写入不同磁盘或者裸设备,从而降低竞争提高性能。

 

 

日志文件相关等待

SQL> select name from v$event_name where name like '%log%';

NAME

----------------------------------------------------------------

log switch/archive

log file sequential read

log file single write

log file parallel write

log buffer space

log file switch (checkpoint incomplete)

log file switch (archiving needed)

log file switch (clearing log file)

switch logfile command

log file switch completion

log file sync

STREAMS capture process waiting for archive log

 

已选择12行。

 

Log File Switch(日志文件切换)

Log File Switch当日志文件发生切换时出现,在数据库进行日志切换时,LGWR需要关闭当前日志组,切换并打开下一个日志组,在这个切换过程中,数据库的所有DML操作都处于停顿状态,直至这个切换完成。

Log File Switch主要包含两个子事件:

log file switch(achiving needed),即日志切换(需要归档)

这个等待事件出现时通常是因为日志组循环写满以后,在需要覆盖先前日志时,发现日志归档尚未完成,出现该等待。由于Redo不能写出,该等待出现时,数据库将陷于停顿状态。

出现该等待,可能表示I/O存在问题、归档进程写出缓慢,也有可能是日志组设置不合理等原因导致。针对不同原因,可以考虑采用的解决方法有:

可以考虑增大日志文件和增加日志组;

移动归档文件到快速磁盘;

调整log_archive_max_processes参数等;

log file switch(checkpoint incomplete),即日志切换(检查电未完成)

当所有的日志组都写满之后。LGWR试图覆盖某个日志文件,如果这时数据库没有完成写出由这个日志文件所保护的脏数据时(检查点未完成),该等待事件出现。该等待出现时,数据库同样将陷于停顿状态。

该等待事件通常表示DBWR写出速度太慢或者I/O存在问题。为解决该问题,可能需要考虑增加额外的DBWR或者增加日志组或日志文件大小。

 

Log File Sync(日志文件同步)

当一个用户提交或回滚数据时,LGWR将会话期的重做由日志缓冲区写入到重做日志中,LGWR完成任务以后会通知用户进程。日志文件同步过程(Log File Sync)必须等待这一过程成功完成。对于回滚操作,该事件记录从用户发出Rollback命令道回滚完成的时间。

如果该等待过多,可能说明LGWR的写出效率低下,或者系统提交过于频繁。针对该问题,可以通过log file parallel write等待事件或User CommitsUser Rollback等统计信息来观察提交或回滚次数。

可能的解决方案主要有:

提高LGWR性能,尽量使用快速磁盘,不要把redo log file存放在RAID5的磁盘上;

使用批量提交;

适当使用NOLOGGING/UNRECOVERABLE等选项

 

Log File Single Write

该事件仅与写日志文件头块相关,通常发生在增加新的组成员和增进序列号(Log switch)时。头块写单个进行,因为头块的部分信息是文件号,每个文件不同。

 

Log File Parallel Write

Log BufferRedo记录到日志文件,主要指常规写操作(相对于Log File Sync)。如果Log Group存在多个组成员,当Flush Log Buffer时,写操作是并行的,这时候此等待事件可能出现。

 

Log Buffer Space(日志缓冲空间)

当数据库产生日志的速度比LGWR的写出速度快,或者当日志切换太慢时,就会发生这种等待。这个等待出现时,通常表明Redo log buffer过小,为解决这个问题,可以考虑增大日志文件的大小或者增加日志缓冲器的大小。

另一个可能的原因是磁盘I/O存在瓶颈,可以考虑使用写入速度更快的磁盘。在允许的条件下设置,可以考虑使用裸设备来存放日志文件,提高写入效率。在一般的系统中,最低的标准是,不要把日志文件和数据文件存放在一起,因为通常日志文件只写不读,分离存放可以获得性能提升,尽量使用RAID10而不是RAID5磁盘来存储日志文件。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多