ORACLE 11g SEQUENCE v1.0
13.04.17 |
1.0 |
|
|
|
|
|
|
|
1. SEQUENCE
시퀀스는 순서대로 증가하는 혹은 감소하는 숫자이다.
보통 유니크한 값으로 사용하며 특수한 경우 (CYCLE 옵션) 를 제외하고 이 값이 중복 될 일은 없다.
2. SEQUENCE OPTIONS
11g 기준으로 ‘create sequence’ 에 다음과 같은 옵션을 사용할 수 있다.
MINVALUE | NOMINVALUE ( 1, default)
CYCLE | NOCYCLE (default)
CACHE (20, default) | NOCACHE
ORDER | NOORDER (default)
[NO]MINVALUE 값은 값의 최저하한을 두는 옵션인데 실상 START WITH 를 사용하는 것과 차이가 느껴지지 않는다.
차이가 발생하는 부분은 CYCLE 을 사용하여 값이 상한을 찍고 최저값으로 돌아가는 상황이다.
CYCLE 은 MAXVALUE 와 함께 사용하는 옵션으로 시퀀스를 최대값까지 다 사용하면 최저값으로 돌아간다.
이 값은 NOMINVALUE 즉 1 이다. MAXVALUE 가 5에 CYCLE 옵션을 사용하는 시퀀스라면 … 3,4,5,1 … 이 된다.
ORDER 는 시퀀스를 요청한 순서가 빠르면 빠른 시퀀스를 얻는걸 보장한다는 것이다. ORDER 와 연관된 이슈는 RAC 환경의
CACHED SEQUENCE 에서 기인한다.
3. TEST
<MINVALUE>
MINVALUE <= START WITH < MAXVALUE 를 만족해야 한다.
위에 대한 확인은 다음과 같이 할 수 있다.
SYS|[TMALL1] OMDBTEST1 >create sequence sys.test start with 10 minvalue 15 increment by 1; create sequence sys.test start with 10 minvalue 15 increment by 1 * ERROR at line 1: ORA-04006: START WITH cannot be less than MINVALUE
SYS|[TMALL1] OMDBTEST1 >create sequence sys.test start with 1 minvalue 10 increment by 1 maxvalue 5; create sequence sys.test start with 1 minvalue 10 increment by 1 maxvalue 5 * ERROR at line 1: ORA-04004: MINVALUE must be less than MAXVALUE |
앞서 이야기 했듯이 MINVALUE 는 CYCLE 을 사용하는 케이스가 아니면 사용할 일이 없다.
Default NOMINVALUE 가 1 값을 가지기 때문에 MINVALUE 지정을 안 한 상태에서 CYCLE 을 사용하는
시퀀스가 MAXVALUE 까지 사용하면 그 다음 값이 1로 돌아간다.
<CYCLE>
NOCYCLE 의 경우 값을 MAXVALUE 까지 사용하면 끝이다.
만약 호출하는 경우 다음과 같이 에러가 발생한다.
SYS|[TMALL1] OMDBTEST1 >/ select test.nextval from dual * ERROR at line 1: ORA-08004: sequence TEST.NEXTVAL exceeds MAXVALUE and cannot be instantiated |
반면 CYCLE 을 이용하는 경우 MAXVALUE 이후 MINVALUE (지정한 경우) 나 1 (MINVALUE 지정하지 않은 경우) 값으로
돌아간다.
<RAC:CACHE>
SEQUENCE 는 Default 로 CACHE 옵션을 사용하며 그 값은 20 이다.
CACHE 는 사용할 값을 메모리에 가져다 놓는 걸 말하는데 이로인해 RAC 환경에서는 다음과 같은 현상이 일어난다.
l CACHE 가 5인 시퀀스 생성 ( 1부터 시작)
l NODE1 에서 NEXTVAL
l NODE2 에서 NEXTVAL
위 결과는 NODE1 -> 1, NODE2 -> 6 이다.
NODE1 에서 최초 호출한 순간 CACHE SIZE 5 만큼 가져가고 (1~5),
NODE2 에서 다시 호출한 순간 마찬가지로 CACHE SIZE 5만큼 가져간다 (6~10)
위 상황에서 NODE2 가 시퀀스 캐시를 다 소모하고 11을 호출하면 (11~15) 값을 가져가고,
NODE1 에서 (1~5) 를 다 소모하고 다음 호출을 하면 16 을 반환한다.
위와 같이 각 노드가 자신이 사용할 시퀀스를 캐시사이즈 만큼 배타적으로 가져가기 때문에
다음과 같은 결과를 얻을 수 있다.
l Insert 이후 바로 commit 함
l 1 > 2 > 1 노드 에 대해 Insert + commit
l ID1 값은 시퀀스.NEXTVAL
l ID2 값은 시분초 값임
ID1 ID2 ---------- ------------------------------ 1 152145 6 152310 2 152506 |
1 > 2 > 1 로 INSERT 를 했기 때문에 사용자는 1,2,3 으로 정렬된 시퀀스를 가져가기 원할 수 있다.
이러한 요구가 있기 때문에 NOCACHE 나 ORDER 를 사용하게 된다.
<RAC:NOCACHE>
NOCACHE 는 문자 그대로 메모리에 시퀀스를 캐싱하지 않겠다는 이야기다.
미래에 사용할 시퀀스를 미리 캐시하지 않기에 사용 요청을 받을때마다 하나씩 반환한다.
그래서 앞서 살펴 본 먼저 들어온 요청이 더 늦게 들어온 요청의 시퀀스보다 뒤쳐지는 현상을 회피할 수 있다.
그러나 위와 같이 순서를 보장하겠다고 호출이 빈번한 시퀀스를 NOCACHE 로 사용하게 되면 row cache lock 경합이 발생한다.
위 경합이 바람직하지 않다는 것은 SEQUENCE 생성 시 default 가 CACHE 20 인 것을 생각해봐도 나온다.
<RAC:ORDER + CACHE>
ORDER 는 앞서 살펴 본 CACHE 에서의 문제, 먼저 호출된 시퀀스가 앞서는 번호를 가져가길 원하는 경우 (즉 정렬된 값) 사용한다.
이 부분까지만 보면 NOCACHE 와 동일하지만 시퀀스를 미리 캐싱해 둔다는게 특징이다.
RAC:CACHE 동일 환경으로 1 > 2 > 1 노드에 대해 INSERT 하는 경우 다음과 같은 결과를 얻는다.
ID1 ID2 ---------- ------------------------------ 1 153744 2 153923 3 154046 |
ID1 = 2 인 값은 NODE2 에서 수행된 값이며 본디 CACHE 만 사용한 경우 값이 6이 들어와야 한다.
하지만 ORDER 옵션을 써서 사용자가 원하는 정렬된 값을 얻었다. (NOCACHE 와 동일한 효과)
다만 NOCACHE 경우보다는 낫다고는 하나 타 노드에서 캐싱되어 있는 시퀀스 값을 메모리를 뒤져 가져가야 하는 부하가 있기에
빈번한 호출에는 사용해서는 안 된다.
<RAC:ALTER CACHE SIZE>
Sequence 를 사용하는 와중에 CACHE SIZE 를 변경하는 경우를 가정한다.
(cache 2) > 1 > 2 > (cache 4) > 1 > 2
CACHE2 로 생성하여 node1 에서 NEXTVAL, 마찬가지로 NODE2
이후 CACHE 를 4로 변경해서 NODE1, NODE2 에서 순차적으로 NEXTVAL 을 수행해 보았다.
위와 같이 cache 2 상태에서 1,2 노드에서 nextval 을 호출하면 1번노드에서는 1, 2번 노드에서는 3을 보게 된다.
이 상태에서 cache size 를 4로 변경하고 다시 1, 2를 호출하면 나오는 값은 5, 9 이 된다.
이는 기존의 cached 값이 버려졌기 때문이다.
기존에 1번 노드에서 캐싱한 값이 (1,2), 2번 노드에서 캐싱한 값이 (3,4) 인 상태에서 alter 후 시퀀스 호출했을 때 5가 나왔다는 건
2,4 값이 버려졌다는 것을 의미한다.
캐시사이즈가 4로 변경되었기에 1번 노드는 (5,6,7,8) 을 가지게 되고 2번 노드는 (9,10,11,12) 를 가지게 된다.
4. REFERENCES
A. CREATE SEQUENCE | B28286-06