oracle sequence cache 機制


聲明

  本文轉自

    http://space.itpub.net/17203031/viewspace-717042

  感謝作者的辛苦勞動,謝謝

  

 

Oracle中,我們沒有MYSQL和SQL Server可以使用的自增數據類型。大部分場景下,如果我們需要生成業務無關的(Business-Independent)主鍵列,序列Sequence對象是我們最方便的選擇。

 

定義Sequence是很簡單的,如果最大程度利用默認值的話,我們只需要定義sequence對象的名字即可。在序列Sequence對象的定義中,Cache是一個可選擇的參數。默認的Sequence對象是有cache選項的,默認取值為20。

 

那么,這個Cache參數對Sequence的使用帶來什么好處?如果不設置,會有什么問題。本篇我們就一起來探討這個問題。

 

1、Sequence Cache簡析

 

簡單的說,Cache 就是Oracle每次向Sequence進行請求時,分配出的獨立數字數量。例如,當我們使用<seq_name>.nextval獲取一個 獨立值時,Oracle需要將sequence對象的數據字典信息更新。如果我們設置cache為10,那么第一次請求nextval的時候,就更新數據 字典信息增加10,取出的10個號放在Oracle服務器的緩存中。

 

在以后每次請求nextval的時候,Oracle就從服務器緩存中去獲取序列值。而不需要更新數據字典信息。只有在分配到緩存的10個數字都已經分配完,或者因為緩存刷新操作剩余數字被清理的情況下,才會再次調用sequence分配機制,再次分出cache個數字。

在cache問題上,我們經常會疑惑為什么我們sequence生成的數字序列會“跳號”。這種跳號現象實際上就是因為cache的數字在緩存中因為各種原因被flush出,這樣才導致生成的數字序列不連續。

注意:在有cache的情況下,sequence只能保證每次獲取到的數字都是唯一、遞增的,從來沒有保證過數字的連續性。

如果我們不設置cache,也就是不啟用序列數字緩存機制,有什么缺點呢?

2、過多的Redo Log生成

我們首先從Redo的統計情況入手,看看cache在這個過程中的影響。我們選擇Oracle 10g作為實驗環境。

 1 SQL> select * from v$version;
 2 
 3 BANNER
 4 
 5 ----------------------------------------------------------------
 6 
 7 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
 8 
 9 PL/SQL Release 10.2.0.1.0 - Production
10 
11 CORE   10.2.0.1.0   Production
12 
13  
14 
15 TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
16 
17 NLSRTL Version 10.2.0.1.0 - Production

分別創建兩個sequence實驗對象

 

SQL> create sequence seq_nocachenocache;

Sequence created


SQL> create sequence seq_cachecache 3;

Sequence created

 

我們先對nocache對象進行實驗。我們選擇autotrace工具,進行三次調用操作,來觀察各種資源使用情況。

--第一次調用;

1 SQL> select seq_nocache.nextval from dual;
2 
3   NEXTVAL
4 
5 ----------
6 
7         1

 

已用時間: 00: 00: 00.01

 

執行計划

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

Plan hash value: 3078288422

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

| Id | Operation       | Name       | Rows | Cost (%CPU)| Time    |

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

|  0 | SELECT STATEMENT |            |    1 |    2  (0)| 00:00:01 |

|  1 | SEQUENCE       | SEQ_NOCACHE |      |           |         |

|  2 |  FAST DUAL     |            |    1 |    2  (0)| 00:00:01 |

------------------------------------------------------------------------
 1 統計信息
 2 
 3 ----------------------------------------------------------
 4 
 5         30 recursive calls
 6 
 7          3 db block gets
 8 
 9          3 consistent gets
10 
11          0 physical reads
12 
13        640 redo size
14 
15        407 bytes sent via SQL*Net to client
16 
17        400 bytes received via SQL*Net from client
18 
19          2 SQL*Net roundtrips to/from client
20 
21          0 sorts (memory)
22 
23          0 sorts (disk)
24 
25          1 rows processed

--第二次調用(篇幅原因,執行計划和部分統計量省略)

SQL> select seq_nocache.nextval from dual;

 

  NEXTVAL

----------

        2

已用時間: 00: 00: 00.01

 

統計信息

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

        14 recursive calls

         3 db block gets

         1 consistent gets

         0 physical reads

       688 redo size

       407 bytes sent via SQL*Net to client

       400 bytes received via SQL*Net from client

         2 SQL*Net roundtrips to/from client

         0 sorts (memory)

         0 sorts (disk)

         1 rows processed

 

--第三次調用

SQL> select seq_nocache.nextval from dual;

 

  NEXTVAL

----------

        3

 

已用時間: 00: 00: 00.01

 

統計信息

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

        14 recursive calls

         3 db block gets

         1 consistent gets

         0 physical reads

       636 redo size

       407 bytes sent via SQL*Net to client

       400 bytes received via SQL*Net from client

         2 SQL*Net roundtrips to/from client

         0 sorts (memory)

         0 sorts (disk)

         1 rows processed

 

 

篇幅原因,本文只表現部分結果。從結果統計量中,可以發現:雖然我們對sequence對象是采用select操作。但是對nocache的序列對象而言,每次操作都會有600左右的redo log生成。

 

那么,對於開啟了cache的sequence對象而言,有什么不同呢?

SQL> select seq_cache.nextval from dual;

  NEXTVAL

----------

        1

已用時間: 00: 00: 00.03

執行計划

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

Plan hash value: 2754437009

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

| Id | Operation       | Name     | Rows | Cost (%CPU)| Time    |

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

|  0 | SELECT STATEMENT |          |    1 |    2  (0)| 00:00:01 |

|  1 | SEQUENCE       | SEQ_CACHE |      |           |         |

|  2 |  FAST DUAL     |          |    1 |    2  (0)| 00:00:01 |

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

統計信息

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

        30 recursive calls

         3 db block gets

         3 consistent gets

         0 physical reads

       688 redo size

       407 bytes sent via SQL*Net to client

       400 bytes received via SQL*Net from client

         2 SQL*Net roundtrips to/from client

         0 sorts (memory)

         0 sorts (disk)

         1 rows processed

 

SQL> select seq_cache.nextval from dual;

 

  NEXTVAL

----------

        2

 

已用時間: 00: 00: 00.00

 

統計信息

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

         0 recursive calls

         0 db block gets

         0 consistent gets

         0 physical reads

         0 redo size

       407 bytes sent via SQL*Net to client

       400 bytes received via SQL*Net from client

         2 SQL*Net roundtrips to/from client

         0 sorts (memory)

         0 sorts (disk)

         1 rows processed

 

SQL> select seq_cache.nextval from dual;

 

  NEXTVAL

----------

        3

 

已用時間: 00: 00: 00.01

 

統計信息

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

         0 recursive calls

         0 db block gets

         0 consistent gets

         0 physical reads

         0 redo size

       407 bytes sent via SQL*Net to client

       400 bytes received via SQL*Net from client

         2 SQL*Net roundtrips to/from client

         0 sorts (memory)

         0 sorts (disk)

         1 rows processed

 

--第四次調用,獲取新的cache值。

SQL> select seq_cache.nextval from dual;

 

  NEXTVAL

----------

        4

 

統計信息

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

        14 recursive calls

         3 db block gets

         1 consistent gets

         0 physical reads

       636 redo size

       407 bytes sent via SQL*Net to client

       400 bytes received via SQL*Net from client

         2 SQL*Net roundtrips to/from client

         0 sorts (memory)

         0 sorts (disk)

         1 rows processed

 

 

 

對cache的sequence對象而言,redo size生成的頻率顯然是低得多。從上面的四次調用中,只有第一次和第四次調用的時候,才生成了redo log記錄。這個顯然同我們設置的cache=3相對應。

 

設置cache之后,Oracle似乎不用為每次的nextval進行數據字典修改,生成redo log記錄。只有cache在內存中使用結束之后,才會進行獲取。

 

在實際的生產環境中,我們對redo size無必要的生成是要盡力避免的。首先,過多的redo log生成,容易造成online redo log的寫入量增加,切換頻繁。第二,redo size和nocache的使用,可能是伴隨着頻繁的commit動作,進而是頻繁的log buffer寫入online log file的過程。同時歸檔量增加。同時,在進行恢復的時候,也要消耗更多的時間。

 

所以,設置cache可以有效減少redo log的大小。

 

從redo size動作,我們猜測在nextval的時候存在數據字典的頻繁更新風險。

 

3、潛在的行鎖爭用(row lock contention

 

我們猜測在nextval的時候,Oracle做了些什么。於是,我們選擇10046事件,跟蹤設置cache和不設置cache的兩種sequence,在底層遞歸調用的行為。

 

我們本次使用oradebug進行事件跟蹤。

SQL> oradebug setmypid;

已處理的語句

SQL> oradebug unlimit;

已處理的語句

SQL> oradebugevent 10046 trace name context forever, level 12

已處理的語句

SQL> select scott.seq_nocache.nextval from dual;

  NEXTVAL

----------

        9

 

SQL> select scott.seq_nocache.nextval from dual;

  NEXTVAL

----------

       10

 

SQL> select scott.seq_nocache.nextval from dual;

  NEXTVAL

----------

       11

 

SQL> select scott.seq_cache.nextval from dual;

  NEXTVAL

----------

        9

 

SQL> select scott.seq_cache.nextval from dual;

  NEXTVAL

----------

       10

 

SQL> select scott.seq_cache.nextval from dual;

  NEXTVAL

----------

       11

 

SQL> oradebug event 10046 trace name context off;

已處理的語句

 

SQL> oradebug tracefile_name

c:\tool\oracle\oracle\product\10.2.0\admin\ots\udump\ots_ora_5932.trc

 

 

打開跟蹤文件,我們首先分析nocache的幾次調用片段。

 

--篇幅原因,本部分有省略;

=====================

PARSING IN CURSOR #1 len=42 dep=0 uid=0 ct=3 lid=0 tim=16143418536 hv=311402377 ad='248b5c60'

select scott.seq_nocache.nextval from dual–第一次調用nocache

END OF STMT

PARSE #1:c=0,e=110,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16143418526

BINDS #1:

EXEC #1:c=0,e=13893,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16143450260

WAIT #1: nam='SQL*Net message to client' ela= 8 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16143453714

=====================

PARSING IN CURSOR #2 len=129 dep=1 uid=0 ct=6 lid=0 tim=16143457545 hv=2635489469 ad='2891ff84'

update seq$ set increment$=:2,minvalue=:3,maxvalue=:4,cycle#=:5,order$=:6,cache=:7,highwater=:8,audit$=:9,flags=:10 where obj#=:1–第一次循環遞歸;

END OF STMT

PARSE #2:c=0,e=129,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=16143457535

BINDS #2:

kkscoacd

 Bind#0

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c69dc bln=24 avl=02 flg=09

 value=1

 Bind#1

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c69ee bln=24 avl=02 flg=09

 value=1

 Bind#2

 oacdty=02 mxl=22(15) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c6a00 bln=24 avl=15 flg=09

 value=999999999999999999999999999

 Bind#3

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cefb8 bln=24 avl=01 flg=05

 value=0

 Bind#4

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cef94 bln=24 avl=01 flg=05

 value=0

 Bind#5

 oacdty=02 mxl=22(01) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c6a12 bln=24 avl=01 flg=09

 value=0

 Bind#6

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c6a24 bln=24 avl=02 flg=09

 value=10

 Bind#7

  oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=01 csi=852 siz=32 ff=0

 kxsbbbfp=248c6a36 bln=32 avl=32 flg=09

 value="--------------------------------"

 Bind#8

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cef70 bln=24 avl=02 flg=05

 value=8

 Bind#9

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cefdc bln=22 avl=04 flg=05

 value=113487

(有省略……)

 

=====================

PARSING IN CURSOR #2 len=42 dep=0 uid=0 ct=3 lid=0 tim=16145504123 hv=311402377 ad='248b5c60'

select scott.seq_nocache.nextval from dual–第二次調用

END OF STMT

PARSE #2:c=0,e=50,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16145504114

BINDS #2:

EXEC #2:c=15625,e=4237,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16145528418

WAIT #2: nam='SQL*Net message to client' ela= 8 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16145532367

=====================

PARSING IN CURSOR #1 len=129 dep=1 uid=0 ct=6 lid=0 tim=16145536517 hv=2635489469 ad='2891ff84'

update seq$ set increment$=:2,minvalue=:3,maxvalue=:4,cycle#=:5,order$=:6,cache=:7,highwater=:8,audit$=:9,flags=:10 where obj#=:1

END OF STMT

PARSE #1:c=0,e=49,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=16145536507

BINDS #1:

kkscoacd

 (……)

 Bind#6

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c6a24 bln=24 avl=02 flg=09

 value=11

 Bind#7

 oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=01 csi=852 siz=32 ff=0

 kxsbbbfp=248c6a36 bln=32 avl=32 flg=09

 value="--------------------------------"

 Bind#8

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cef70 bln=24 avl=02 flg=05

 value=8

 Bind#9

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cefdc bln=22 avl=04 flg=05

 value=113487

 

=====================

PARSING IN CURSOR #1 len=42 dep=0 uid=0 ct=3 lid=0 tim=16147403782 hv=311402377 ad='248b5c60'

select scott.seq_nocache.nextval from dual–第三次調用

END OF STMT

=====================

PARSING IN CURSOR #2 len=129 dep=1 uid=0 ct=6 lid=0 tim=16147424639 hv=2635489469 ad='2891ff84'

update seq$ set increment$=:2,minvalue=:3,maxvalue=:4,cycle#=:5,order$=:6,cache=:7,highwater=:8,audit$=:9,flags=:10 where obj#=:1

END OF STMT

PARSE #2:c=0,e=43,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=16147424633

BINDS #2:

kkscoacd

 

Bind#6

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c6a24 bln=24 avl=02 flg=09

 value=12

 Bind#7

 oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=01 csi=852 siz=32 ff=0

 kxsbbbfp=248c6a36 bln=32 avl=32 flg=09

 value="--------------------------------"

 Bind#8

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cef70 bln=24 avl=02 flg=05

 value=8

 Bind#9

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cefdc bln=22 avl=04 flg=05

 value=113487

 

 

 

注意三次調用過程中的幾個標注紅色的部分。三次調用nextval,之后都存在一個遞歸調用更新seq$基表的過程。Seq$基表顯然是記錄系統sequence的數據字典表。更新信息雖然包括了所有字段,但是bind#6和bind#9需要額外注意。

 

Bind#6在undate語句中對應字段highwater,顯然是表示當前sequence對象達到的最大數值,也就是更新之后的修改值。Bind#9表示的obj#編號,應該對應的11387就是我們的nocache實驗sequence編號。

SQL> select object_type, object_id from dba_objects where wner='SCOTT' and object_name='SEQ_NOCACHE';

OBJECT_TYPE         OBJECT_ID

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

SEQUENCE               113487

 

說明,在沒有cache的情況下,每次調用nextval都會促使Oracle去更新且commit數據字典seq$記錄。

 

那么,對cache的sequence而言,又是如何呢?

 

 

PARSING IN CURSOR #2 len=40 dep=0 uid=0 ct=3 lid=0 tim=16156274459 hv=1095976807 ad='24882bec'

select scott.seq_cache.nextval from dual–第一次調用

END OF STMT

PARSE #2:c=0,e=67,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16156274454

BINDS #2:

EXEC #2:c=0,e=84,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16156274601

WAIT #2: nam='SQL*Net message to client' ela= 6 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16156274643

FETCH #2:c=0,e=46,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=16156274725

WAIT #2: nam='SQL*Net message from client' ela= 568 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16156275360

FETCH #2:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=16156275411

WAIT #2: nam='SQL*Net message to client' ela= 2 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16156275445

WAIT #2: nam='SQL*Net message from client' ela= 2197902 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16158473393

STAT #2 id=1 cnt=1 pid=0 pos=1 bj=113488 p='SEQUENCE SEQ_CACHE (cr=0 pr=0 pw=0 time=57 us)'

STAT #2 id=2 cnt=1 pid=1 pos=1 bj=0 p='FAST DUAL (cr=0 pr=0 pw=0 time=8 us)'

=====================

PARSING IN CURSOR #1 len=40 dep=0 uid=0 ct=3 lid=0 tim=16158473685 hv=1095976807 ad='24882bec'

select scott.seq_cache.nextval from dual–第二次調用;

END OF STMT

PARSE #1:c=0,e=36,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16158473680

BINDS #1:

EXEC #1:c=0,e=73,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16158473813

WAIT #1: nam='SQL*Net message to client' ela= 5 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16158473855

=====================

PARSING IN CURSOR #2 len=129 dep=1 uid=0 ct=6 lid=0 tim=16158474024 hv=2635489469 ad='2891ff84'

update seq$ set increment$=:2,minvalue=:3,maxvalue=:4,cycle#=:5,order$=:6,cache=:7,highwater=:8,audit$=:9,flags=:10 where obj#=:1

END OF STMT

PARSE #2:c=0,e=30,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=16158474020

BINDS #2:

kkscoacd

 Bind#0

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c58a0 bln=24 avl=02 flg=09

 value=1

 Bind#1

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c58b2 bln=24 avl=02 flg=09

 value=1

 Bind#2

 oacdty=02 mxl=22(15) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c58c4 bln=24 avl=15 flg=09

 value=999999999999999999999999999

 Bind#3

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cefb8 bln=24 avl=01 flg=05

 value=0

 Bind#4

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cef94 bln=24 avl=01 flg=05

 value=0

 Bind#5

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c58d6 bln=24 avl=02 flg=09

 value=3

 Bind#6

 oacdty=02 mxl=22(02) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=248c58e8 bln=24 avl=02 flg=09

 value=13

 Bind#7

  oacdty=01 mxl=32(32) mxlc=00 mal=00 scl=00 pre=00

 oacflg=18 fl2=0001 frm=01 csi=852 siz=32 ff=0

 kxsbbbfp=248c58fa bln=32 avl=32 flg=09

 value="--------------------------------"

 Bind#8

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cef70 bln=24 avl=02 flg=05

 value=8

 Bind#9

 oacdty=02 mxl=22(22) mxlc=00 mal=00 scl=00 pre=00

 oacflg=08 fl2=0001 frm=00 csi=00 siz=24 ff=0

 kxsbbbfp=088cefdc bln=22 avl=04 flg=05

 value=113488

 

=====================

PARSING IN CURSOR #2 len=40 dep=0 uid=0 ct=3 lid=0 tim=16160280316 hv=1095976807 ad='24882bec'

select scott.seq_cache.nextval from dual–第三次調用

END OF STMT

PARSE #2:c=0,e=38,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16160280311

BINDS #2:

EXEC #2:c=0,e=77,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=16160280449

WAIT #2: nam='SQL*Net message to client' ela= 6 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16160280593

FETCH #2:c=0,e=51,p=0,cr=0,cu=0,mis=0,r=1,dep=0,og=1,tim=16160280682

WAIT #2: nam='SQL*Net message from client' ela= 643 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16160281398

FETCH #2:c=0,e=3,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=0,tim=16160281451

WAIT #2: nam='SQL*Net message to client' ela= 3 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16160281482

*** 2012-02-23 13:30:07.421

WAIT #2: nam='SQL*Net message from client' ela= 14238981 driver id=1413697536 #bytes=1 p3=0 obj#=-1 tim=16174520496

STAT #2 id=1 cnt=1 pid=0 pos=1 bj=113488 p='SEQUENCE SEQ_CACHE (cr=0 pr=0 pw=0 time=52 us)'

STAT #2 id=2 cnt=1 pid=1 pos=1 bj=0 p='FAST DUAL (cr=0 pr=0 pw=0 time=10 us)'

 

 

 

在三次調用中,只更新了一次seq$數據字典表。而且,更新的bind#6為13,實際上就是一次更新,多取出三個取值。以后的幾次調用中,就不需要在更新該數據記錄了。

 

由此,我們可以得到結論,無論對於cache還是nocache序列對象,都是存在更新數據字典表seq$的動作的。區別就是在於更新bind#6 highwater的頻度和一次更新步長。

 

進一步想,如果我們處在一個高並發的情況下,系統頻繁的多會話請求sequence取值。如果我們的sequence沒有設置cache,那么每次都要更新數據字典,都要進行commit操作。多個會話還會出現該sequence記錄的爭用,出現等待事件row lock contention。

 

所以,一般情況下,我們建議設置一個較大的cache值,用於進行性能的優化。

 

4、寫在后面的話

 

本篇解析了在單實例環境下,cache對於sequence的重要性。在RAC環境下,cache和noorder選項的作用更大。在RAC中,多個實例爭用情況會讓sequence設計的不合理效果放大。所以,在沒有特殊情況下,還是設置合理的cache值,減少系統潛在性能瓶頸。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM