◆ 언두 데이터 관리
  - 언두 데이터 관리법에는 Auto와 Manual이 있다.
  - 8i까지는 언두 세그먼트를 롤백 세그먼트라 불렀다.(8i까지는 수동으로 DBA가 직접 관리)
  - 적어도 하나의 언두 테이블스페이스는 존재해야 한다.
  - 우리가 건드릴 수 있는 것은 오직 Non-System 언두 세그먼트 뿐이다.


◆ 언두 세그먼트의 목적
  - 트랜잭션 롤백
  - 읽기 일관성
  - 트랜잭션 복구


◆ 언두와 관련된 파라미터
  - UNDO_MANAGEMENT : 언두 세그먼트 관리를 자동인지 수동인지 결정.(AUTO or MANUAL)
  - UNDO_TABLESPACE : 현재 시스템의 언두 테이블스페이스명 지정.
  - UNDO_RETENTION : 커밋된 후에도 어느 일정시간동안은 언두 데이터를 덮어쓰지 않도록 보장하기 위한 시간.(단위:초)


◆ 언두 세그먼트 정보 조회와 관련된 데이터 딕셔너리와 동적성능뷰
  - DBA_ROLLBACK_SEGS
  - V$ROLLNAME
  - V$ROLLSTAT
  - V$UNDOSTAT
  - V$SESSION
  - V$TRANSACTION


◆ DML의 순서
  ① 언두 세그먼트 확보
  ② 리두로그에 기록
  ③ 언두 세그먼트에 기록
  ④ DB캐시에 기록

DB를 생성하면 기본적으로 10개의 언두 세그먼트가 만들어진다.(_SYSSMU1$ ~ _SYSSMU10$)


A사용자가 홍길동을 일지매로 바꾸려는 update문을 날렸을 때 먼저 언두 세그먼트를 확보해야 하는데 만약 확보를 하지 못했다면 update문은 에러가 난다.
A사용자가 아직 커밋을 날리지 않은 상태에서 B사용자가 접속하면 2번 언두 세그먼트를 확보한다. B사용자 또한 아직 커밋을 날리지 않았다면, C사용자는 3번 언두 세그먼트를 확보한다.
A사용자가 커밋 날리면 그다음 들어오는 D사용자는 1번 언두 세그먼트를 사용할 수 있다.
F사용자가 들어왔는데 시스템의 모든 언두 세그먼트가 사용중이라면 F사용자가 날리는 DML은 모두 에러난다.

8i까지만 해도 DBA가 갯수를 고려해 언두 세그먼트를 일일이 다 만들어줘야 했다. 굉장히 불편한 일이었다.
9i부터는 자동으로 오라클이 언두 세그먼트를 관리해준다. (Automatic Undo Management)

언두 세그먼트에는 바뀌기 이전 값이 들어가있는데, 커밋을 날리면 언두 세그먼트의 내용이 바로 지워진다고 생각하지만 그렇지 않다.
A사용자가 홍길동에서 일지매로 바꾸는 DML문을 날렸을 때 언두 세그먼트에는 홍길동이 들어있다. 커밋을 날리면 언두 세그먼트에 있는 홍길동이 바로 지워지지는 않는다. 다른 사용자가 작업을 하여 만약 언두 세그먼트에 있는 홍길동 데이터가 덮어씌여졌다면 모르나, 아직 덮어씌여지지 않았다면 나중에 배울 플래시백을 통해 복구 가능하다.
당연한 얘기지만 커밋을 안하면 언두 세그먼트에 있는 A사용자가 변경하기 이전 값은 누구도 덮어쓸 수 없다.


◆ 트랜잭션 복구
홍길동을 일지매로 바꾸는 1000건을 update하고 커밋을 한번도 날리지 않은 상태에서 서버가 정전이 되어 꺼져버리는 사태가 발생했다. 이후 다시 서버를 켜면 데이터는 홍길동일까 일지매일까?

1번 터미널
create table gg (name varchar2(10));

insert into gg values ('hong');

commit;

update gg set name='ill';

select * from gg;        // 홍길동이 일지매로 바뀐 것을 검색. 커밋은 안날린 상태.

2번 터미널
shutdown abort;         // 정전과 같은 사태 발생시킴.

1번 터미널
select * from gg;        // 서버가 강제종료되어 에러남.

2번 터미널
startup                       // SMON이 인스턴스 복구를 수행하기 때문에 시간이 조금 걸림

1번 터미널
select * from gg;         // 홍길동 결과가 나옴. 즉, 커밋하지 않은 데이터는 모두 롤백됨.


◆ 롤포워드와 롤백
100을 500으로 변경하는 update문을 날리고 커밋을 날리지 않은 상태에서 서버가 강제종료 되었다가 다시 켰을 때 커밋되지 않은 데이터가 어떻게 되는지 과정을 알아보자.

① 일단 오라클은 커밋된 것과 커밋되지 않은 것의 구분 없이 무조건 리두로그파일에 있는 기록내용을 전부 다 데이터파일로 들이붓는다. 그렇게 해놓고 일단 DB를 오픈상태까지 올린다.
② 언두 세그먼트에 데이터가 있다는 것은 아직 커밋이 되지 않았다는 것이므로 언두 세그먼트에 있는 것을 데이터파일에 덮어쓴다.

결과적으로 커밋되지 않은 데이터는 원래의 값으로 돌아가고 커밋된 데이터는 변경된 값으로 돌아가게 된다.



◆ 언두 세그먼트와 Temporary 테이블스페이스의 공통점
  - 여러 개를 만들 수 있다.

◆ 언두 세그먼트와 Temporary 테이블스페이스의 차이점
  - Temporary 테이블스페이스는 여러개를 만들어놓고 동시에 여러개 사용 가능하다.
  - 하지만 언두 세그먼트는 동시에 여러개를 쓸 수 없다.

언두 세그먼트의 특징은 늘어나는 건 되는데 반대로 줄어드는 건 안된다.
일반 데이터파일은 사용량을 줄일 수 있는데, 언두 데이터파일은 줄일 수 없다.
왜 줄일 수 없을까?
처음에 언두 데이터파일을 100M 만들어놓고 autoextend on 옵션을 줬다고 하자. 사용자 1명이 붙으면 1M가 사용된다고 할 때 사용자 만명이 동시에 붙으면 언두 사이즈가 10G가 되버린다.
이후 사용자가 줄어 10명까지 동시에 쓴다고 하면 실제 10M 사용량 이외의 용량은 낭비이다.
그럴때는 10M 용량의 언두를 새로 만들어 놓고, 10G 언두는 삭제해주어야 한다. 이것이 DBA가 해야 할 일 중 하나이다.


◆ 사용 중에 언두 테이블스페이스 변경



◆ Snapshot too old 에러에 대하여...


A사용자의 쿼리가 11시에 결과가 나왔는데 그때 10번 사원의 급여가 원래 급여인 2000이 계산되어 나왔을까, 바뀐 급여인 3000이 계산되어 나왔을까?
답은 2000이 나오든지, 아니면 snapshot too old 에러가 난다.
이유는 무엇일까?

A사용자의 서버프로세스는 10시 시점에 sum(sal)을 구하는 쿼리가 실행되면 10시 시점에 불러와져야 할 데이터의 SCN을 기억하여 블록을 읽을 때마다 SCN검사를 하여 맞는 것만을 끌어올린다. 10시 시점의 SCN을 100이라 하자. 잘 읽고 있다가 마지막 블록에 10번 사원의 2000값이 B사용자의 쿼리에 의해 3000으로 바뀌어버렸다. 그리고 커밋을 수행했으니 SCN이 100이 아닌 더 큰값으로 바뀌어버렸다.
A사용자의 서버프로세스는 10번 사용자의 급여값을 읽으려 하는데 이미 DB캐시에 올라와져 있으므로 DB캐시로 가서 SCN을 본다. 그러나 이미 커밋이 날려졌으므로 이전 값인 2000은 언두 세그먼트에 저장되어 있을 것이다. 그래서 언두세그먼트로 가서 만약 운이 좋아서 2000값이 아직 덮어씌여지지 않았다면 그 2000값을 가져와서 sum을 계산한다. 하지만 덮어씌여졌다면 snapshot too old 에러를 띄운다.

이 snapshot too old 에러는 이뿐만 아니라 여러가지 경우에도 자주 일어나는 에러이다.

위 상황과는 별도로 한가지 예를 더 살펴보자.
A사용자가 100만건을 update하는 쿼리를 수행하면 DB캐시에 변경된 100만건이 들어있을 것이다. 사용자B가 100만건을 select하려 하면 언두 세그먼트에서 바뀌기 전 before image를 CR블록으로 복사할 것이다. 그런데 워낙 100만건의 방대한 데이터라서 CR블록으로 복사하는데만도 시간이 오래 걸리는 상황이다.
조금만 더 기다리면 CR블록으로 복사가 끝마치는 상황인데, A사용자가 그전에 커밋을 날려버린 것이다. 그러면 그때까지 끌어올려지던 CR블록은 바보가 되어버린다...
또한 커밋을 했기 때문에 이후에 다른 사용자에 의해 100만건의 before image가 덮어씌여질 수 있다. 이때도 snapshot too old 에러가 발생한다.

그래서 커밋을 날렸더라도 일정시간은 언두 데이터를 덮어쓰지 않고 기다려달라고 하는 UNDO_RETENTION 파라미터가 있는 것이다.


◆ 언두 테이블스페이스 생성

SQL> create undo tablespace 테이블스페이스명
   datafile '데이터파일명'
   size 크기
   autoextend on;


◆ 언두 테이블스페이스에 데이터파일 추가

SQL> alter tablespace 테이블스페이스명
   add datafile '데이터파일명'
   size 크기
   autoextend on;


◆ 언두 테이블스페이스 지정

SQL> alter system set undo_tablespace=언두테이블스페이스명;


◆ 언두 테이블스페이스 삭제

SQL> drop tablespace 언두테이블스페이스명;


◆ 언두 세그먼트 조회 쿼리

SQL> select segment_name, owner, tablespace_name, status
   from dba_rollback_segs;


 

'오라클 > Admin' 카테고리의 다른 글

[Admin] Extent와 Block과의 관계  (0) 2010.09.02
[Admin] Rowid  (0) 2010.09.02
[Admin] ASSM(Automatic Segment Space Management)  (0) 2010.09.01
[Admin] Database Block  (0) 2010.09.01
[Admin] Types of Segments  (0) 2010.09.01
Posted by 겨울섬
,