1. 程式人生 > >RAC 環境下序列不同步的問題

RAC 環境下序列不同步的問題

具體的說解決辦法有2個: 1.設定cache 的值為空,(通過PLSQL檢視顯示為0); 2.建立序列的時候,增加order屬性,使用cache+order屬性 ; oracle為了在rac環境下為了sequence的一致性,使用了三種鎖:row cache lock、SQ鎖、SV鎖。 row cache lock的目的是在sequence指定nocache的情況下呼叫sequence.nextval過程中保證序列的順序性; cache引數告訴oracle預先分配一個sequence numbers的集合,並且保留在記憶體中,以便sequence number能夠被快速的訪問。這個記憶體的大小就是cache所指定的大小,當多個使用者同時訪問一個sequence的時候,是在oracle SGA中讀取sequence當前的合理數值,如果併發訪問太大,cache的大小不夠,那麼就會產生sequence cache相關的等待(enq: SQ - contention),影響系統性能。 在RAC多節點環境下,Sequence的Cache屬性對效能的影響很大。應該儘量賦予cache+noorder屬性,並要給予足夠的cache值。(這種情況就造成了今天廣西的這種情況) 如果需要保障順序,必須賦予cache+order屬性。但這時為了保障順序,例項之間需要不斷的交換資料。因此效能稍差。 本文除了講述oracle sequence的一般用法外,還著重說明了sequence在rac環境中容易引起的效能問題和分析解決方法。 sequence的概念及作用
sequence是用來在多使用者環境下產生唯一整數的資料庫物件。序列產生器順序生成數字,它可用於自動生成主鍵值,並能協調多行或者多表的主鍵操作。沒有sequence,順序的值只能靠編寫程式來生成。先找出最近產生的值然後自增長。這種方法要求一個事務級別的鎖,這將導致在多使用者併發操作的環境下,必須有人等待下一個主鍵值的產生。而且此方法很容易產生主鍵衝突的錯誤,如下圖:
time a......trans1 begin.........................................................
 |
 取max value=5 
 |
time b...... max value+1=6........trans2 begin.....................
 |  |
 other action max value=5
 |  |
time c..... commit;  max value+1=6
   |
   commt(ora-00001)
如上圖,事務2會報主鍵衝突的錯誤,而再重新整理一下頁面(再執行一邊程式),可能就正常了。
還有一個問題,那就是完成生成主鍵的程式(一般情況包含plsql塊)本身對於併發呼叫也是一個瓶頸,因為這樣的程式段往往是提供給好多程式去呼叫,如果程式碼端寫的不夠優化(比如沒有使用邦定變數等等),或者此程式碼段存在問題,那麼它所影響的是系統的全域性。我們應該提倡開發人員使用sequence。sequence消除了序列化問題,而且改善了應用的併發能力。 建立sequence
sequence的命名最重要的是要統一,命名規則是次要的。
 CREATE SEQUENCE emp_sequence
      INCREMENT BY 1
      START WITH 1
      NOMAXVALUE
      NOCYCLE
      CACHE 10;
這裡需要重點說明的是cache引數,它是為了應對併發訪問的。cache引數告訴oracle預先分配一個sequence numbers的集合,並且保留在記憶體中,以便sequence number能夠被快速的訪問。這個記憶體的大小就是cache所指定的大小,當多個使用者同時訪問一個sequence的時候,是在oracle SGA中讀取sequence當前的合理數值,如果併發訪問太大,cache的大小不夠,那麼就會產生sequence cache相關的等待(enq: SQ - contention),影響系統性能。
既然cache涉及到了記憶體,那麼就會想到oracle例項恢復的問題。如果資料庫shutdown abort,sequence會如何呢?當然會有問題,sequence number儲存在記憶體裡的但是沒有被應用到表中的會丟失! 修改sequence
除了修改sequence的starting number,你什麼都能改,如果想改starting number,只能先drop然後create。
ALTER SEQUENCE emp_sequence
    INCREMENT BY 10
    MAXVALUE 10000
    CYCLE
    CACHE 20;
修改很有用,最典型的情況是“需要把sequence 的current value改大一點,避免程式報錯!”。你就可以看看current value是多少,然後修改increment by 足夠大的值,然後執行.nextval,最後別忘了再將increnent by改成原來的值,還要注意做這些工作的前提是當前沒有人用此sequence。 使用 sequence
CURRVAL 和 NEXTVAL 能夠在以下情況使用:
insert的values字句、select中的select列表、update中的set字句
CURRVAL 和 NEXTVAL 不能夠在以下情況使用:
子查詢、檢視和實體化檢視的查詢、帶distinct的select語句、帶group by和order by的select語句、帶union或intersect或minus的select語句、select中的where字句、create table與alter table中的default值、check約束條件。 刪除sequence
drop sequence seq_a;
當刪除sequence後,對應它的同義詞會被保留,但是引用時會報錯。 oracle rac環境中的sequence
oracle為了在rac環境下為了sequence的一致性,使用了三種鎖:row cache lock、SQ鎖、SV鎖。
row cache lock的目的是在sequence指定nocache的情況下呼叫sequence.nextval過程中保證序列的順序性;
SQ鎖是應用於指定了cache+noorder的情況下呼叫sequence.nextval過程中。
SV鎖(dfs lock handel) 是呼叫sequence.nextval期間擁有的鎖。前提是建立sequence時指定了cache 和order屬性 (cache+order)。order引數的目的是為了在RAC上節點之間生成sequence的順序得到保障。 建立sequence賦予的cache值較小時,有enq:sq-contention等待增加的趨勢。
cache的預設值是20.因此建立併發訪問多的sequence時,cacheh值應取大一些。否則會發生enq:sq-contention等待事件。 rac上建立sequence時,如果指定了cache大小而賦予noorder屬性,則各節點將會把不同範圍的sequence值cache到記憶體上。若兩個節點之間都必須通過依次遞增方式使用sequence,必須賦予如下的order屬性(一般不需要這樣做)
sql> create sequence seq_b cache 100 order;
如果是已賦予了cache+order屬性的sequence,oracle使用SV鎖進行同步。SV鎖爭用問題發生時的解決方法與sq鎖的情況相同,就是將cache 值進行適當調整。 在RAC多節點環境下,Sequence的Cache屬性對效能的影響很大。應該儘量賦予cache+noorder屬性,並要給予足夠的cache值。如果需要保障順序,必須賦予cache+order屬性。但這時為了保障順序,例項之間需要不斷的交換資料。因此效能稍差。