このリリースは 18.1 からの修正リリース(2026年 2月 12日リリース)です。
18.X からのアップデートではダンプ、リストアは不要です。
しかしながら、ltree型の列に対するインデックスがある場合には、アップグレード後にインデックス再構築が必要です。
PostgreSQL 18.1 から 18.2 への変更点
18.2, 17.8, 16.12, 15.16, 14.21 の各バージョンが同時にリリースされており、本ページでは共通の記載としています。各修正項目が適用されるバージョン系列番号を項目末尾に括弧書きで記載しています。
- 予期せぬ次元のoidvectorやint2vectorを防止するようになりました。(CVE-2026-2003) (Tom Lane) (18)(17)(16)(15)(14)
- 予期せぬデータ型を受け入れる演算子に付加される選択率推定が厳格化されました。(CVE-2026-2004) (Tom Lane) (18)(17)(16)(15)(14)
- contrib/pgcryptoのPGP復号化関数でバッファオーバーランが修正されました。(CVE-2026-2005) (Michael Paquier) (18)(17)(16)(15)(14)
- マルチバイト文字長の不十分な検証が修正されました。(CVE-2026-2006) (Thomas Munro, Noah Misch) (18)(17)(16)(15)(14)
- contrib/pg_trgmで文字列の小文字化の振る舞いについて厳格化されました。(CVE-2026-2007) (Heikki Linnakangas) (18)
- contrib/ltreeで大文字小文字を区別しないマッチの一貫性の欠如が修正されました。 (Jeff Davis) (18)
- 「ALTER TABLE ... ADD CONSTRAINT」で名前を付けてNOT NULL制約を加えるときに、その列に別の名前のNOT NULL制約が既にあった場合にはエラーを出すようになりました。 (Alvaro Herrera, Srinath Reddy Sadipiralla) (18)
- 副問合せでのCTE参照が集約関数のセマンティックレベルを決定することが禁止されました。 (Tom Lane) (18)(17)(16)(15)(14)
- CTE問合せでのMERGEの変更内容取得について、トリガの遷移表が修正されました。 (Dean Rasheed) (18)(17)(16)(15)
- エグゼキュータで、副問い合わせなどテーブル以外の処理対象エントリに属するrowmarkの誤った除外が修正されました。 (Dean Rasheed) (18)
- UPDATEまたはDELETEの対象となるパーティションテーブルのすべての子テーブルが除外されている場合に発生するエラーが修正されました。 (Amit Langote) (18)(17)(16)(15)(14)
- 配列添字内の副問い合わせに対する式評価の誤りが修正されました。 (Andres Freund) (18)
- 非決定論的照合順序におけるテキストの部分文字列検索が修正されました。 (Laurenz Albe) (18)
- クエリに重複したウィンドウ関数呼び出しが含まれる場合に発生する可能性のある、プランナエラーが回避されました。 (Meng Zhang, David Rowley) (18)(17)(16)
- 集合を返す関数とグルーピングセットに関するプランナのエラーが修正されました。 (Richard Guo) (18)
- 副問い合わせのGROUPING句にVOLATILE関数または集合を返す関数が含まれる場合の、誤った最適化が回避されました。 (Richard Guo) (18)
- 式に関する統計情報を検索するときに、PlaceHolderVarノードを詳しく調べるようになりました。 (Richard Guo) (18)
- 式をインデックスと照合する際に、no-op(何もしない)のPlaceHolderVarノードを調べるようになりました。 (Richard Guo) (18)
- プランナのOR句からScalarArrayOpインデックス条件への変換が修正されました。 (Tender Wang, Tom Lane) (18)
- インデックスの述語がWHERE句が真であることを暗示する場合でも、部分ハッシュインデックスでのIndex Scanができるようになりました。 (Tom Lane) (18)(17)(16)(15)(14)
- UNLOGGEDのBRINインデックスに対してWALを出力しないようになりました。 (Kirill Reshke) (18)(17)(16)(15)(14)
- 並列GINインデックス構築で正しい順序付け関数を使用するようになりました。 (Tomas Vondra) (18)
- 未読のNOTIFYメッセージによってまだ必要とされるCLOGの切り捨てが防止されました。 (Joel Jacobson, Heikki Linnakangas) (18)(17)(16)(15)(14)
- NOTIFYメッセージ処理中のエラー発生を、FATALにエスカレートする、すなわち、コネクション切断するようになりました。 (Heikki Linnakangas) (18)(17)(16)(15)(14)
- クエリIDのハッシュを計算する際に、グループ化式を考慮するようになりました。 (Jian He) (18)
- 同時の更新と共に「EXPLAIN ANALYZE MERGE ...」を行なった際に、更新回数が誤ってカウントされる問題が修正されました。 (Dean Rasheed) (18)(17)
- タプルをロックするときの後続のupdate chainにおける不具合が修正されました。 (Jasper Smit) (18)(17)(16)(15)(14)
- 大規模テーブルの増分バックアップにおける誤った処理が修正されました。 (Robert Haas, Oleg Tkachenko) (18)(17)
- 動的共有メモリにロックを取得していたバックエンドプロセスが、FATAL発生時にクラッシュする可能性があり、修正されました。 (Rahila Syed) (18)(17)(16)(15)(14)
- 非同期I/Oコードの競合状態が修正されました。 (Andres Freund) (18)
- クラッシュ後にマルチトランザクションの有効なSLRUセグメントが誤って切り詰めされる可能性があり、防止されました。 (Heikki Linnakangas) (18)(17)(16)(15)(14)
- pg_stat_get_backend_activity() の結果が誤ってエンコーディングされる問題が修正されました。 (Chao Li) (18)(17)(16)(15)(14)
- メモリコンテクストのログ出力の再帰的な実行が防止されました。 (Fujii Masao) (18)(17)(16)(15)(14)
- 並列実行コンテクストを再初期化する際のメモリコンテクストの使用方法が修正されました。 (Jakub Wartak, Jeevan Chalke) (18)(17)(16)(15)(14)
- 新しいmultixid(マルチトランザクションID)を生成する際に、次のmultixidのオフセットを設定するように変更し、コーナーケースで必要だった待機ループが削除されました。 (Andrey Borodin) (18)(17)(16)(15)(14)
- データ変更を伴うCTEの複数回書き換えが回避されました。 (Bernice Southey, Dean Rasheed) (18)(17)(16)(15)(14)
- DSM(動的共有メモリ)レジストリのエントリの初期化を再試行できるように修正されました。 (Nathan Bossart) (18)(17)
- ページがスワップアウトされている場合でも、NUMAステータスビューの取得が失敗しないように修正されました。 (Tomas Vondra) (18)
- 古いバージョンのlibnumaを使用してNUMAページ状態を問い合わせた際に、権限不足エラーが発生しないように修正されました。 (Tomas Vondra) (18)
- チェックポイントレコードが示すREDOポイントまで遡るWALが存在しない場合、リカバリを失敗させるように修正されました。 (Nitin Jadhav) (18)(17)(16)(15)(14)
- ALTER PUBLICATION文を処理するときに元のクエリツリーが書き換えられてしまう問題が修正されました。 (Sunil S) (18)(17)(16)(15)(14)
- 「CREATE SUBSCRIPTION ... CONNECTION」で指定された接続オプションを、パブリッシャ側の walsender に渡すように修正されました。 (Fujii Masao) (18)(17)(16)(15)
- 新たに作成または同期されたレプリケーションスロットが無効化される不具合があり、修正されました。 (Zhijie Hou) (18)(17)(16)(15)(14)
- レプリケーションスロットのデータベースに保持させる必要のある最も古いXID(xmin)を計算するときの競合状態が修正されました。 (Zhijie Hou) (18)(17)(16)(15)(14)
- 論理レプリケーションのサブスクリプションの初期同期において、データコピーを開始する前にpg_replication_originエントリの追加をコミットするように修正されました。 (Zhijie Hou) (18)(17)(16)(15)(14)
- パラレルワーカによるアプライ処理が失敗した後に、論理レプリケーションの進捗を進めないように修正されました。 (Zhijie Hou) (18)(17)(16)
- 論理レプリケーションのスロット同期(slotsync)ワーカプロセスが、LOCK_TIMEOUTを知らせるシグナルを正しく処理するように修正されました。 (Zhijie Hou) (18)(17)
- ストリーミングレプリケーションのスタンバイサーバの再起動時に「ERROR: unexpected data beyond EOF in block ... of relation ...」エラーが発生することがあり、修正されました。 (Anthonin Bonnefoy) (18)(17)(16)(15)(14)
- SQL/JSON pathの型不一致に関するエラーメッセージが正しい内容を示すように修正されました。 (Jian He) (18)(17)
- パーティション範囲の境界を解析する際に、列の位置の追跡を誤る問題が修正されました。 (myzhen) (18)(17)(16)(15)(14)
- エラーメッセージ内の軽微な誤りがいくつか修正されました。 (Man Zeng, Tianchen Zhang) (18)(17)(16)(15)(14)
- LLVMバージョン17以降で、JITコンパイル時に関数をインライン化できない問題が修正されました。 (Anthonin Bonnefoy) (18)(17)(16)(15)(14)
- LLVMバージョン21で動作するようにJITコードが修正されました。 (Holger Hoffstatte) (18)(17)(16)(15)(14)
- 古い(RHEL7時代の)システムヘッダーファイルでビルドできるよう、aarch64固有のコードが修正されました。 (Tom Lane) (18)
- autotoolsによるconfigureスクリプトでio_uring_queue_init_mem()が使えるか否かの判定が修正されました。 (Masahiko Sawada) (18)
- 新たな設定パラメータfile_extend_methodが追加されました。これはposix_fallocate()の使用を制御します。 (Thomas Munro) (18)(17)(16)
- Windowsでもopen()の「O_CLOEXEC」フラグを参照するように修正されました。 (Bryan Green, Thomas Munro) (18)(17)(16)
- Solaris上でmesonを使ってビルドしたpostgresコマンドがロングオプション(--XXX形式)の解析に失敗しており、修正されました。 (Tom Lane) (18)(17)(16)
- GNU/Hurdでもプロセスタイトルの変更が可能になりました。 (Michael Banck) (18)(17)(16)(15)(14)
- psqlでVACUUMのオプションをタブ補完する際の不具合が修正されました。 (Yugo Nagata) (18)
- psqlのプロンプトエスケープ「%P」の表示が修正されました。 (Chao Li) (18)
- pg_dumpのシーケンスを収集するロジックが修正されました。 (Nathan Bossart) (18)
- pg_dumpでoauth_validator_libraries設定値を引用符で正しくクォートするように修正されました。 (ChangAo Chen) (18)
- pg_dumpの--binary-upgradeオプションでアサート失敗が起きる問題が修正されました。 (Vignesh C) (18)(17)
- pgbenchのパイプラインモードで複数の\syncpipelineを使用した場合に発生する誤ったエラー処理が修正されました。 (Yugo Nagata) (18)(17)
- pg_resetwalでOldestXIDを変更したときに、変更後の値を表示するように修正されました。 (Heikki Linnakangas) (18)(17)(16)(15)(14)
- pg_upgradeで、次のマルチトランザクションIDに0を設定することと、次のマルチトランザクションオフセットにUINT32_MAXの値を設定することが、可能になりました。 (Maxim Orlov) (18)(17)(16)(15)
- contrib/amcheckでBTreeインデックスの親ページ検査で正しいスナップショットを使うように修正されました。 (Mihail Nikalayeu) (18)(17)(16)(15)(14)
- contrib/amcheckでBTreeインデックスの「half-dead」ページを正しく処理するように修正されました。 (Heikki Linnakangas) (18)(17)(16)(15)(14)
- contrib/amcheckでBTreeインデックスのルートページ分割が未完了の状態を正しく処理するように修正されました。 (Heikki Linnakangas) (18)(17)(16)(15)(14)
- contrib/pg_buffercacheで、メモリを必要以上に使ってしまう問題が修正されました。 (David Geier) (18)
- contrib/intarrayの「@@」演算子用の選択度推定において、特定の条件下で整数オーバーフローが発生する問題が修正されました。 (Chao Li) (18)(17)(16)(15)(14)
- conrib/ltreeにおけるマルチバイトエンコーディング処理の問題が修正されました。 (Jeff Davis) (18)(17)(16)(15)(14)
- contrib/pg_stat_statementsを使用しているときに、IN句内に定数と非定数式が混在している場合に、そのSQLを実行するバックエンドプロセスのクラッシュやアサート失敗が発生しており、修正されました。 (Sami Imseih) (18)
- タイムゾーンデータファイルがtzdata release 2025cへ更新されました。 (Tom Lane) (18)(17)(16)(15)(14)
- インプレイスによるカタログ更新に関する問題が修正されました。 (Noah Misch) (17)(16)(15)(14)
これらのデータ型はNULLを含まない1次元配列を想定していますが、それを破るキャスト経路がありました。これによりクラッシュやサーバメモリ暴露を含む誤動作を引き起こす可能性がありました。
(誤動作例:本来はエラーになるべき) db1=# SELECT ARRAY[ARRAY[1,2,3],ARRAY[4,5,6]]::int2vector; array ------- 1 0 (1 row)
contrib/intarray拡張に含まれる選択率推定関数は、入力が想定したデータ型であるか検査していなかったため、任意コード実行のために悪用される恐れがありました。サードパーティ拡張は類似の危険に備えて、intarrayと同様の技法で検査し防御を加えるべきです。
そのような拡張で対応が行なわれるまで時間がかかるため、今後は、演算子に非組み込みの選択率推定関数を付加するためにスーパーユーザ―権限が必要になりました。
そのため、新たなデータ型や演算子を導入する拡張を一般ユーザで導入(CREATE EXTENSION)する運用をしている場合に、これからはスーパーユーザで行う必要が生じるかもしれません。
作りこまれたメッセージを長すぎるセッションキーで復号化すると、バッファオーバーランが起きて、これによる任意コード実行も可能でした。
いくつかのバグのため、攻撃者が作りこまれたSQLを発行して文字列のバッファオーバーランを起こすことができて、これによる任意コード実行も可能でした。
本修正後は、文字列関数がデータベース内に既に格納されている不正なテキストを処理するときに「ERROR: invalid byte sequence for encoding」のエラーが発生するようになります。
§ § § § § § § § § § § § § § § § § § § § § § § § § § § § § §
PostgreSQL 18以降では、一部のロケールにおいて文字列の小文字化で(バイト数でなく)文字数が増えることがあります。それによる潜在的なバッファオーバーランの危険性があり、修正されました。
ltreeのインデックス関係ルーチンはケースフォールドに元となる演算子とは異なる実装を使っていました。これらが一致した動作をするのは、デフォルト照合順序プロバイダがlibcのシングルバイト文字エンコーディングのときだけでした。
データベースのデフォルト照合順序のケースフォールドを使うように修正されました。データベースが照合順序プロバイダにlibcのシングルバイト文字エンコーディングを使っていないなら、本修正を含むバージョンアップ後に、インデックスアクセスメソッドが何であれ、ltree型の列を含むインデックスを再構築する必要があります。さもないと、誤った検索結果が生じるおそれがあります。
これまでは、NOT NULL制約名は元のままで何も行われませんが、エラーも出ませんでした。同名のNOT NULL制約を加えようとした場合には、これまで通り、何も行われず、エラーも出ない動作をします。
本修正で、外側の集約では入れ子のCTEを使用できないものとして「ERROR: outer-level aggregate cannot use a nested CTE」エラーを出すようになりました。これまでは予期せぬ「ERROR: unexpected outer reference in CTE query」エラーが場合によっては出るという動作でした。
本修正は以前のマイナーリリースでの変更(17.7等の 56番)を取り消すものです。標準SQLでは集約内の副問合せは完全に禁止されているため、このようなケースはエラーとして扱えば十分と判断されました。
(問題が生じる問合せ形状の例:これからは以下のSELECT文はエラーになる) CREATE TABLE t8 (c1 int); INSERT INTO t8 VALUES (1), (2), (3); SELECT c1, (WITH cte1(x,y) AS (SELECT 1,2) SELECT count((SELECT t8.c1 FROM cte1))) AS ss FROM t8;
文単位のAFTERトリガを伴うテーブルに対し、MERGEと別のDML操作の両方を含みデータ変更を行うCTE問合せを実行すると、トリガに渡される遷移表には、MERGEで変更される行が含まれず、他のDML操作で変更される行だけが含まれました。
(以下のWITH句付きMERGE文は2行のINSERTが生じるが、これまでは、
t9テーブルのINSERT文のトリガに渡される遷移表には1行しか含まれなかった。)
CREATE TABLE t9 (a int);
WITH cte1 AS (INSERT INTO t9 VALUES (1))
MERGE INTO t9 USING (VALUES (2)) AS v(a) ON t9.a = v.a
WHEN NOT MATCHED THEN INSERT VALUES (v.a);
rowmarkは行ロックや可視性制御のための内部的に使われるメタデータです。
この誤りにより、問合せ対象テーブルの更新が並行している場合に、VALUESやCTE(WITH句)、サブクエリを伴う、MERGEやUPDATE、DELETEで、誤った問い合わせ結果が生じる可能性がありました。想定される行の更新について、EvalPlanQual再チェックを要する場合に該当します。
EvalPlanQual再チェックは主としてREAD COMMITTEDトランザクション分離レベルで実行される内部処理です。
このような場合、何もする必要がないにもかかわらず、エクゼキュータが「ERROR: could not find junk ctid column」を報告する可能性がありました。
外部テーブルを子テーブルとしている場合に現象が報告されました。
不具合により、誤った問い合わせ結果が返ったり、バックエンドプロセスのクラッシュが生じることがありました。
(障害を起こす問合せ例 - いずれも 18.1 ではクラッシュする)
db1=# SELECT (array[1,2])[(SELECT g.i)] FROM generate_series(1, 1) g(i);
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
db1=# SELECT (array[1,2])[(SELECT g.i):(SELECT g.i + 1)] FROM generate_series(1, 1) g(i);
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
非決定論的照合順序を使用する場合、検索文字列の末尾で発生する一致を検出できませんでした。
(誤動作例: 'testx'の末尾の'x'がマッチせず、'y'への置換に失敗する)
db1=# CREATE COLLATION test_nondeterministic (
provider = icu, locale = 'und-u-ks-level2', deterministic = false);
db1=# SELECT replace(
'testx' COLLATE "test_nondeterministic",
'x' COLLATE "test_nondeterministic", 'y') AS res1;
res1
-------
testx
(1 row)
このような呼び出しの重複排除に関する混乱により、「ERROR: WindowFunc with winref 2 assigned to WindowAgg with winref 1」といったエラーを引き起こす可能性がありました。
ProjectSetプランノードを構築するとき、グループ化式を含む部分式が入力プランによって既に計算済みであることを検出できませんでした。これにより、非効率的なプランや、「ERROR: variable not found in subplan target list」などのエラーが発生していました。
(障害動作例)
db1=# CREATE TABLE t18 (id int, brands text[], markets text[]);
db1=# INSERT INTO t18 VALUES (1, '{Brand A,Brand B}', '{Market A}'),
(2, '{Brand B,Brand C}', '{Market B}'),
(3, '{Brand A}', '{Market A,Market B}');
db1=# SELECT brands, unnest(markets) AS market, count(DISTINCT id) FROM t18
GROUP BY GROUPING SETS (brands, market, ())
ORDER BY brands ASC, market ASC;
ERROR: variable not found in subplan target list
(正しい結果)
brands | market | count
-----------------------+----------+-------
{"Brand A"} | | 1
{"Brand A","Brand B"} | | 1
{"Brand B","Brand C"} | | 1
| Market A | 2
| Market B | 2
| | 3
(6 rows)
プランナが、このようなグループ化された列を参照する外部クエリの制約をプッシュダウンしようとしたため、VOLATILE関数の多重評価による不正な動作や、副問い合わせのWHERE/HAVING句に集合を返す関数の導入することによるエラーが発生していました。
(誤動作例)
db1=# CREATE TABLE t16 (id serial8, j json);
db1=# INSERT INTO t16 (j) VALUES ('[{"animal": "cats"}, {"animal": "dogs"}]');
db1=# SELECT animal FROM (
SELECT json_array_elements(j) ->> 'animal' animal,
count(*) FROM t16 GROUP BY 1) x WHERE animal LIKE 'c%';
ERROR: set-valued function called in context that cannot accept a set
(正しい結果)
animal
--------
cats
(1 row)
この変更により、プランナは副問い合わせからプルアップされた式やGROUP BYで使われる式について関連する統計情報を見つけられるようになり、デフォルト推定値で代用することを回避できます。
これまで、式の統計情報を見つけられず実行プランが劣化することがありえました。この制限は古くからあるものの、以前のバージョンで問題の報告が無いため、18.x系列以降のみが修正対象となりました。
PostgreSQL 18では、PlaceHolderVarが以前より多用されるため、従来インデックスを使用できた一部のクエリでインデックスを使用できなくなっていました。この退行を防ぐためにロジックが追加されました。
PlaceHolderVarはPostgreSQLのプランナの実装で使われている構造体変数です。
コードがRelabelTypeノードを正しく処理せず、無効な式を生成したり、有効な変換を実行できなかったりすることがありました。潜在的に予期せぬエラーや誤った問い合わせ結果が生じる可能性があります。
(問題が生じる問い合わせ例)
db1=# CREATE TYPE typ19 AS (r float8, i float8);
db1=# CREATE TABLE t19 (f1 typ19 PRIMARY KEY);
db1=# INSERT INTO t19 SELECT (x, x+1)::typ19 FROM generate_series(1,10000) x;
db1=# ANALYZE t19;
db1=# EXPLAIN SELECT * FROM t19 WHERE f1 = (1,2)::typ19 OR f1 = (3,4)::typ19;
QUERY PLAN
---------------------------------------------------------------------------
Index Only Scan using t19_pkey on t19 (cost=0.29..12.61 rows=2 width=37)
Index Cond: (f1 = ANY ('{"(1,2)","(3,4)"}'::typ19[]))
(2 rows)
→ 修正前バージョンでは Bitmap Heap/Index Scan と BitmapOr のプランになり、
上記のように効率的な配列へのインデックス検索に変換されない。
通常、プランナは述語によって暗黙的に示されるWHERE句を削除します。なぜなら、すべてのインデックスエントリに対して必ず成立するため、テストする意味がないからです。しかし、ハッシュインデックスのように先頭インデックスキーにWHERE句を必要とするインデックスの場合、この処理がIndex Scanプランの作成を妨げる可能性がありました。 このようなインデックスを検討するときにはWHERE句を削除しないようになりました。
(問題が生じる問い合わせ例)
db1=# CREATE TABLE t20 AS SELECT generate_series(1, 1000)::int x;
db1=# CREATE INDEX idx20 ON t20 USING hash (x) WHERE x = 1;
db1=# ANALYZE t20;
db1=# EXPLAIN SELECT x FROM t20 WHERE x = 1;
QUERY PLAN
-----------------------------------------------------------------
Index Scan using idx20 on t20 (cost=0.00..8.02 rows=1 width=4)
Index Cond: (x = 1)
(2 rows)
→ 修正前バージョンでは、これが Seq Scan の実行プランになってしまう
めったに使用されないコードパスの1つで、インデックスがUNLOGGEDとマークされている場合でも、BRINインデックスに関連するWALレコードが誤って出力されていました。その結果、クラッシュリカバリで「FATAL: could not create file "base/5/32819": File exists」といったエラーが発生して、WALレコードのリプレイに失敗していました。
並列コードでは、デフォルトの順序付け演算子(列のデータ型のbtree演算子クラスによって決定される)が使用されていましたが、gin演算子クラスで指定された順序付け関数を(それがあるなら)使用する必要がありました。これにより、データ型にbtree演算子クラスが存在しない場合はエラーになり、演算子クラスが適合しない順序付け関数を指定している場合には無効なインデックスが生成される問題が発生していました。
これまで、バックエンドによるNOTIFYメッセージの吸い上げが遅いときに「ERROR: could not access status of transaction」エラーが発生することがありました。
以前は、バックエンドがNOTIFYメッセージの受信中にエラーを検出すると、そのメッセージを読み飛ばし、クライアントにエラーを報告して処理を続行していました。
しかし、この動作には多くの問題がありました。大きな懸念点の一つは、クライアントが通知の喪失を知る適切な手段がなく、ましてやその内容を知る手段がないことです。アプリケーションロジックによっては、通知が失われるとアプリケーションが待機状態になってしまう可能性がありました。また、残りのメッセージは誰かが新しいNOTIFYを送信するまで処理されません。さらに、NOTIFY信号受信時に接続がアイドル状態の場合、無関係な理由によりERRORは常にFATALにエスカレートされていました。
一貫性を保ち、アプリケーションに通知が失われた可能性があることを明確に伝えるため、本修正が選択されました。
以前は、GROUP BYの式を除いて同一の2つのクエリが、contrib/pg_stat_statementsやその他のクエリIDを利用ツールにおいて、誤って統合されていました。
(pg_stat_statementsの問題となる動作例)
db1=# CREATE TABLE t25 (id int, g1 int, g2 int)
db1=# SELECT count(*), max(g1) g1, max(g2) g2 FROM t25 GROUP BY g1;
db1=# SELECT count(*), max(g1) g1, max(g2) g2 FROM t25 GROUP BY g2;
db1=# SELECT queryid, query, calls FROM pg_stat_statements WHERE query ~ 't25 GROUP BY';
queryid | query | calls
---------------------+--------------------------------------------------------------+-------
2402898342116734224 | SELECT count(*), max(g1) g1, max(g2) g2 FROM t25 GROUP BY g1 | 2
(1 row)
→ 修正後は異なるステートメントと解釈されて2行が出力される
EXPLAINの出力でスキップされた(skipped)タプルの数が誤っていたり、アサートが有効なビルドではアサート失敗が発生していました。
このコードパスでは、update chain内の最初の新しいタプルのxmin値の確認が省略されていたため、元の更新処理が中止され、その領域がVACUUMによってすぐに回収されて再利用された場合、無関係なタプルがロックされることがありました。これにより、予期せぬトランザクションの遅延やデッドロックが生じる可能性がありました。
本障害による以下の予期せぬエラーも確認されています。
ERROR: t_xmin ... is uncommitted in tuple ... to be updated in table ...
update chainは、インデックス更新をしないHOT UPDATE処理を実現するためのデータ構造です。
ベースバックアップと増分バックアップの間に、セグメントサイズ(通常1GB)を超えるテーブルがVACUUMで切り詰められた場合、pg_combinebackupが「file ... has truncation block length ... in excess of segment size」というエラーで失敗する可能性がありました。これにより増分バックアップのリストアが妨げられていました。
トランザクションコンテキスト外でFATALエラーが発生した際に、動的共有メモリセグメントがデタッチされ既にマップされていない領域に対してロックの解除処理が実行されて、バックエンドプロセスのクラッシュが発生していました。
非同期I/O操作の結果コードが取得される前に上書きされる可能性がありました。
該当コードはVACUUM処理の中で実行されます。問題が生じうるケースでは切り詰め処理をスキップするように変更されました。
セッションのアクティビティ文字列を保持する共有メモリバッファは、不完全なマルチバイト文字で終わることがあります。そのような不完全な文字は読み取り時に切り詰めることになっていますが、この関数ではその処理が行われていませんでした。
メモリコンテクストのログ出力を要求するシグナルが継続的に送られた場合に、ログ出力コードが再帰的に実行されてしまうことがあり、これにより理論上はスタックオーバーフローが発生する可能性がありました。
補助的なデータ構造の寿命が並列コンテキストよりも短いために、クラッシュが発生することがありました。この問題は、PostgreSQLコアのみを使用している場合には到達可能であることは確認されていませんが、拡張機能において問題が発生したことが報告がされています。
以前のロジックでは、発生しない更新を待ち続けて動作が止まってしまうことがありました。
以前は、自動更新可能ビューやルール付きのリレーションを更新するときに、元の問合せにデータ変更を伴うCTEが含まれていると、リライタが再帰的にそのCTEを複数回書き換えしていました。この動作は非効率であるうえ、CTE内にALWAYS指定の生成列の更新が含まれている場合には、偽性のエラーを引き起こす可能性がありました。
(障害動作例 - エラーにならない動作が正しい)
db1=# CREATE TABLE t36 (i int GENERATED ALWAYS AS IDENTITY);
db1=# CREATE TABLE t36b (j int);
db1=# CREATE VIEW v36 AS SELECT * FROM t36b;
db1=# WITH cte AS (INSERT INTO t36 DEFAULT VALUES RETURNING i)
DELETE FROM v36 USING cte WHERE j = i;
ERROR: cannot insert a non-DEFAULT value into column "i"
DETAIL: Column "i" is an identity column defined as GENERATED ALWAYS.
HINT: Use OVERRIDING SYSTEM VALUE to override.
動的共有メモリ(DSM)のエントリの初期化途中で失敗したとしても、次にそのエントリの使用を試みる際に初期化を再度試行できるようになりました。これまで一度初期化が失敗したエントリは、失敗した状態のままで残り続けていました。
pg_shmem_allocations_numaビューの参照時でそのような場合に、これまでは「ERROR: invalid NUMA node id ...」エラーを出していましたが、取得できない値にNULLを返すようになりました。
2.0.19より前のlibnumaで以下のようなエラー発生が報告されました。
db1=# SELECT * FROM pg_shmem_allocations_numa; ERROR: failed NUMA pages inquiry status: Operation not permitted
リカバリ開始前に、チェックポイントレコードが示すREDOポイントまで遡るWALが存在するかどうかを明示的に検査して、存在しなければ以下のようなPANICを出すようになりました。
PANIC: could not find redo location ... referenced by checkpoint record at ...
以前は、この状況でリカバリを行うプロセスがクラッシュしたり、データ破損を引き起こしたりする能性がありました。
この誤りによる実害としては、ALTER PUBLICATIONに対して駆動されたイベントトリガが複数指定されたpublishオプションの最初の1つしか認識できませんでした。また、ALTER PUBLICATIONがプリペアドステートメントとして用意されていた場合、その再実行時に同様にオプション指定が失われました。
この修正以前は、接続オプションのうち「options」が無視されていました。そのため、たとえば walsender セッション内でカスタムのサーバーパラメータを設定することができませんでした。これは PostgreSQL 15 でのリファクタリングによって壊れる前までは実際に動作していた挙動であり、今回の修正で以前の挙動が復元されます。
同時実行中のチェックポイント処理との競合状態にあるときに、レプリケーションスロットが必要としているWALが削除されてしまう可能性があり、その結果、そのスロットが即座に無効化されてしまう問題がありました。
この不具合により、論理レプリケーションスロット作成時に「ERROR: cannot build an initial slot snapshot as oldest safe xid follows snapshot's xmin」エラーが発生する可能性がありました。
これまでは、コピー処理が失敗した場合、新しく追加された pg_replication_originエントリがトランザクションのロールバックによって失われていました。その結果、共有メモリ内の状態が不整合になっていました。
これまでは、パラレルワーカのアプライ処理が失敗すると、サブスクライバ側でトランザクションが失われることがありました。
これまではタイムアウトのシグナルが事実上無視されていました。
これまでは、型が正しくない場合に本来出すべきエラーの代わりに、「ERROR: cache lookup failed for type 0」という誤ったエラーが発生していました。
(修正前に誤ったエラーが出るケースの正常動作例)
db1=# CREATE TABLE t49 (path) AS SELECT '$'::text;
db1=# SELECT json_value('"aaa"', t49 RETURNING json) FROM t49;
ERROR: JSON path expression must be of type jsonpath, not of type t49
これまでは、例えばパーティション境界の値を列のデータ型にキャストする際のエラーで、誤った列名が表示されることがありました。
(誤動作例: b列の型不一致なのにエラーでa列を出している)
db1=# CREATE TABLE t50 (a int, b int, c int) PARTITION BY RANGE (a, b);
db1=# CREATE TABLE t50_p1 PARTITION OF t50
FOR VALUES FROM (minvalue, now()) TO (100, 100);
ERROR: specified value cannot be cast to type integer for column "a"
例えば、バックアップマニフェスト内のタイムライン番号が不一致でエラーが発生した場合、本来、終了タイムライン番号を表示すべきところで、開始タイムライン番号を表示する誤りがあり、修正されました。
§ § § § § § § § § § § § § § § § § § §
これまではaarch64マシンでコンパイルに失敗しました。
これまでは、この判定が間違っていたため、非同期I/Oバッファの最適化に失敗していました。その結果、バックエンドプロセスの終了が必要以上に遅くなっていました。
mesonビルドの場合には問題は発生しません。
PostgreSQL16以降ではプラットフォームで提供されているなら、posix_fallocate()を使用してリレーションファイルを拡張します。しかし、posix_fallocate()が使えたとしても、一部のファイルシステムでは不具合がありました。
BTRFSの圧縮が無効化されたり、古いLinuxカーネルバージョンのXFSで偽性のENOSPC(空き領域なし)が生じることがありました。
その回避策として、file_extend_methodパラメータを「write_zeros」に設定することで、旧方式(ゼロのブロックを書き込む)でのファイル拡張ができるようになりました。
Windowsで「COPY TO/FROM PROGRAM」などで子プロセスを起動する際、子プロセスにファイルハンドルがリークしていました。大きな被害はありませんが望ましくありませんでした。修正によりPOSIXと同様の動作になりました。
サーバーに未接続の場合、%P(パイプラインステータス)が他のプロンプトエスケープと同様に何も表示されないように修正されました。
これまでは、pg_dumpの実行と同時にシーケンスが削除された場合、それがダンプ対象ではない場合でも、エラーとなっていましたが、エラーにならないように修正されました。
また、pg_dumpの実行でシーケンスの読み取り権限がない場合、誤った値をバックアップに出力していましたが、正しくエラーになるように修正されました。
この設定の値をダンプする必要がある場合、pg_dumpは間違った引用符ルールを適用していました。
サブスクリプション関連のオブジェクトの処理でアサート失敗が起きていました。アサートを無効にした実運用むけビルドでは障害の悪影響は特にありません。
パイプラインモードで問合せのエラーが発生した後に複数の\syncpipelineコマンドが実行された場合、これまでは「ERROR: failed to exit pipeline mode」と誤ったエラーメッセージを表示するか、アサートを有効ビルドではアサート失敗となっていました。
他の変更できる変数では、変更後の値を表示するようになっています。
これらが有効な値であるのに設定ができないために、マルチトランザクションIDが周回するタイミングでpg_upgradeが失敗する可能性がありました。
このために「CREATE INDEX CONCURRENTLY」で作成されたインデックスに対して、誤ってエラーを報告していました。
これまでは、half-deadページに親のダウンリンクが存在しない状態を「ERROR: mismatch between parent key and child high key ...」と誤ってエラー報告していました。
これまでは「ERROR: block ... is not true root」エラーを誤って報告していました。
これまでは、NUMAページの状態を保存する配列の要素サイズを、本来はintで十分なところをuint64として扱っていたため、必要な量の2倍のメモリを確保していました。
プランナ統計情報に整数最大値(INT_MAX)が含まれる場合にオーバーフローが発生して、不正確な選択度推定による劣ったプランが作成される可能性がありました。
従来の実装では、不完全なマルチバイト文字が内部実装上のlower()関数に引数として渡されるケースがあり、その結果、文字エンコーディングに関する予期せぬエラーや、誤った問い合わせ結果がもたらされる可能性がありました。
今回の変更は1976年以前のバハ・カリフォルニアの歴史的データのみです。
インプレイス(データを直接書き換える形)での更新はトランザクションのロールバックでも保持されるため、非トランザクション型の無効化メッセージを送信するようになりました。また、他のセッションが更新内容を参照できるようになる前に、更新内容をWALに記録することを保証されるようになりました。これらの修正により、リレーションのfrozen-XID属性が不整合になるシナリオを防止されます。frozen-XID属性の不整合が発生すると、CLOG(コミットログ)の早期切り捨てや、その後の「could not access status of transaction」エラーの原因となる可能性があります。