Hi,

On Tue, 9 Aug 2022 00:21:02 +0900
Yugo NAGATA <nag...@sraoss.co.jp> wrote:

> On Wed, 27 Jul 2022 22:50:55 -0400
> Tom Lane <t...@sss.pgh.pa.us> wrote:
> 
> > Yugo NAGATA <nag...@sraoss.co.jp> writes:
> > > I've looked at the commited fix. What I wonder is whether a change in
> > > IsInTransactionBlock() is necessary or not.
> > 
> > I've not examined ANALYZE's dependencies on this closely, but it doesn't
> > matter really, because I'm not willing to assume that ANALYZE is the
> > only caller.  There could be external modules with stronger assumptions
> > that IsInTransactionBlock() yielding false provides guarantees equivalent
> > to PreventInTransactionBlock().  It did before this patch, so I think
> > it needs to still do so after.
> 
> Thank you for your explanation. I understood that IsInTransactionBlock()
> and PreventInTransactionBlock() share the equivalent assumption.
> 
> As to ANALYZE, after investigating the code more, I found that setting 
> XACT_FLAGS_NEEDIMMEDIATECOMMIT in IsInTransactionBlock() is needed indeed.
> That is, some flags in pg_class such as relhasindex can be safely updated
> only if ANALYZE is not in a transaction block and never rolled back.  So,
> in a pipeline, ANALYZE must be immediately committed.
> 
> However, I think we need more comments on these functions to clarify what
> users can expect or not for them.  It is ensured that the statement that
> calls PreventInTransactionBlock()  or receives false from
> IsInTransactionBlock() never be rolled back if it finishes successfully.
> This can eliminate the harmful influence of non-rollback-able side effects.
> 
> On the other hand, it cannot ensure that the statement calling these
> functions is the first or only one in the transaction in pipelining. If
> there are preceding statements in a pipeline, they are committed in the
> same transaction of the current statement.
> 
> The attached patch tries to add comments explaining it on the functions.

I forward it to the hackers list because the patch is to fix comments.
Also, I'll register it to commitfest.

The past discussion is here.
https://www.postgresql.org/message-id/flat/17434-d9f7a064ce2a88a3%40postgresql.org

> 
> > > In fact, the result of IsInTransactionBlock does not make senses at
> > > all in pipe-line mode regardless to the fix. ANALYZE could commit all
> > > previous commands in pipelining, and this may not be user expected
> > > behaviour.
> > 
> > This seems pretty much isomorphic to the fact that CREATE DATABASE
> > will commit preceding steps in the pipeline.  
> 
> I am not sure if we can think CREATE DATABASE case and ANLALYZE case
> similarly. First, CREATE DATABASE is one of the commands that cannot be
> executed inside a transaction block, but ANALYZE can be. So, users would
> not be able to know ANALYZE in a pipeline causes a commit from the
> documentation. Second, ANALYZE issues a commit internally in an early
> stage not only after it finished successfully. For example, even if
> ANALYZE is failing because a not-existing column name is specified, it
> issues a commit before checking the column name. This makes more hard
> to know which statements will be committed and which statements not
> committed in a pipeline. Also, as you know, there are other commands
> that issue internal commits.
> 
> > That's not great,
> > I admit; we'd not have designed it like that if we'd had complete
> > understanding of the behavior at the beginning.  But it's acted
> > like that for a couple of decades now, so changing it seems far
> > more likely to make people unhappy than happy.  The same for
> > ANALYZE in a pipeline.
> 
> > > If the first command in a pipeline is  DDL commands such as CREATE
> > > DATABASE, this is allowed and immediately committed after success, as
> > > same as the current behavior. Executing such commands in the middle of
> > > pipeline is not allowed because the pipeline is regarded as "an implicit
> > > transaction block" at that time. Similarly, ANALYZE in the middle of
> > > pipeline can not close and open transaction.
> > 
> > I'm not going there.  If you can persuade some other committer that
> > this is worth breaking backward compatibility for, fine; the user
> > complaints will be their problem.
> 
> I don't have no idea how to reduce the complexity explained above and
> clarify the transactional behavior of pipelining to users other than the
> fix I proposed in the previous post. However, I also agree that such
> changing may make some people unhappy. If there is no good way and we
> would not like to change the behavior, I think it is better to mention
> the effects of commands that issue internal commits in the documentation
> at least.
> 
> Regards,
> Yugo Nagata
> 
> -- 
> Yugo NAGATA <nag...@sraoss.co.jp>


-- 
Yugo NAGATA <nag...@sraoss.co.jp>
diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 50f092d7eb..ee9f0fafdd 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -3455,6 +3455,10 @@ AbortCurrentTransaction(void)
  *
  *	We must also set XACT_FLAGS_NEEDIMMEDIATECOMMIT in MyXactFlags, to ensure
  *	that postgres.c follows through by committing after the statement is done.
+ *	This ensures that the statement that calls this function never be rolled
+ *	back if it finishes successfully. Note that if there are preceding statements
+ *	in a pipeline, they are committed in the same transaction of the current
+ *	statement.
  *
  *	isTopLevel: passed down from ProcessUtility to determine whether we are
  *	inside a function.  (We will always fail if this is false, but it's
@@ -3573,6 +3577,10 @@ CheckTransactionBlock(bool isTopLevel, bool throwError, const char *stmtType)
  *	a transaction block than when running as single commands.  ANALYZE is
  *	currently the only example.
  *
+ *	Returning false ensures that the statement that calls this function never
+ *	be rolled back if it finishes successfully. See comments on
+ *	PreventInTransactionBlock.
+ *
  *	isTopLevel: passed down from ProcessUtility to determine whether we are
  *	inside a function.
  */

Reply via email to