지난 시간에 이어 Undo(Rollback)에 대해 알아보겠습니다
오라클 8i 이전에는 Undo 세그먼트를 데이터베이스 관리자가 수동으로 관리했고
rollback_segments 파라미터에 의해 그 개수도 고정적이었으나
9i부터 도입된 AUM(Automatic Undo Management)에 의해
Undo 세그먼트마다 하나의 트랜잭션이 할당되는 것을 목표로 세그먼트가 관리됩니다
트랜잭션에 독립적으로 할당해 줄 Undo 세그먼트가 없을 때는
가장 적게 사용되는 Undo 세그먼트 중 하나를 할당합니다
Undo 세그먼트에 저장된 정보를 왜 사용할까요?
먼저, 트랜잭션에 의한 변경사항을 최종 커밋하지 않고 롤백(Transaction Rollback)하고자 할 때 이용합니다
다음은 지난 Redo 관련 글에서 언급했지만 Instance Crash 발생 후 Redo를 이용해 Roll forward 단계가 완료되면
최종 커밋되지 않은 변경사항까지 모두 복구되므로
시스템이 셧다운된 시점에 아직 커밋되지 않았던 트랜잭션들을 모두 롤백해야 하는데
이 때 Undo 세그먼트에 저장된 Undo 데이터를 사용합니다
Roll forward 단계에 대해 알아보시려면 아래 ↓ 클릭
2020/02/01 - [DBMS] - [DBMS] Oracle(오라클)_2
마지막으로 Undo 데이터는 읽기 일관성(Read Consistency)을 위해 사용되는데
이 부분을 이해하기 위해서는 Undo 메커니즘에 대한 이해가 필요하기 때문에 살펴보겠습니다
위의 그림은 Undo 세그먼트를 간략히 표현한 것인데
Undo 세그먼트 중 Initial Extent, 그 중에서도 첫 번째 블록에는 Undo 세그먼트 헤더정보가 있습니다
Undo 세그먼트 헤더에는 트랜잭션 테이블 슬롯(Transaction Table Slot)이 위치하는데
각 슬롯에 기록되는 사항들은 아래와 같습니다
① 트랜잭션 ID [USN(Undo Segment Number)# + Slot# + Wrap#] ② 트랜잭션 상태정보(Transaction Status)
③ 커밋 SCN ( 트랜잭션이 커밋된 경우) ④ Last UBA(Undo Block Address) ⑤ 기타
① 번의 트랜잭션 ID 구성을 통해
트랜잭션을 시작하려면 Undo 세그먼트에 있는 트랜잭션 테이블로부터 슬롯(Slot)을 할당받아야 하며
할당받은 슬롯에 자신이 현재 Active 상태임을 표시하고서 갱신을 시작함을 알 수 있습니다
참고로, 트랜잭션 슬롯을 곧바로 얻지 못해 이용 가능한 슬롯이 생기기를 기다릴 때 발생하는
대기 이벤트가 undo segment tx slot입니다
이제 트랜잭션이 발생시키는 데이터 또는 인덱스 블록에 대한 변경사항은
각 DML 오퍼레이션 별로 Undo 블록에 기록되는데
Insert 는 추가된 레코드의 rowid
Update 는 변경 컬럼에 대한 before image
Delete 는 지워지는 로우의 모든 컬럼에 대한 before image 입니다
④번 Last UBA는 트랜잭션의 기록사항들을
가장 마지막 Undo 레코드 뒤에 계속 추가해 나가려고 유지하는 일종의 포인터이며
각 Undo 레코드 간에는 체인 형태로 연결되어 데이터를 롤백하고자 할 때 이 체인을 따라 작업을 수행하게 됩니다
아직 커밋되지 않은 Active 상태의 트랜잭션이 사용하는 Undo 블록과 트랜잭션 테이블 슬롯은
절대 다른 트랜잭션에 의해 재사용되지 않고
사용자가 커밋해 트랜잭션이 완료되면 트랜잭션 상태정보를 'committed'로 변경하고
그 시점의 ③ 커밋 SCN을 트랜잭션 슬롯에 저장합니다
이제 이 트랜잭션 슬롯과 Undo 블록들은 다른 트랜잭션에 의해 재사용될 수 있지만
가장 먼저 커밋된 트랜잭션 슬롯부터 순차적으로(in a circular fashion) 재사용되기 때문에
Undo 데이터는 커밋 후에도 남아있을 수 있습니다
9i에서 AUM이 도입되면서 새롭게 생긴 파라미터가 undo_retention인데
트랜잭션이 완료되었어도 지정한 시간 동안은 Undo 데이터를 재사용하지 말라고 힌트를 주는 것입니다
그런데 강제성을 갖지 않아 새로 할당할 공간까지 부족해지면 재사용이 가능해집니다
그래서 10g부터는 retention guarantee과 Automatic Undo Retention Tuning기능을 새로 도입했는데
Undo 테이블스페이스에 guarantee 옵션을 설정하면 공간이 부족해 에러가 발생하더라도
지정된 시간 이내에 커밋된 Undo 정보는 재사용하지 않도록 하고
시스템 상황에 따라 tuned_undo_retention 값을 오라클이 자동으로 계산해 Undo Extent의 상태정보를 관리합니다
마지막으로 블록 헤더의 ITL 슬롯을 살펴보고 마치도록 하겠습니다
Undo 세그먼트 헤더에 트랜잭션 테이블 슬롯이 있다면
각 데이터 블록과 인덱스 블록 헤더에는 ITL(Interested Transaction List) 슬롯이 있습니다
ITL 슬롯에 저장되는 내용은 아래와 같습니다
① ITL 슬롯 번호 ② 트랜잭션 ID ③ UBA(Undo Block Address) - 트랜잭션에 의해 발생한 변경 이전 데이터(before image)가 저장된 Undo 블록 주소를 가리키는 포인터 ④ 커밋 Flag ⑤ Locking 정보 ⑥ 커밋 SCN
특정 블록에 속한 레코드를 갱신하려면 먼저 블록 헤더로부터 ITL 슬롯을 확보하고
트랜잭션ID를 기록하고 현재 해당 트랜잭션이 Active 상태임을 표시해야합니다
ITL 슬롯을 할당받지 못하면 트랜잭션은 계속 진행하지 못하고 블로킹(Blocking) 되었다가
해당 블록을 갱신하던 앞선 트랜잭션 중 하나가 커밋 또는 롤백될 때 비로소 ITL 슬롯을 얻어 작업을 진행할 수 있습니다
오라클은 레코드가 저장되는 로우마다 그 헤더에 Lock Byte를 할당해
해당 로우를 갱신 중인 트랜잭션의 ITL 슬롯 번호를 기록합니다(로우 단위(row-level) Lock)
오라클의 Lock 원리는 다음에 설명하도록 하고 오늘의 학습을 마치겠습니다-_-
'DBMS' 카테고리의 다른 글
[DBMS] Oracle(오라클)_2 (0) | 2020.02.01 |
---|---|
[DBMS] Oracle(오라클)_1 (0) | 2019.12.15 |