web-dev-qa-db-ja.com

Postgresはネストされたトランザクションまたは自律型トランザクションをサポートしていますか?

コードの一部を独自のトランザクションとしてコミットする必要がある状況があります。
テーブルを作成しましたsubtransaction_tbl

CREATE TABLE subtransaction_tbl
(
  entryval integer
)

そして言語plpython3uの関数:

CREATE FUNCTION subtransaction_nested_test_t() RETURNS void
AS $$
plpy.execute("INSERT INTO subtransaction_tbl VALUES (1)")
with plpy.subtransaction():
    plpy.execute("INSERT INTO subtransaction_tbl VALUES (2)")
$$ LANGUAGE plpython3u;

最初の状況:

BEGIN TRANSACTION;
INSERT INTO subtransaction_tbl VALUES (4);
select  subtransaction_nested_test_t();
COMMIT TRANSACTION;

テーブルのエントリは正しいです:1,2,4

2番目の状況:

BEGIN TRANSACTION;
INSERT INTO subtransaction_tbl VALUES (4);
select  subtransaction_nested_test_t();
ROLLBACK TRANSACTION;

テーブルの値が入力されていません

期待していた1または2をテーブルに追加する必要がありますsubtransaction_tblしかし、驚いたことに、値は挿入されませんでした。新しいサブトランザクションが関数によって開かれ、親トランザクションに依存するべきではないと想像しました。私が正しいかどうか知らせてください。

Postgresには自律的なトランザクションがありますか?または、plpython3u関数を変更する必要がありますか?

19
SarthAk

Postgres 11より前のPostgresにはno自律型トランザクションがあり、SQL procedures が追加されました。 関数で行われたすべてのことは、トランザクションでロールバックされます。

これは機能の議論です:

Postgres 10以前では、回避策は(ab-)use dblink を使用することです:

SAVEPOINT の関連概念もあります。 (同じではありません!):

plpython

plpythonにはsubtransactionswith plpy.subtransaction():)がありますが、自律型トランザクションとは異なります。別のCOMMITはありません。それがするすべては、それらをアトミックにするためにいくつかのステートメントを一緒にバンドルすることです。これがないと、途中で例外が発生し、その例外をキャッチすると、この例外までのコードのみが実行されます。それをサブトランザクションにラップする場合、それは全部かゼロかです。これは、自律型トランザクションではなく、SAVEPOINTを使用するようなものです。 ドキュメントごと

サブトランザクションコンテキストマネージャーはエラーをトラップしません。スコープ内で実行されたすべてのデータベース操作がアトミックにコミットまたはロールバックされることを保証するだけです。

18

Postgresはネストされたトランザクションをサポートしますが、それらは従来のSQLとは異なり、ネストされた部分的なポイントを持つトランザクションに似ています。

最上位には常に通常のBEGIN/COMMIT/ROLLBACKがあり、ネストされたレベルでは次のコマンドを使用する必要があります。

  • SAVEPOINT name-トランザクションに固有の名前で新しいセーブポイントを作成します
  • RELEASE SAVEPOINT name-セーブポイントをコミットしますが、含まれているトランザクションがコミットする場合にのみ持続します
  • ROLLBACK TO SAVEPOINT name-セーブポイントをロールバックします

また、次のことも確認する必要があります。

  • SAVEPOINTに使用される名前は一意です。
  • 1つのSAVEPOINTでの失敗は、上位レベルに伝達されます。

最後のビットは、自動的に実行できるライブラリを使用しない限り、少し注意が必要です。

pg-promise と書いたとき、これら2つの規定が保証されていることを確認しました。

  • トランザクションレベルに基づいて、セーブポイント名がlevel_1level_2などのように自動的に生成されます。
  • 子トランザクションが失敗した場合に備えて、ROLLBACK TO SAVEPOINT nameに加えてトップレベルのROLLBACKを実行します。すべて標準のpromise-chainingロジックに基づいて構築されています。

説明されているPostgreSQLのネストされたトランザクションの limitations も参照してください...

19
vitaly-t