{"id":90992,"date":"2021-05-11T22:53:47","date_gmt":"2021-05-11T22:53:47","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=90992"},"modified":"2021-07-14T13:06:49","modified_gmt":"2021-07-14T13:06:49","slug":"oracle-sequences-rac","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/oracle-sequences-rac\/","title":{"rendered":"Oracle Sequences: RAC"},"content":{"rendered":"<p><strong>The series so far:<\/strong><\/p>\n<ol>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/oracle\/oracle-sequences-the-basics\/\">Oracle sequences: The basics<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/oracle\/oracle-sequences-rac\/\">Oracle sequences: RAC<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/typical-uses-oracle-sequences\/\">Typical uses of Oracle sequences<\/a><\/li>\n<li><a href=\"https:\/\/www.red-gate.com\/simple-talk\/databases\/oracle-databases\/oracle-sequences-12c-features-including-identity\/\">Oracle sequences \u2013 12c features including \u201cidentity\u201d<\/a>\u00a0<\/li>\n<\/ol>\n\n<p>In my first <a href=\"https:\/\/www.red-gate.com\/simple-talk\/sql\/oracle\/oracle-sequences-the-basics\/\">article on Sequences<\/a>, I reviewed the fundamental reason why Oracle Corp. introduced the mechanism (i.e. synthetic\/surrogate keys) and the mechanical threats (cache size and index contention) that still had to be addressed by the developer\/DBA. In this article, I\u2019ll spend most of my time explaining how the problems can get worse (and be addressed) as you move from single-instance Oracle to multi-instance Oracle (RAC). I\u2019ll end the article by mentioning the newer features of sequences that appeared in the upgrades from 12c to 19c, emphasizing one RAC scalability feature.<\/p>\n<p>NOTE: Literally minutes after I had emailed the final draft of this article to the Simple Talk editor, a question came up on the Oracle-L list server asking why duplicate values were appearing from a sequence with\u00a0<strong><em>scale<\/em><\/strong>\u00a0and\u00a0<strong><em>extend<\/em><\/strong>\u00a0enabled\u00a0 when the queries accessing it were running parallel. The answer arrived shortly afterwards: this is due to (unpublished) bug 31423645, fixed in Oracle 19.11 with back-ports possible for earlier versions of Oracle.&#8221;<\/p>\n<h2>RAC<\/h2>\n<p>Whenever you move from single-instance to multi-instance, the fundamental problem is how to avoid excessive competition between instances for \u201cpopular\u201d data blocks. This generic issue turns into two specific issues for sequences:<\/p>\n<ul>\n<li>Refreshing the sequence \u201ccache\u201d updates a specific row in table <code>sys.seq$<\/code>.<\/li>\n<li>Every session that\u2019s inserting consecutive values into an index will be trying to access the same \u201cright-hand \/ high-value\u201d index leaf block.<\/li>\n<\/ul>\n<p>There is another issue with sequences and RAC, though, that has to be considered before worrying about possible hot spots. How do the instances co-ordinate their use of sequence values and avoid the risk of two instances using the same value? There are two solutions: the default <code>noorder <\/code>mechanism where each instance behaves as if it doesn\u2019t know about the other instances. The other is the <code>order<\/code> option, where the instances continuously negotiate through the use of <strong><em>global enqueues<\/em><\/strong> to determine which instance should be responsible for the sequence at any moment.<\/p>\n<h3>Default Mechanism (noorder)<\/h3>\n<p>Imagine you have created a sequence with the basic command<\/p>\n<pre class=\"lang:ps theme:powershell-ise\">create sequence s1 cache 5000;<\/pre>\n<p>As demonstrated in the previous article, Oracle creates a row in the <code>seq$<\/code> table with <code>highwater = 1<\/code> and <strong><em>cache<\/em><\/strong> = 5000. The first instance to call for <code>s1.nextval<\/code> reads this row into its global memory area and returns the value 1 to the calling session, updating the table to set the table\u2019s <code>highwater<\/code> to 5001. (Note: I have said that the \u201cinstance\u201d is calling for a value, more accurately, I should say a session in the instance.)<\/p>\n<p>What happens when the next instance calls for <code>s1.nextval<\/code>? It will do what any instance normally does; it will read the current values of the row from <code>seq$<\/code> and say <em>\u201cthe current high value is 5001, the cache size is 5000<\/em>; I will update <code>seq$.highwater<\/code><em> to 10,001 and return the value 5001 to the session\u201d<\/em>. If a third instance then calls for <code>s1.nextval<\/code><strong><em>,<\/em><\/strong> the same procedure takes place \u2013 it reads the current state of the row, updates the <code>highwater <\/code>to 15,001, and returns 10,001 to the user session.<\/p>\n<p>Any of the three instances could be the first to exhaust its cache \u2013 when it does, it will read the <code>seq$<\/code> row again, update the <code>highwater <\/code>by 5,000 and return the value that used to be the <code>highwater<\/code>. If this is the first instance, its call to <code>nextval<\/code> will jump from 5,000 to 15,001.<\/p>\n<p>The upshot of this <code>noorder<\/code> mechanism is that each instance will be working its way through a different range of numbers, and there will be no overlaps between instances. If you had sessions that logged on to the database once per second to issue a call to <code>nextval<\/code> (and they ended up connecting through a different instance each time), then the values returned would appear to be fairly randomly scattered over a range dictated by <em>\u201cnumber of instances x cache size.\u201d<\/em> Uniqueness would be guaranteed, but ordering would not.<\/p>\n<p>What does this do for the two hot spots, though? I chose a cache size of 5,000 rather than leaving it to default to 20 so that there would be a reasonably large gap between instances that would help to address both points. As it stands, the <code>seq$<\/code> block for the sequence\u2019s row would move between instances to be updated at a fairly low frequency. The instances will spend most of their time inserting key values into leaf blocks that are spaced a few blocks apart in the index with intermittent collisions each time an instance refreshes its cache. To a very large degree, optimizing a sequence in a RAC system simply means setting a big enough cache size \u2013 in some cases <code>cache<\/code> <code>1e6<\/code> would be a perfectly reasonable setting.<\/p>\n<p>This isn\u2019t a complete solution to all the performance problems, and I\u2019ll have more to say about that after a brief diversion into sequences created with the non-default <code>order<\/code> option.<\/p>\n<h3>Sequences with ORDER<\/h3>\n<p>If you\u2019re running single-instance Oracle, then your sequence values are always generated in order. Some of the values may get lost, some of them may be used out of order by the sessions that acquired them, but there is only one source for <em>\u201cthe next value.\u201d<\/em> That value is generated by the instance as <em>\u201cthe previous value\u201d<\/em> plus <em>\u201cthe increment,\u201d<\/em> so the values are always generated in order.<\/p>\n<p>As noted above, in multi-instance Oracle, the instances will, by default, have separate non-overlapping caches that will be out of synch with each other by an amount relating to the cache size. When you view the sequence from a global perspective, there\u2019s no guarantee that values will be generated in order \u2013 and that\u2019s where the RAC-specific <strong><em>order<\/em><\/strong> option comes into play.<\/p>\n<p>If you declare a sequence with the <strong><em>order<\/em><\/strong> option, Oracle adopts a strategy of using a single \u201ccache\u201d for the values and introduces a mechanism for making sure that only one instance at a time can access and modify that cache. Oracle does this by taking advantage of its <strong><em>Global Enqueue<\/em><\/strong> services. Whenever a session issues a call to <code>nextval<\/code><strong><em>,<\/em><\/strong> the instance acquires an exclusive SV lock (global enqueue) on the sequence cache, effectively saying, <em>\u201cwho\u2019s got the most up to date information about this sequence \u2013 I want control\u201d<\/em>. The one instance holding the SV lock in exclusive mode is then the only instance that can increment the cached value and, if necessary, update the <code>seq$<\/code> table by incrementing the <strong><em>highwater<\/em><\/strong>. This means that the sequence numbers will, once again, be generated in order.<\/p>\n<p>The immediate penalty you pay for invoking the <strong><em>order<\/em><\/strong> option is that you serialize the generation of values. The rate at which you can generate sequence numbers is dictated by the rate at which the Global Enqueue Server processes (LCK0\/LMD) can manage to move the SV lock for the sequence between the instances. Unless your sequence is only supposed to supply values at a fairly low rate, you probably don\u2019t want to use this option \u2013 it doesn\u2019t scale.<\/p>\n<p>It is an odd detail that while the sequence information is passed between instances through the <strong><em>SV<\/em><\/strong> enqueue, the enqueue statistics (<code>v$enqueue_stat<\/code>) won\u2019t show any <strong><em>gets<\/em><\/strong> on the <strong><em>SV<\/em><\/strong> enqueue. (The system wait events (<code>v$system_event<\/code>) will report waits for <code>enq: SV -  contention<\/code>, but the individual sessions (<code>v$session_event<\/code>) will show these waits only as <code>events in waitclass other<\/code>.)<\/p>\n<h3>Performance Impact<\/h3>\n<p>All the performance issues that appear in single-instance Oracle reappear in multi-instance Oracle but tend to get worse because of the need for the instances to co-ordinate their activity through the Global Cache Service or Global Enqueue Service (or both).<\/p>\n<p>In particular, when an instance needs to update <code>seq$<\/code><strong><em>,<\/em><\/strong> it may need to call the <strong><em>Global Cache<\/em><\/strong> service to get exclusive access (<code>gc current get<\/code>) to the block that it needs to update. Similarly, if the sequence is being used to generate a unique key, then the instance may also need to call the global cache service to get exclusive access to the relevant index leaf block, and the \u201cright-hand\/high-value\u201d problem that appears in single-instance Oracle can become a disaster area in multi-instance Oracle.<\/p>\n<p>The possible threats are made a little more subtle, though, by the choice between declaring the sequence as <code>order<\/code> or <code>noorder<\/code>. There are 4 combinations to consider:<\/p>\n<p>Noorder \/ cache N<br \/>\nOrder \/ cache N<br \/>\nNoorder \/ nocache<br \/>\nOrder \/ nocache<\/p>\n<p>To give you some idea of the effect of the different options, I set up a 3-node RAC system and ran a simple PL\/SQL block on each node to do 1,000 single-row inserts of <code>sequence.nextval<\/code> with a 1\/100 second sleep between inserts. I then tested each of the 4 options above (with <em>N = 5000<\/em> for the cache tests). The actual work done for the inserts was tiny (less than 1 second CPU); the <strong><em>excess<\/em><\/strong> wait time due to RAC-related wait events was as follows (in order of <strong><em>excess<\/em><\/strong> time lost):<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"376\" height=\"88\" class=\"wp-image-90993\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/05\/word-image-73.png\" \/><\/p>\n<p>Clearly, <code>cache<\/code> is better than <code>nocache<\/code>, and <code>noorder<\/code> is better than <code>order<\/code>. A large cache with <code>noorder<\/code> is by far the most efficient option. The overheads of global enqueue management for ordering are significant, as are the overheads of maintaining the <code>seq$<\/code> table.<\/p>\n<p>There are defects to this specific test, of course. First, it\u2019s running VMs, so the virtual <strong><em>interconnect<\/em><\/strong> speeds are slower than they would be on big dedicated hardware; secondly, I haven\u2019t included any indexes in this test, and the different patterns of index contention could be significant; finally, I\u2019m only using one session per instance to do the inserts while production systems are likely to see different patterns of contention between sessions that are running on the same instance.<\/p>\n<p>There are too many possible variations in the patterns of activity that different applications might have, so it\u2019s not sensible for me to create and report tests for all of them. Just remember that you need to think about how your application will be working, then design a couple of models to work out the most appropriate strategy for your circumstances. I will, however, make a few general comments on how the different options may affect the performance of your production system based on my initial statement about the two critical points: refreshing the sequence cache and inserting into the sequence-based unique index.<\/p>\n<h3>Noorder \/ Cache N<\/h3>\n<p><strong>Refreshing the cache:<\/strong> an instance that reaches its high water and needs to refresh its cache will have to acquire the relevant <code>seq$<\/code> block in exclusive mode. For low cache values (e.g. the default 20), this may happen very frequently and introduce significant waits for <strong><em>\u201cgc\u201d<\/em><\/strong> (global cache) events. For large values (e.g. the 5,000 in my test), this may be sufficiently rare that any <strong><em>\u201cgc\u201d<\/em><\/strong> waits are insignificant compared to the rest of the workload.<\/p>\n<p><strong>Inserting into the index:<\/strong> imagine two instances and a sequence with a cache size of 5,000 where node 1 has been busier than Node 2. Node 1 is currently inserting values in the range 25,001 to 30,000 and has just reached 28,567. Node 2 is inserting values in the range 5,001 to 10,000 and has just reached 9,999. The two instances are inserting into different index leaf blocks, so there\u2019s no contention. After one more insert, Node 2 needs to refresh its cache, so it now starts to insert values in the range 30,001 to 35,000, but Node 1 is currently inserting a few values just a little larger than 28,567. The two nodes will be inserting into the same high-value leaf block for a little while until that leaf block splits and probably leaves Node 1 inserting into one leaf block and Node 2 inserting into the one just above it. For a couple of seconds, there might be a fierce battle for ownership between the two instances, and you\u2019re likely to see waits for various \u201cgc\u201d events for the index, including <em>\u201cgc cr block busy\u201d<\/em>, <em>\u201cgc buffer busy release\u201d<\/em> and <em>\u201cgc buffer busy acquire\u201d<\/em>. I\u2019ll comment on the workaround, or damage limitation mechanism, for this behaviour on my way to the section on 12c enhancements.<\/p>\n<h3>Order \/ Cache N<\/h3>\n<p><strong>Refreshing the cache:<\/strong> the comments from <strong><em>\u201c<\/em><\/strong><code>noorder\/cache N<\/code><strong><em>\u201d<\/em><\/strong> regarding <strong><em>\u201cgc\u201d<\/em><\/strong> waits still apply, but since only one instance will need to update the <code>seq$<\/code> table at any one moment, the impact will be greatly reduced. But this savings has been at the cost of the continuous stream of waits for the <strong><em>SV<\/em><\/strong> enqueue.<\/p>\n<p><strong>Inserting into the index:<\/strong> If you don\u2019t do something to avoid the issue, the contention on the right-hand \/ high-value leaf block on the index will be huge. Every instance will constantly be demanding the block in current mode, and you will see a lot of waits for \u201cgc\u201d events for the index; you may also see several waits for <em>\u201cenq: TX \u2013 index contention\u201d<\/em> as the current high_value block splits. Of course, if you take action to avoid the contention on the high-value index leaf block, you must have done something that stops consecutive values belonging to the same index leaf block, which means they can\u2019t be consecutive anymore. This suggests you didn\u2019t really need the \u201corder\u201d option.<\/p>\n<p>Noorder \/ NoCache<\/p>\n<p><strong>Refreshing the cache:<\/strong> If there\u2019s no \u201ccache\u201d, the row in <code>seq$<\/code> has to be updated on every single call to <code>sequence.nextval<\/code>. Every instance will request exclusive access to the relevant block and show lots of time lost on various \u201cgc\u201d waits. However, since updating the highwater also results in the dictionary cache (rowcache) being updated, there will also be a lot of time spent waiting on \u201crow cache lock\u201d events.<\/p>\n<p><strong>Inserting into the index:<\/strong> Even though you\u2019ve specified noorder, the effect of the nocache means that the values supplied will be very well ordered with no \u201ccache-size\u201d gap between instances. All the instances will insert into the same high-value leaf block at the same time. There will be <strong><em>\u201cgc\u201d<\/em><\/strong> waits on the index as well as on <code>seq$<\/code>. Given all the waits for <code>seq$<\/code> and <strong><em>row cache locks<\/em><\/strong>, the extra time lost due to these waits for the index leaf block may not be extreme.<\/p>\n<h3>Order \/ Nocache<\/h3>\n<p><strong>Refreshing the cache:<\/strong> As for <code>noorder\/nocache<\/code>, there is no cache, so every call to <code>sequence.nextval<\/code> is a request to update the <code>seq$<\/code> table and invalidate the row cache entry for the sequence on all instances. In fact, I could see no difference between <code>order<\/code><strong><em>\/<\/em><\/strong><code>nocache<\/code> and <code>noorder<\/code><strong><em>\/<\/em><\/strong><code>nocach<\/code><strong><em>e. <\/em><\/strong>Possibly the difference in timing between these two cases in my test was purely one of luck.<\/p>\n<p><strong>Inserting into the index:<\/strong> Again, the argument of <code>noorder<\/code><strong><em>\/<\/em><\/strong><code>nocache<\/code> applies.<\/p>\n<h3>Performance \u2013 further thoughts<\/h3>\n<p>From the list of 4 combinations, it should be clear that <code>noorder\/cache N<\/code> with a large cache is the most scalable option, as it separates the (index) activity of the instances and minimizes the contention for updating the <code>seq$<\/code> table. However, it still has effects that might need further consideration.<\/p>\n<p>First is the simple observation that you can expect the index to be roughly twice the \u201cpacked\u201d size. If you do a test on a single instance inserting into an indexed column the values from 1 to 1,000,000 from one session and the values from 1,000,001 to 2,000,000 from another session, you will find that the lower range of values will result in 50\/50 leaf block splits. In contrast, the upper range of values will result in 90\/10 splits. If you have N instances doing inserts from a sequence with a large cache, all but the instance using the top-most range of values will be doing 50\/50 leaf block splits all the time. The only comment I can make on this is that it isn\u2019t nice, but it\u2019s probably not terribly important.<\/p>\n<p>More significant is that I\u2019ve ignored the effects of multiple sessions in each instance using the sequence for inserts. In a single instance (of a multi-instance RAC), you could have many sessions inserting values that are very similar, and though this won\u2019t generally produce contention between instances, it can produce contention between sessions in the same instance (i.e. buffer busy waits, index ITL waits, etc.). The \u201csingle instance\u201d workaround I mentioned in the previous article of adding a factor like <code>(1 + mod(sid, 16)) * 1e10<\/code> to the value supplied by the sequence is a positive danger in these circumstances. For example, entries generated by session 99 of instance 1 might end up in the same index leaf block as rows generated by session 99 of instance 2. You need to go one step further for RAC. In addition to adding a factor to spread sessions across multiple leaf blocks, you also need to add a factor that ensures that different instances will stay separated by adding an \u201cinstance factor\u201d like <code>(1 + mod(instance,999) * 1e14<\/code> as well. And this brings me to 12c Enhancements.<\/p>\n<h2>Sequences in 12c<\/h2>\n<p>Oracle 12c (12cR2) brings several enhancements to sequences. You can associate a sequence with a table column using the <strong><em>identity<\/em><\/strong> mechanism. Alternatively, you can use <strong><em>\u201c<\/em><\/strong><code>sequence.nextval<\/code><strong><em>\u201d<\/em><\/strong> as a default value for a column if you\u2019d rather not declare an identity. You can create sequences that can be used \u201clocally\u201d \u2013 i.e. they are private to a session. You can <strong><em>restart<\/em><\/strong> a sequence. Finally, 12c automates the business of minimizing index contention on RAC by introducing the \u201cscale\u201d option (though it\u2019s not documented in the SQL Reference manual and probably shouldn\u2019t be used until 18c).<\/p>\n<p>Here\u2019s a little script that produces the same pattern of results on 12.2.0.1 and 19c, demonstrating the new automatic scalability option:<\/p>\n<pre class=\"lang:tsql theme:ssms2012-simple-talk\">create sequence s1;\r\ncreate sequence s2 scale;\r\ncreate sequence s3 scale extend;\r\ncreate sequence s4 maxvalue 1e8 scale;\r\ncreate sequence s5 maxvalue 1e8 scale extend;\r\ncreate sequence s6 maxvalue 1e5 scale;\r\nset linesize 48\r\ncolumn nextval format 999,999,999,999,999,999,999,999,999,999,999,999\r\nselect\r\n        s1.nextval,\r\n        s2.nextval,\r\n        s3.nextval,\r\n        s4.nextval,\r\n        s5.nextval\r\nfrom\r\n        dual\r\n\/<\/pre>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"418\" height=\"122\" class=\"wp-image-90994\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2021\/05\/word-image-74.png\" \/><\/p>\n<p>I\u2019ve declared the first three sequences without a <code>maxvalue<\/code> (which means the implicit <code>maxvalue<\/code> is 1e28 \u2013 1) and the next two with an explicit <code>maxvalue<\/code> of 1e8. I\u2019ve given the final sequence a <code>maxvalue<\/code> of 1e5, but for reasons that will become clear, I haven\u2019t tried to select it from <strong><em>dual<\/em><\/strong>.<\/p>\n<p>All six sequences have supplied the value 1 \u2013 with some adjustments \u2013 as their first value. Apart from the simple declaration of <code>s1<\/code><strong><em>,<\/em><\/strong> the results have all been expanded to include a leading six-digit number: 101720. The first three digits are <code>(100 + mod(instance_number,100))<\/code><em>, <\/em>and the next three are <code>mod(sid,1000)<\/code>. This matches exactly the sort of strategy I\u2019ve described above and in the previous article to minimize contention on index leaf blocks (at the cost of seeing 50\/50 leaf block splits almost everywhere.)<\/p>\n<p>The significance of the <code>extend<\/code> option is visible when you compare <code>s2<\/code> with <code>s3<\/code> or <code>s4<\/code> with <code>s5<\/code>. In the absence of the <code>extend<\/code> option, the value created by the six-digit prefix has to fall within the defined <code>maxvalue<\/code>. This means the largest possible \u201craw\u201d sequence number will be 6 orders of magnitude lower than you expected. (And that\u2019s why I didn\u2019t try selecting <code>s6.nextval<\/code> from <code>dual<\/code> \u2013 it would have raised Oracle error <em>\u201cORA-64603: NEXTVAL cannot be instantiated for S6. Widen the sequence by 1 digits or alter sequence with SCALE EXTEND\u201d<\/em>). If you include the <code>extend<\/code> option, the prefix is multiplied by enough powers of 10 that your actual specified <code>maxvalue<\/code> can be reached without raising an error.<\/p>\n<p>It\u2019s a nice thought that your code no longer needs to impose scalability on the use of sequences, but you do still have to do a little design work before you take advantage of this option. If you\u2019ve implemented something like this new \u201cdouble prefix\u201d in the past to maximize the scalability of your sequences, you will already be familiar with the problem: you need to decide the smallest possible safe <code>maxvalue<\/code> for a sequence before you create the sequence.<\/p>\n<p>Imagine you actually needed \u201craw\u201d values up to 1e8 (ca. 6 bytes), then a suitably selected <code>maxvalue<\/code> with <strong><em>scale<\/em><\/strong> and <strong><em>extend<\/em><\/strong> would give you a 15 digit number (ca. 9 bytes). If you hadn\u2019t specified a <code>maxvalue<\/code><strong><em>,<\/em><\/strong> your sequence would become a 28 (or 32, with <strong><em>extend<\/em><\/strong>) digit number. This means a typical 15 (or 17) bytes which would leave you storing an extra 6 (or 8) bytes per row, per index entry in the primary key, per row in any child table, and per index entry in any <em>\u201cforeign key index\u201d<\/em>. This may not matter very much if it avoids a performance threat, but it\u2019s a detail that requires a deliberate choice \u2013 you should always try to be aware of consequences, even if you decide to ignore them.<\/p>\n<h2>Summary<\/h2>\n<p>This article reviewed sequences in light of the basic contention threat that is always present in any multi-instance (RAC) system and identified two hot spots: updates to the <code>seq$<\/code> table as a sequence cache is refreshed, and the high-value index leaf block if nothing is done to spread the sequence values used by different instances across different leaf blocks.<\/p>\n<p>It\u2019s shown that the default RAC behaviour of sequences \u2013 where every instance gets its own range of values \u2013 helps to avoid the index contention, though a large cache size is needed for the best effect. At the same time, it demonstrated that a large cache size minimizes the frequency of updates to, hence competition for, the <code>seq$<\/code> table.<\/p>\n<p>The <code>order<\/code> option decreases scalability as it makes every instance compete for the current high-value index leaf block. It also adds overhead as the sequence information is passed around the instances through the Global Enqueue service.<\/p>\n<p>Even though you can reduce cross-instance contention by setting a large cache size, you will still have some contention between one pair of instances each time an instance refreshes its cache. There will still be contention between sessions within each instance as they compete for the \u201cinstance-local\u201d high-value index leaf block. This leads us to the idea of pre-fixing the sequence value with a two-part prefix constructed from the instance number and session number. In 12c (though documented only in 18c), Oracle allows creating a sequence that handles this work with no extra coding required. However, the necessary static declaration does require deciding whether to use some extra space to avoid any risk of running out of sequence values.<\/p>\n<p>I\u2019ve also briefly mentioned a couple of new features in 12c that add a little extra power and convenience to sequences. The next article will start looking at examples of the various ways to use sequences, and how they work might sometimes be surprising.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Using sequences when scaling up with Oracle RAC presents more issues with contention. In this article, Jonathan Lewis explains how to avoid the problems.&hellip;<\/p>\n","protected":false},"author":101205,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[53,143533],"tags":[48462,143556,124952],"coauthors":[39048],"class_list":["post-90992","post","type-post","status-publish","format-standard","hentry","category-featured","category-oracle-databases","tag-oracle-rac","tag-oracle-sequence","tag-redgate-deploy"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/90992","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/101205"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=90992"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/90992\/revisions"}],"predecessor-version":[{"id":90996,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/90992\/revisions\/90996"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=90992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=90992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=90992"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=90992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}