Call now: 252-767-6166  
Oracle Training Oracle Support Development Oracle Apps

 
 Home
 E-mail Us
 Oracle Articles
New Oracle Articles


 Oracle Training
 Oracle Tips

 Oracle Forum
 Class Catalog


 Remote DBA
 Oracle Tuning
 Emergency 911
 RAC Support
 Apps Support
 Analysis
 Design
 Implementation
 Oracle Support


 SQL Tuning
 Security

 Oracle UNIX
 Oracle Linux
 Monitoring
 Remote s
upport
 Remote plans
 Remote
services
 Application Server

 Applications
 Oracle Forms
 Oracle Portal
 App Upgrades
 SQL Server
 Oracle Concepts
 Software Support

 Remote S
upport  
 Development  

 Implementation


 Consulting Staff
 Consulting Prices
 Help Wanted!

 


 Oracle Posters
 Oracle Books

 Oracle Scripts
 Ion
 Excel-DB  

Don Burleson Blog 


 

 

 


 

 

 
 

Sequence cache and RAC

RAC tuning tips

October 3,  2015

 

Sequence cache and RAC

The sequence database object needs special attention for applications running on Oracle RAC. It is common for an Oracle sequence to be a point of contention when the application is deployed on Oracle RAC. Most applications create a sequence similar to the following example.

 

SQL> create sequence

  2     emp_pk_id_seq

  3     start with 1000

  4     increment by 1

  5     nocache;

 

Sequence created.

 

It has become a standard practice for many sequences to have the nocache directive. The main reason for specifying nocache is so that the next sequence value is not lost when the instance abnormally terminates. If both cache and nocache are omitted, the default is to cache 20 sequence values in memory.

 

In the next example, a sequence is created with the default cache value and the first two values are selected.

 

SQL> create sequence              

  2     cache_example_sequence

  3     start with 1

  4     increment by 1;

 

Sequence created.

 

SQL> select     

  2     cache_example_sequence.nextval

  3  from

  4     dual;

 

   NEXTVAL

----------

         1

 

SQL> select     

  2     cache_example_sequence.nextval

  3  from

  4     dual;

 

   NEXTVAL

----------

         2

 

The database is abnormally terminated and after startup, the next value of the sequence is selected.

 

SQL> select     

  2     cache_example_sequence.nextval

  3  from

  4     dual;

 

   NEXTVAL

----------

        21

 

It's important to note that a gap now exists in the values generated by this sequence. The sequence has generated values 1, 2, and 21. The first twenty values were in the cache but only the first two were actually used. When the instance abnormally terminated, sequence values 3 through 20 were lost.

 

For sequences that are used to generate primary key values, the gap in ID values is inconsequential, as most end users won't notice the gap. Sequence gaps are most noticeable for entities like invoices or check numbers. Accountants determine if a check has yet to clear the bank by gaps in the check number sequence. Unless you are dealing with accountants, almost every other occurrence of missing numbers in a sequence is irrelevant. Yet humans tend to like order and gaps in the numbers mean disorder, chaos. It often takes training to educate users that gaps in sequences are truly meaningless. It is easier for the database designer to use nocache so that there will be no missing sequence values than it is to take the time to teach users that sequence gaps are perfectly acceptable. There are other reasons for ensuring no gaps in the sequence numbers, but most are for convenience not factual business requirements. Over time, the database designer simply started using nocache without any second thoughts. For many, nocache is now a simple habit.

 

The problem with nocache sequences in Oracle RAC lies with the sequence being a global database object. Any node in the cluster can generate the next value. In a database where the sequence is used frequently by many sessions, the sequence can become a bottleneck. While a session is generating the sequence's next value, other sessions must wait, and coordinate through the Cluster Interconnect for access to the resource. In a single-instance database, all of this coordination is done locally, entirely in memory. In an Oracle RAC database, processes on different nodes need to talk to each other through the private network, which can really slow the process down.

 

To show the effect of nocache on sequences in Oracle RAC, we will have two sessions, each of which will select from the same sequence in a loop, over and over again. The sequence is altered to use nocache.

 

SQL> alter sequence          

  2     cache_example_sequence

  3     nocache;

 

Sequence altered.

 

 

Next, an anonymous PL/SQL block is executed concurrently in two sessions, one session attached to instance orcl1 and the other session attached to instance orcl2.

 

SQL> set timing on

SQL> declare

  2     curr_val number;

  3     cnt       number;

  4  begin

  5     cnt := 0;

  6     while cnt <= 100000

  7     loop

  8        select cache_example_sequence.nextval

  9           into curr_val

 10        from

 11           dual;

 12        cnt := cnt + 1;

 13     end loop;

 14  end;

 15  /

 

PL/SQL procedure successfully completed.

 

Elapsed: 00:19:59.61

 

The elapsed runtime of 19:59.61 is from the session on the orcl1 instance. The code executed on the orcl2 instance completed in 20:43.22. Each session required approximately 20 minutes to gather 100,000 sequence values when run concurrently.

 

Next, the sequence is modified to cache 20 values. The instances are bounced to eliminate any memory caching in the instances from skewing the results.

 

SQL> alter sequence

  2     cache_example_sequence

  3     cache 20;

 

Sequence altered.

 

The same anonymous PL/SQL block is executed concurrently in both instances.

 

SQL> set timing on

SQL> declare

  2     curr_val number;

  3     cnt       number;

  4  begin

  5     cnt := 0;

  6     while cnt <= 100000

  7     loop

  8        select cache_example_sequence.nextval

  9           into curr_val

 10        from

 11           dual;

 12        cnt := cnt + 1;

 13     end loop;

 14  end;

 15  /

 

PL/SQL procedure successfully completed.

 

Elapsed: 00:00:41.19

 

The first session completed in 00:41.19 and the second session completed in 00:49.18. Just by making a simple, small change in the sequence's cache value (setting ?cache 20?), the runtime of this sample program decreased from 20 minutes to less than 1 minute!

 

To further illustrate the effect of the sequence's cache value, the sequence will be modified with larger cache sizes and the same PL/SQL block will be executed concurrently in two instances. When the cache value was increased to 100, the PL/SQL block completed in 00:10.98 for the first session and 00:11.57 for the second session, now around 10 seconds. When the sequence's cache value was increased to 1000, the PL/SQL block's run times were 00:01.06 and 00:02.62, each less than 3 seconds. The following table summarizes the results.

 

 

Cache Value

Node 1 Session Runtime

Node 2 Session Runtime

None

19:59.61

20:43.22

20

00:41.19

00:49.18

100

00:10.98

00:11.57

1000

00:01.06

00:02.62

Table 3.1 Sequence Runtimes With Caching

 

It should be obvious from these results the effect the sequence's cache value. These results were obtained on a two-node RAC database running on a laptop, definitely not production hardware. Your results will most likely differ depending on the system's configuration. No matter the resources available to the RAC cluster, this simple test can be used to illustrate the effect of the cache values for a sequence.

 

Some readers may be thinking, ?When am I ever going to code a loop that does nothing more than select the sequence's next value?? This is a fair question. The simple example above is only meant to demonstrate sequence contention. This example had only two concurrent sessions running on two Oracle RAC nodes. In practice, there may be more than 100 concurrent sessions on three or four nodes. Sequence contention can certainly exist and can exhibit performance not that different than this simple example.

 

While a real application would never code selecting the sequence's next value in a loop like this example, other than as an academic exercise, an application would code a statement similar to the following.

 

insert into

   destination_table

select

   my_sequence.next_val,

   column

from

   source_table;

 

In the case of the sample insert statement above, the sequence's next value will be generated for each row of the result set which is not that different from a loop as used in this example. Insert 100,000 rows into a table that gets one column populated from a sequence database object and we have effectively leveraged the sequence similar to our example. Alternatively, there could be a trigger on the destination table that generates the sequence's next value for every row inserted into that table with a similar effect.

 

Using nocache for a sequence in an Oracle RAC database can lead to poor application performance. It is best to set a high cache value. Most sequences will benefit from a cache value of 100 or higher. Obviously, the more contention for this resource, the higher its cache value should be. It is not out of the ordinary to see a cache value of 1,000 for a sequence in an Oracle RAC database. The following query can be used to determine which sequences have nocache specified.

 

select

   sequence_owner,

   sequence_name

from

   dba_sequences

where

   cache_size = 0;

 

Any sequences owned by application users should be checked to ensure the cache value would not cause the sequence to be an application bottleneck. Note that we never attempt to change any sequences that are part of the Oracle Data Dictionary.

 

Examining the wait events for a session can identify contention for sequences objects. Querying v$session_wait will show all of the events our session waited on. It is often useful to see the top 5 wait events.  The script below shows the top five wait events for one of the sessions involved in the sequence example.

 

<  current_session_top5_waits.sql

SQL> select

  2     *

  3  from

  4     (select

  2         event,

  3         total_waits,

  4         time_waited

  5      from

  6         v$session_event

  7      where

  8         sid=SYS_CONTEXT('USERENV','SID')

  9      order by

 10         time_waited desc)

 11  where

 12     rownum <= 5;

 

EVENT                          TOTAL_WAITS TIME_WAITED

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

row cache lock                       94154       40306

gc cr block lost                       393       17826

gc current block lost                  371       17462

gc cr block busy                     37397        6731

gc current block 2-way               93214        5587

 

Four of the top five wait events for this session all start with ?gc?. The previous chapter reviewed some of these global cache wait events seen above. The remainder of these Cache Fusion waits will be discussed in a later chapter.

 

The top wait event is the row cache lock event.  So how does this wait event prove the contention is for a sequence database object? To know for sure, the specific parameter values of the row cache lock wait event need to be examined for that session. While the session was running and experiencing contention, this session's specific wait event was captured.

 

<  current_session_wait.sql

SQL> select

  2     event,

  3     p1,

  4     p2,

  5     p3

  6  from

  7     v$session_wait

  8  where

  9     sid=SYS_CONTEXT('USERENV','SID');

 

EVENT                             P1        P2       P3

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

row cache lock                    13         0        5

 

In the output above, the session is experiencing the row cache lock wait event. Notice the P1 value is 13. Examining the v$rowcache view shows the Data Dictionary object type that is involved. For the row cache lock wait event, the P1 value links to the cache# column of the v$rowcache view

 

SQL> select          

  2     parameter,

  3     gets,

  4     getmisses

  5  from

  6     v$rowcache

  7  where

  8     cache#=13;

 

PARAMETER                  GETS  GETMISSES

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

dc_sequences              64740      64283

 

The output above shows that the session is experiencing contention for the dc_sequences object type. Also notice that the number of get misses is very high compared to the number of gets. However, the metric shown in this query may have a low get misses ratio compared to total gets and the application can still have sequence contention. The v$rowcache metric shown is for all sequence database objects, even ones that have little or no contention. In the end, the above has shown that our session was experiencing a bottleneck, a wait, on something in the row cache which subsequently confirmed this to be the part of the row cache that deals with sequences.

 

What has yet to answered is which sequence is involved in the bottleneck. To answer that question, one would have to look at the code being executed for that session. If access to the code is not available, then one can always start a SQL trace in session to determine the sequence involved.

 

It should be noted that some versions of Oracle RAC that are experiencing contention for sequences may not manifest themselves as the row cache lock wait event shown in this chapter. These examples were run on Oracle 11.2.0.4 and Oracle 12.1.0.1 and obtained similar results. Some versions may show the wait event to be enq: SQ - contention which is a fancy way of indicating sequence (SQ) enqueues (lock) contention.

 

 

 
 
 
Learn RAC Tuning Internals!

This is an excerpt from the landmark book Oracle RAC Performance tuning, a book that provides real world advice for resolving the most difficult RAC performance and tuning issues.

Buy it  for 30% off directly from the publisher.


Hit Counter

 

Burleson is the American Team

Note: This Oracle documentation was created as a support and Oracle training reference for use by our DBA performance tuning consulting professionals.  Feel free to ask questions on our Oracle forum.

Verify experience! Anyone considering using the services of an Oracle support expert should independently investigate their credentials and experience, and not rely on advertisements and self-proclaimed expertise. All legitimate Oracle experts publish their Oracle qualifications.

Errata?  Oracle technology is changing and we strive to update our BC Oracle support information.  If you find an error or have a suggestion for improving our content, we would appreciate your feedback.  Just  e-mail:  

and include the URL for the page.


                    









Burleson Consulting

The Oracle of Database Support

Oracle Performance Tuning

Remote DBA Services


 

Copyright © 1996 -  2020

All rights reserved by Burleson

Oracle ® is the registered trademark of Oracle Corporation.

 

 

��  
 
 
Oracle Training at Sea
 
 
 
 
oracle dba poster
 

 
Follow us on Twitter 
 
Oracle performance tuning software 
 
Oracle Linux poster