diff options
author | Michael Paquier <michael@paquier.xyz> | 2024-11-28 09:43:22 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2024-11-28 09:43:22 +0900 |
commit | 76653134ae87c7c08e1eb58da07af9f64ec78ccb (patch) | |
tree | af3d6e120a49af4381d78e8fdca563b066763f6d | |
parent | c26831e7362487b4f2c606e1223207baa1d495cb (diff) | |
download | postgresql-76653134ae87c7c08e1eb58da07af9f64ec78ccb.tar.gz postgresql-76653134ae87c7c08e1eb58da07af9f64ec78ccb.zip |
Revert "Handle better implicit transaction state of pipeline mode"
This reverts commit d77f91214fb7 on all stable branches, due to concerns
regarding the compatility side effects this could create in a minor
release. The change still exists on HEAD.
Discussion: https://postgr.es/m/CA+TgmoZqRgeFTg4+Yf_CMRRXiHuNz1u6ZC4FvVk+rxw0RmOPnw@mail.gmail.com
Backpatch-through: 13
-rw-r--r-- | doc/src/sgml/protocol.sgml | 21 | ||||
-rw-r--r-- | src/backend/access/transam/xact.c | 13 | ||||
-rw-r--r-- | src/backend/tcop/postgres.c | 18 | ||||
-rw-r--r-- | src/bin/pgbench/t/001_pgbench_with_server.pl | 155 |
4 files changed, 23 insertions, 184 deletions
diff --git a/doc/src/sgml/protocol.sgml b/doc/src/sgml/protocol.sgml index 84eec5da7e3..59dbd13d6f6 100644 --- a/doc/src/sgml/protocol.sgml +++ b/doc/src/sgml/protocol.sgml @@ -1070,17 +1070,16 @@ SELCT 1/0;<!-- this typo is intentional --> <para> If the client has not issued an explicit <command>BEGIN</command>, - then an implicit transaction block is started and each Sync ordinarily - causes an implicit <command>COMMIT</command> if the preceding step(s) - succeeded, or an implicit <command>ROLLBACK</command> if they failed. - This implicit transaction block will only be detected by the server - when the first command ends without a sync. There are a few DDL - commands (such as <command>CREATE DATABASE</command>) that cannot be - executed inside a transaction block. If one of these is executed in a - pipeline, it will fail unless it is the first command after a Sync. - Furthermore, upon success it will force an immediate commit to preserve - database consistency. Thus a Sync immediately following one of these - commands has no effect except to respond with ReadyForQuery. + then each Sync ordinarily causes an implicit <command>COMMIT</command> + if the preceding step(s) succeeded, or an + implicit <command>ROLLBACK</command> if they failed. However, there + are a few DDL commands (such as <command>CREATE DATABASE</command>) + that cannot be executed inside a transaction block. If one of + these is executed in a pipeline, it will fail unless it is the first + command in the pipeline. Furthermore, upon success it will force an + immediate commit to preserve database consistency. Thus a Sync + immediately following one of these commands has no effect except to + respond with ReadyForQuery. </para> <para> diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index cb8bedc46df..4a2ea4adbaf 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -3501,6 +3501,16 @@ PreventInTransactionBlock(bool isTopLevel, const char *stmtType) stmtType))); /* + * inside a pipeline that has started an implicit transaction? + */ + if (MyXactFlags & XACT_FLAGS_PIPELINING) + ereport(ERROR, + (errcode(ERRCODE_ACTIVE_SQL_TRANSACTION), + /* translator: %s represents an SQL statement name */ + errmsg("%s cannot be executed within a pipeline", + stmtType))); + + /* * inside a function call? */ if (!isTopLevel) @@ -3611,6 +3621,9 @@ IsInTransactionBlock(bool isTopLevel) if (IsSubTransaction()) return true; + if (MyXactFlags & XACT_FLAGS_PIPELINING) + return true; + if (!isTopLevel) return true; diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 26aaaf19e19..3f427f1b47f 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -2780,17 +2780,6 @@ start_xact_command(void) xact_started = true; } - else if (MyXactFlags & XACT_FLAGS_PIPELINING) - { - /* - * When the first Execute message is completed, following commands - * will be done in an implicit transaction block created via - * pipelining. The transaction state needs to be updated to an - * implicit block if we're not already in a transaction block (like - * one started by an explicit BEGIN). - */ - BeginImplicitTransactionBlock(); - } /* * Start statement timeout if necessary. Note that this'll intentionally @@ -4929,13 +4918,6 @@ PostgresMain(const char *dbname, const char *username) case 'S': /* sync */ pq_getmsgend(&input_message); - - /* - * If pipelining was used, we may be in an implicit - * transaction block. Close it before calling - * finish_xact_command. - */ - EndImplicitTransactionBlock(); finish_xact_command(); valgrind_report_error_query("SYNC message"); send_ready_for_query = true; diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index 44a98b4d5df..afc9ecfaf77 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -897,161 +897,6 @@ $node->pgbench( } }); -# Try SET LOCAL as first pipeline command. This succeeds and the first -# command is not executed inside an implicit transaction block, causing -# a WARNING. -$node->pgbench( - '-t 1 -n -M extended', - 0, - [], - [qr{WARNING: SET LOCAL can only be used in transaction blocks}], - 'SET LOCAL outside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_set_local_1' => q{ -\startpipeline -SET LOCAL statement_timeout='1h'; -\endpipeline -} - }); - -# Try SET LOCAL as second pipeline command. This succeeds and the second -# command does not cause a WARNING to be generated. -$node->pgbench( - '-t 1 -n -M extended', - 0, - [], - [qr{^$}], - 'SET LOCAL inside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_set_local_2' => q{ -\startpipeline -SELECT 1; -SET LOCAL statement_timeout='1h'; -\endpipeline -} - }); - -# Try REINDEX CONCURRENTLY as first pipeline command. This succeeds -# as the first command is outside the implicit transaction block of -# a pipeline. -$node->pgbench( - '-t 1 -n -M extended', - 0, - [], - [], - 'REINDEX CONCURRENTLY outside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_reindex_1' => q{ -\startpipeline -REINDEX TABLE CONCURRENTLY pgbench_accounts; -SELECT 1; -\endpipeline -} - }); - -# Try REINDEX CONCURRENTLY as second pipeline command. This fails -# as the second command is inside an implicit transaction block. -$node->pgbench( - '-t 1 -n -M extended', - 2, - [], - [], - 'error: REINDEX CONCURRENTLY inside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_reindex_2' => q{ -\startpipeline -SELECT 1; -REINDEX TABLE CONCURRENTLY pgbench_accounts; -\endpipeline -} - }); - -# Try VACUUM as first pipeline command. Like REINDEX CONCURRENTLY, this -# succeeds as this is outside the implicit transaction block of a pipeline. -$node->pgbench( - '-t 1 -n -M extended', - 0, - [], - [], - 'VACUUM outside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_vacuum_1' => q{ -\startpipeline -VACUUM pgbench_accounts; -\endpipeline -} - }); - -# Try VACUUM as second pipeline command. This fails, as the second command -# of a pipeline is inside an implicit transaction block. -$node->pgbench( - '-t 1 -n -M extended', - 2, - [], - [], - 'error: VACUUM inside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_vacuum_2' => q{ -\startpipeline -SELECT 1; -VACUUM pgbench_accounts; -\endpipeline -} - }); - -# Try subtransactions in a pipeline. These are forbidden in implicit -# transaction blocks. -$node->pgbench( - '-t 1 -n -M extended', - 2, - [], - [], - 'error: subtransactions not allowed in pipeline', - { - '001_pgbench_pipeline_subtrans' => q{ -\startpipeline -SAVEPOINT a; -SELECT 1; -ROLLBACK TO SAVEPOINT a; -SELECT 2; -\endpipeline -} - }); - -# Try LOCK TABLE as first pipeline command. This fails as LOCK is outside -# an implicit transaction block. -$node->pgbench( - '-t 1 -n -M extended', - 2, - [], - [], - 'error: LOCK TABLE outside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_lock_1' => q{ -\startpipeline -LOCK pgbench_accounts; -SELECT 1; -\endpipeline -} - }); - -# Try LOCK TABLE as second pipeline command. This succeeds as LOCK is inside -# an implicit transaction block. -$node->pgbench( - '-t 1 -n -M extended', - 0, - [], - [], - 'LOCK TABLE inside implicit transaction block of pipeline', - { - '001_pgbench_pipeline_lock_2' => q{ -\startpipeline -SELECT 1; -LOCK pgbench_accounts; -\endpipeline -} - }); - # Working \startpipeline in prepared query mode with serializable $node->pgbench( '-c4 -t 10 -n -M prepared', |