1. 개념

 LOB은 일반 primitive type, varchar 등과 달리 4000 bytes 이상이 되도 문제없이 저장한다. 또한, 오라클 내부적으로 4000 bytes를 넘지 않으면 inline LOB이라고 해서 redo log에도 남고, lob locator 할당 없이 row가 저장된 데이터 블록 또는 다른 데이터 블록을 직접 가리켜서 저장한다.

 

2. LOB 내부 설계 구조

 out of line LOB(differed LOB)의 경우 lob locator를 가지게되서 같은 column에서 공유하는 LOB index(B* tree)를 타게된다. lob locator는 inode, lob id 등으로 구성되는데, lob id를 키로 LOB index의 특정 leaf node에 접근할 수 있다. 이 leaf node는 한 데이터 블록이고, 데이터가 저장된 데이터 블록을 가리키는 포인터들을 저장하고 있다. 물론 데이터를 저장하는 곳은 할당받은 LOB segment 안이다.

 

 또한, LOB index는 old key도 저장해서 이전 커밋 버전의 데이터 블록을 가리킬 수 있다. 그러므로 flashback query로 LOB을 조회해도 CR(consistent read)가 가능하다. 예상할 수 있듯이, new key는 현재 LOB을 볼 수 있는 leaf node를 말하고, DBMS_LOB 패키지로 여러 블록을 쓰는 LOB 데이터의 중간 블록만 수정하면 수정되는 데이터 블록만 바꿔서 효율적으로 큰 데이터를 CR로 보여줄 수 있다.

 

3. 사족

 이러한 특별한 구조로 인해 rollback을 하면 일반 데이터는 undo segment에서 찾아온 UNDO를 적용하고 redo log에 이를 남기지만, LOB은 leaf node의 데이터 블록을 가리키는 포인터를 수정한다거나, leaf node 블록 자체를 되돌리는 작업을 하고 이를 redo log에 남긴다.

 이 설명은 DBMS에 따라 다를 수 있으며, LOB 데이터를 file system에 맡겨서 파일에 저장한다면 LOB index의 leaf node가 데이터 블록이 아닌 파일을 가리킬 수도 있다.

https://www.slideshare.net/tanelp/oracle-lob-internals-and-performance-tuning

'Oracle DB' 카테고리의 다른 글

알면 좋은 RDBMS 구조 키워드  (0) 2021.07.19
DB에 redo log가 필요한 이유  (0) 2020.04.06
SGA - DB buffer cache  (0) 2019.09.03
SGA - large pool, java pool, fixed SGA  (0) 2019.09.03
SGA - shared pool  (0) 2019.08.31
Posted by sjo200
,

기본적으로 DB는 DBWR가 직접 파일에 변경사항을 쓰기 전, LGWR가 redo log에 할 일을 한 레코드 단위로 쓴다. 이 레코드는 redo와 undo redo로 구성된다. undo redo는 redo로 바뀐 사항을 다시 undo하기 위해 redo log에 쓰는 undo의 redo이다. 이는 undo가 꼭 필요하기 때문인데, undo는 다음 세 가지 1. rollback, 2. tx recovery, 3. CR(consistency read)를 위해 필요하다. 아래 설명은 각각의 예시를 말한다.

1. 사용자가 rollback하면 redo 레코드의 redo로 바뀐 부분을, redo 레코드의 undo redo로 되돌린다.

2. DB가 redo를 쓰던 도중에 종료되면 roll forward recovery를 시작한다. 마지막 checkpoint 이후 redo log에 남겨진 내용을 모두 적용시키고, 다시 rollback하여 커밋된 내용만 남긴다.

3. isolation level 중 read committed, repeatable read는 특정 시점의 데이터 블록을 다시 보기 위해 undo를 사용해야한다.

 

참고

d2.naver.com/helloworld/407507

'Oracle DB' 카테고리의 다른 글

알면 좋은 RDBMS 구조 키워드  (0) 2021.07.19
DBMS의 LOB 저장 구조  (0) 2020.04.09
SGA - DB buffer cache  (0) 2019.09.03
SGA - large pool, java pool, fixed SGA  (0) 2019.09.03
SGA - shared pool  (0) 2019.08.31
Posted by sjo200
,

트랜잭션의 격리 수준에는 4 가지가 있다. 두 tx A, B가 함께 begin해서 동시에 진행된다고 생각하고 낮은 수준부터 차례대로 문제점을 짚어본다. 당연히 낮은 레벨은 상위 레벨의 문제점을 포함하며, 간략한 설명을 위해 나만의 pseudo 쿼리로 설명한다.

 

 1. dirty read

A - insert x (not committed)

B - select * -> x가 보임

dirty read

 

 2. read commited

A - insert x, commit

A - update x set a

B - select * -> commit 전이므로 a가 보인다.

A - commit

B - select * -> commit 이후이므로 x가 보인다. tx B는 조회할때마다 다른 결과를 볼 수 있는 문제가 있다.

non-repeatable reads

 

 3. repeatable read (MySQL을 제외한 대부분 DB는 기본적으로 read committed이고, for update 구문을 쓰면 repeatable read가 된다.)

B - select count(*) -> 3이 나왔다면,

A - insert x, commit

B - select count(*) -> 4가 나온다. (A의 commit 이후 새 row가 보인다. 조회할때마다 추가된 row가 보일 수 있는 문제가 있다.)

phantom reads

 

 4. serializable

없음

 

아래는 예제를 이해하기 쉽게 그림으로 잘 나타낸 글이다.

https://nesoy.github.io/articles/2019-05/Database-Transaction-isolation

 

undo segment 사용법에 따라 레벨이 나눠지는데, read committed라고 해서 undo segment에 txid를 저장하지 않을리는 없다. 다만 repeatable read를 하게되면 특정 xid 이전까지 undo record chain을 쭉 따라가야 하는 overhead가 있고, undo retention이 끝나서 실패할 위험도 있다. 그래서 다들 read committed를 쓰는 듯 하다.

'backend' 카테고리의 다른 글

oracle golden gate 19c 예제  (0) 2020.08.28
Kafka의 exactly-once semantic  (0) 2019.11.21
분산 데이터베이스의 CAP 이론  (0) 2019.08.31
Load Balancer  (0) 2019.08.03
Posted by sjo200
,