Wait Events

2025-10-16Oracle / RAC / 性能优化

All about Wait

                Events

What are Wait Events?

Common Wait Events

Wait Event Views

[Automatic Workload

  Repository](http://www.pafumi.net/Wait_Events.html#Automatic_Workload_RepositoryAWR)

Time Model Statistics

Tracing Wait Events

Wait Interface

Query Examples

At any given moment, every Oracle process is either busy

  servicing a request or waiting for something specific to happen.
  By "busy" we mean that the process wishes to use the CPU. For
  example, a dedicated server process might be searching the buffer
  cache to see if a certain data block is in memory. This process
  would be said to be busy and not waiting. The ARC0 process,
  meanwhile, might be waiting for LGWR to signal that an online redo
  log needs archiving. In this case, the ARC0 process is waiting.
  By querying v$ views, we can see what events processes are waiting
  on to an amazing level of detail.

Using the wait event interface, you can get insights into where

  time is being spent. If a report takes four hours to complete, for
  example, the wait event interface will tell you how much of that
  four hours was spent waiting for disk reads caused by full table
  scans, disk reads caused by index lookups, latch contention, and
  so on.
  The wait event interface provides much more information to work
  with than cache hit ratios do.You get data that can touch upon so
  many different areas of your database such as disk I/O, latches,
  parallel processing, network traffic, checkpoints, and row-level
  locking. At the same time, you get incredible detail such as the
  file number and block number of a block being read from disk, or
  the name of a latch being waited on along with the number of
  retries.

Common Wait

                    Event Names and What They Mean 

Although there are many different types of wait events, the

  majority of them come up very infrequently or tend not to be
  significant. In practice, only a few dozen wait events tend to be
  of interest to most DBAs. You'll see different wait events
  surfacing in different environments based on which Oracle features
  have been implemented and which capabilities of the database are
  being taxed the most. For example, the PX wait events won't appear
  if you aren't using parallel query, and the virtual circuit status
  wait event won't appear if you are not using the multi-threaded
  server architecture (or shared server architecture as it is more
  recently called). Along those lines, the log file sync and enqueue
  wait events probably won't be prevalent in a primarily read-only
  system. 

If you want a quick instance wide

    wait event status, showing which events are the biggest
    contributors to total wait time, you can use the following query
    :

select event, total_waits,time_waited from

      V$system_event
      where event NOT IN
      ('pmon timer',
      'smon timer', 'rdbms ipc reply', 'parallel deque wait',
      'virtual circuit',
      '%SQL*Net%', 'client message', 'NULL event')
    order by time_waited desc;

EVENT

      TOTAL_WAITS        
      TIME_WAITED
    ------------------------         
      -------------      
      -------------
    db file sequential
      read             

35051309

      15965640
    latch
      free                           

1373973

      1913357
    db file scattered
      read               

2958367

      1840810
    enqueue                                 

2837

      370871
    buffer busy
      waits                     

444743

      252664
    log file parallel
      write               

146221

      123435
    Here are some of the most common wait events and what
  they mean:
  1. DB File Scattered Read.
        That generally happens during a or . As
        full table scans are pulled into memory, they rarely fall
        into contiguous buffers but instead are scattered throughout
        the buffer cache. A large number here indicates that your
        table may have missing indexes, statistics are not updated
        or your indexes are not used. Although it may be more
        efficient in your situation to perform a full table scan
        than an index scan, check to ensure that full table scans
        are necessary when you see these waits. Try to cache small
        tables to avoid reading them in over and over again, since a
        full table scan is put at the cold end of the LRU (Least
        Recently Used) list. You
        can use the report to help identify the query in question
        and fix it.
      The init.ora
    parameter db_file_multiblock_read_count
    specifies the maximum numbers of blocks read in that way.
    Typically, this parameter should have values of 4-16 independent
    of the size of the database but with higher values needed with
    smaller Oracle block sizes. If you have a high wait time for
    this event, you either need to reduce the cost of I/O, e.g. by
    getting faster disks or by distributing your I/O load better, or
    you need to reduce the amount of full table scans by tuning SQL
    statements. The appearance of the‘db file scattered read’ and ‘db file sequential read’events
    may not necessarily indicate a problem, as IO is a normal
    activity on a healthy instance. However, they can indicate
    problems if any of the following circumstances are true:
    • The data-access method is bad (that is, the SQL statements are
    poorly tuned), resulting in unnecessary or inefficient IO
    operations
    • The IO system is overloaded and performing poorly
    • The IO system is under-configured for the load
    • IO operations are taking too long

If this Wait Event is a significant

    portion of Wait Time then a number of approaches are possible:
    o Find which SQL statements perform Full Table or Fast Full
    Index scans and tune them to make sure these scans are necessary
    and not the result of a suboptimal plan.
  • The view V$SQL_PLAN view can help:
    For Full Table scans:
    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;

For Fast Full Index scans:

    select sql_text from
      v$sqltext t, v$sql_plan p
      where
      t.hash_value=p.hash_value 
          and p.operation='INDEX'
        and
      p.options='FULL SCAN'
      order by
      p.hash_value, t.piece;

o In cases where such multiblock scans

    occur from optimal execution plans it is possible to tune the
    size of multiblock I/Os issued by Oracle by setting the instance
    parameter DB_FILE_MULTIBLOCK_READ_COUNT so that:
    DB_BLOCK_SIZE x DB_FILE_MULTIBLOCK_READ_COUNT = max_io_size of
    system 
    Query tuning should be used to optimize online SQL to use
    indexes.
  1. DB File Sequential Read.
  Is the wait
      that comes from the physical side of the database. It related
      to memory starvation and non selective index use. Sequential
      read is an index read followed by table read because it is
      doing index lookups which tells exactly which block to go to.
    This could indicate poor
      joining order of tables or un-selective indexes in your
    SQL or waiting for writes to TEMP space (direct loads,
    Parallel DML (PDML) such as parallel updates. It could mean that a lot of index reads/scans
    are going on. Depending on the problem it may help to tune
    PGA_AGGREGATE_TARGET and/or DB_CACHE_SIZE. 
  The
    sequential read event identifies Oracle reading blocks
    sequentially, i.e. one after each other. It is normal for this
    number to be large for a high-transaction, well-tuned system,
    but it can indicate problems in some circumstances. You should
    correlate this wait statistic with other known issues within the
    report, such as inefficient SQL. Check to ensure that index
    scans are necessary, and check join orders for multiple table
    joins. The DB_CACHE_SIZE will also be a determining factor in
    how often these waits show up. Problematic hash-area joins
    should show up in the PGA memory, but they're also memory hogs
    that could cause high wait numbers for sequential reads. They
    can also show up as direct path read/write waits. These
  circumstances are usually interrelated. When they occur in
  conjunction with the appearance of the 'db file scattered read' and 'db file sequential read' in
  the Top 5 Wait Events section, first you should examine the SQL
  Ordered by Physical Reads section of the report, to see if it
  might be helpful to tune the statements with the highest resource
  usage. 
  It could be because the indexes are fragmented. If that is the
  case, rebuilding the index will compact it and will produce to
  visit less blocks.
  Then, to determine whether there is a potential I/O bottleneck,
  examine the OS I/O statistics for corresponding symptoms. Also
  look at the average time per read in the Tablespace and File I/O
  sections of the report. If many I/O-related events appear high in
  the Wait Events list, re-examine the host hardware for disk
  bottlenecks and check the host-hardware statistics for indications
  that a disk reconfiguration may be of benefit.
  Block reads are fairly inevitable so the aim should be to minimize
  unnecessary I/O. I/O for sequential reads can be reduced by tuning
  SQL calls that result in full table scans and using the
  partitioning option for large tables.
  1. Free Buffer Waits.
    When a session needs a free buffer and cannot find one, it will
    post the database writer process asking it to flush dirty blocks
    (No place to put a new block). Waits in this category may
    indicate that you need to increase
      the DB_BUFFER_CACHE, if all your SQL is tuned. Free
    buffer waits could also indicate that unselective SQL is causing
    data to flood the buffer cache with index blocks, leaving none
    for this particular statement that is waiting for the system to
    process. This normally indicates that there is a substantial
    amount of DML (insert/update/delete) being done and that the
    Database Writer (DBWR) is not writing quickly enough; the buffer
    cache could be full of multiple versions of the same buffer,
    causing great inefficiency. To address this, you may want to
    consider accelerating
      incremental checkpointing, using more DBWR processes,
    or increasing the number of physical disks. To investigate if
    this is an I/O problem, look at the report I/O Statistics.
    Increase the DB_CACHE_SIZE; shorten the checkpoint; tune the
    code to get less dirty blocks, faster I/O, use multiple DBWR’s.
  1. Buffer Busy Waits. A buffer busy wait happens when multiple
    processes concurrently want to modify the same block in the
    buffer cache. This typically happens during massive parallel
    inserts if your tables do not have free lists and it can happen
    if you have too few rollback segments. Buffer busy waits should not be greater than 1 percent.
    Check the Buffer Wait Statistics section (or V$WAITSTAT) to find
    out if the wait is on a segment header. If this is the case,
    increase the freelist groups or increase the pctused to pctfree
    gap. If the wait is on an undo header, you can address this by
    adding rollback segments; if it's on an undo block, you need to
    reduce the data density on the table driving this consistent
    read or increase the DB_CACHE_SIZE. If the wait is on a data
    block, you can move data to another block to avoid this hot
    block, increase the freelists on the table, or use Locally
    Managed Tablespaces (LMTs). If it's on an index block, you
    should rebuild the index, partition the index, or use a reverse
    key index. To prevent buffer busy waits related to data blocks,
    you can also use a smaller block size: fewer records fall within
    a single block in this case, so it's not as "hot." When a DML
    (insert/update/ delete) occurs, Oracle writes information into
    the block, including all users who are "interested" in the state
    of the block (Interested Transaction List, ITL). To decrease
    waits in this area, you can increase the initrans, which will
    create the space in the block to allow multiple ITL slots. You
    can also increase the pctfree on the table where this block
    exists (this writes the ITL information up to the number
    specified by maxtrans, when there are not enough slots built
    with the initrans that is specified). Buffer busy waits can be
    reduced by using reverse-key indexes for busy indexes and by
    partitioning busy tables.
    Buffer Busy Wait on Segment
      Header – Add freelists (if inserts) or freelist groups
    (esp. RAC). Use ASSM.
  Buffer Busy Wait on Data
      Block – Separate ‘hot’ data; potentially use reverse key
    indexes; fix queries to reduce the blocks popularity, use
    smaller blocks, I/O, Increase initrans and/or maxtrans (this
    one’s debatable). Reduce records per block
    Buffer Busy Wait on
      Undo Header – Add rollback segments or increase size of
    segment area (auto undo) 
    Buffer Busy Wait on
      Undo block – Commit more (not too much) Larger rollback
    segments/area. Try to fix the SQL.
  1. Latch Free. Latches are
    low-level queuing mechanisms (they're accurately referred to as
    mutual exclusion mechanisms) used to protect shared memory
    structures in the system global area (SGA). Latches are like
    locks on memory that are very quickly obtained and released.
    Latches are used to prevent concurrent access to a shared memory
    structure. If the latch is not available, a latch free miss is
    recorded. Most latch problems are related to the failure to use
    bind variables (library cache latch), redo generation issues
    (redo allocation latch), buffer cache contention issues (cache
    buffers LRU chain), and hot blocks in the buffer cache (cache
    buffers chain). There are also latch waits related to bugs;
    check MetaLink for bug reports if you suspect this is the case.
    When latch miss ratios are greater than 0.5 percent, you should
    investigate the issue. If
  latch free waits are in the Top 5 Wait Events or high in the
  complete Wait Events list, look at the latch-specific sections of
  the report to see which latches are contended for.
  1. Enqueue. An enqueue is a lock that protects a shared
    resource. Locks protect shared resources, such as data in a
    record, to prevent two people from updating the same data at the
    same time application, e.g. when a select for update is
    executed.. An enqueue includes a queuing mechanism, which is
    FIFO (first in, first out). Note that Oracle's latching
    mechanism is not FIFO. Enqueue waits usually point to the ST
    enqueue, the HW enqueue, the TX4 enqueue, and the TM enqueue.
    The ST enqueue is used for space management and allocation for
    dictionary-managed tablespaces. Use LMTs, or try to preallocate
    extents or at least make the next extent larger for problematic
    dictionary-managed tablespaces. HW enqueues are used with the
    high-water mark of a segment; manually allocating the extents
    can circumvent this wait. TX4s are the most common enqueue
    waits. TX4 enqueue waits are usually the result of one of three
    issues. The first issue is duplicates in a unique index; you
    need to commit/rollback to free the enqueue. The second is
    multiple updates to the same bitmap index fragment. Since a
    single bitmap fragment may contain multiple rowids, you need to
    issue a commit or rollback to free the enqueue when multiple
    users are trying to update the same fragment. The third and most
    likely issue is when multiple
      users are updating the same block. If there are no free
    ITL slots, a block-level lock could occur. You can easily avoid
    this scenario by increasing the initrans and/or maxtrans to
    allow multiple ITL slots and/or by increasing the pctfree on the
    table. Finally, TM enqueues occur during DML to prevent DDL to
    the affected object. If you have foreign keys, be sure to index them to avoid
    this general locking issue.
    Enqueue - ST
    Use LMT’s or pre-allocate large extents 
    Enqueue - HW
    Pre-allocate extents above HW (high water mark.)
    Enqueue – TX
    Increase initrans and/or maxtrans (TX4) on (transaction) the
    table or index.  Fix locking issues if TX6.  Bitmap
    (TX4) & Duplicates in Index (TX4).
    Enqueue - TM
    Index foreign keys; Check application (trans. mgmt.) locking of
    tables.  DML Locks.
  1. Log Buffer Space
    Look at increasing log buffer size. This wait occurs because you
    are writing the log buffer faster than LGWR can write it to the
    redo logs, or because log
      switches are too slow. To address this problem,
    increase the size of the redo log files, or increase the size of
    the log buffer, or get faster disks to write to. You might even
    consider using solid-state disks, for their high speed. 
  The session is waiting for space in the log
    buffer. (Space becomes available only after LGWR has written the
    current contents of the log buffer to disk.) This typically
    happens when applications generate redo faster than LGWR can
    write it to disk.
  1. Log File Switch
    log file switch (checkpoint incomplete): May indicate excessive
    db files or slow IO subsystem
    log file switch (archiving needed):  Indicates archive
    files are written too slowly
    log file switch completion: May need more log files per
    May indicate excessive db files or slow IO subsystem. All commit
    requests are waiting for "logfile switch (archiving needed)" or
    "logfile switch (chkpt. Incomplete)." Ensure that the archive
    disk is not full or slow. DBWR may be too slow because of I/O.
    You may need to add more or larger redo logs, and you may
    potentially need to add database writers if the DBWR is the
    problem.
  1. Log File Sync
    Could indicate excessive commits. A Log File Sync happens each
    time a commit (or rollback) takes place. If there are a lot of
    waits in this area then you may want to examine your application
    to see if you are committing too frequently (or at least more
    than you need to). When a user commits or rolls back data, the
    LGWR flushes the session's redo from the log buffer to the redo
    logs. The log file sync process must wait for this to
    successfully complete. To reduce wait events here, try to commit
    more records (try to commit a
      batch of 50 instead of one at a time, use BULKS, , for example).
    Put redo logs on a faster disk, or alternate redo logs on
    different physical disks (with no other DB Files, ASM, etc) to
    reduce the archiving effect on LGWR. Don't use RAID 5, since it
    is very slow for applications that write a lot; potentially
    consider using file system direct I/O or raw devices, which are
    very fast at writing information. The associated event, ‘log
    buffer parallel write’ is used by the redo log writer process,
    and it will indicate if your actual problem is with the log file
    I/O. Large wait times for this event can also be caused by
    having too few CPU resources available for the redolog writer
    process.
  1. Idle Event. There are several idle wait events listed
    after the output; you can ignore them. Idle events are generally
    listed at the bottom of each section and include such things as
    SQL*Net message to/from client and other background-related
    timings. Idle events are listed in the stats$idle_event table.
  1. global
  2. cache

      cr request: (OPS) This wait event shows the amount of
    time that an instance has waited for a requested data block for
    a consistent read and the transferred block has not yet arrived
    at the requesting instance. See Note 157766.1 'Sessions Wait
    Forever for 'global cache cr request' Wait Event in OPS or RAC'.
    In some cases the 'global cache cr request' wait event may be
    perfectly normal if large buffer caches are used and the same
    data is being accessed concurrently on multiple instances. 
    In a perfectly tuned, non-OPS/RAC database, I/O wait events
    would be the top wait events but since we are avoiding I/O's
    with RAC and OPS the 'global cache cr request' wait event often
    takes the place of I/O wait events.

12.

    library cache pin: Library cache
    latch contention may be caused by not using bind variables. It
    is due to excessive parsing of SQL statement. 
  The session wants to pin an object in
    memory in the library cache for examination, ensuring no other
    processes can update the object at the same time. This happens
    when you are compiling or parsing a PL/SQL object or a view.
  1. CPU
        time
      This is not really a wait event (hence, the new name), but
      rather the sum of the CPU used by this session, or the amount
      of CPU time used during the snapshot window. In a heavily
      loaded system, if the CPU time event is the biggest event,
      that could point to some CPU-intensive processing (for
      example, forcing the use of an index when a full scan should
      have been used), which could be the cause of the bottleneck.
      When CPU Other is a significant component of total Response
      Time the next step is to find the SQL statements that access
      the most blocks. Block accesses are also known as Buffer Gets
      and Logical I/Os. The report lists such SQL statements in
      section SQL ordered by Gets. 
  1. DB File Parallel
        Read  If you are doing a lot of partition
      activity then expect to see that wait even. it could be a
      table or index partition. This Wait Event is used when Oracle
      performs in parallel reads from multiple datafiles to
      non-contiguous buffers in memory (PGA or Buffer Cache). This
      is done during recovery operations or when buffer prefetching
      is being used as an optimization i.e. instead of performing
      multiple single-block reads. If this wait is an important
      component of Wait Time, follow the same guidelines as 'db file
      sequential read'. 
  This may occur during
      recovery or during regular activity when a session batches
      many single block I/O requests together and issues them in
      parallel. 
  1. PX qref latch
      Can often mean that the Producers are producing data quicker
      than the Consumers can consume it. Maybe we could increase
      parallel_execution_message_size to try to eliminate some of
      these waits or we might decrease the degree of parallelism. If
      the system workload is high consider to decrease the degree of
      parallelism. If you have DEFAULT parallelism on your
      object  you can decrease the value of
      PARALLEL_THREADS_PER_CPU.  Have in mind  DEFAULT
      degree = PARALLEL_THREADS_PER_CPU * #CPU's  
  1. Log File Parallel
        Write. It occurs when waiting for writes of REDO
      records to the REDO log files to complete. The wait occurs in
      log writer (LGWR) as part of normal activity of copying
      records from the REDO log buffer to the current online log.
      The actual wait time is the time taken for all the outstanding
      I/O requests to complete. Even though the writes may be issued
      in parallel, LGWR needs to wait for the last I/O to be on disk
      before the parallel write is considered complete. Hence the
      wait time depends on the time it takes the OS to complete all
      requests.
      Log file parallel write waits can be reduced by moving log
      files to the faster disks and/or separate disks where there
      will be less contention.
  1. SQL*Net more data to
        client
      This means the instance is sending a lot of data to the
      client. You can decrease this time by having the client bring
      back less data. Maybe the application doesn't need to bring
      back as much data as it is. 
  1. SQL*Net message to
        client
      The “SQL*Net message to client” Oracle metric indicates the
      server (foreground process) is sending a message to the
      client, and it can be used to identify throughput issues over
      a network, especially distributed databases with slow database
      links. The SQL*Net more data to client event happens when
      Oracle writes multiple data buffers (sized per SDU) in a
      single logical network call.
  1. enq: TX – row lock
        contention:
      Oracle keeps data consistency with the help of locking
      mechanism. When a particular row is being modified by the
      process, either through Update/ Delete or Insert operation,
      oracle tries to acquire lock on that row. Only when the
      process has acquired lock the process can modify the row
      otherwise the process waits for the lock. This wait situation
      triggers this event. The lock is released whenever a COMMIT is
      issued by the process which has acquired lock for the row.
      Once the lock is released, processes waiting on this event can
      acquire lock on the row and perform DML operation
  1. direct Path writes:
  1. direct Path reads / direct path writes:
  1. write complete waits:
  1. direct path read temp or direct path write temp:
  1. Undo segment extension:
  1. wait for a undo record:
  1. Control File Parallel Write
  1. Control File Sequential Read
  1. DB File Parallel Write:
  1. Library Cache load lock
  1. log file sequential read

Idle events are usually not

  very interesting from a tuning standpoint

      | 
        client message
         | PX Deq: Execute Reply
       |
      | 
        dispatcher timer
         | PX Deq: Execution Msg
       |
      | 
        gcs for action
         | PX Deq: Signal ACK
       |
      | 
        gcs remote message
         | PX Deq: Table Q Normal
       |
      | 
        ges remote message
         | PX Deque wait
       |
      | 
        i/o slave wait
         | PX Idle Wait
       |
      | 
        jobq slave wait
         | queue messages
       |
      | 
        lock manager wait for remote message
         | rdbms ipc message
       |
      | 
        null event
         | slave wait
       |
      | 
        parallel query dequeue
         | smon timer
       |
      | 
        pipe get
         | SQL*Net message from client
       |
      | 
        PL/SQL lock timer
         | SQL*Net message to client
       |
      | 
        pmon timer
         | SQL*Net more data from client
       |
      | 
        PX Deq Credit: need buffer
         | virtual circuit status
       |
      | 
        PX Deq Credit: send blkd
         | wakeup time manager
       |

If an Oracle process has work to do but, must wait for

  something to happen before it can continue, then the process will
  be waiting on a non-idle wait
    event. If a process has nothing to do, it will be waiting
  on an idle wait event. So
  what happens if a process has work to do and is busy doing it?
  When a process is busy, there will be no information in the wait
  event interface since the process is not waiting. 

When we look at the wait event

  information extracted from an Oracle instance, we see detailed
  information about how many times and how much time was spent
  waiting for specific events to occur. But we do not see anything
  about the time periods in which the process requested use of the
  CPU. This means that the wait event interface is not able to
  provide information about the following: 
  • Time spent using the CPU
  • Time spent waiting for a CPU to become available
  • Time spent waiting for requested memory to be swapped back in
    to physical memory

This is important to keep in

    mind because there is an easy trap to fall into. You could be
    troubleshooting a very slow SELECT statement and learn from the
    wait event interface that the process does not have significant
    wait events when running the query. This could lead you to think
    that the statement is optimal, and that it just takes a long
    time to run. In fact, however, the query might be performing
    huge numbers of logical reads and the number of buffer gets
    could be reduced by rewriting the query. 

When Oracle needs to access a data block and the block is already

  in the buffer cache, a logical read occurs with no physical read.
  The process is able to read the block without the occurrence of
  any wait events. Large amounts of CPU time could be consumed on
  significant numbers of logical reads, and the wait event interface
  will have nothing to show for the elapsed time.
  Statement parsing and spinning while waiting for a latch to become
  available are two other examples of activities not accounted for
  by the wait event interface. An Oracle process uses CPU time while
  parsing a statement or spinning on a busy latch; since no waiting
  is involved, the wait event interface does not have anything to
  report.
  In Statspack, the report that lists wait event information also
  lists CPU usage. This is very helpful information. It allows us to
  easily compare time spent waiting to time spent processing, so we
  know where to focus our tuning efforts. However, it should be
  pointed out that the CPU usage information in this section of the
  Statspack report does not come from the wait event interface.
  Instead, Statspack merges data collected from the wait event
  interface with CPU usage information collected from the v$sysstat
  dynamic performance view. 

The Oracle kernel is capable of timing many activities including

  wait events. When timed_statistics is set to FALSE, all times in
  the wait event interface will appear as zero. You may enable timed
  statistics collection at the instance or the session level with
  the following commands: 
  • ALTER SYSTEM SET timed_statistics = TRUE;
  • ALTER SESSION SET timed_statistics = TRUE;

You may enable timed statistics at the instance level on the next

  and all subsequent instance restarts by adding the following line
  to the instance parameter file: 
    timed_statistics = trueIn practice, the overhead of collecting timed statistics is
  extremely small, so by default this parameter is set to TRUE.

Wait Event Views

There are two common ways of collecting wait event information:

  the Oracle extended trace (10046 event) and using V$ views; we
  will focus on this one 
  Any user with the SELECT ANY TABLE system privilege or the
  SELECT_CATALOG_ROLE role can query the v$ views. Only users who
  can connect to the database as SYSDBA or execute the DBMS_SUPPORT
  or DBMS_SYSTEM packages can activate wait event tracing in other
  database sessions.
  Oracle provides a number of views to aid in tuning; a few are:
  • V$SYSTEM_EVENT, which gives you total system
  waits for an event since database startup.
  • V$SESSION_EVENT, All waits the session
  encountered so far at the session level.
  • V$SESSION_WAIT gives you what an active
  session is waiting on at that point in time.
  • V$SESSION, which gives you session
  information and has a column ROW_WAIT_OBJ# that tells you the
  object involved when joined with OBJECT_ID or DATA_OBJECT_ID in
  DBA_OBJECTS. 

There are several V$ views for tracking history called

  V$%_HISTORY, including V$ACTIVE_SESSION_HISTORY (ASH), which
  samples non-idle wait events every second and new columns in
  V$SESSION to combine information in V$SESSION_WAIT.  The
  information is held for 30 minutes, then is stored in AWR:
  DBA_HIST_ACTIVE_SESS_HIST 

V$SYSTEM_EVENT

  The v$system_event view shows one row for each wait event name,
  along with the total number of times a process has waited for this
  event, the number of timeouts, the total amount of time waited,
  and the average wait time. All of these figures are cumulative for
  all Oracle processes since the instance started. Wait events that
  have not occurred at least once since instance startup do not
  appear in this view. The v$system_event view has the following
  columns: 

Name Null? Type

—————————————– ——– ——————

EVENT VARCHAR2(64)

TOTAL_WAITS NUMBER

TOTAL_TIMEOUTS NUMBER

TIME_WAITED NUMBER

AVERAGE_WAIT NUMBER

TIME_WAITED_MICRO NUMBER

TOTAL_WAITS_FG NUMBER

TOTAL_TIMEOUTS_FG NUMBER

TIME_WAITED_FG NUMBER

AVERAGE_WAIT_FG NUMBER

TIME_WAITED_MICRO_FG NUMBER

EVENT_ID NUMBER

WAIT_CLASS_ID NUMBER

WAIT_CLASS# NUMBER

WAIT_CLASS VARCHAR2(64)EVENT = The name of the wait event. You can see a list of all

  wait event names known to your Oracle kernel with the following
  query:
          SELECT name FROM v$event_name order by 1;
  TOTAL_WAITS = The total number of times a process has waited for
  this event since instance startup. 
  TOTAL_TIMEOUTS = The total number of times a process encountered a
  timeout while waiting for an event. When a process begins to wait
  for an event, it specifies a timeout period after which the
  operating system should wake it up if the event has not yet
  transpired. For example, when an Oracle process issues an I/O
  request to read a block from a data file (the db file sequential
  read wait event), the process sets a timeout of one second.
  Usually the I/O request will complete in less than one second and
  no timeout will occur. But if the read should take longer than one
  second for whatever reason, a timeout will occur and the process
  will wake up. The process might do some minor housekeeping, but it
  will likely just begin another timeout period of one second and
  continue waiting for the same event.
  TIME_WAITED and AVERAGE_WAIT show the cumulative (sum) and average
  time spent by processes waiting for this event, in centiseconds.
  Multiply these figures by 100 in order to get the wait time in
  seconds. These two columns will show as zero if timed statistics
  are not enabled.
  TIME_WAITED_MICRO is the same as TIME_WAITED, except that the time
  is in microseconds. Multiply this figure by 1000000 in order to
  get the wait time in seconds.

Consider the following query from v$system_event: set linesize 180

select substr(event,1,40) event, total_waits, total_timeouts, 100*time_waited Time_Waited_Sec, 100*average_wait Average_Wait_Sec

FROM v$system_event

WHERE event IN ('SQL*Net message from client', 'smon timer', 'db file sequential read', 'log file parallel write');

EVENT TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED_SEC AVERAGE_WAIT_SEC

—————————————- ———– ————– ————— —————-

log file parallel write 768 0 1596.92 60

db file sequential read 5190 0 286.57 72

smon timer 15 8 1306738.37 1605427

SQL*Net message from client 266 0 16189800 60864

V$SESSION_EVENT

  The v$session_event view is a lot like the v$system_event view,
  except that it shows separate rows of information for each Oracle
  process. As with v$system_event, event names do not appear in this
  view if the process has not waited for them at least once. Also,
  when an Oracle process terminates (as in the case of when a user
  logs off the database) all of the rows in v$session_event for that
  process permanently disappear. The v$session_event view has the
  following columns: 

Name Null? 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)SID = Session ID. You can query v$session in order to determine

  the SID of the session whose wait events you want to investigate
  EVENT = The name of the wait event, e.g. "library cache lock" 
  TOTAL_WAITS = total number of times this session has waited 
  TOTAL_TIMEOUTS = total no. of times timeouts occurred for this 
  TIME_WAITED = the total time (in 100th of sec) waited 
  AVERAGE_WAIT = the average wait per wait 
  MAX_WAIT = indicates the maximum amount of time the process had to
  wait for the event. Like TIME_WAITED and AVERAGE_WAIT, the unit of
  measure is centiseconds and will display as zero if timed
  statistics are not enabled
  TIME_WAITED_MICRO = same as time_waited; but in micro seconds 
  EVENT_ID = the event ID of the event 
  WAIT_CLASS_ID = the class of the waits 
  WAIT_CLASS# 
  WAIT_CLASS 

Note = V$EVENT_NAME has the event details joined on EVENT#

  column 

Consider the following query which displays all wait event

  information for the current SQL*Plus session: 

SELECT event, total_waits, time_waited_micro, max_wait

FROM v$session_event

WHERE SID = (SELECT sid FROM v$session WHERE audsid = USERENV ('sessionid'));

EVENT TOTAL_WAITS TIME_WAITED_MICRO MAX_WAIT

—————————— ———– —————– ———-

log file sync 1 19629 2

db file sequential read 3 26128 1

db file scattered read 678 1154632 8

SQL*Net message to client 76 352 0

SQL*Net more data to client 1 63 0

SQL*Net message from client 75 1118656279 26930

SQL*Net break/reset to client 4 22281 2

You can see that the Oracle process serving this session has

  spent 1.180760 seconds waiting for disk I/O. Although there have
  been 76 instances where the process waited for the networking
  software to allow it to send a message to the client (the SQL*Plus
  program), each of these waits was shorter than the 0.01 second
  resolution of the MAX_WAIT column in v$session_event. (All 76
  waits combined added up to only 0.000352 seconds.) Far and away,
  the Oracle process has spent the vast majority of its time (over
  18 minutes) waiting for a SQL statement to be entered at the
  SQL*Plus prompt. 

V$SESSION_WAIT

  The v$session_wait view shows one row for each Oracle process. The
  row indicates the name of the wait event and additional parameters
  that provide further information about exactly what the process is
  waiting for (or information about the most recent wait event if
  the process is not currently waiting). While the v$system_event
  and v$session_event views show cumulative wait event information,
  the v$session_wait view shows information as of the present moment
  only. The v$session_wait view has the following columns: 

Name Null? 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)

WAIT_TIME_MICRO NUMBER

TIME_REMAINING_MICRO NUMBER

TIME_SINCE_LAST_WAIT_MICRO NUMBER

The following query shows the parameters associated with the db

  file scattered read wait event: 

SELECT *

FROM v$event_name

WHERE name = 'db file scattered read';

EVENT# NAME PARAMETER1 PARAMETER2 PARAMETER3

———- ———————- ———— ———– ———–

188 db file scattered read file# block# blocks

This tells us that when a process is waiting for a multi-block

  read from disk to complete (as in the case of a full table scan
  where the data blocks were not already in the buffer cache), we
  can see the file from which the blocks are being read as well as
  the starting block and number of blocks. 

The following query was run while a session was performing a full

  table scan: 

set linesize 32000

SELECT sid,seq#,substr(event,1,35) event, p1text, p1, p2text, p2, p3text, p3, wait_time, seconds_in_wait, state

FROM v$session_wait WHERE sid = 442;

   SID       SEQ# EVENT

———- ———- ——————————

P1TEXT P1 P1RAW

—————————— ———- ——–

P2TEXT P2 P2RAW

—————————— ———- ——–

P3TEXT P3 P3RAW WAIT_TIME SECONDS_IN_WAIT

—————————— ———- ——– ———- —————

STATE

    442          303 db file scattered read

file# 17 00000011

block# 2721 00000AA1

blocks 8 00000008 -1 0

WAITED SHORT TIME

You can see that the process was not waiting at the moment this

  query was run, but its last wait had been for an I/O request to
  read eight blocks from file 17 starting at block 2721. That I/O
  request had completed in less than 0.01 second. (Note the -1 in
  the WAIT_TIME column when the STATE is WAITED SHORT TIME.) Why did
  Oracle choose to read eight blocks at a time? Because the
  db_file_multiblock_read_count instance parameter was set to eight.
  For most wait events this view is sufficient, but it is hardly a
  robust tuning tool for at least two important reasons:
  • The view is a snapshot of the present. When
  the waits cease to exist, the history of those waits experienced
  by the session earlier disappears too, making after-effect
  diagnosis difficult. V$SESSION_EVENT provides cumulative but not
  very detailed data.
  • V$SESSION_WAIT contains information only
  about wait events; for all other relevant information such as the
  userid and terminal you have to join it with the view V$SESSION.
  The V$SESSION View
  Oracle provides an interface to check what these values are .
  useful work, idle time and waits. 
  The information is available in V$SESSION 
  • EVENT = shows what the session is/was stuck on
  • SECONDS_IN_WAIT = shows the waits right now
  • WAIT_TIME = shows the last wait time
  • STATE – shows what is the session doing now
              -
  WAITING. The session is waiting on that event right now 
  • The amount of time
  it has been waiting so far is shown under SECONDS_IN_WAIT 
  • WAITED
  KNOWN TIME. The session waited for some time on that event, but
  not just now 
  • The amount of time
  it had waited is shown under WAIT_TIME 
  • WAITED
  SHORT TIME. The session waited for some time on that event, but it
  was too short to be recorded 
  • WAIT_TIME shows -1
  Wait Time Accounting 
  Value of STATE ---> WAITING = check SECONDS_IN_WAIT 
  ---> WAITED KNOWN TIME = check WAIT_TIME 
  ---> WAITED SHORT TIME = WAIT_TIME is -1 
  Two additional columns have been added to v$session that are
  helpful for wait event analysis: blocking_session and
  blocking_session_status. 
  The blocking_session column contains the session id (SID) of the
  holder of the resource that the waiting session is waiting for.
  The blocking_session_status column indicates the validity of the
  contents of the blocking_session column. 
  If blocking_session_status is VALID, a valid SID is present in the
  blocking_session column. We can find out who is holding the lock
  very quickly: 

SELECT sid, blocking_session, username, blocking_session_status status

FROM v$session

WHERE blocking_session_status = 'VALID';

SID BLOCKING_SESSION USERNAME STATUS

— —————- ——– ———–

154 157 TSUTTON VALID

If we combine this with the wait event information available in

  v$session, we see: 

SELECT sid, blocking_session, username, event, seconds_in_wait siw

FROM v$session

WHERE blocking_session_status = 'VALID';

SID BLOCKING_SESSION USERNAME EVENT SIW

— —————- ——– —————————— —

154 157 TSUTTON enq: TX – row lock contention 318

The V$EVENT_NAME View

  The v$event_name view shows reference information rather
  than up-to-the-moment information about instance performance. This
  view shows one row for each wait event known to the Oracle kernel.
  Associated with each wait event are up to three
  parameters-additional pieces of information that provide more
  detail about a wait situation. This view displays the definition
  of P(n) columns from V$SESSION_WAIT and can be joined on the NAME
  column.
  The v$event_name view has the following columns: 

Name Null? 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)EVENT# = Number of the wait event.

  NAME = Name of the event.
  PARAMETER1 = Description of the value for P1.
  PARAMETER2 = Description of the value for P2.
  PARAMETER3 = Description of the value for P3.
  WAIT_CLASS_ID = ID of the wait class
  WAIT_CLASS# = Number of the class.
  WAIT_CLASS = The name of the wait class (Idle, Network, System
  I/O, etc.)

The v$system_event and v$session_event views show cumulative

  information about past waits in summary form, leaving out
  parameter information from each individual wait.
  As we will see in the next sections, wait event parameters come
  into play in the v$session_wait view and wait event trace files. 

The V$SESSION_WAIT_HISTORY View

  The v$session_wait_history view, helps by showing the last
  ten wait events each session has experienced.
  The columns in v$session_wait_history are: 

DESC v$session_wait_history

Name Null? Type

—————————————– ——– —————————-

SID NUMBER

SEQ# NUMBER

EVENT# NUMBER

EVENT VARCHAR2(64)

P1TEXT VARCHAR2(64)

P1 NUMBER

P2TEXT VARCHAR2(64)

P2 NUMBER

P3TEXT VARCHAR2(64)

P3 NUMBER

WAIT_TIME NUMBER

WAIT_COUNT NUMBER

As an example, the following query shows the ten most recent wait

  events for a session: 

SELECT sid, seq#, event, wait_time, p1, p2, p3

FROM v$session_wait_history

WHERE sid = 154

ORDER BY seq#;

SID SEQ# EVENT WAIT_TIME P1 P2 P3

— —- ———————— ———- —— —— ——

154 1 db file sequential read 28 4 3547 1

154 2 log buffer space 18 0 0 0

154 3 log buffer space 36 0 0 0

154 4 db file sequential read 0 4 3559 1

154 5 db file sequential read 0 4 1272 1

154 6 db file sequential read 0 4 3555 1

154 7 log buffer space 9 0 0 0

154 8 db file sequential read 0 4 3551 1

154 9 db file sequential read 6 4 1268 1

154 10 log buffer space 8 0 0 0

In the above query, we see that the session’s most recent waits

  alternated between single-block disk reads and log buffer space.
  This makes sense, since the SQL that the session was performing
  looked like: 

INSERT INTO table1 (column1, column2)

SELECT column1, column2

FROM table2

WHERE …

From this list of recent waits, we can also drill down to get

  more detail. The p1 and p2 values for db file sequential read
  indicate the file and block numbers being read, so we can quickly
  determine what segment was being read. 

The V$EVENT_HISTOGRAM View

The columns of v$event_histogram are:

SQL> DESCRIBE v$event_histogram

Name Null? Type

—————————————– ——– —————————-

EVENT# NUMBER

EVENT VARCHAR2(64)

WAIT_TIME_MILLI NUMBER

WAIT_COUNT NUMBER

The v$system_event view shows the number of waits, total time

  waited, and average wait time for a given wait event name
  (system-wide since instance startup). However, this aggregation
  can cloud the picture, because a small number of long waits can
  skew the data. For example, consider the following query from
  v$system_event: 

SELECT event, total_waits, time_waited, average_wait

FROM v$system_event

WHERE event = 'enq: TX – row lock contention';

EVENT TOTAL_WAITS TIME_WAITED AVERAGE_WAIT

—————————– ———– ———– ————

enq: TX – row lock contention 17218 2101966 122

We see that there have been 17,218 waits and that the average

  wait time was 1.22 seconds, but we have no idea how the wait times
  are distributed. Were all of these waits roughly the same length?
  Were most of them under one second long and a few really long
  waits threw off the average? We can’t tell from v$system_event.
  However, we can look at v$event_histogram for a more complete
  picture: 

SELECT event, wait_time_milli, wait_count

FROM v$event_histogram

WHERE event = 'enq: TX – row lock contention';

EVENT WAIT_TIME_MILLI WAIT_COUNT

—————————– ————— ———-

enq: TX – row lock contention 1 833

enq: TX – row lock contention 2 635

enq: TX – row lock contention 4 372

enq: TX – row lock contention 8 395

enq: TX – row lock contention 16 781

enq: TX – row lock contention 32 3729

enq: TX – row lock contention 64 3050

enq: TX – row lock contention 128 410

enq: TX – row lock contention 256 47

enq: TX – row lock contention 512 46

enq: TX – row lock contention 1024 37

enq: TX – row lock contention 2048 3

enq: TX – row lock contention 4096 6880

We see that very few of the waits were anywhere near 1.22

  seconds. Nearly 60% of the waits were less than 0.128 seconds
  (with most of those between 16 milliseconds and 64 milliseconds),
  and most of the remaining waits were between 2.048 seconds and
  4.096 seconds (at which point some timed out and started new
  waits). In this way, the v$event_histogram view gives us a more
  accurate picture of wait times summarized by event name. 

The V$SYSTEM_WAIT_CLASS and

  V$SESSION_WAIT_CLASS View

The two new views v$system_wait_class and v$session_wait_class

  enable us to get system and session wait information summarized by
  wait classes. This gives us a higher level view of what is
  happening in the system or session, rather than focusing on
  individual events. The views are roughly equivalent to the views
  v$system_event and v$session_event, except that they roll up the
  events by wait class. The wait times are expressed in centiseconds
  since instance startup for v$system_wait_class and centiseconds
  since session connection for v$session_wait_class. 

The following queries show how much time (in centiseconds) has

  been spent on waits in each class across the system since instance
  start and for one specific session since that session began: 

SELECT wait_class, time_waited

FROM v$system_wait_class

ORDER BY time_waited DESC;

WAIT_CLASS TIME_WAITED

————- ———–

Idle 777450022

System I/O 1261584

User I/O 116667

Configuration 116481

Application 72301

Other 12432

Commit 3496

Concurrency 319

Network 1

SELECT wait_class, time_waited

FROM v$session_wait_class

WHERE sid = 154

ORDER BY time_waited DESC;

WAIT_CLASS TIME_WAITED

————- ———–

Idle 612453

User I/O 1500

Configuration 28

Commit 11

Other 0

Application 0

Network 0

Since the wait times shown in these views are aggregations since

  system or session startup, these views are best used by taking
  samples and comparing the results to determine waits over a period
  of time. For instance, you could get data for the entire instance
  at time T1: 

DROP TABLE swc_snap;

CREATE TABLE swc_snap AS

SELECT wait_class, total_waits, time_waited

FROM v$system_wait_class;

And then, at time T2 a while later, get a summary of waits

  between T1 and T2: 

SELECT a.wait_class, (a.time_waited – b.time_waited) tm_waited

FROM v$system_wait_class a, swc_snap b

WHERE a.wait_class = b.wait_class

AND a.total_waits > NVL (b.total_waits, 0)   

ORDER BY tm_waited DESC;

WAIT_CLASS TM_WAITED

————— ———-

Idle 255767

Application 171

System I/O 156

User I/O 44

Other 21

Commit 13

Network 1

The V$SESSION_WAIT_HISTORY View

The v$session_wait_history view makes it a little easier to catch

  detailed information by preserving the last ten waits for each
  session. But what if you want detailed information about a
  session’s waits for a period further back in time? This is where
  the Active Session History feature of Oracle 10g—ASH for
  short—comes in handy. ASH makes detailed information about a
  sampling of waits encountered by all sessions available to us for
  a very long time. 

The background daemon process called MMNL queries v$session once

  each second and stores information about all active sessions in a
  circular buffer in memory accessible by a new view called
  v$active_session_history. How far back you can look at sessions in
  this view depends on session activity and how much memory Oracle
  allocated for ASH. Oracle’s goal is to keep at least a few hours
  of session data available in this view. The
  v$active_session_history view includes much of the detailed wait
  event information shown in v$session: 

SQL> DESC v$active_session_history

Name Null? Type

—————————————– ——– —————————-

SAMPLE_ID NUMBER

SAMPLE_TIME TIMESTAMP(3)

SESSION_ID NUMBER

SESSION_SERIAL# NUMBER

USER_ID NUMBER

SQL_ID VARCHAR2(13)

SQL_CHILD_NUMBER NUMBER

SQL_PLAN_HASH_VALUE NUMBER

SQL_OPCODE NUMBER

SERVICE_HASH NUMBER

SESSION_TYPE VARCHAR2(10)

SESSION_STATE VARCHAR2(7)

QC_SESSION_ID NUMBER

QC_INSTANCE_ID NUMBER

EVENT VARCHAR2(64)

EVENT_ID NUMBER

EVENT# NUMBER

SEQ# NUMBER

P1 NUMBER

P2 NUMBER

P3 NUMBER

WAIT_TIME NUMBER

TIME_WAITED NUMBER

CURRENT_OBJ# NUMBER

CURRENT_FILE# NUMBER

CURRENT_BLOCK# NUMBER

PROGRAM VARCHAR2(48)

MODULE VARCHAR2(48)

ACTION VARCHAR2(32)

CLIENT_ID VARCHAR2(64)

As you can see, v$active_session_history captures the essential

  wait-related data from v$session. It also captures useful
  information about the SQL statement currently being executed, as
  well as current object number, file, and block being accessed.
  When a wait that was sampled by ASH completes, Oracle fills in the
  time_waited column for the row in v$active_session_history with
  the actual duration of the wait. 

The AWR writes data from v$active_session_history to disk at

  regular intervals, preserving one sample every ten seconds from
  each active session. So, active session information remains
  accessible—although with less detail—even after the data has aged
  out of v$active_session_history. 

Because ASH is always “on,” you always have access to detailed

  information about waits encountered in sessions within the last
  few hours. This means that if a user complains about a performance
  problem, you may be able to query v$active_session_history and
  gain insight into the problem without having to initiate an
  extended SQL trace or start a close watch of v$session while they
  reproduce the problem. 

An important thing to keep in mind about

  v$active_session_history, however, is that it is populated by
  sampling v$session once each second. A session may encounter many
  different waits during a one second period, but only the one wait
  that was in progress when ASH collected its sample will be
  recorded in v$active_session_history. For this reason, ASH is
  valuable for general aggregate queries but not for precise
  counting of individual events or determining minimum or maximum
  wait times. Statistically speaking, the data collected by ASH is
  probably more accurate over a larger time interval and/or number
  of sessions. 

For example, you might query v$active_session_history to see what

  percentage of time over the last two hours a particular group of
  sessions spent waiting on disk reads. However, using this view to
  determine how many disk read waits a session encountered in the
  last minute probably will not yield very accurate results. 

Even though ASH data is only a sampling of active sessions, the

  information can prove to be quite useful. For example, the
  following query shows that sessions running the ARXENV application
  over the last two hours encountered a great deal of row-level lock
  contention: 

SELECT DECODE (session_state, 'WAITING', event, NULL) event,

   session_state, COUNT(*), SUM (time_waited) time_waited

FROM v$active_session_history

WHERE module = 'ARXENV'

AND sample_time > SYSDATE - (2/24)

GROUP BY DECODE (session_state, 'WAITING', event, NULL), session_state;

EVENT SESSION_STATE COUNT(*) TIME_WAITED

—————————— ————- ——– ———–

                           ON CPU             124           0

log file sync WAITING 2 52686

db file scattered read WAITING 2 28254

db file sequential read WAITING 1 6059

control file sequential read WAITING 1 9206

SQL*Net break/reset to client WAITING 1 9140

enq: TX – row lock contention WAITING 922 930864016

In addition to running queries against the

  v$active_session_history view, you can use Enterprise Manager to
  run reports that will display ASH data. 

Although ASH runs on all Oracle databases by default, you are not

  allowed to query the v$active_session_history view (or run the
  corresponding reports in Enterprise Manager) unless you have
  purchased the Diagnostic Pack.

Another significant facility relevant to the wait event interface

  it’s the Automatic Workload Repository—or AWR for short. AWR is
  basically a next-generation Statspack. By default, AWR collects an
  hourly snapshot of database performance information, storing the
  data in tables in the SYS schema. AWR is configured automatically
  when you create an Oracle database. You can call the
  dbms_workload_repository package to collect a snapshot on demand,
  purge a snapshot or range of snapshots, or change the snapshot
  interval or retention period. (By default snapshots are collected
  at the top of each hour and are purged after seven days.) 

AWR collects the same type of data that Statspack does—including

  system-level statistics, resource-intensive SQL, and of course
  instance-wide wait event information. AWR also collects data such
  as time model statistics (which we will discuss in the next
  section). As an aside, Statspack also collects a lot of this new
  information, including time model statistics. 

You can generate an AWR report of database activity between two

  snapshots by running the awrrpt.sql script in the rdbms/admin
  directory under $ORACLE_HOME. This script offers reports formatted
  as plain text or HTML. The reports will look familiar if you have
  used Statspack before. You can use Enterprise Manager to generate
  AWR reports as well. 

AWR offers many benefits over Statspack. For one, it is more

  tightly integrated into the Oracle kernel, reducing resource
  requirements and overhead when collecting snapshots. AWR snapshots
  also include ASH data from v$active_session_history, providing
  session-level information to complement the system-level data
  collection familiar to Statspack users. 

Data collected by AWR is made easily accessible via views with

  names that start DBA_HIST. This enables you to write your own
  reports that extract just the data you need to address a specific
  situation, if for some reason you don’t find what you need in the
  standard AWR report. For example, the following query displays the
  two most recent snapshot IDs: 

SELECT snap_id, substr(begin_interval_time,1,25) Begin_Interval, substr(end_interval_time,1,25) End_Interval

FROM (SELECT snap_id, begin_interval_time, end_interval_time

     FROM dba_hist_snapshot
     ORDER BY end_interval_time DESC)

WHERE ROWNUM <= 2;

SNAP_ID BEGIN_INTERVAL_TIME END_INTERVAL_TIME

———- ————————- ————————-

   362 10-MAR-05 04.00.02.018 PM 10-MAR-05 05.00.36.581 PM
   361 10-MAR-05 03.00.25.885 PM 10-MAR-05 04.00.02.018 PM

Just like ASH, you are not allowed to query the AWR views (or run

  AWR reports) unless you have licensed the Diagnostic Pack. Because
  AWR consumes system resources when collecting snapshots and uses
  up storage in the SYSAUX tablespace, you may want to disable the
  collection of AWR snapshots if you are not licensed to use AWR.
  This may be done by using the dbms_workload_repository package. If
  AWR is not available to you, Statspack is still a good way to go.

Oracle has a concept called Time Model Statistics. This

  information provides yet another way to see how time is spent, and
  with greater detail than was available previously. The
  v$sys_time_model view shows time model statistics for the entire
  system since instance startup, while the v$sess_time_model view
  shows time model statistics for each session since session start.
  The columns in these two views are as follows: 

DESC v$sys_time_model

Name Null? Type

—————————————- ——– —————————

STAT_ID NUMBER

STAT_NAME VARCHAR2(64)

VALUE NUMBER

DESC v$sess_time_model

Name Null? Type

—————————————- ——– —————————

SID NUMBER

STAT_ID NUMBER

STAT_NAME VARCHAR2(64)

VALUE NUMBER

A sample query from v$sys_time_model shows the following:

SELECT stat_name, value / 1000000 seconds

FROM v$sys_time_model

ORDER BY seconds DESC;

STAT_NAME SECONDS

———————————————— ———-

DB time 80970.190

sql execute elapsed time 75057.271

DB CPU 44448.628

background elapsed time 29333.160

PL/SQL execution elapsed time 8824.538

background cpu time 5170.311

parse time elapsed 1270.147

hard parse elapsed time 838.068

PL/SQL compilation elapsed time 176.731

sequence load elapsed time 112.334

connection management call elapsed time 44.644

failed parse elapsed time 11.946

hard parse (sharing criteria) elapsed time 5.579

hard parse (bind mismatch) elapsed time 4.610

failed parse (out of shared memory) elapsed time 0.000

Java execution elapsed time 0.000

inbound PL/SQL rpc elapsed time 0.000

This query shows us a lot more information about how Oracle

  sessions have spent their time (categorically) than v$sysstat and
  v$sesstat do. Of course, we have to know how to interpret this
  information before we can put it to work for us. Values in these
  views are shown in microseconds, and they do not include
  background processes unless “background” appears in the statistic
  name. The “DB time” statistic shows elapsed time spent on database
  calls (user processes only). This amounts to time spent on the CPU
  or waiting on non-idle wait events. For a description of the other
  time model statistics, see the v$sess_time_model view listing in
  the Database Reference manual. 

From this query, among many other useful facts, we can see that

  no time has been spent executing Java, very little time has been
  spent hard parsing or compiling PL/SQL, background processes have
  used about 10% of the CPU time, and about 11% of the elapsed time
  for user sessions was spent on PL/SQL execution.
  DBA's should be familiar with the SQL trace facility built into
  Oracle. 

The extended SQL trace facility, also known as event 10046,

  allows us to capture in a trace file detailed information about
  every wait event encountered by a database session. 
  By using the commands below, you can enable SQL trace for your
  session: 

Using the TOP

    Unix command or the v$session view you can check the
    SID and SERIAL# number of the session to monitor. 
    select
      sid, serial#, substr(terminal,1,10) terminal,
      substr(program,1,40) program 
    from
      v$session 
    where
      terminal in('OCR04','IMGSVR')
      -- where username = 'FRAUDGUARD';;

Then, you

    activate the trace by using the package dbms_monitor. This package, among many
  other things, makes it very easy to turn extended SQL trace on and
  off in any Oracle session. With one easy to remember call, you can
  turn extended SQL trace on or off, with wait events and/or bind
  variables captured in the trace file:

SQL> DESC dbms_monitor

PROCEDURE SESSION_TRACE_DISABLE

Argument Name Type In/Out Default?

—————————— ———————– —— ——–

SESSION_ID BINARY_INTEGER IN DEFAULT

SERIAL_NUM BINARY_INTEGER IN DEFAULT

PROCEDURE SESSION_TRACE_ENABLE

Argument Name Type In/Out Default?

—————————— ———————– —— ——–

SESSION_ID BINARY_INTEGER IN DEFAULT

SERIAL_NUM BINARY_INTEGER IN DEFAULT

WAITS BOOLEAN IN DEFAULT

BINDS BOOLEAN IN DEFAULT –

    ALTER SESSION SET events '10046 trace name context forever, level 12';

    EXECUTE dbms_monitor.session_trace_enable (waits=>TRUE, binds=>TRUE);

Instead of enabling extended SQL trace for a specific Oracle

  session, you can enable it for a specific client identifier or
  combination of service, module, and action. Any time any Oracle
  session has the specified client identifier or combination of
  service, module, and action, the session will be traced. Sessions
  can set or clear their client identifier at will by calling the
  dbms_session package, and they can set their module and action by
  calling the dbms_application_info package. 

Suppose a web-based application uses a pool of 30 database

  connections to serve user requests and maintains a
  current_sessions table to keep track of the state of each end-user
  session. When a user clicks a button in their browser window, the
  application server receives the HTTP request and hands it off to
  an application server process. The application server process
  grabs a free database connection from the pool and accesses the
  database as necessary to service the request. It is likely that
  subsequent requests from the same user will be processed using
  different database connections.

With dbms_monitor, the application could be modified in a way to

  make extended SQL trace a whole lot easier. We mentioned that the
  application uses the current_sessions table to maintain state for
  each end user session. Each time the application server grabs a
  database connection from the pool, it could set the client
  identifier for the Oracle session to the session_id from the
  current_sessions table before doing any database access for that
  end user session. Then the application could clear the client
  identifier before returning the database connection to the pool.
  The Oracle calls could look like this: 

EXECUTE dbms_session.set_identifier ('session_id174837492748');

…do the work for this end user session…

EXECUTE dbms_session.clear_identifier

To trace this end user session, we could now call the

  dbms_monitor package like this: 

EXECUTE dbms_monitor.client_id_trace_enable ('session_id174837492748', waits=>TRUE, binds=>TRUE);

This call to dbms_monitor will cause each Oracle process to write

  extended SQL trace data to a trace file for all calls that occur
  while the client identifier for the session is set to the
  specified value. However, each Oracle process will write to its
  own trace file. This will cause the trace data to be split over
  multiple files. To address this problem, Oracle 10g provides a new
  command-line utility called trcsess. The trcsess utility reads
  multiple trace files and consolidates entries from the various
  files that meet the specified criteria into one trace file that
  can be processed by TKPROF. To consolidate the trace data for our
  current example, we could use the following commands: 

$ cd $ORACLE_BASE/admin/$ORACLE_SID/udump

$ trcsess output=/home/rschrag/case1403/case1403-trial1.trc clientid=session_id174837492748

In this way the dbms_monitor package and trcsess utility make it

  a lot easier to collect extended SQL trace data from an end user’s
  session when connection pooling or other session aggregation
  techniques are used by the application server tier.

Example using SID and SERIAL

    TURN

ON:

               exec 
                  dbms_monitor.session_trace_enable(&SID,
                              &SERIAL, waits=>
                                  true, binds=> true)
                        /* code to be traced
                executes during this time window */
                            TURN OFF:    
                                  exec  exec 

dbms_monitor.session_trace_disable(&SID,

                                                      &SERIAL)
  Example
    using Service or Module:
    BEGIN

–>Enable/Disable

        Client Identifier Trace.

DBMS_MONITOR.client_id_trace_enable (client_id

        => ‘my_id’); 

DBMS_MONITOR.client_id_trace_disable (client_id

        => ‘my_id’);  

–>Enable/Disable

        Service, Module and Action Trace. 

DBMS_MONITOR.serv_mod_act_trace_enable (service_name=>'my_service');

DBMS_MONITOR.serv_mod_act_trace_enable (service_name=>'my_service',

        module_name=>'my_module'); 

DBMS_MONITOR.serv_mod_act_trace_enable (service_name=>'my_service',module_name=>‘my_module’,action_name=>'INSERT');

DBMS_MONITOR.serv_mod_act_trace_disable (service_name=>'my_service',module_name=>'my_module',action_name

        =>'INSERT'); 

–>Enable/Disable

        Session Trace .  

DBMS_MONITOR.session_trace_enable;

DBMS_MONITOR.session_trace_enable(session_id =>

        12, serial_num => 1011);  

DBMS_MONITOR.session_trace_disable(session_id =>

        12, serial_num => 1011);

END;

/

    With the DBMS_MONITOR package, Oracle offers a fully supported
    means of activating and deactivating diagnostic data collection
    for a specific business action (or actions) you want to trace. 

un TKPROF to translate

  the trace file created before into a readable output file. This
  step can optionally create a SQL script that stores the statistics
  in the database. 
  tkprof trace_file 
    file_name sys=no explain=user/passwd@connection

When SQL trace is enabled for a session, the Oracle process

  writes detailed trace information (including timing data if timed
  statistics are enabled) to a trace file in a directory specified
  by the user_dump_dest instance parameter. These trace files are
  plain text files and human readable, but rather tedious and
  repetitive. You can optionally run trace files through a processor
  such as TKPROF instead of looking at them directly.
  Oracle has the ability to direct a process to include additional
  information in the trace file, including wait event information.
  In earlier releases of Oracle, we activated the wait event tracing
  facility by setting debug event 10046. Debug event 10046 still
  works in Oracle 9i, but recent releases of Oracle include a PL/SQL
  package built-in that gives a more friendly means for activating
  wait event tracing.
  Setting debug events allows a DBA to instruct an Oracle instance
  to take on a special, atypical behavior. Debug events can be used,
  for example, to cause Oracle to write a system level dump file
  whenever an ORA-0600 error occurs or skip over corrupted blocks in
  a table when performing a full table scan. Most debug events
  should never be set unless you are directed to do so by Oracle
  Support. Some debug events can put your database at risk.
  Debug event 10046 affects the amount of information written to
  trace files. It is a very safe debug event, and one of the few
  that you are allowed to set without special permission from Oracle
  Support. Debug event 10046 can be set to the following values: 
      | 
         | 
       |
      | 
        10046 trace name context forever, level 1
         | Enables ordinary SQL trace
       |
      | 
        10046 trace name context forever, level 4
         | Enables SQL trace with bind variable values included in
          trace file
       |
      | 
        10046 trace name context forever, level 8
         | Enables SQL trace with wait event information included
          in trace file
       |
      | 
        10046 trace name context forever, level 12
         | Equivalent of level 4 and level 8 together
       |
      | 
        10046 trace name context off
         | Turns off tracing
       |

You can set the 10046 debug event to trace your session and

  collect wait event information in the trace file with either of
  the following commands: 

    EXECUTE SYS.DBMS_SUPPORT.START_TRACE

    ALTER SESSION SET events '10046 trace name context forever, level 8';

You can set the 10046 debug event to trace another session on the

  database with any of the following commands:
  Find the session:
  set linesize 150
  column Name format a14
  column SID format 9999
  column PID format 99999
  column TERM format a15
  column OSUSER format a15
  column Program format a15
  column Stats format a10
  column Logon_time format a20
  select a.username Name, a.sid SID, a.serial#, b.spid PID,

SUBSTR(A.TERMINAL,1,9)

    TERM, SUBSTR(A.OSUSER,1,9)
    OSUSER,

substr(a.program,1,10)

    Program, a.status
    Status,

to_char(a.logon_time,'MM/DD/YYYY

    hh24:mi') Logon_time
  from v$session a, v$process b
  where a.paddr = b.addr
    and a.serial#
    <> '1'
    and a.status =
    'ACTIVE'
    and a.username like
    upper('%&user%') -- if you want to filter by username
  order by a.logon_time;

Calling DBMS_SUPPORT as shown

  here is equivalent to activating debug event 10046 at level 8. You
  may include optional additional parameters in the procedure call
  to activate level 4 or 12. The DBMS_SUPPORT package is not
  installed in the database by default. You need to run the
  dbmssupp.sql script found in the rdbms/admin directory as SYS
  before you can call DBMS_SUPPORT.
  It should also be pointed out that the SET_EV procedure in the
  DBMS_SYSTEM package is not officially supported by Oracle
  Corporation-they prefer that you use DBMS_SUPPORT instead. The
  reason is that DBMS_SYSTEM.SET_EV allows you to set any debug
  event in any session. As mentioned above some debug events can
  potentially be dangerous, and DBMS_SYSTEM.SET_EV lets you set such
  events in any session.
  Unlike timed statistics, tracing consumes a significant amount of
  system resources. Therefore it is important to use the tracing
  facility sparingly. Trace only the sessions you need to trace, and
  only for as long as you need. Turn off tracing as soon as it is no
  longer needed with any of the following commands:

    EXECUTE SYS.DBMS_SUPPORT.STOP_TRACE

    ALTER SESSION SET EVENTS '10046 TRACE NAME CONTEXT OFF';

    ALTER SESSION SET sql_trace = FALSE;

    EXECUTE SYS.DBMS_SUPPORT.STOP_TRACE_IN_SESSION (sid, serial#)

    oradebug setorapid [Oracle PID from v$process]

oradebug session_event 10046 trace name context forever, level 0

    EXECUTE SYS.DBMS_SYSTEM.SET_EV (sid, serial#, 10046, 0, '')

When you set debug event 10046 to a level of 8 or 12 (or call

  START_TRACE or START_TRACE_IN_SESSION in DBMS_SUPPORT), the Oracle
  process will write a line into the trace file every time it
  finishes waiting for an event. The line in the trace file will
  contain almost the same information that would have appeared in
  the v$session_wait view, but perhaps in a slightly less friendly
  format. You can also see in the trace file which cursor (and
  therefore which SQL statement) the wait event was associated with.
  Here is an excerpt from a trace file generated by setting debug
  event 10046 to level 12 on an Oracle 8i database: 
    =====================
    PARSING IN CURSOR #1 len=80 dep=0 uid=502 oct=3 lid=502 
    tim=2293771931 hv=2293373707 ad='511dca20'
    SELECT /*+ FULL */ SUM (LENGTH(notes))
    FROM   customer_calls
    WHERE  status = :x
    END OF STMT
    PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=0,tim=2293771931
    BINDS #1:
     bind 0: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=03 oacfl2=0 
     size=24 offset=0
       bfp=09717724 bln=22 avl=02 flg=05
       value=43
    EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=2293771931
    WAIT #1: nam='SQL*Net message to client' ela= 0 p1=675562835 p2=1 p3=0
    WAIT #1: nam='db file scattered read' ela= 3 p1=17 p2=923 p3=8
    WAIT #1: nam='db file scattered read' ela= 1 p1=17 p2=931 p3=8
    WAIT #1: nam='db file scattered read' ela= 2 p1=17 p2=939 p3=8
    WAIT #1: nam='db file sequential read' ela= 0 p1=17 p2=947 p3=1
    WAIT #1: nam='db file scattered read' ela= 3 p1=17 p2=1657 p3=8
    WAIT #1: nam='db file scattered read' ela= 1 p1=17 p2=1665 p3=8
    WAIT #1: nam='db file scattered read' ela= 2 p1=17 p2=1673 p3=8
    WAIT #1: nam='db file scattered read' ela= 0 p1=17 p2=1681 p3=8
    WAIT #1: nam='db file scattered read' ela= 3 p1=17 p2=1761 p3=8
    WAIT #1: nam='db file scattered read' ela= 1 p1=17 p2=1769 p3=8
    WAIT #1: nam='db file scattered read' ela= 1 p1=17 p2=1777 p3=8
    WAIT #1: nam='db file scattered read' ela= 0 p1=17 p2=1785 p3=8
    WAIT #1: nam='db file scattered read' ela= 2 p1=17 p2=1841 p3=8
    WAIT #1: nam='db file scattered read' ela= 1 p1=17 p2=1849 p3=8The "ela=" figures indicate the duration of the wait. In trace
  files generated by Oracle 8i and earlier, the elapsed time is
  shown in centiseconds. Beginning in Oracle 9i, the elapsed time is
  shown in microseconds.
  You can see that when the session executed the query, there was a
  wait shorter than one centisecond for a message to be sent to the
  client, followed by a bunch of waits for I/O requests against file
  17. Most of the I/O requests were multi-block reads, reading eight
  blocks at a time while performing a full table scan of the
  CUSTOMER_CALLS table.
  You can probably imagine how large and overwhelming trace files
  can get when anything but a trivial application is traced. This is
  why Oracle provides the TKPROF utility. TKPROF takes a trace file
  as input and generates a nicely formatted, easy to read report.
  Unfortunately, the TKPROF that comes with Oracle 8i and earlier
  releases ignores wait event information written in the trace file.
  To analyze the wait event information collected by a trace in an
  Oracle 8i or earlier environment, you will need to either pore
  through the trace file manually or write your own trace file
  parser and formatter. (We've heard of people writing perl scripts
  to do this, but we have never come across them.)
  The TKPROF utility that comes with Oracle 9i is capable of
  reporting wait event information summarized by distinct statement.
  By default Oracle 9i TKPROF ignores wait event information in the
  trace file as earlier releases did. However, if the "waits=yes"
  command line argument is provided, a separate table of wait event
  statistics will appear in the report for each distinct statement.
  Here is a sample excerpt from a TKPROF report showing wait event
  information: 
    ********************************************************************************
    SELECT   A.customer_id, A.customer_name, COUNT (*) purchases,
             MAX (B.transaction_date) last_purchase_date
    FROM     customers A, purchase_history B
    WHERE    B.customer_id = A.customer_id
    GROUP BY A.customer_id, A.customer_name
    ORDER BY A.customer_id
    call     count       cpu    elapsed       disk      query    current        rows
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    Parse        1      0.06       0.12          0         27          0           0
    Execute      1      0.00       0.00          0          0          0           0
    Fetch     1461     21.41      25.80       7801       5905          5       21893
    ------- ------  -------- ---------- ---------- ---------- ----------  ----------
    total     1463     21.47      25.93       7801       5932          5       21893
    Misses in library cache during parse: 1
    Optimizer goal: CHOOSE
    Parsing user id: 17
    Rows     Row Source Operation
    -------  ---------------------------------------------------
      21893  SORT GROUP BY
    1525494   HASH JOIN
      31212    TABLE ACCESS FULL CUSTOMERS
    1525494    INDEX FAST FULL SCAN PURCHASE_HISTORY_PK (object id 7824)
    Elapsed times include waiting on following events:
      Event waited on                             Times   Max. Wait  Total Waited
      ----------------------------------------   Waited  ----------  ------------
      SQL*Net message to client                    1461        0.00          0.00
      db file sequential read                         4        0.00          0.01
      db file scattered read                        750        0.07          2.25
      direct path write                             271        0.83          2.79
      direct path read                              254        0.00          0.01
      SQL*Net message from client                  1461        1.28         22.40
    ********************************************************************************You can see that the query was parsed and executed once, and
  there were 1461 fetches to read 21893 rows. The Oracle process
  used 21.47 CPU seconds and 25.93 seconds of elapsed time to parse,
  execute, and fetch the query. The elapsed time was greater than
  the CPU time because the Oracle process had to wait on several
  wait events. The listing at the bottom of the report shows the
  process waited on network roundtrips to the client and reads and
  writes to disk.
  All of these waits seem to make sense: There was one network
  roundtrip to the client for each fetch call, and it took SQL*Plus
  a long time (over 22 seconds) to display the 21,893 rows of data
  on my display. The db file sequential reads and db file scattered
  reads resulted from the table access and index fast full scan. The
  direct path writes and reads resulted from the hash join and sort
  operations. If you add the CPU time of 21.47 seconds and the wait
  times (5.06 seconds not including the SQL*Net message from client
  waits) you come up with an elapsed time of 26.53 seconds. However,
  the report shows the total elapsed time as 25.93 seconds. This is
  a good example of the round-off error that is not unusual when
  thousands of very short time intervals are added together.
  In some situations you may not be able to identify exactly which
  session to trace. This happens frequently when your database is
  supporting a web application that has frequent short connections,
  or an application server tier that maintains a pool of database
  connections all logged on as the same Oracle user. You may have a
  specific query you want to collect wait event information for, but
  you may not know which session will be executing the query. One
  way to deal with this situation is to trace all of the sessions
  being started by your application for a brief period. This can be
  done easily with the following SQL*Plus script: 

SPOOL traceall.sql

SET HEADING OFF FEEDBACK OFF

SELECT 'EXECUTE SYS.dbms_system.set_ev (' || TO_CHAR (sid) |

   ', ' || TO_CHAR (serial#) || ', 10046, 8, '''')'

FROM v$session

WHERE username = 'WEB_USER';

SPOOL OFF

SET FEEDBACK ON

@traceall.sql

This script will start wait event tracing on all sessions

  connected to the database as the WEB_USER user. To stop tracing
  simply change the 8 after the 10046 to a 0 and run the script
  again. You should think about how many sessions this script will
  trace and how that will affect server load before running on a
  production system.
  After you've traced a number of sessions, you can scan the trace
  files for occurrences of a specific query with a command like the
  following: 
    grep -n 1234567890 *.trcReplace 1234567890 with the hash value or address of the
  statement you are interested in. (You can get these values by
  querying v$sql.) The output of the above grep command will tell
  you which trace files the query appears in and on which lines. You
  can then go to that point in the trace files and get detailed wait
  event information.
  Trace files are easiest to work with when you use a dedicated
  server connection to the database. If you connect to the database
  using Oracle's shared server architecture then different SQL
  statements may be executed by different server processes. Each
  server process writes to its own trace file. Thus the trace
  information for the session can be spread over several trace
  files.
  In the latest versions of Oracle, the wait
    interface has been radically redesigned to provide more
    information with less DBA intervention. In this article, we will
    explore those new features and see how they aid us in the
    diagnosis of performance problems. For most of the performance
    problems, you will get an extended analysis from Automatic
    Database Diagnostic Manager (ADDM), but for immediate problems
    not yet captured by ADDM, the wait interface provides valuable
    data for diagnosis. 

Enhanced Session Waits

    The first enhancement involves V$SESSION_WAIT itself. It's best
    explained through an example.  Let's

imagine

    that your user has complained that her session is hanging. You
    found out the session's SID and selected the record from the
    view V$SESSION_WAIT for that SID. The output is shown below. 

SID : 269

SEQ# : 56

EVENT : enq: TX – row lock contention

P1TEXT : name|mode

P1 : 1415053318

P1RAW : 54580006

P2TEXT : usn<<16 | slot

P2 : 327681

P2RAW : 00050001

P3TEXT : sequence

P3 : 43

P3RAW : 0000002B**

WAIT_CLASS_ID : 4217450380

WAIT_CLASS# : 1

WAIT_CLASS : Application

WAIT_TIME : -2

SECONDS_IN_WAIT : 0

STATE : WAITED UNKNOWN TIME** Note the columns shown in bold; of those

  columns, , , and 
  are new in 10_g_. The column  indicates
  the type of the wait that must be either addressed as a valid wait
  event or dismissed as an idle one. In the above example, the wait
  class is shown as , meaning that it's a wait
  that requires your attention.
This column
    highlights those few records that could prove most relevant for
    your tuning. For example, you could use a query like the
    following to get the wait sessions for events.  select wait_class, event, sid, state, wait_time, seconds_in_wait

from v$session_wait

order by wait_class, event, sid

/

Here is a sample output: WAIT_CLASS EVENT SID STATE WAIT_TIME SECONDS_IN_WAIT

———- ——————– ———- ——————- ———- —————

Application enq: TX – 269 WAITING 0 73

        row lock contention        

Idle Queue Monitor Wait 270 WAITING 0 40

Idle SQL*Net message from client 265 WAITING 0 73

Idle jobq slave wait 259 WAITING 0 8485

Idle pmon timer 280 WAITING 0 73

Idle rdbms ipc message 267 WAITING 0 184770

Idle wakeup time manager 268 WAITING 0 40

Network SQL*Net message to client 272 WAITED SHORT TIME -1 0

Here you can see that several events (such as

   and ) are
  clearly classified as  events. You could eliminate
  them as nonblocking waits; however, sometimes these "idle" events
  can indicate an inherent problem. For example, the SQL*Net-related
  events may indicate high network latency, among other factors. 
  The other important thing to note is the value of 
  as -2. Some platforms such as Windows do not support a fast timing
  mechanism. If the initialization parameter 
  isn't set on those platforms, accurate timing statistics can't be
  determined. In such cases, a very large number is shown in this
  column in Oracle9_i_, which clouds the issue further. In 10_g_,
  the value -2 indicates this condition—the platform does not
  support a fast timing mechanism and  is
  not set. (For the remainder of the article, we will assume the
  presence of a fast timing mechanism.) 
  Sessions

Show

    Waits Too
Remember the long-standing requirement
  to join V$SESSION_WAIT to V$SESSION in order to get the other
  details about the session? Well, that's history. In 10_g_,
  the view V$SESSION also shows the waits shown by V$SESSION_WAIT.
  Here are the additional columns of the view V$SESSION that show
  the wait event for which the session is currently waiting. EVENT#                     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_CLASS_ID NUMBER

WAIT_CLASS# NUMBER

WAIT_CLASS VARCHAR2(64)

WAIT_TIME NUMBER

SECONDS_IN_WAIT NUMBER

STATE VARCHAR2(19)

The columns are identical to those in

  V$SESSION_WAIT and display the same information, eliminating the
  need to look in that view. So, you need to check only one view for
  any sessions waiting for any event.
Let's revisit
    the original problem: The session with SID 269 was waiting for
    the event , indicating
    that it is waiting for a lock held by another session. To
    diagnose the problem, you must identify that other session. But
    how do you do that?  In
  Oracle9_i_ and below, you might have to write a complicated
  (and expensive) query to get the SID of the lock holding session.
  In 10_g_, all you have to do is issue the following query:
select BLOCKING_SESSION_STATUS, BLOCKING_SESSION

from v$session

where sid = 269;

BLOCKING_SE BLOCKING_SESSION

———– —————-

VALID 265

There it is: the session with SID 265 is

  blocking the session 269. Could it be any easier? 
  How
    Many Waits? 
  The user is still in your cubicle because her question is still
  not answered satisfactorily. Why has her session taken this long
  to complete? You can find out by issuing: select * from v$session_wait_class where sid = 269;

The output comes back as: SID SERIAL# WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS TOTAL_WAITS TIME_WAITED

—- ——- ————- ———– ————- ———– ———–

269 1106 4217450380 1 Application 873 261537

269 1106 3290255840 2 Configuration 4 4

269 1106 3386400367 5 Commit 1 0

269 1106 2723168908 6 Idle 15 148408

269 1106 2000153315 7 Network 15 0

269 1106 1740759767 8 User I/O 26 1

Note the copious information here about the

  session's waits. Now you know that the session has waited 873
  times for a total of 261,537 centi-seconds for application-related
  waits, 15 times in network-related events, and so on. Extending the same principle, you can see the
  system-wide statistics for wait classes with the following query.
  Again, the time is in centi-seconds. select * from v$system_wait_class;

WAIT_CLASS_ID WAIT_CLASS# WAIT_CLASS TOTAL_WAITS TIME_WAITED

————- ———– ————- ———– ———–

1893977003 0 Other 2483 18108

4217450380 1 Application 1352 386101

3290255840 2 Configuration 82 230

3875070507 4 Concurrency 80 395

3386400367 5 Commit 2625 1925

2723168908 6 Idle 645527 219397953

2000153315 7 Network 2125 2

1740759767 8 User I/O 5085 3006

4108307767 9 System I/O 127979 18623

Most problems do not occur in isolation; they

  leave behind tell-tale clues that can be identified by patterns.
  The pattern can be seen from a historical view of the wait classes
  as follows. select * from v$waitclassmetric;

This view stores the statistics related to

  wait classes over the last minute. select wait_class#, wait_class_id, 

average_waiter_count "awc", dbtime_in_wait,

time_waited, wait_count

from v$waitclassmetric;

WAIT_CLASS# WAIT_CLASS_ID AWC DBTIME_IN_WAIT TIME_WAITED WAIT_COUNT

———– ————- —- ————– ———– ———-

      0    1893977003    0              0           0          1
      1    4217450380    2             90        1499          5
      2    3290255840    0              0           4          3
      3    4166625743    0              0           0          0
      4    3875070507    0              0           0          1
      5    3386400367    0              0           0          0
      6    2723168908   59              0      351541        264
      7    2000153315    0              0           0         25
      8    1740759767    0              0           0          0
      9    4108307767    0              0           8        100
     10    2396326234    0              0           0          0
     11    3871361733    0              0           0          0

Note the and related

  statistics. For the value , we saw that the 2
  sessions waited for this class in the last minute for a total of 5
  times and for 1,499 centi-seconds. But what is this wait class?
  You can get that information from V$SYSTEM_WAIT_CLASS as shown
  above—it's the class . Note the column named , a
  very useful one, it shows the time spent inside the database. 
  Everyone

Leaves

    a Trail
  Finally the user leaves and you breathe a sigh of relief. But you
  may still want to get to the bottom of what different waits
  contributed to the problem in her session in the first place.
  Sure, you can easily get the answer by querying V$SESSION_WAIT—but
  unfortunately, the wait events are not present now and hence the
  view does not have any records of them. What would you do? 
  In 10_g_, a history of the session waits is maintained
  automatically for the last 10 events of active sessions, available
  through the view V$SESSION_WAIT_HISTORY. To find out these events,
  you would simply issue: select event, wait_time, wait_count

from v$session_wait_history

where sid = 265;

EVENT WAIT_TIME WAIT_COUNT

—————————— ———- ———-

log file switch completion 2 1

log file switch completion 1 1

log file switch completion 0 1

SQL*Net message from client 49852 1

SQL*Net message to client 0 1

enq: TX – row lock contention 28 1

SQL*Net message from client 131 1

SQL*Net message to client 0 1

log file sync 2 1

log buffer space 1 1

When the sessions become inactive or

  disconnected, the records disappear from that view. However, the
  history of these waits is maintained in AWR tables for further
  analysis. The view that shows the session waits from the AWR is
  V$ACTIVE_SESSION_HISTORY.

_Example 1:

    Buffer Busy Waits > 10000 in v$session_event._

_Oracle

      Reference Manual_

_Example 2:

      Buffer busy wait in v$session_wait._

_Oracle Reference Manual_

_Listing 2:

      In which table is the hot block?_

_Example 3:

      Hotblock search results._

_g__g_

_Listing 3: Display session wait history._

_Example 4:

      Session wait history._

_Listing 4:

      Query v$active_session_history._

_Example 5:

      v$active_session_history output._

Query

        examples
  What resource is currently in high demand?

select

  active_session_history.event,

sum(active_session_history.wait_time

  • active_session_history.time_waited)
  ttl_wait_time

from

  v$active_session_history active_session_history

where

  active_session_history.sample_time between sysdate - 60/2880 and
  sysdate

group by

  active_session_history.event

order by 2;

Wait

  Event                    
  TTL_WAIT_TIME
  -------------

SQL*Net message to

  client                 
  4

null

  event                                
  5

LGWR wait for redo

  copy                 
  161

ksfd: async disk

  IO                     
  476

direct path

  read                      
  30025

latch: cache buffers

  chains           
  33258

direct path

  write                     
  93564

log file sequential

  read             
  178662

db file sequential

  read              
  458653

log file

  sync                        
  612660

control file single

  write           
  1127626

read by other

  session               
  2024242

db file parallel

  write              
  2278618

control file parallel

  write         
  3091888

enq: CF –

  contention                
  4108238

rdbms ipc

  reply                     
  4283877

db file scattered

  read              
  4357653

class slave

  wait                    
  5123780

control file sequential

  read         6971659

rdbms ipc

  message                  
  11899157

jobq slave

  wait                    
  14732974

log file parallel

  write            
  15310721

log buffer

  space                   
  21405250

SQL*Net message from

  client         26272575

log file switch

  completion         
  66115558

enq: HW –

  contention              
  100841479

buffer busy

  waits                 
  114070065

What

  user is waiting the most?

select sesion.sid, sesion.username,

sum(active_session_history.wait_time

  +
  active_session_history.time_waited) ttl_wait_time
from
  v$active_session_history active_session_history, v$session sesion

where

  active_session_history.sample_time between sysdate - 60/2880 and
  sysdate
 and
  active_session_history.session_id = sesion.sid

group by sesion.sid,

  sesion.username

order by 3;

SID

  User       TTL_WAIT_TIME

—– ———- ————-

135

  SCOTT          
  91167481

149

  SCOTT         
  107409491

153

  SCOTT         
  110796799

What

  SQL is currently using the most resources?

select

  active_session_history.user_id, dba_users.username,
  sqlarea.sql_text,

sum(active_session_history.wait_time

  • active_session_history.time_waited) ttl_wait_time
from
  v$active_session_history active_session_history, v$sqlarea
  sqlarea, dba_users

where

  active_session_history.sample_time between sysdate - 60/2880 and
  sysdate
 and
  active_session_history.sql_id = sqlarea.sql_id
 and
  active_session_history.user_id = dba_users.user_id

group by

  active_session_history.user_id,sqlarea.sql_text,
  dba_users.username

order by 4;

USER_ID User

  SQL_TEXT                                               
  TTL_WAIT_TIME

——- ——

  -----------------------------------------------------  
  -------------
 57
  SCOTT  insert into sys.sourcetable (select * from
  sys.source$)     304169752

What

  object is currently causing the highest resource waits?

set linesize 90

  col object_name heading
  'Object|Name'       format a27
  col c2 heading
  'Object|Type'               
  format a20
  col c3 heading
  'Event|Name'                
  format a30
  col c4 heading 'Total|Wait Time|(in secs)'  format 999,999
  select obj.object_name , 
         obj.object_type c2, 
         active_session_history.event
  c3,
  round((sum(active_session_history.wait_time +
  active_session_history.time_waited)/ 100),2)  c4
      from v$active_session_history
  active_session_history, dba_objects obj
     where active_session_history.sample_time between
  sysdate - 60/2880 and sysdate
       and active_session_history.current_obj# =
  obj.object_id
    group by obj.object_name, obj.object_type,
  active_session_history.event
    order by 4;

OBJECT_NAME

  OBJECT_TYPE  Wait
  Event                    
  TTL_WAIT_TIME

————– ————

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

SOURCE$ TABLE

  ksfd: async disk
  IO                      
  23

SOURCETABLE TABLE

  ksfd: async disk
  IO                     
  453

SOURCETABLE TABLE

  latch: cache buffers
  chains           
  33258

SOURCETABLE TABLE

  db file scattered
  read                
  82593

SOURCETABLE TABLE

  db file sequential
  read              
  111202

SOURCETABLE TABLE

  control file parallel
  write          
  137237

SOURCETABLE TABLE

  read by other
  session                
  165501

SOURCETABLE TABLE

  log file
  sync                        
  612660

SOURCE$ TABLE

  log buffer
  space                     
  932308

SOURCETABLE TABLE

  control file sequential
  read         1428575

SOURCE$ TABLE

  log file switch
  completion          
  1856281

SOURCE$ TABLE

  read by other
  session               
  1858741

SOURCE$ TABLE

  db file scattered
  read              
  4275060

SOURCETABLE TABLE

  rdbms ipc
  reply                     
  4283877

SOURCETABLE TABLE

  log buffer
  space                   
  14152000

SOURCE$ TABLE

  enq: HW -
  contention               
  25483656

SOURCETABLE TABLE

  log file switch
  completion         
  59228080

SOURCETABLE TABLE

  enq: HW -
  contention               
  75357823

SOURCETABLE TABLE

  buffer busy
  waits                 
  114055403

Getting the SQL

Full Code