단일 사용자 모드 데이터베이스 청소

포스트그레스큐엘은 하나의 데이터베이스에서 약 이십일억개의 트랜잭션 밖에 처리하지 못합니다.

이 한계는 포스트그레스큐엘이 만들어질 때부터 지금까지 바뀌지 않았습니다.

데이터베이스 내 가장 오래된 트랜잭션 번호와 현재 번호를 비교해서 그 차이가 이십일억정도 차이가 나면 그 데이터베이스는 읽기 전용으로 바뀝니다.

서버 로그에는
WARNING:  database "mydb" must be vacuumed within 177009986 transactions
HINT:  To avoid a database shutdown, execute a database-wide VACUUM in "mydb". 
이런 로그와 그 다음에는
ERROR:  database is not accepting commands to avoid wraparound data loss in database "mydb"
HINT:  Stop the postmaster and vacuum that database in single-user mode.
이런 로그를 남깁니다.

한글 로그라면,
경고:  "mydb" 데이터베이스는 177009986번의 트랜잭션이 발생되기 전에 VACUUM 작업을 해야 합니다.
힌트:  데이터베이스가 종료되지 않도록 하려면 "mydb" 데이터베이스 수준의 VACUUM을 실행하십시오. 

이런 로그와 그 다음에는

오류:  "mydb" 데이터베이스 트랜잭션 ID 겹침에 의한 자료 손실을 방지하기 위해 더 이상 자료 조작 작업을 허용하지 않습니다
힌트:  postmaster를 중지하고 단일 사용자 모드로 서버를 실행한 뒤 VACUUM 작업을 하십시오.
이런 로그를 볼 수 있을 것입니다.

이 로그를 본다면, autovacuum 기능으로 처리하지 못했기에, 데이터베이스 청소를 강제로 해야합니다. 

두번째 로그인 단일 사용자 모드로 청소를 하라고 알려주는 상황이면, 더 이상 답이 없습니다.  힌트에서 알려주는 대로 서비스를 중지하고 단일 사용자 모드로 청소하는 것 외에는 달리 방법이 없습니다.

여기서 정말 중요한 것. 그 청소가 시작되면, 아주 차분하게 청소가 끝나길 기다려야 한다는 것입니다.

이 작업이 언제 끝나지? 또 다른 방법이 없을까? 빨리 끝낼 방법은?
이런 수많은 질문과 그 나름의 답을 찾는 것이 그다지 도움이 되질 않습니다.
이런 질문의 나름대로의 답이 어쩌면 훌륭한 해결책이 될지도 모르겠지만, 대부분 사태를 더 악화시킵니다.
그냥 느긋하게 단일 사용자 모드 청소 작업이 끝날 때까지 기다리는 것이 제일 안전합니다.

굳이 한 팁을 알려드리면,
단일 사용자 모드로 데이터베이스에 접속 하고, 그냥 해당 데이터베이스 전체 청소 작업보다, 제일 늙은 테이블만 청소하고, 그것이 끝나면 다중 사용자 모드(일반적인 서버 실행 환경)로 실행 한 뒤 뒷처리를 하는 것도 한 방법입니다.

키워드는 age(pg_class.relfrozenxid) 와, age(pg_database.datfrozenxid) 값입니다.

이 글의 핵심은 이런 경고 메시지와 오류 메시지를 보지 않게 데이터베이스를 항상 젊게 관리하는 것입니다.