PostgreSQL EOL対応|確認手順と移行の判断基準
目次
PostgreSQLのサポート終了(EOL)を過ぎても、データベースはその日に止まりません。だから放置されやすく、セキュリティ診断で「EOLバージョンを使用」と指摘されたり、RDSから延長サポート課金の通知が届いた時点で慌てることになります。確認すべき順番どおりに、今のバージョン、EOL日、取れる選択肢を整理します。
結論:バージョンとEOL日を確認し、「延長サポート/マイナー更新/メジャーアップグレード」の3択に落とす
PostgreSQLコミュニティのバージョニングポリシーでは、各メジャーバージョンのサポート期間は初回リリースから約5年です。その間は四半期ごと(通常2月・5月・8月・11月)にマイナーリリースが出ます。サポート終了後は、重大な脆弱性が見つかってもそのバージョン向けの修正版は出ません。
対応は次の3択です。
- マイナー更新で済む(例:16.2 → 16.10)。メジャーバージョンがサポート内なら、最新マイナーへ追随するだけ。ダウンタイムは再起動分のみ。
- 延長サポートで時間を買う(マネージドサービス限定)。RDS/AuroraのExtended Supportのように、コミュニティEOL後も一定期間パッチが提供される仕組みを使う。追加課金が発生する。
- メジャーアップグレードする(例:14 → 17)。pg_upgradeか論理レプリケーションで移行する。計画と検証が必要。
判断の順番は固定です。稼働バージョンを正確に取り、そのバージョンのEOL日を確認し、マネージドかセルフホストかで選択肢を絞ります。順番を崩すと「延長サポートを検討したら対象外だった」「マイナー更新で足りたのに大掛かりな移行を計画していた」といった手戻りが起きます。
切り分け手順:どのレイヤのサポートが切れているのかを順番に確認する
「PostgreSQLがEOL」と言われたとき、実際に切れているレイヤは3つあり得ます。PostgreSQL本体のメジャーバージョン(コミュニティのサポート期限)、OSディストリビューションのパッケージ(RHEL/Ubuntu同梱版やPGDGリポジトリの提供終了)、そしてマネージドサービス側の提供期限(RDS/Auroraの標準サポート終了日。コミュニティEOLと一致しないことがある)です。
セキュリティ診断のレポートはOSパッケージのバージョン文字列を見ていることが多く、本体はサポート内なのにOS側の提供が終わっている場合もあります。どのレイヤの話なのかを先に確定させてください。
稼働中のバージョンとEOL状態を確認するSQL・コマンド
最初にサーバが返すバージョンを取ります。psql --versionはクライアント側の値なので、サーバ側を確認してください。
-- 人が読む用(ビルド情報込み)
SELECT version();
-- 比較・スクリプト判定用(例: 160010 = 16.10)
SHOW server_version_num;
-- データファイルの実体がどこか(複数クラスタ混在の切り分け)
SHOW data_directory;
SHOW config_file;
セルフホストなら、OS上に複数バージョンのバイナリが同居していないかも確認します。
# RHEL系
rpm -qa | grep -E 'postgresql[0-9]+'
systemctl list-units --type=service | grep postgres
# Debian/Ubuntu(クラスタごとのバージョンとポートが出る)
pg_lsclusters
# 起動中プロセスからバイナリの実パスを特定する
ps -o pid,args -C postgres | head -3
取得したメジャーバージョンを、PostgreSQL公式の「Versioning Policy」ページのEOL日一覧と突き合わせます。目安としては、13系が2025年11月、14系が2026年11月、15系が2027年11月、16系が2028年11月、17系が2029年11月、18系が2030年11月の終了予定です。日付は公式ページが正式な情報源で、繰り上げ・繰り下げもあるため必ず最新を確認してください。
同時にマイナーバージョンも判定します。server_version_numが同メジャーの最新マイナーより小さければ、EOLより先にマイナー更新の対象です。
RDS/Auroraの延長サポート対象かどうかを確認する
マネージドで見るのは「標準サポート終了日」と「延長サポートの設定値」の2つです。
# 稼働バージョンとマイナー自動更新の設定
aws rds describe-db-instances \
--query 'DBInstances[].{id:DBInstanceIdentifier,engine:Engine,ver:EngineVersion,minorAuto:AutoMinorVersionUpgrade}' \
--output table
# そのバージョンがどこへアップグレードできるか(移行先候補の列挙)
aws rds describe-db-engine-versions --engine postgres \
--engine-version 14 --include-all \
--query 'DBEngineVersions[].{ver:EngineVersion,status:Status,targets:ValidUpgradeTarget[].EngineVersion}'
# 強制アップグレードなどの保留メンテナンスが来ていないか
aws rds describe-pending-maintenance-actions
Statusがdeprecatedのバージョンは新規作成ができず、期限到来後は自動アップグレードの対象になります。
延長サポート(Extended Support)は、明示的に無効化しない限り期限到来時に自動で有効化され、課金が始まります。RDS/Auroraではengine-lifecycle-supportで制御でき、無効側にしておくと期限時点で次のメジャーバージョンへ自動アップグレードされます。課金単位(vCPU時間ベース)や期間による単価の変動、対象バージョンは改定されるため、請求に関わる判断はAWS公式ドキュメントと料金ページで確認してください。アップグレードが間に合わないので延長サポートを使うのか、課金を避けて自動アップグレードを受け入れるのかは、自動アップグレードのタイミングを自分で選べない点を含めて決める必要があります。
移行先としてRDSからAuroraへ寄せる選択肢もありますが、ストレージとレプリケーションの仕組みが違うため挙動も変わります。詳細はAurora/RDS PostgreSQLの違いと性能差の原因を参照してください。
EOL後に実際に何が起きるのか:止まるもの・止まらないものと緊急度の判断基準
まず止まらないもの。EOLを過ぎてもPostgreSQLは動き続けます。ライセンスキーのような停止機構はなく、クエリもレプリケーションもそのままです。
止まるのは修正の提供です。認証バイパスや権限昇格のCVEが出ても、そのバージョン向けのパッチは出ません。データ破損系バグの修正も届かなくなります。過去のマイナーリリースには、特定条件下でインデックスが破損する、論理レプリケーションがデータを取りこぼすといった修正が含まれており、この供給が止まるのが一番の問題です。OSベンダーやPGDGからのパッケージ提供も終わり、yum updateやapt upgradeに新しいものが降ってきません。障害時のコミュニティ・ベンダー対応も「まずサポート対象バージョンに上げてください」で止まります。
緊急度は次の軸で判断します。
| 条件 | 緊急度 |
|---|---|
| DBがインターネットから到達可能/アプリ経由で任意SQLが通る余地がある | 高:期限前に移行、間に合わないなら延長サポート |
| PCI DSSなど「サポート対象のソフトウェアを使う」ことを求める基準の対象 | 高:監査指摘として扱われる |
| マネージドで自動アップグレードが設定されている | 高:勝手に上がる日が決まっている |
| 閉域・内部ネットワークのみ、接続元が限定され、停止可能な業務 | 中:次の定期メンテで計画的に実施 |
| 近い将来に基盤刷新が確定している | 中:刷新に合わせて一度だけ移行する |
閉域なら永久に放置してよい、とはなりません。実務では、拡張やドライバの新バージョンが古いサーバを対象外にし始めるほうが先に問題になります。pg_stat_statementsやPostGISのようなよく使う拡張も、新しいリリースは古いサーバをサポートしなくなっていきます。
対処パターン別の手順:マイナー更新・pg_upgrade・論理レプリケーション
マイナー更新は最優先で、かつ最も安全です。マイナーリリースはカタログ非互換を伴わないため、原則としてパッケージ入れ替えと再起動だけで完了します。一部のリリースでは、特定の不具合の影響を受けたインデックスに対するREINDEXなど、リリースノートに明記された追加作業が必要です。
# RHEL系・PGDGリポジトリの例
sudo systemctl stop postgresql-16
sudo dnf update postgresql16 postgresql16-server postgresql16-contrib
sudo systemctl start postgresql-16
psql -c "SHOW server_version_num;"
リリースノートの「Migration to Version xx.y」節を読み、追加作業の有無を確認してください。
メジャーアップグレードはpg_dump/restore、pg_upgrade、論理レプリケーションの3択です。数十GB以上だとpg_dumpはリストア時間が読めなくなるため、実務上は後者2つから選びます。
pg_upgrade –link でダウンタイムを短縮する手順と事前チェック
pg_upgradeはシステムカタログを変換し、ユーザーデータのファイルはコピーまたはハードリンクで引き継ぎます。--linkならデータサイズにほぼ依存せず、数分から十数分で終わります。
# 1. 新バージョンのバイナリと空のクラスタを用意(locale/encodingは旧と一致させる)
sudo dnf install -y postgresql17-server
sudo -u postgres /usr/pgsql-17/bin/initdb \
-D /var/lib/pgsql/17/data --locale=C --encoding=UTF8 --data-checksums
# 2. 旧クラスタを停止してからチェックのみ実行
sudo systemctl stop postgresql-14
sudo -u postgres /usr/pgsql-17/bin/pg_upgrade \
-b /usr/pgsql-14/bin -B /usr/pgsql-17/bin \
-d /var/lib/pgsql/14/data -D /var/lib/pgsql/17/data \
--check
# 3. 本実行(--link はハードリンク。同一ファイルシステムが必須)
sudo -u postgres /usr/pgsql-17/bin/pg_upgrade \
-b /usr/pgsql-14/bin -B /usr/pgsql-17/bin \
-d /var/lib/pgsql/14/data -D /var/lib/pgsql/17/data --link
事前チェックで引っかかりやすいのは次の4点です。
- チェックサム設定の不一致。
pg_controldata <datadir> | grep -i checksumで旧側を確認し、initdbの--data-checksumsを揃える。 - 論理レプリケーションスロットの残存。PostgreSQL 17より前はスロットが残っていると失敗する。移行前に
pg_drop_replication_slot()で削除し、アップグレード後に再作成する。未消費のスロットはWAL肥大化の主因でもあるので、仕組みはPostgreSQL WAL肥大化の原因|レプリケーションスロットで確認してください。 - 拡張の未インストール。旧クラスタの拡張の共有ライブラリが新バージョン側に無いと失敗する。
- 削除された型・機能の利用。
reg*型の列やabstimeなど、バージョンによって持ち込めないものがある。
--linkの最大の注意点は、実行後に旧クラスタを起動してはいけないことです。ファイルを共有しているため、どちらかを起動すると両方のデータが破損します。切り戻しはバックアップからのリストアになるので、--linkを選ぶならバックアップ取得と、どの時点でロールバックを諦めるかの判断基準を事前に決めておきます。
アップグレード後の必須作業は2つです。
# 統計情報の再作成(これを省くと実行計画が崩れる)
sudo -u postgres /usr/pgsql-17/bin/vacuumdb --all --analyze-in-stages
# 拡張のバージョン追従
psql -c "ALTER EXTENSION pg_stat_statements UPDATE;"
さらに、OSを跨いで移行した場合(RHEL 7→9、古いUbuntuからの移行など)はglibcのバージョンが変わり、照合順序(collation)の並び順が変わることがあります。 この状態ではテキスト列のB-treeインデックスが不整合になるため、REINDEXが必要です。EOL対応は古いOSごと作り直すケースが多いので、ここは必ず確認してください。datcollversion/collversionの不一致はpg_database・pg_collationで検出できます。
PostgreSQL 18への移行で起きやすいエラーはPostgreSQL 18 移行でつまずく原因と対処法にまとめています。
論理レプリケーションで切り替え時間を数分に抑える手順
停止可能時間が数分しかない、OSやインスタンスタイプも同時に変える、クラウドへ移す。このいずれかに当てはまるなら論理レプリケーションです。新旧を並走させ、追いついた時点で接続先を切り替えます。
-- 旧(publisher)側。セルフホストなら wal_level = logical が必要
-- RDS/Aurora では rds.logical_replication = 1(再起動が必要)
CREATE PUBLICATION pub_all FOR ALL TABLES;
# スキーマだけを新サーバへ移す
pg_dump -h old-host -d appdb --schema-only --no-publications > schema.sql
psql -h new-host -d appdb -f schema.sql
-- 新(subscriber)側
CREATE SUBSCRIPTION sub_all
CONNECTION 'host=old-host dbname=appdb user=repl password=***'
PUBLICATION pub_all WITH (copy_data = true);
-- 初期コピーの進捗('r' = ready になれば同期完了)
SELECT srsubstate, count(*) FROM pg_subscription_rel GROUP BY 1;
-- 遅延の確認(publisher側で実行)
SELECT slot_name, active,
pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS behind
FROM pg_replication_slots;
制約も押さえておきます。
- 主キーまたは
REPLICA IDENTITYが必要。無いテーブルはUPDATE/DELETEが複製されない。REPLICA IDENTITY FULLで回避できるが、subscriber側が全列比較になり負荷が上がる。 - シーケンスは複製されない。切り替え直前に
setvalで引き継ぐ(PostgreSQL 18以降はシーケンス同期の機能があるので、バージョンごとの対応範囲を確認)。 - DDLは複製されない。並走中はスキーマ変更を凍結する。
- ラージオブジェクトは対象外。
切り替えは、①アプリ停止 → ②遅延が0になるのを確認 → ③シーケンス補正 → ④DROP SUBSCRIPTION(スロットも整理)→ ⑤ANALYZE→ ⑥接続先変更 → ⑦アプリ起動、の順です。切り戻し用に逆方向のパブリケーションを先に用意しておくかどうかも、事前に決めておきます。
OSS-DB Silver 対策テキスト(OSS教科書)
PostgreSQLの仕組みを体系的に学ぶなら、OSS-DB Silverの公式対応テキストが近道です。資格を取らなくても基礎固めに役立ちます。
よくある質問
PostgreSQLのサポート期間は何年?EOL日はどこで確認できる?
コミュニティ版は初回リリースから約5年です。正式な一覧はPostgreSQL公式サイトの「Versioning Policy」ページにあり、各メジャーバージョンの初回リリース日とEOL日が載っています。クラウドのマネージドサービスは独自のカレンダーを持ち、コミュニティEOLより前後することがあるため、RDS/Aurora/Cloud SQLなどは各社のドキュメントを別途確認してください。
EOLを過ぎたPostgreSQLはそのまま使い続けられる?
技術的には動きます。止まるのは修正パッチの提供で、脆弱性やデータ破損系バグが見つかっても対応手段がアップグレードしか残りません。マネージドサービスでは延長サポート課金や自動アップグレードが発生するため、そのままではいられない点に注意してください。
メジャーアップグレードでバージョンは飛ばせる?
pg_upgradeは古いバージョンから最新まで一気に移行できます(下限はツール側の対応範囲を確認)。ただし飛ばした分の非互換が一度に来ます。14→17なら、recovery.confの廃止(12)、wal_keep_segments→wal_keep_size(13)、promote_trigger_fileの削除(16)といった設定変更や、password_encryptionのmd5非推奨化などを、該当する全バージョンのリリースノートの互換性の節で確認してください。アプリ側はバージョンごとの型変換・関数の挙動差が影響します。Oracleからの移行と併発する場合の注意点はOracle PostgreSQL移行の注意点|症状別の切り分けと対処にまとめてあります。
アップグレード後に性能が落ちたときはどこを見る?
確認順は固定です。(1)ANALYZEが走っているか(pg_stat_user_tables.last_analyze)。(2)問題のクエリの実行計画が変わっていないか。旧環境と新環境でEXPLAIN (ANALYZE, BUFFERS)を取って比較します。読み方はPostgreSQL EXPLAIN ANALYZEの見方を参照してください。(3)パラメータが引き継がれているか。新しいpostgresql.confでshared_buffersやwork_mem、random_page_costがデフォルトに戻っていないかをpg_settingsで確認します。(4)それでも説明がつかなければjitを疑います。短時間クエリが大量に来るワークロードではJITのコンパイル時間で遅くなることがあり、SET jit = offで切り分けられます。
再発防止:EOLに追われないためのバージョン管理と年次アップグレード運用
EOL対応が毎回突発プロジェクトになるのは、バージョンの棚卸しが定常業務になっていないからです。
まずインベントリを機械的に取ります。server_version_numをメトリクスとして収集し、監視システムに持たせる。クラウドならdescribe-db-instancesの結果を定期的に保存しておけば十分です。
次に四半期ごとのマイナー更新を定例化します。マイナーリリースは年4回でスケジュールが読めるので、定例メンテナンス枠に組み込めば「マイナーが何年も古い」状態は消えます。RDSならAutoMinorVersionUpgradeを有効にし、メンテナンスウィンドウを業務影響の小さい時間帯に設定してください。
メジャーは年1回、N-1〜N-2を維持します。最新を追う必要はありませんが、EOLまで1年を切ったバージョンに留まらないという基準を決めれば、常に2〜3年の猶予が残ります。
アップグレード手順は使い捨てにしません。pg_upgradeのコマンド、事前チェックで引っかかった項目、切り戻し判断のタイミングを手順書に残し、検証環境で年1回実行する。手順が動く状態を保つこと自体がリスク低減になります。
延長サポートは期限付きの借金として扱います。使う判断は妥当ですが、有効化と同時に移行完了の期日をチケット化しないと、延長期間の終わりに同じ状況を繰り返します。
EOL日は事前に分かっている数少ないリスクです。カレンダーに載せて定常運用に落とし込めば、監査で指摘されてから慌てるサイクルから抜けられます。
さらに学ぶには
アップグレード後の性能劣化やロック競合に落ち着いて対処するには、MVCCとVACUUM、実行計画、ロックの仕組みを一通り押さえておくのが近道です。運用でよく出る症状からの切り分けはPostgreSQLが遅い・詰まる原因|VACUUMと実行計画、ロックにまとめています。