PostgreSQL에서 CPU를 과도하게 사용하는 autovacuum 동작을 감지했습니다.
지금까지 현업에서 사용했던 Oracle, MySQL, MSSQL과 같은 데이터베이스에서는 본 적 없는 것이라서 좀 알아보다 보니 흥미로워서 정리해 보았습니다.
Dead Tuple과 Vacuum/autovacuum에 대해서 알아보기 전, 우선 더 쉬운 전달을 위해 MVCC에 대해서 짚고 가보겠습니다.
MVCC (Multi-Version Concurrency Control)
MVCC는 번역하면 다중 버전 동시성 제어라고 합니다.
예를 들어 Transaction을 생각하시면 됩니다. Transaction은 작업을 한 단위로 묶어 Commit 전 변경사항을 Undo/Redo 할 수 있습니다. 그리고 읽기/쓰기에 무결성 보장을 위해 MVCC를 구현합니다.
재미있는 점은 각 데이터베이스마다 약간씩 다르게 기능을 구현하고 있다는 점입니다.
주요 차이점 정리
DBMS | MVCC 기본 동작 | Garbage Collection | 성능 |
---|---|---|---|
PostgreSQL | Dead Tuple을 남기며 새로운 버전 생성 | Autovacuum | 우수 |
MySQL (InnoDB) | Undo Log에서 이전 버전 관리 | Purge Thread | 우수 |
Oracle | Undo Segment에서 버전 관리 | SMON | 매우 우수 |
SQL Server | Snapshot Isolation에서 유사한 방식 제공 | 자동 버전 관리 | 유연성 있음 |
이와 같이 MVCC는 각 DB마다 서로 다른 방식 및 용어로 비슷하게 구현되어 있습니다.
Dead Tuples
PostgreSQL의 Dead Tuples는 수정/삭제 시 쌓이는 데이터입니다.
MVCC + Lock 기능을 사용하는 MySQL 같은 데이터베이스와는 다르게, 트랜잭션이 동시에 일어날 때 충돌을 줄이고 성능을 향상시킵니다. 데이터를 읽는 동안에도 변경 작업이 가능하므로, 읽기 성능에 최적화된 구조입니다.
그렇다면 이렇게 쌓인 데이터는 언제 제거되는 걸까요?
Autovacuum
이렇게 쌓인 데이터를 정리하기 위해 Autovacuum이 존재합니다. Dead Tuple이 임계치까지 쌓이게 되면, 최적화를 위해 Garbage Collection을 실행하며 이를 Autovacuum이라고 합니다.
Autovacuum 데몬이 돌면서 임계치에 자동으로 실행됩니다. 또한, 수동으로 실행하는 vacuum 또한 존재합니다.
마치며
autovacuum에 대해서 알아보다 각 DB별 MVCC 구현과 차이점이 흥미로워 보여서 간단하게 정리해 보았습니다.