このリリースは 12.15 からの修正リリース(2023年 8月 10日リリース)です。
12.X からのアップデートではダンプ、リストアは不要です。
しかしながら、NULL値を含む列に BRINインデックスを使っている場合には、インデックスを再構築することを推奨します。
また、12.10 よりも前のバージョンからアップデートする場合には、12.10 のリリース情報も参照してください。
PostgreSQL 12.15 から 12.16 への変更点
15.4、14.9、13.12、12.16、11.21 の各バージョンが同時にリリースされており、本ページでは共通の記載としています。各修正項目が適用されるバージョン系列番号を項目末尾に括弧書きで記載しています。
- 拡張のスクリプトで、クォートやバックスラッシュ、ドル記号を含む名前のスキーマや所有者名を置き換えすることが禁止されました。 (Noah Misch) (15)(14)(13)(12)(11)
- MERGE が行単位セキュリティ(RLS)ポリシーを適切に適用するように修正されました。 (Dean Rasheed) (15)
- 揮発性の関数を含む結合条件のラテラル結合で、Memoize を使わないように修正されました。 (Richard Guo) (14)(15)
- BRINインデックスで、行の無い範囲と全てが NULL の範囲を混同して、誤った問い合わせ結果を返す誤りが修正されました。 (Tomas Vondra) (15)(14)(13)(12)(11)
- DROP DATABASE が中断されたときに破損したデータベースが残ってしまうのを回避するようになりました。 (Andres Freund) (15)(14)(13)(12)(11)
- パーティションインデックスで、有効であるか未作成であるかが正しく印付けされるようになりました。 (Michael Paquier) (15)(14)(13)(12)(11)
- ALTER TABLE .. ATTACH PARTITION で、パーティションインデックスと子インデックスを照合するとき、無効な子インデックスを無視するようになりました。 (Michael Paquier) (15)(14)(13)(12)(11)
- 全てのパーティションがアタッチされた後、パーティションインデックスを有効と印付けするとき、エラーになることがあり、修正されました。 (Michael Paquier) (15)(14)(13)(12)(11)
- 拡張に拡張の指定スキーマ外のオブジェクトが含まれている場合に、ALTER EXTENSION SET SCHEMA が、エラーをだすようになりました。 (Michael Paquier, Heikki Linnakangas) (15)(14)(13)(12)(11)
- テーブルアクセスメソッドの依存関係の追跡について修正されました。 (Michael Paquier) (15)
- プランナで一意性の証明に部分的なユニークインデックスを使わないようになりました。 (David Rowley) (15)(14)(13)(12)(11)
- 偽性の定数の JOIN句を伴う外部テーブルの結合で、不正なプラン生成を回避するようになりました。 (Etsuro Fujita) (15)(14)(13)(12)(11)
- RLS(行単位セキュリティ)の式とセキュリティバリアビューにおいて、ルールアクションを展開するときに、副問い合わせを正しく扱うようになりました。 (Tom Lane) (15)(14)(13)(12)(11)
- SERIALIZABLE分離モードにおける衝突検出での競合条件が修正されました。 (Thomas Munro) (15)(14)(13)(12)(11)
- 継承テーブルまたはパーティションテーブルを対象とした、EvalPlanQual検査の誤動作が修正されました。 (Tom Lane) (15)(14)
- 外側の入れ子ループ(Nested Loop)に由来するパラメータを含むキーのハッシュを伴うハッシュ結合について、修正されました。 (Tom Lane) (15)(14)(13)(12)
- 複合型列のフィールドを更新しようとするときの間欠的に生じる障害が修正されました。 (Tom Lane) (15)(14)(13)(12)(11)
- トリガを伴う UPDATE 文のいくつかの場合で、問い合わせ処理内におけるメモリリークが防止されました。 (Tomas Vondra) (15)(14)(13)(12)
- Incremental Sort 実行プランノードが再スキャンされるときの、問い合わせ処理内におけるメモリリークが防止されました。 (James Coleman, Laurenz Albe, Tom Lane) (15)(14)(13)
- jsonpath の datetime() メソッドの入力として、小数点以下の秒を受け付けできるようになりました。 (Tom Lane) (15)(14)(13)
- 極めて複雑なテキスト検索で、スタックオーバーフローによるクラッシュが防止されました。 (Tom Lane) (15)(14)(13)(12)(11)
- pg_hba.conf と pg_ident.conf で 10240バイトまでのトークンが使えるようになりました。 (Tom Lane) (15)(14)(13)(12)(11)
- 拡張が GUCプレフィックスの予約を宣言しているときに、該当する既存の設定項目が確実に検査されるようになりました。 (Karina Litskevich, Ekaterina Sokolova) (15)
- C++ の out of memory の条件に誤解があり、修正されました。 (Heikki Linnakangas) (15)(14)(13)(12)(11)
- plancache.c での稀なヌルポインタのクラッシュが修正されました。 (Tom Lane) (15)(14)(13)
- ロジカルレプリケーションのサブスクリプションが DROP されたときに、そのサブスクリプションに対する統計エントリのリークが回避されました。 (Masahiko Sawada) (15)
- ページ解放が結果としてフリースペース範囲を合体させる場合に、おそらく有用な共有メモリセグメントの追跡を失うことがあり、修正されました。 (Dongming Liu) (15)(14)(13)(12)(11)
- VACUUM がある種の btreeインデックスの破損を検出した後も継続できるようになりました。 (Peter Geoghegan) (15)(14)(13)(12)(11)
- VACUUM が pg_database.datfrozenxid や pg_database.datminmxid で無効なデータを検出した後、WrapLimitsVacuumLock が確実に解放されるようになりました。 (Andres Freund) (15)(14)(13)(12)(11)
- クラッシュリカバリ時にプリペアドトランザクションの二重リプレイが回避されました。 (suyu.cmj, Michael Paquier) (15)(14)(13)(12)(11)
- 新しく作成されたけれどもまだ空のテーブルが、次のチェックポイントでfsync されるようになりました。 (Heikki Linnakangas) (15)(14)(13)(12)(11)
- UNLOGGED なインデックスの初期フォーク作成を必ず WAL に記録するようになりました。 (Heikki Linnakangas) (15)(14)(13)(12)(11)
- 偽性の「missing contrecord」エラーが出力されないようになりました。 (Thomas Munro) (15)
- jsonpath コードの過度に厳密なアサーションが修正されました。 (David Rowley) (15)(14)(13)(12)
- 既にアボートされたトランザクションで、拡張クエリプロトコルを使用して空ステートメントを処理する際のアサート失敗を回避するようになりました。 (Tom Lane) (15)(14)(13)(12)(11)
- stats_fetch_consistency 設定がトランザクション内で変更された場合のアサート失敗を回避するようになりました。 (Kyotaro Horiguchi) (15)
- contrib/fuzzystrmatch の Soundex の difference() 関数が空の入力を正常に処理できるように修正されました。 (Alexander Lakhin, Tom Lane) (15)(14)(13)(12)(11)
- contrib/hstore で入力の空白チェックが強化されました。 (Evan Jones) (15)(14)(13)(12)(11)
- contrib/intarray の gist__int_ops インデックス演算子クラスを使用した最大サイズを超過した入力配列が禁止されました。 (Ankit Kumar Pandey, Alexander Lakhin) (15)(14)(13)(12)(11)
- contrib/intarray の GiSTインデックスエントリで無駄な二重展開を回避するようになりました。 (Konstantin Knizhnik, Matthias van de Meent, Tom Lane) (15)(14)(13)(12)(11)
- contrib/pageinspect の gist_page_items()関数が、インデックスに INCLUDE句で追加された列が含まれている場合でも動作するように修正されました。 (Alexander Lakhin, Michael Paquier) (15)(14)
- psql で標準入出力が端末でない場合に、PSQL_WATCH_PAGER環境変数を無視し、ページャを使わないようになりました。 (Tom Lane) (15)
- pg_dump で、関数定義時に一意インデックスへの依存関係を必要とする、BEGIN ATOMIC を用いた SQL関数を正しく処理できるように修正されました。 (Tom Lane) (15)(14)
- pg_dumpで、依存関係ループの問題に関する詳細情報の表示が改善されました。 (Tom Lane) (15)
- pgbenchで、preparedモードで空のパイプラインに対して生じるクラッシュが回避されました。 (Álvaro Herrera) (15)
- pg_index.indisreplident がリレーションキャッシュのエントリ内で常に最新となるようになりました。 (Shruthi Gowda) (15)(14)(13)(12)(11)
- make_etagsスクリプトで、Exuberant ctags 以外の ctag が動作するように修正されました。 (Masahiko Sawada) (15)
- アーカイブが有効で、二相トランザクションのリカバリが必要な場合に、スタンバイサーバの昇格時に発生する障害が修正されました。 (Julian Markwort) (14)(13)
- 遅延チェックポイント終了フラグの再初期化漏れが修正されました。 (suyu.cmj) (14)(13)(12)(11)
- OpenSSL 3.0.0 以降でのコンパイル時に非推奨の警告を表示しないようになりました。 (Peter Eisentraut) (13)(12)(11)
この制限は信頼された拡張に対する SQLインジェクションを防止するものです。
拡張のスクリプトには @extschema@ や @extowner@ といったプレースホルダを使うことができます。これに対して、作りこまれたスキーマ名や所有者名を適用させることで、SQLインジェクションが狙えました。標準で付属している拡張には脆弱性はありません。また、攻撃者はデータベース作成権限が必要です。(CVE-2023-39417)
MERGE が UPDATE アクションを実行するとき、ターゲットテーブルに定義された UPDATE と SELECT の RLSポリシーを適用して、通常の WHERE句 を持つ UPDATE の動作と一貫性を持たせるべきです。しかしながら、そうなっておらず、MERGEではINSERT の RLSポリシーを INSERT と UPDATE のアクションに適用していました。(CVE-2023-39418)
加えて、MERGE が DO NOTHING アクションを行うとき、ターゲットテーブルのDELETE の RLSポリシーを、既存行に適用していました。こちらはセキュリティ障害ではありませんが、予期せぬエラーを引き起こす可能性がありました。
揮発性のフィルタ条件を含むサブプランに Memoize を適用すると、誤った問い合わせ結果がもたらされます。この検査が一部漏れていて、LATERAL を使う場合にこのような実行プランが発生する可能性がありました。
本障害により、返すべき NULL値の結果を返さない可能性があります。NULL を検索するかもしれない BRINインデックスは、バージョンアップ後に再構築してください。
(誤動作例: SELECT結果で 1000行が返るべきところで 0行が返っている) db1=# CREATE TABLE t_brin (id int, v text); db1=# CREATE INDEX ON t_brin USING brin (id); db1=# INSERT INTO t_brin SELECT null, null FROM generate_series(1, 1000); db1=# INSERT INTO t_brin SELECT g, g::text FROM generate_series(1001, 2000) g; db1=# SET enable_seqscan TO false; db1=# SELECT id FROM t_brin WHERE id IS NULL; id ---- (0 rows)
これまで DROP DATABASE が取消できない段階に進んだ後に中断された場合、対応する pg_database の行の削除はロールバックされてしまうため、DROP を中断したデータベースは(中身はおそらく破損しているにもかかわらず)アクセス可能な状態で残りました。
取消不能な操作を開始する前に、データベースに使用不能(invalid) の印付けをするように修正されました。この印付けをした後の何らか失敗で、データベースは部分的に残った状態になりますが、再度 DROP DATABASE をする以外のことはできなくなります。例えば接続を試みると「ERROR: cannot connect to invalid database "..."」というエラーになります。
新たなパーティションインデックスが既存インデックスと一致するけれども、一部パーティションにおいては無効なインデックスである場合に、パーティションインデックスは有効と印付けしてしまう可能性がありました。これにより、その後のパーティションテーブルに対する問い合わせで、誤動作(誤った問い合わせ結果)やアサート失敗を引き起こす可能性がありました。
アタッチするテーブルの無効なインデックスは無視されて、その代わりに新たな子インデックスが作成されるようになりました。
インデックスの pg_index エントリの更新では、有効フラグ(indisvalid)列以外の列について古いデータを使う可能性がありました。報告された症状の例は、トランザクション内でいくつかの DDL 操作をした後にパーティションのアタッチを行うと「ERROR: attempted to update invisible tuple」が出ることです。
このような場合には以前から以下のエラーが出る実装になっていましたが、検出できないケースがあり、予期せぬ振る舞いが生じていました。
ERROR: extension "ext1" does not support SET SCHEMA DETAIL: obj1 is not in the extension's schema "extscm1"
ALTER TABLE ... SET ACCESS METHOD は、テーブルのアクセスメソッドを変更するときに、関連する pg_depend のエントリを更新することに失敗していました。
この障害により、組み込みでないアクセスメソッドを使っているとき、依存するオブジェクトが未だあるのにアクセスメソッドを DROP できてしまう危険性がありました。
なお、バージョンアップで本修正を適用しても、既に欠損している pg_depend のエントリが修復されることはありません。
テーブルをスキャンするときにその部分インデックスを使わない場合には読み取った行の一意性が保たれないかもしれないため、これにより誤ったプランを作ってしまう可能性がありました。結果として誤った問い合わせ結果も生じます。
不正なプランにより、結果として誤った問い合わせ結果が生じる可能性もあります。
以下の例では、リモートサーバ側で結合を行うプランとなっていますが、「CURRENT_USER = SESSION_USER」の条件が消えてしまっています。このような結合をリモートサーバ側にプッシュダウンすることは、今のところサポートされていません。このような結合対象テーブルと無関係な条件が付加されている場合には、ローカルサーバ側で結合するプランを生成するように修正されました。
(不正なプラン生成の例) db1=# explain (verbose, costs off) SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1 AND CURRENT_USER = SESSION_USER) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: t1.c1, t2.c1, t1.c3 -> Foreign Scan Output: t1.c1, t2.c1, t1.c3 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2) Remote SQL: SELECT r1.c1, r2.c1, r1.c3 FROM (public.t1 r1 INNER JOIN public.t2 r2 ON (((r1.c1 = r2.c1)))) ORDER BY r1.c3 ASC NULLS LAST, r1.c1 ASC NULLS LAST (6 rows)
プラン作成時にアサート失敗や奇妙なエラーを引き起こす可能性がありました。
ビットマップヒープスキャンを使っていて、GINインデックスを使っていて、さらに、最初は空の btree インデックスを調べるときに、衝突が見落とされる可能性がありました。
このような場合、不適切に衝突しているトランザクションのコミットを許すことになるため、トランザクション分離に失敗する結果を招きます。これにより、誤った問い合わせ結果や誤った更新結果が生じる可能性がありました。
EvalPlanQual検査は、READ COMMITTED分離モードのトランザクションで実行される処理です。この誤りにより、READ COMMITTED分離モードで UPDATE や DELETE動作が、同時更新と衝突しているためスキップされるべきところでも、実行されました。これにより、誤った問い合わせ結果や誤った更新結果が生じる可能性がありました。
(報告された誤動作ケース) db1=# CREATE TABLE t12p (id int, v int); db1=# CREATE TABLE t12c1 () INHERITS (t12p); db1=# CREATE TABLE t12c2 () INHERITS (t12p); db1=# INSERT INTO t12c1 VALUES (1,1); db1=# INSERT INTO t12c2 VALUES (1,1); (トランザクション1) db1=# BEGIN; BEGIN db1=*# UPDATE t12p SET v = 2 WHERE v = 1; UPDATE 2 (トランザクション2) db1=# BEGIN; BEGIN db1=*# DELETE FROM t12p WHERE v = 1; (ここでロック待ちになる) db1=*# COMMIT; COMMIT (ロック待ちが解放されるが 1行だけ DELETEされる誤動作) DELETE 1 db1=*# SELECT * FROM t12p; id | v ----+----- 1 | 2 (1 row) db1=*# COMMIT; COMMIT
そのようなパラメータの値が変更された後で結合を再スキャンするとき、ハッシュテーブルを再構築しなければなりませんが、それをしていませんでした。その結果、結合の出力行が失われて誤った問い合わせ結果が生じることがありました。
(バージョン15.3 での障害動作例) db1=# CREATE TABLE t13a AS SELECT generate_series(1, 10)::int AS c1; db1=# CREATE TABLE t13b AS SELECT c1 AS c2 FROM t13a; db1=# CREATE TABLE t13c AS SELECT c1 AS c3 FROM t13a; db1=# SET enable_hashjoin TO off; db1=# SELECT ta.c1, s.* from t13a ta, LATERAL ( SELECT tb.c2, tc.c3 from t13b tb JOIN t13c tc ON tb.c2 = tc.c3 + ta.c1 ORDER BY 1,2) s; ⇒ 45行の結果が返る(Hash Join 以外の方式で、正しい結果) db1=# SET enable_hashjoin TO on; db1=# SET enable_mergejoin TO off; db1=# SELECT ta.c1, s.* from t13a ta, LATERAL ( SELECT tb.c2, tc.c3 from t13b tb JOIN t13c tc ON tb.c2 = tc.c3 + ta.c1 ORDER BY 1,2) s; ⇒ 9行の結果が返る(Hash Join が使われて、誤った結果)
複合型列の値全体が TOAST外部格納を必要とするほど大きい場合、内部的なキャッシュ処理のタイミングによってはエラー(「ERROR: unsupported byval length: ...」)やサーバプロセスのクラッシュが発生しました。
(修正前バージョンの動作、修正後は 2つ目の SELECT も成功する) db1=# SELECT jsonb_path_query('"2023-08-10 12:34:56+9"', '$.datetime()'); jsonb_path_query ----------------------------- "2023-08-10T12:34:56+09:00" (1 row) db1=# SELECT jsonb_path_query('"2023-08-10 12:34:56.789+9"', '$.datetime()'); ERROR: datetime format is not recognized: "2023-08-10 12:34:56.789+9"
修正後は max_stack_depth 設定に基づいて、スタックの上限超過を報告する ERROR で問い合わせが終了するようになります。
これまでは 256バイトが上限で、場合によっては長さが不足することがありました。そのような場合、「LOG: authentication file token too long, skipping: ...」が出て、設定ファイルの読み込みに失敗します。LDAP認証で長いオプション設定値を与えるときに失敗するケースが報告されました。
誤って一部のエントリが読み飛ばされて、見逃されることがありました。
JIT が使われている場合に、C++ の「new」で out of memory になるとき、想定された C++ の例外に進むべきところ、PostgreSQL の FATAL エラーになっていました。
セグメントは新しいフリースペースの大きさに対して適切な bin (集計区間) に移動されて、後続の検索で見つかるようになりました。この問題により、解放されたメモリが十分あるはずであるのに、動的共有メモリの割り当てに失敗することが報告されました。
無効な隣接ページリンクを検出すると、問題をログ出力しますが VACUUM処理は継続するようになります。これまでは ERROR を出して中断していました。REINDEX をしなければ壊れたインデックスは修復されませんが、そうするまで VACUUM を完了できないことは、より悪い問題を引き起こすリスクになります。
このロックはセッション終了や何らか他のエラーに遭遇した時には解放されますが、ロック解放に失敗することで後にデッドロックを引き起こす可能性がありました。
いくつかの既にディスクにフラッシュされた 2相トランザクション状態データを伴うチェックポイント途中でのクラッシュの後、クラッシュリカバリがプリペアドトランザクションを 2回リプレイしようとして、startup プロセスで「FATAL: lock is already held」などの致命的なエラーが発生する可能性がありました。
これを行わないと、オペレーティングシステムのクラッシュによって空のファイルが失われた場合、その後のテーブル操作が「could not open file」エラーで失敗する可能性がありました。
UNLOGGEDインデックスのメインデータフォークは WAL に記録されませんが、クラッシュ後にインデックスをリストアするための一貫した状態を確保するために、その初期フォークは WAL に記録する必要があります。初期フォークが空の場合に WAL書き出しが行われていなかったため、修正されました。これは標準的インデックスアクセスメソッド(AM) では生じないケースですが、一部の拡張ではおそらく該当します。
pg_waldump と walsender からの不正確な苦情がログに記録されるのを避けるために、この場合を単純な WAL の終了として扱います。WALレコードに問題がない場合でも、pg_waldump 実行時に下記のエラーメッセージが出力されていました。
pg_waldump: error: error in WAL record at 0/1FFFF98: missing contrecord at 0/1FFFFE0
クエリが「like_regex」の結果に「.type()」演算子を適用した場合にアサート失敗していました。非アサートビルドではバグはありません。
(アサートビルドでバックエンドプロセスが終了する SQL文の例) SELECT jsonb_path_query('["string", "string"]', '($[0] like_regex ".{7}").type()');
アルファベット文字を含まない入力文字列を使用すると、予測不能な出力が発生しました。
場合によっては、文字が誤って空白文字として認識されて捨てられてしまうことがありました。
Mac OS X の en_US.UTF-8 ロケールは isspace(0x85) をバグで真と返すため、UTF-8 では \u0105 が 0xc4 0x85 とエンコードされ、0x85 が空白文字と解釈されていました。
以前は、このような場合に NOTICE メッセージで報告しますが、そのまま続行して無効なインデックスエントリを作成していました。これはインデックスの読み取り時にクラッシュを引き起こす危険があります。「ERROR: input array is too big (.. maximum allowed, .. current), ...」というエラーメッセージを出して、データ更新するコマンドを中断するようになりました。
(これまで報告されていた NOTICEメッセージ例) NOTICE: input array is too big (199 maximum allowed, 3001 current), use gist__intbig_ops opclass instead
インデックスが INCLUDE指定によりインデックスキー以外の列を含んでいた場合、gist_page_items() はインデックスのリーフページで情報を表示できなかったり、非リーフページで無条件にクラッシュしていました。
\watch 以外のコマンドでの PSQL_PAGER と同じ扱いになります。
GROUP BY や ON CONFLICT句を使っている場合に該当する可能性がありました。そのような関数は一意インデックスの後にダンプする必要がありますが、そうなっておらず、「warning: could not resolve dependency loop」という警告が出力されました。
詳細情報は infoレベルで出力されていましたが、-v (--verbose ) 指定無しのデフォルトのログレベルでは出力されないため、warningレベルで出力するようになりました。
ここでの空のパイプラインとは pgbenchスクリプトで \startpipeline の直後に\endpipeline を記述した場合を指します。
場合によっては値が古い可能性がありました。リレーションキャッシュのコピーに依存するコードは本体にないため、PostgreSQL に限って言えば潜在的なバグに過ぎません。ただし、これに起因してバグが発生する拡張が存在する可能性があります。
必要な二相トランザクションが最新の (部分的な) ログセグメントに記録されている場合、「ERROR: requested WAL segment .. has already been removed」という誤ったメッセージが出力され、昇格に失敗していました。
チェックポイントが不必要に遅延したり、アサート有効ビルドでアサート失敗したりする可能性がありました。