Re: BUG #17434: CREATE/DROP DATABASE can be executed in the same transaction with other commands
Tom Lane <tgl@sss.pgh.pa.us>
From: Tom Lane <tgl@sss.pgh.pa.us>
To: "David G. Johnston" <david.g.johnston@gmail.com>
Cc: Bruce Momjian <bruce@momjian.us>, Yugo Nagata <nagata@sraoss.co.jp>,
PostgreSQL mailing lists <pgsql-bugs@lists.postgresql.org>
Date: 2022-07-15T21:06:51Z
Lists: pgsql-bugs, pgsql-hackers
Attachments
- ensure-immediate-commit-in-extended-protocol-1.patch (text/x-diff) patch
"David G. Johnston" <david.g.johnston@gmail.com> writes: > On Thu, Jul 14, 2022 at 5:37 PM Tom Lane <tgl@sss.pgh.pa.us> wrote: >> Hmm, that one seems to have slipped past me. I agree it doesn't >> look good. But why isn't the PreventInTransactionBlock() check >> blocking the command from even starting? > I assume because pgbench never sends a BEGIN command so the create database > sees itself in an implicit transaction and happily goes about its business, > expecting the system to commit its work immediately after it says it is > done. Yeah. Upon inspection, the fundamental problem here is that in extended query protocol we typically don't issue finish_xact_command() until we get a Sync message. So even though everything looks kosher when PreventInTransactionBlock() runs, the client can send another statement which will be executed in the same transaction, risking trouble. Here's a draft patch to fix this. We basically just need to force finish_xact_command() in the same way as we do for transaction control statements. I considered using the same technology as the code uses for transaction control --- that is, statically check for the types of statements that are trouble --- but after reviewing the set of callers of PreventInTransactionBlock() I gave that up as unmaintainable. So what this does is make PreventInTransactionBlock() set a flag to be checked later, back in exec_execute_message. I was initially going to make that be a new boolean global, but I happened to notice the MyXactFlags variable which seems entirely suited to this use-case. One thing that I'm dithering over is whether to add a check of the new flag in exec_simple_query. As things currently stand that would be redundant, but it seems like doing things the same way in both of those functions might be more future-proof and understandable. (Note the long para I added to justify not doing it ;-)) regards, tom lane
Commits
-
Rethink handling of [Prevent|Is]InTransactionBlock in pipeline mode.
- f48aa5df4e03 11.19 landed
- ae47f8a9664a 14.7 landed
- 942cc240f959 13.10 landed
- 1cca4a75ffb8 12.14 landed
- 18431ee6f511 15.2 landed
- 20432f873140 16.0 landed
-
Doc: add comments about PreventInTransactionBlock/IsInTransactionBlock.
- fec80da849f3 11.19 landed
- e70cd16f2223 15.2 landed
- e613ace1f0d5 16.0 landed
- 8befa05d7889 14.7 landed
- 1949135e79e8 13.10 landed
- 17e9ecac0118 12.14 landed
-
Force immediate commit after CREATE DATABASE etc in extended protocol.
- f92944137cde 16.0 landed
- a0c632c1dea7 15.0 landed
- 9e3e1ac458ab 11.17 landed
- 968b89257b11 12.12 landed
- 964f42aa297b 10.22 landed
- 6c193c2ace32 13.8 landed
- 3e1297a63f76 14.5 landed