⚠️

PostgreSQL:シーケンスを知らなかった

に公開

普段保守をしているのですが、テーブルへインサートが失敗しているということがあり、調査していると、見慣れないエラーが表示されていました。

ERROR:  nextval: reached maximum value of sequence "xxxxx" (99999999)

...しーけんす?
普段こいつを意識することがなかったので、このシーケンスとやらについて調べてみました。

起きてたこと

前置きにもある通りなのですが、シーケンスが最大値に達していたため、レコードのインサートに失敗していました。
対象のテーブルは、アプリケーションの特定のデータ受信処理で異常データを検知した場合に、その情報を格納する役割があり、どうやらその異常データ判定処理がバグっていて(おい)大量のデータがインサートされ続けていた結果、シーケンスとやらの上限値に達してしまっていたようです。

シーケンスとは

まずシーケンスのまとめから。

  • 連続した整数を生成するための単一行テーブル。
  • 独立したオブジェクトなので、テーブルに直接関連付けしなくても利用できる。
  • PostgreSQLの場合SERIAL型のカラムは自動でシーケンスが生成される
    といった性質があります。
    今回私が見たケースでは、主キーがこのSERIAL型で、それに対応するシーケンスが上限に達していたためインサートができなくなっていました。

このシーケンスを知るまでは、「新しいレコードの主キー?自動で採番されるやろw」みたいな感覚でした。浅はかですね。
この「自動で採番される」という仕組みの裏にはシーケンスの存在があることを知りました。
当たり前ですが、何事も仕組みを知るのは大切ですね。

暫定対応

暫定対応としては以下のようなクエリを実行することで、対処しました。

SELECT * FROM <シーケンス名>;
でデータの確認

SELECT * FROM pg_sequences WHERE sequencename = <シーケンス名>;
で設定値の確認

ALTER SEQUENCE <シーケンス名> MAXVALUE <新しい最大値>
でシーケンスの最大値を増やす

気にしたポイントとしては、シーケンスの最大値です。
というのも、SERIAL型、SMALLSERIAL型、BIGSERIAL型でMAXVALUEで設定できる値が異なります。この辺りは事前にしっかり調べておく必要がありますね。

最後に

そもそもなんでこんな設計になってんだ...というシステムへの不満はありますが、シーケンスについて理解できたのはよかったです。

Discussion