mirror of
https://github.com/postgres/postgres.git
synced 2025-05-25 00:04:05 -04:00
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
This commit is contained in:
parent
c93dffd89b
commit
7668e85a40
@ -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>
|
||||
|
@ -3603,6 +3603,16 @@ PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
|
||||
errmsg("%s cannot run inside a subtransaction",
|
||||
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?
|
||||
*/
|
||||
@ -3714,6 +3724,9 @@ IsInTransactionBlock(bool isTopLevel)
|
||||
if (IsSubTransaction())
|
||||
return true;
|
||||
|
||||
if (MyXactFlags & XACT_FLAGS_PIPELINING)
|
||||
return true;
|
||||
|
||||
if (!isTopLevel)
|
||||
return true;
|
||||
|
||||
|
@ -2775,17 +2775,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
|
||||
@ -4971,13 +4960,6 @@ PostgresMain(const char *dbname, const char *username)
|
||||
|
||||
case PqMsg_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;
|
||||
|
@ -968,180 +968,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 SET LOCAL with \syncpipeline. This succeeds and the command
|
||||
# launched after the sync is outside the implicit transaction block
|
||||
# of the pipeline, causing a WARNING.
|
||||
$node->pgbench(
|
||||
'-t 1 -n -M extended',
|
||||
0,
|
||||
[],
|
||||
[qr{WARNING: SET LOCAL can only be used in transaction blocks}],
|
||||
'SET LOCAL and \syncpipeline',
|
||||
{
|
||||
'001_pgbench_pipeline_set_local_3' => q{
|
||||
\startpipeline
|
||||
SELECT 1;
|
||||
\syncpipeline
|
||||
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',
|
||||
|
Loading…
x
Reference in New Issue
Block a user