MVCC 사용 시 주의할 점
MVCC 사용 시 주의할 점 (Caveats)
MVCC가 동시성 문제를 대부분 해결해 주지만, 모든 명령이 전부 MVCC에 안전한 건 아니에요. 몇 가지 예외는 공식 문서가 따로 짚어주고 있는데, 이 페이지에서 그 주의점들을 하나씩 살펴볼게요.
출처: 공식문서
MVCC에 안전하지 않은 DDL 명령
일부 DDL 명령, 현재로는 TRUNCATE 와 테이블을 다시 쓰는(rewriting) 형태의 ALTER TABLE 이 MVCC에 안전하지 않아요. 무슨 뜻이냐면, 해당 DDL이 커밋된 뒤에 그보다 먼저 찍힌 스냅샷을 사용하는 동시 트랜잭션에는 그 테이블이 텅 빈 것처럼 보인다는 거예요.
하지만 실질적인 피해는 제한적이에요. 이 문제는 그 DDL이 시작되기 전에 해당 테이블에 접근하지 않았던 트랜잭션에게만 발생하거든요. 이미 테이블에 접근한 트랜잭션은 최소 ACCESS SHARE 테이블 잠금을 보유하고 있어서, 그 트랜잭션이 끝날 때까지 DDL이 차단되거든요. 그래서 이 명령들이 대상 테이블에 대한 연속된 쿼리 사이에서 눈에 띄는 불일치를 만들지는 않지만, 대상 테이블과 DB의 다른 테이블 사이에는 보이는 불일치가 생길 수 있어요.
직렬화 격리는 핫 스탠바이에서 지원 안 됨
직렬화(Serializable) 트랜잭션 격리 수준은 아직 핫 스탠바이 복제 대상(hot standby replica)에는 추가되지 않았어요. 핫 스탠바이 모드에서 현재 지원되는 가장 엄격한 격리 수준은 Repeatable Read죠.
프라이머리에서 모든 영구 데이터베이스 쓰기를 Serializable 트랜잭션 안에서 수행하면 모든 스탠바이가 결국 일관된 상태에 도달하는 건 보장되지만, 스탠바이에서 돌아가는 Repeatable Read 트랜잭션은 프라이머리의 어떤 직렬 실행과도 일치하지 않는 일시적인 상태를 보는 경우가 있을 수 있어요.
시스템 카탈로그 접근은 예외
시스템 카탈로그에 대한 내부 접근은 현재 트랜잭션의 격리 수준으로 이뤄지지 않아요. 그 결과, 새로 만든 테이블 같은 DB 객체는 동시에 실행되는 Repeatable Read·Serializable 트랜잭션에도 보이는데요, 정작 그 객체 안의 행들은 보이지 않아요. 반대로, 보다 높은 격리 수준에서 시스템 카탈로그를 명시적으로 조회하는 쿼리는, 동시에 생성된 DB 객체를 나타내는 행을 보지 못해요.