Undo란?
- 8i까지는 롤백(rollback)이라는 용어를 사용.
롤백 세그먼트를 생성하고 ONLINE/OFFLINE의 상태변경 등의 작업을 DB관리자가 수동으로 관리했고, rollback_segments 파라미터에 의해 개수 고정.
롤백 세그먼트를 더 이상 확장할 수 없을 때 곧바로 ORA-01562 에러 발생.
- 9i부터 오라클사는 공식 문서에 Undo라는 용어를 사용.
AUM(Automatic Undo Management)기능 도입.
Undo 세그먼트마다 하나의 트랜잭션이 할당되는 것을 목표로 세그먼트 개수를 오라클이 자동 관리.
트랜잭션에 독립적으로 할당해 줄 Undo 세그먼트가 없을 때는(Online으로 전환할 수 있는 Offline 세그먼트가 없고 새로운 Undo 세그먼트를 생성할
공간도 부족할 때)8i에서처럼 가장 적게 사용되는 Undo 세그먼트 중 하나를 할당.
Undo 세그먼트를 더 이상 확장할 수 없을 때 다른 Undo 세그먼트로부터 Free Undo Space를 가져 올 수 있으며(Dynamic Extent Transfer),
Undo 테이블스페이스 내에 있는 모든 Undo Space를 소진했을때 비로소 에러 발생.
- Undo 세그먼트의 구조는 일반 테이블 세그먼트와 같다.(익스텐트 단위로 확장, 버퍼 캐시에 캐싱, 변경사항을 Redo로그에 로깅)
- 다른 점이라면 Undo 세그먼트에 저장하는 내용이다.
각 트랜잭션 별로 Undo 세그먼트를 할당(두 개이상의 트랜잭션이 하나의 Undo 세그먼트를 할당받아 같이 사용할 수 있음)해 주고
그 트랜잭션이 발생시킨 테이블과 인덱스의 변경사항들을 Undo 레코드 단위로 Undo 세그먼트 블록에 기록한다.
Undo 의 목적
목적 | 설명 |
---|
Transaction Rollback | 최종 커밋하지 않고 롤백하고자 할 때 Undo 데이터 이용 |
Transaction Recovery(instance Recovery시 rollback 단계) | Instance Crash 발생 후 Redo를 이용해 Roll forward 단계가 완료되면 최종 커밋되지 않은 변경사항까지 모두 복구. |
Read Consistency | 읽기 일관성을 위해 사용.(다른DB는 Lock을 통해 읽기 일관성을 구현) |
(1). Undo 세그먼트 트랜잭션 테이블 슬롯
Transaction Table Slot
컬럼 | 내용 | 비고 |
---|
Transaction ID | USN# + Slot# + Wrap# | USN : Undo Segment Number |
Transaction Status | 상태정보 | COMMITTED, ACTIVE |
Commit SCN | | 트랜잭션이 커밋된 경우 |
Last UBA | Undo 레코드 체인을 유지하는 일종의 포인터 | UBA: Undo Block Address |
기타 | | |
트랜잭션의 시작/종료
상태 | Transaction Table 슬롯 | 비고 |
---|
시작 | 슬롯을 할당 받고, Status 를 ACTIVE 로 변경 | 슬롯을 얻지 못한경우 undo segment tx slot (대기이벤트) 발생 |
종료 | Status 를 COMMITTED 로 변경, Commit SCN 저장 | |
!undo header.jpg!
- Undo 세그먼트 중 첫 번째 익스텐트, 그중에서도 첫 번째 블록에는 Undo 세그먼트 헤더정보가 담긴다.
- Undo 세그먼트 헤더에는 트랜잭션 테이블 슬롯(Transaction Table Slot)이 위치하며 각 슬롯에 기록되는 사항은 위 표와 같다.
- 트랜잭션을 시작하려면 먼저 Undo 세그먼트에 있는 트랜잭션 테이블로 부터 슬롯을 할당 받아야 하며, 할당받은 슬롯에 자신이 현재 Active 상태임을 표시.
(트랜잭션 슬롯을 얻지 못해 이용 가능한 슬롯이 생기기를 기다릴 때 발생하는 대기 이벤트가 'undo segment tx slot')
- 트랜잭션이 발생시키는 데이터 또는 인덱스 블록에 대한 변경사항은 Undo 블록에 Undo 레코드로서 하나씩 차례대로 기록된다.
구분 | 내용 |
---|
Insert | 추가된 레코드의 rowid | Update | 변경되는 컬럼에 대한 before image |
---|
Delete | 지워지는 로우의 모든 컬럼에 대한 before image |
---|
v$transaction.used_ublk | 현재 사용 중인 Undo 블록 개수 |
---|
v$transaction.used_urec | 현재까지 기록한 Undo 레코드 양 |
---|
- 사용자가 커밋해 트랜잭션이 완료되면 트랜잭션 상태정보를 'commited'로 변경하고 그 시점의 커밋 SCN을 트랜잭션 슬롯에 저장. 이 트랜잭션 슬롯과 Undo 블록들은
다른 트랜잭션에 의해 재상용될 수 있다.(in a circular fashion - 가장 먼저 커밋된 트랜잭션 슬롯부터 순차적으로 재사용)
(2). 블록헤더 ITL 슬롯
컬럼 | 내용 | 비고 |
---|
ITL 슬롯 번호 | | |
Transaction ID | | |
UBA | Undo Block Address | CR 블록을 생성할때 사용 |
커밋Flag | | |
Locking 정보 | | |
커밋 SCN | | 트랜젹션이 커밋 된 경우 |
- 특정 블록에 속한 레코드를 갱신하려면 먼저 블록 헤더로부터 ITL 슬롯을 확보하여 트랜잭션 ID를 기록하고 Active 상태임을 표시한 후에야 블록 갱신 가능.
initrans : 블록을 처음 사용하려고 포맷할 때 블록 헤더에 ITL슬롯을 몇 개 할당할지를 결정하는 파라미터.
maxtrans : initrans 파라메터에서 지정한 갯수만큼 다 썼을 때, 지정된 갯수(maxtrans파라메터) 만큼 ITL 슬롯을 추가 할당.
pctfree에 의해 예약된 공간이 update(인텍스는 insert)에 의해 모두 사용되고 없다면 ITL을 할당받지 못해 Lock 경합이 발생.
(ITL 슬롯이 부족할 때 발생하는 대기 이벤트가 'enq:TX - allocate ITL entry')
!block header.jpg!
Lock Byte
- 레코드가 저장되는 ROW마다, 헤더에 Lock Byte를 할당해, 트랜잭션의 ITL 슬롯 번호를 기록해 둔다. (Row-level Lock)
레코드 갱신 시도시
순서 | 대상 | 값 | 동작 | 비고 |
---|
#1 | 레코드의 헤더 | Lock Byte | TRUE 인 경우 다음 단계 진행 | FALSE 인 경우 레코드 갱신 |
#2 | ITL 슬롯 | Transaction ID | 값을 얻어 다음 단계 진행 | |
#3 | Transaction Table 슬롯 | Status | COMMITTED 인 경우 레코드 갱신 | ACTIVE 인 경우 대기 |
DBMS 별 레코드 정보 관리
DBMS | 레코드 정보 관리 방법 | Lock 에스컬레이션 | 비고 |
---|
오라클 | 레코드 속성 | 없음 | 별도 리소스 사용 없음 |
다른 DBMS | Lock 매니저 | 있음 | |
참조문서
블로그(오라클 성능 문제에 대한 통찰) : http://ukja.tistory.com/252
위키(오라클클럽) : http://wiki.gurubee.net/pages/viewpage.action?pageId=3900637