PostgreSQL을 다시 시작하면 시퀀스 값이 33 증가하는 수수께끼

어느 날 애플리케이션의 DEBUG 로그를 살펴보면 레코드의 id 열 값이 실제 레코드 수보다 극단적으로 커진다는 것을 알았습니다. 이 컬럼의 값은 시퀀스를 사용하여 번호를 매기고 있기 때문에 하나씩 늘어나기를 기대합니다. "설마 버그인가?"라고 초조했지만, 자원 절약을 위해 매일 밤 DB를 중지하고 있기 때문이었습니다.

재현 확인



손쉽게 PostgreSQL 12.3 의 Docker 공식 이미지 를 사용해 검증해 보겠습니다.

  • PostgreSQL 시작
    $ docker run --name testdb -e POSTGRES_PASSWORD=mysecretpassword -d postgres:12.3
    

  • psql로 연결
    $ docker exec -it testdb psql -U postgres
    psql (12.3 (Debian 12.3-1.pgdg100+1))
    Type "help" for help.
    
    postgres=# 
    

  • 시퀀스를 만들고 값을 얻습니다.
    postgres=# create sequence myseq;
    CREATE SEQUENCE
    postgres=# select nextval('myseq');
     nextval
    ---------
           1
    (1 row)
    

  • DB 재부팅
    $ docker restart testdb
    

  • 시퀀스의 값을 다시 얻는다 → 2가 아니다!
    postgres=# select nextval('myseq');
     nextval
    ---------
          34
    (1 row)
    

  • Sequence Caching: Oracle vs. PostgreSQL 에 의하면, 재기동했을 때에 32 (고정 사이즈) + 1 (시퀀스의 캐쉬 사이즈. 디폴트치로부터 바꾸고 있는 경우는 더욱 커진다)만 번호가 진행되어 버리는 것 같습니다.

    보충



    참고 페이지를 보면 「4. DB를 재기동한다」로 DB를 제대로 정지하고 있지 않는 것이 우선 그렇습니다. DB를 안전하게 중지하는 단계로 다시 시도해 봅니다.

  • 시퀀스를 만들고 값을 얻습니다.
    postgres=# create sequence myseq;
    CREATE SEQUENCE
    postgres=# select nextval('myseq');
     nextval
    ---------
           1
    (1 row)
    

  • DB 재부팅
    $ docker exec -it testdb su postgres -c 'pg_ctl stop -m fast'
    
    waiting for server to shut down....
    $ docker start testdb
    

  • 시퀀스 값을 다시 가져옵니다.
    postgres=# select nextval('myseq');
     nextval
    ---------
           2
    (1 row)
    

  • 이번에는 예상대로 2가 되었습니다. DB를 억지로 멈추지 말라는 것이군요.

    보충 2



    덧붙여 이번 문제가 일어난 실제의 환경에서는, PostgreSQL 는 아니고 Amazon Aurora PostgreSQL 를 사용하고 있어, AWS CLI 를 사용해 정지시키고 있었습니다. 억지로 멈추고 싶지는 않지만 왜 ...
    $ aws rds stop-db-cluster --db-cluster-identifier mydbcluster
    

    요약



    시퀀스를 사용하여 컬럼의 값을 번호 매기면 때때로 결번이 발생할 수 있습니다. 트랜잭션이 롤백되면 결번이 발생한다는 것을 알고 있었지만 DB를 중지하면 결번이 (32도!) 발생한다는 것을 몰랐습니다. 공부가 되었습니다.

    다만, Aurora 의 거동에 대해서는 정보원을 찾을 수 없었고, Aurora 를 정지했을 때에도 시퀀스가 ​​날아가는 것이 기대인지는 모르고 남았습니다.

    참고



  • Sequence Caching: Oracle vs. PostgreSQL
  • postgresql sequence jump 30 or 33 number with cache equals 1 - Stack Overflow
  • 좋은 웹페이지 즐겨찾기