postgresql:prepare transaction

4372 ワード

一般事務はsessionレベルであり、prepare transactionは現在のサービスを現在のsessionと分離し、恒久化記録を行い、事務提出成功確率を高めることがメリットとなります。
普通の事務はsessionレベルで、comitの過程で、もしserverに異常が発生したら、システムが崩壊し、電源が切れるなど、sessionが消えて、comitが失敗します。prepare transactionは耐久化された記録であり、システムが崩壊しても、再起動後はまだcomitができます。
prepare transactionは主に二つの段階の提出を実現するために使われます。一般的に事務管理器で使われます。普通のclientは直接使用しないでください。begin、start transactionを使うべきです。
前提:システムパラメータmax_prepared_tractionsは0以上の設定が必要です。alter systemを参照してください。
max_ならprepared_tractionsは0でエラーが発生します。
postgres=# prepare transaction 'prep1';
ERROR:  prepared transactions are disabled
HINT:  Set max_prepared_transactions to a nonzero value.
prepare transactionは特別で、prepare transpactionを実行した後、元の事務の役割領域はすぐに終わりました。照会事務にinsertのデータも存在しません。この時もまたBeginの新しい事務ができます。
postgres=# begin;
BEGIN
postgres=# insert into t1 values(666, 'test666');
INSERT 0 1
postgres=# select * from t1 where id=666;
 id  |  name
-----+---------
 666 | test666
(1 row)

postgres=# prepare transaction 'prep1';
PREPARE TRANSACTION

postgres=# select * from t1 where id=666;
 id | name
----+------
(0 rows)


postgres=# select * from pg_prepared_xacts;
 transaction |  gid  |           prepared            |  owner   | database
-------------+-------+-------------------------------+----------+----------
        3316 | prep1 | 2021-06-25 01:48:39.618381+00 | postgres | postgres
(1 row)

postgres=# \q
comit preparedはprepare transactionのsessionで実行してもいいし、他のセッションで実行してもいいし、server再起動後に実行してもいいです。
[postgres@hgcndn ~]$ psql -p 5432 -U postgres -h 127.0.0.1
psql (12.4)
Type "help" for help.

postgres=#  select * from pg_prepared_xacts;
 transaction |  gid  |           prepared            |  owner   | database
-------------+-------+-------------------------------+----------+----------
        3316 | prep1 | 2021-06-25 01:48:39.618381+00 | postgres | postgres
(1 row)

postgres=# select * from t1 where id=666;
 id | name
----+------
(0 rows)

postgres=# commit prepared 'prep1';
COMMIT PREPARED

postgres=# select * from t1 where id=666;
 id  |  name
-----+---------
 666 | test666
(1 row)

postgres=# select * from pg_prepared_xacts;
 transaction | gid | prepared | owner | database
-------------+-----+----------+-------+----------
(0 rows)

rollback preparedは、prepare transactionのsessionで実行することができ、他のセッションで実行することもでき、server再起動後に実行することもできます。
postgres=# begin;
BEGIN
postgres=# insert into t1 values(777, 'test777');
INSERT 0 1
postgres=# prepare transaction 'prep2';
PREPARE TRANSACTION
postgres=#  select * from pg_prepared_xacts;
 transaction |  gid  |           prepared            |  owner   | database
-------------+-------+-------------------------------+----------+----------
        3317 | prep2 | 2021-06-25 02:21:52.226903+00 | postgres | postgres
(1 row)

postgres=#
postgres=# rollback prepared 'prep2';
ROLLBACK PREPARED
postgres=#
postgres=#  select * from pg_prepared_xacts;
 transaction | gid | prepared | owner | database
-------------+-----+----------+-------+----------
(0 rows)
特に、トランザクションでset(非localの場合)については、set後にprepare transpactionを行うと、setのパラメータは継続して有効となります。pg公式文書の説明を引用して、「Thus,in this one respect PREPARE TRANSACTION acts more like COMMIT than ROLLBACK.」
postgres=# show client_encoding;
 client_encoding
-----------------
 UTF8
(1 row)

postgres=# begin;
BEGIN
postgres=# set client_encoding  to 'UNICODE';
SET
postgres=# show client_encoding;
 client_encoding
-----------------
 UNICODE
(1 row)

postgres=# prepare transaction 'prep1';
PREPARE TRANSACTION
postgres=# show client_encoding;
 client_encoding
-----------------
 UNICODE
(1 row)
参考資料https://www.postgresql.org/docs/13/sql-prepare-transaction.html https://www.postgresql.org/docs/13/sql-commit-prepared.html https://www.postgresql.org/docs/13/sql-rollback-prepared.html