안녕하세요
PostgreSQL 11.5를 사용하고 있습니다.
현재 저희는 대용량으로 사용하고 있어 일주일에 한번씩 vacuum 을 기동하고 있습니다.
헌데 이상하게 postgres와 저희가 사용하는 database는 정상적으로 age가 줄어드는데 template0, template1은 age가 줄지 않아 DB를 하번씩 재기동 하고 있습니다.
해당 database의 age를 DB를 재기동하지 않고 age를 초기화 할 수 있는 방법이 있을까요?
뭔가 이상한데요.
그 데이터베이스들은 autovacuum에서 알아서 나이관리를 할터인데요.
쓰지 않는 템플릿 데이터베이스 이기 때문에, 트랜젹션 겹침 방지 작업 대상이 되어도 금방 처리 되기 때문에,
서버를 다시 시작해야할 상황까지는 가지 않을 것 같습니다.
왜 서버를 재실행해야만 하는지를 먼저 파악하는 것이 맞을 것 같습니다.
autovacuum이 처리하는 속도가 느려서 그런거 같습니다.
현재 해당 DB에 테이블이 약 70만개 정도 있는 상태 입니다.
하루에 age가 올라가는 속도가 약 1억~2억 정도 입니다.
DB를 재기동하면 template0, template1 age가 정상적으로 줄어들고요
저희가 사용하는 시스템이 DML이 아주 많은 시스템이거든요
처음에는 autovacuum이 정상적으로 처리를 해줬는데 DML양이 늘어나면서 20억이 되기전에 처리가 되지 않더라구요
아... template1 가 아니라, 업무에 사용하는 데이터베이스가 그렇다는거죠?
autovacuum_freeze_max_age 설정값을 5억에서 7억 정도로 늘리고,
그 만큼 나이가 들기 전에,
age(pg_class.relfrozenxid) 값이 큰 것부터 수동으로 vacuum 하는 스크립트를 사용해야 할 것 같네요.
template0, template1 은 템플릿 데이터베이스입니다. 이 데이터베이스는 사용하지 않는 데이터베이스입니다.
트랜잭션이 발생하는 데이터베이스 기준으로 관리자의 개입이 필요한 vacuum 작업을 하셔야할 것 같습니다.
아 저희가 사용하는 database는 수동 vacuum을 주기적으로 돌려서 age가 내려갑니다.
업무용 dB는 age가 10억이 되면 vacuum을 돌리고 있습니다.
명령어는 vacuum; 이렇게 돌리고 있습니다.
해당 명령어가 수행되면 업무용db는 age가 1억 미만으로 떨어 집니다. 그런데 template0, template1에 대한 age가 떨어지지 않고 20억이되서 읽기모드로 전환된적이 여러번 있습니다.
그래서 현재는 template0, template1이 17억이 되면 db를 재기동하고 재기동이 되면 template0, template1의 age가 5천으로 떨어지더라구요
문서를 찾아보니 template0, template1 데이터베이스는 autovacuum으로만 age를 떨어뜨릴수 있다고 하는데 다른 방법이 없는지요
autovacuum 기능을 켜두세요
테이블 크기가 커서 autovacuum 작업으로 맡기면 시간이 너무 오래걸려 수동 작업이 필요하다고 판단되면,
그 테이블들을 대상으로 autovacuum 관리 대상이 아니다고 지정하는 것이 바른 관리 기법입니다.
이렇게 해당 테이블은 autovacuum 에게 맡기지 않고, 수동으로 처리하겠다면, 반드시 autovacuum_freeze_max_age 값보다 더 늙기 전에 테이블을 젊게 만드는 일도 잘 하셔야합니다.
현재 운영DB는 vacuum으로 정상적으로 age 관리가 잘되고 있습니다.
저희 시스템의 테이블이 70만개가 넘고 매달 신규 테이블이 생성되는 방식이라 하나씩 제외하는 방식은 어려울꺼 같습니다.
그래서 db 전체를 vacuum으로 돌리고 있고요
그런데도 template0, template1 데이터베이스의 age가 계속 문제가 되네요. 무언가 다른 방법이 없을까요?
template1 은 접속이 가능하기 때문에, vacuumdb 명령으로 수동 vacuum이 가능합니다.
필요하다면, 데이터베이스 전체를 주기적으로 vacuum 작업을 해서, 계속 젊음을 유지할 수 있습니다만,
(운영 데이터베이스만 하는 것이 아니라, template1 , 그외 접속할 수 있는 모든 데이터베이스를 해주어야겠죠)
template0는 접속이 불가능한 데이터베이스입니다.
데이터베이스 관리자 조차 해당 데이터베이스 형상 변경을 막는 것이 안전하다고 판단하기 때문입니다.
autovacuum 권장 방법이고요,
정말 autovacuum을 쓰기 싫다면,
template1 데이터베이스로 접속해서
alter databasde template0 allow_connections 1;
작업으로 template0 데이터베이스의 접속을 허용하고,
vacuumdb template0 명령으로 해당 데이터베이스 젊게 한 뒤,
다시 template1 데이터베이스로 접속해서,
alter databasde template0 allow_connections 0;
해당 데이터베이스 접속을 막습니다.
이 일련의 과정을 주기적으로 하시면 됩니다.
다시 한번 말씀드리지만 권장하지 않습니다.
저 allow_connections 옵션이 어느 버전부터 들어왔는지는 모르겠네요.
만일 allow_connections 옵션이 안 먹히는 버전이라면,
--접속허용
update pg_database set datallowconn = true where datname = 'template0';
--접속금지
update pg_database set datallowconn = false where datname = 'template0';
쿼리 작업을 하셔야합니다.
다시 질문 드립니다.
template0는 월래 깡통 데이터베이스여서 age가 안올라간다고 하는데 저희 시스템에서는 age가 아주 빠르게 올라 갑니다.
혹시 template0의 age가 올라가는 케이스가 있을까요? 단운 DML로는 안올라간다고 되어 있어서요
말씀대로 template0의 age가 올라가는 원인을 찾아서 해결하는게 맞는거 같아서요
-- postgres라는 데이터베이스에 접속해서 t라는 테이블 구조를 살펴봅니다. postgres=# \d t "public.t" 테이블 필드명 | 종류 | Collation | NULL허용 | 초기값 --------+---------+-----------+----------+-------- a | integer | | | b | integer | | | -- 모든 데이터베이스 나이를 봅니다. postgres=# select datname, age(datfrozenxid) from pg_database; datname | age -----------+----- postgres | 58 template1 | 58 template0 | 58 (3개 행) -- postgres 데이터베이스 안에 있는 t 테이블에 자료를 하나 입력합니다. -- DML 작업을 한거죠. 트랜잭션 번호를 하나 증가하는 일입니다. postgres=# insert into t values (1,1); INSERT 0 1 -- 다시 모든 데이터베이스 나이를 살펴 보니, DML 작업이 일어나지 않은 template1, template0 데이터베이스 모두 나이를 먹었네요. -- 시간은 모든 사람에게 평등하게 흘러가는거죠! postgres=# select datname, age(datfrozenxid) from pg_database; datname | age -----------+----- postgres | 59 template1 | 59 template0 | 59 (3개 행)