Thread: statement_timeout vs DECLARE CURSOR

statement_timeout vs DECLARE CURSOR

From
Christophe Pettus
Date:
Hi,

We've encountered some unexpected behavior with statement_timeout not cancelling a query in DECLARE CURSOR, but only if
theDECLARE CURSOR is outside of a transaction: 

xof=# select version();
                                                      version
-------------------------------------------------------------------------------------------------------------------
 PostgreSQL 13.4 on x86_64-apple-darwin19.6.0, compiled by Apple clang version 12.0.0 (clang-1200.0.32.29), 64-bit
(1 row)

xof=# set statement_timeout = '1s';
SET
xof=# \timing
Timing is on.
xof=# select * from (with test as (select pg_sleep(10), current_timestamp as cur_time) select 1 from test ) as slp;
ERROR:  canceling statement due to statement timeout
Time: 1000.506 ms (00:01.001)
xof=# declare x no scroll cursor with hold for select * from (with test as (select pg_sleep(10), current_timestamp as
cur_time)select 1 from test ) as slp; 
DECLARE CURSOR
Time: 10001.929 ms (00:10.002)
xof=#

but:

xof=# set statement_timeout = '1s';
SET
xof=# \timing
Timing is on.
xof=# begin;
BEGIN
Time: 0.161 ms
xof=*# declare x no scroll cursor with hold for select * from (with test as (select pg_sleep(10), current_timestamp as
cur_time)select 1 from test ) as slp; 
DECLARE CURSOR
Time: 0.949 ms
xof=*# fetch all from x;
ERROR:  canceling statement due to statement timeout
Time: 1000.520 ms (00:01.001)
xof=!# abort;
ROLLBACK
Time: 0.205 ms
xof=#




Re: statement_timeout vs DECLARE CURSOR

From
Christophe Pettus
Date:

> On Sep 27, 2021, at 10:42, Christophe Pettus <xof@thebuild.com> wrote:
> We've encountered some unexpected behavior with statement_timeout not cancelling a query in DECLARE CURSOR, but only
ifthe DECLARE CURSOR is outside of a transaction: 

A bit more poking revealed the reason: The ON HOLD cursor's query is executed at commit time (which is, logically, not
interruptible),but that's all wrapped in the single statement outside of a transaction. 


Re: statement_timeout vs DECLARE CURSOR

From
Tom Lane
Date:
Christophe Pettus <xof@thebuild.com> writes:
>> On Sep 27, 2021, at 10:42, Christophe Pettus <xof@thebuild.com> wrote:
>> We've encountered some unexpected behavior with statement_timeout not cancelling a query in DECLARE CURSOR, but only
ifthe DECLARE CURSOR is outside of a transaction: 

> A bit more poking revealed the reason: The ON HOLD cursor's query is executed at commit time (which is, logically,
notinterruptible), but that's all wrapped in the single statement outside of a transaction. 

Hmm ... seems like a bit of a UX failure.  I wonder why we don't persist
such cursors before we get into the uninterruptible part of COMMIT.

            regards, tom lane



Re: statement_timeout vs DECLARE CURSOR

From
Tom Lane
Date:
I wrote:
> Christophe Pettus <xof@thebuild.com> writes:
>> A bit more poking revealed the reason: The ON HOLD cursor's query is executed at commit time (which is, logically,
notinterruptible), but that's all wrapped in the single statement outside of a transaction. 

> Hmm ... seems like a bit of a UX failure.  I wonder why we don't persist
> such cursors before we get into the uninterruptible part of COMMIT.

Oh, I see the issue.  It's not that that part of COMMIT isn't
interruptible; you can control-C out of it just fine.  The problem
is that finish_xact_command() disarms the statement timeout before
starting CommitTransactionCommand at all.

We could imagine pushing the responsibility for that down into
xact.c, allowing it to happen after CommitTransaction has finished
running user-defined code.  But it seems like a bit of a mess
because there are so many other code paths there.  Not sure how
to avoid future bugs-of-omission.

            regards, tom lane