레코드의 다중 버전 관리
- 동시에 하나의 레코드에 대해서 여러개의 버전이 관리됨
- 특정 레코드가 어떤 트랜잭션에 의해서 변경되고 있는 경우, 다른 트랜잭션은 이전 버전의 레코드만 읽을 수 있음
-> 특별한 잠금 없이 레코드를 읽을 수 있음 (Consistent non-locking read라고 표현)
- 데이터 페이지에는 항상 가장 최근 버전의 레코드가 저장됨 (Commit되지 않은 경우라 하더라도)
- 레코드의 변경이 가해지면, 이전 버전은 시스템 테이블 스페이스의 Undo 영역으로 복사됨
- Undo 영역에 저장될 수 있는 레코드의 버전 개수는 제한이 없음
- 각 트랜잭션은 시작 시점에 따라서 접근 가능한 트랜잭션 번호를 관리 (하나의 트랜잭션 번호가 아니라 범위의)
- 만약, 하나의 레코드가 아주 빈번하게 변경되었다면, 어떤 트랜잭션에서 해당 레코드를 찾기 위해서
변경 이력(Linked list)을 여러번 찾아 올라가야만 접근 가능한 레코드를 가져올 수도 있음 (오버헤드 가능성) - 트랜잭션의 Isolation-level에 따라서 가시성을 가지는 트랜잭션 번호의 범위가 달라짐
- Undo log의 종류
- INSERT : Insert 에 의해서 발생한 Undo log 레코드이며 트랜잭션이 완료되면 불필요하므로 삭제됨
- UPDATE : Update 또는 Delete에 의해서 발생한 Undo log 레코드. 트랜잭션이 완료되어도, MVCC를 위해서 보관되어야 함. - SELECT의 경우 ... FOR UPDATE와 ... LOCK IN SHARE MODE 가 사용된 경우에만 레코드를 잠금
Index 의 다중 버전 관리
- 인덱스는 하나의 레코드에 대해서 모든 버전에 대한 포인터를 모두 가지고 있어야 함
- 인덱스는 트랜잭션 아이디 값을 가지고 있어야 함 (Covering Index와 해당 항목이 특정 트랜잭션에서 가시성이 있는지 검증하기 위해서)
- 전체적으로 긴 트랜잭션은 성능상 좋지 않음 (많은 변경 이력들을 관리해야 하기 때문에)
Purge garbage (더 이상 필요치 않은 Undo log)
- 최종적으로 불필요한 Undo log 레코드는 Purge thread가 모두 제거하게 됨
- Update 작업이 매우 빈번한 경우, Purge thread가 불필요한 Undo log 제거를 제때에 처리하지 못할 수 있음
-> 이런 경우 "History length" 가 계속 증가하게 됨 (SHOW ENGINE INNODB STATUS 명령으로 확인 가능) - innodb_max_purge_lag 설정으로 Purge thread의 작업을 조정 가능하며,
이 설정값에 의해서 Update 작업이 느려질 가능성도 있음
Undo log 포맷
- Primary key
- 트랜잭션 아이디 (현재 레코드를 변경한 트랜잭션의 아이디)
- 변경 이전 값
댓글 없음:
댓글 쓰기