Thread
Commits
-
Improve management of statement timeouts.
- 22f6f2c1ccb5 13.0 landed
-
Reset statement_timeout between queries of a multi-query string.
- 2b2bacdca010 13.0 landed
-
Rearm statement_timeout after each executed query.
- f8e5f156b30e 11.0 cited
-
BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
The Post Office <noreply@postgresql.org> — 2019-10-03T06:38:33Z
The following bug has been logged on the website: Bug reference: 16035 Logged by: Raj Mohite Email address: rmohite@xento.com PostgreSQL version: 10.8 Operating system: Windows 10 Description: I have created a simple sql where I have added STATEMENT_TIMEOUT = 1 seconds and added explicit delay(pg_sleep(5) ) of 5 seconds inside CTE. Below sql should get killed after 1 second but looks like it is running for 5 seconds. SET STATEMENT_TIMEOUT = '1s';SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; Note: If we remove the quoted string 'Billy' AS emp_name from above sql then proper timeout is getting applied. If we keep quoted string -- 'Billy' AS emp_name in the comment then also it doesn't work. Solution: We are still finding the root cause for the above behavior but I found that if we will put the SET STATEMENT_TIMEOUT before and after the sql then it working fine. Example: SET STATEMENT_TIMEOUT = '3s';SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub;SET STATEMENT_TIMEOUT = '1s'; Above example will timeout after 3 seconds i.e. it will consider the 1st timeout value. Can you please help us to know why STATEMENT_TIMEOUT is not working in first example?
-
Re: BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
Tom Lane <tgl@sss.pgh.pa.us> — 2019-10-03T14:51:46Z
[ cc'ing Tatsuo and Andres, as authors of the relevant commit ] PG Bug reporting form <noreply@postgresql.org> writes: > PostgreSQL version: 10.8 > Below sql should get killed after 1 second but looks like it is running for > 5 seconds. > SET STATEMENT_TIMEOUT = '1s';SELECT * FROM ( WITH test AS ( SELECT > pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; I can reproduce this in v10, but only if I submit the two statements as a single query string: psql (10.10) Type "help" for help. regression=# \timing Timing is on. regression=# SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; ?column? ---------- 1 (1 row) Time: 5007.648 ms (00:05.008) If they're sent as separate statements then it works as expected: psql (10.10) Type "help" for help. regression=# \timing Timing is on. regression=# SET STATEMENT_TIMEOUT = '1s';SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; SET Time: 0.635 ms ERROR: canceling statement due to statement timeout Time: 1000.707 ms (00:01.001) In v11 and up it works the same either way: psql (11.5) Type "help" for help. regression=# \timing Timing is on. regression=# SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; ERROR: canceling statement due to statement timeout Time: 1001.187 ms (00:01.001) ... or does it? regression=# SET STATEMENT_TIMEOUT = '10s'; SET Time: 0.462 ms regression=# SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; ?column? ---------- 1 (1 row) Time: 5005.946 ms (00:05.006) The v10-and-below behavior is consistent with the idea that the initial value of statement_timeout is applied across the whole multi-statement query string. Since you didn't set statement_timeout till after the query string started, the new value doesn't apply until the next submitted command. The newer behavior is simply not very consistent. If you had a prevailing statement_timeout then it continues to apply; but if you didn't, and you set one, then it's armed immediately and applies to the rest of the query string (as a whole, not per-statement). The change in behavior seems to be a consequence of f8e5f156b, which made start_xact_command do this unconditionally: + /* + * Start statement timeout if necessary. Note that this'll intentionally + * not reset the clock on an already started timeout, to avoid the timing + * overhead when start_xact_command() is invoked repeatedly, without an + * interceding finish_xact_command() (e.g. parse/bind/execute). If that's + * not desired, the timeout has to be disabled explicitly. + */ + enable_statement_timeout(); The commit message claims that this only affected extended query protocol, but that's obviously false, because start_xact_command is also called by exec_simple_query. Not sure what if anything we should do about this. The semantics of SET within a multi-statement string have always been pretty squishy: most variables will affect the remaining statements, but a few won't. But I don't like the fact that simple query's timeout behavior can no longer be categorized as either of those alternatives. "It affects the later statements, except when it doesn't" seems unsatisfactory. tl;dr: I do not think this is buggy in v10. But arguably there's a bug in later branches, and they need to go back to behaving like v10. regards, tom lane -
Re: BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
Tatsuo Ishii <ishii@sraoss.co.jp> — 2019-10-04T08:10:08Z
> [ cc'ing Tatsuo and Andres, as authors of the relevant commit ] > > PG Bug reporting form <noreply@postgresql.org> writes: >> PostgreSQL version: 10.8 > >> Below sql should get killed after 1 second but looks like it is running for >> 5 seconds. > >> SET STATEMENT_TIMEOUT = '1s';SELECT * FROM ( WITH test AS ( SELECT >> pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > > I can reproduce this in v10, but only if I submit the two statements as > a single query string: > > psql (10.10) > Type "help" for help. > > regression=# \timing > Timing is on. > regression=# SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT > pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > ?column? > ---------- > 1 > (1 row) > > Time: 5007.648 ms (00:05.008) > > If they're sent as separate statements then it works as expected: > > psql (10.10) > Type "help" for help. > > regression=# \timing > Timing is on. > regression=# SET STATEMENT_TIMEOUT = '1s';SELECT * FROM ( WITH test AS ( SELECT > pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > SET > Time: 0.635 ms > ERROR: canceling statement due to statement timeout > Time: 1000.707 ms (00:01.001) > > In v11 and up it works the same either way: > > psql (11.5) > Type "help" for help. > > regression=# \timing > Timing is on. > regression=# SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT > pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > ERROR: canceling statement due to statement timeout > Time: 1001.187 ms (00:01.001) > > ... or does it? > > regression=# SET STATEMENT_TIMEOUT = '10s'; > SET > Time: 0.462 ms > regression=# SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT > pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > ?column? > ---------- > 1 > (1 row) > > Time: 5005.946 ms (00:05.006) > > The v10-and-below behavior is consistent with the idea that the initial > value of statement_timeout is applied across the whole multi-statement > query string. Since you didn't set statement_timeout till after the query > string started, the new value doesn't apply until the next submitted > command. > > The newer behavior is simply not very consistent. If you had a prevailing > statement_timeout then it continues to apply; but if you didn't, and you > set one, then it's armed immediately and applies to the rest of the query > string (as a whole, not per-statement). > > The change in behavior seems to be a consequence of f8e5f156b, > which made start_xact_command do this unconditionally: > > + /* > + * Start statement timeout if necessary. Note that this'll intentionally > + * not reset the clock on an already started timeout, to avoid the timing > + * overhead when start_xact_command() is invoked repeatedly, without an > + * interceding finish_xact_command() (e.g. parse/bind/execute). If that's > + * not desired, the timeout has to be disabled explicitly. > + */ > + enable_statement_timeout(); > > The commit message claims that this only affected extended query > protocol, but that's obviously false, because start_xact_command > is also called by exec_simple_query. > > Not sure what if anything we should do about this. The semantics > of SET within a multi-statement string have always been pretty > squishy: most variables will affect the remaining statements, but > a few won't. But I don't like the fact that simple query's timeout > behavior can no longer be categorized as either of those alternatives. > "It affects the later statements, except when it doesn't" seems > unsatisfactory. > > tl;dr: I do not think this is buggy in v10. But arguably there's > a bug in later branches, and they need to go back to behaving > like v10. I understand the original reporter's complain. Also I understand Tom's complain to v11's behavior. I will look into the v11 (and above) code. Best regards, -- Tatsuo Ishii SRA OSS, Inc. Japan English: http://www.sraoss.co.jp/index_en.php Japanese:http://www.sraoss.co.jp
-
Re: BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
Tatsuo Ishii <ishii@sraoss.co.jp> — 2019-10-06T07:22:20Z
>> tl;dr: I do not think this is buggy in v10. But arguably there's >> a bug in later branches, and they need to go back to behaving >> like v10. > > I understand the original reporter's complain. Also I understand Tom's > complain to v11's behavior. I will look into the v11 (and above) code. I admit v11's current behavior is inconstant, but I am not sue going to back V10's behavior is a good idea. With attached patch (against master), SET STATEMENT_TIMEOUT immediately affects to subsequent commands in the multi statement. I think this is not only more intuitive than v10's behavior but it meets the original reporter's expectation. SET STATEMENT_TIMEOUT = '10s'; SET Time: 0.418 ms -- SELECT timeout in 1 second. SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; ERROR: canceling statement due to statement timeout Time: 1001.107 ms (00:01.001) Here are results of test cases attached (statement_timeout.sql). \timing Timing is on. -- SELECT timeout in 1 second. SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; psql:/home/t-ishii/tmp/statement_timeout.sql:3: ERROR: canceling statement due to statement timeout Time: 1001.138 ms (00:01.001) SET STATEMENT_TIMEOUT = '10s'; SET Time: 0.434 ms -- SELECT timeout in 1 second. SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; psql:/home/t-ishii/tmp/statement_timeout.sql:7: ERROR: canceling statement due to statement timeout Time: 1000.978 ms (00:01.001) -- This time SELECT succeeds and STATEMENT_TIMEOUT is set to 8 secinds. SET STATEMENT_TIMEOUT = '8s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; ?column? ---------- 1 (1 row) Time: 5004.886 ms (00:05.005) SHOW STATEMENT_TIMEOUT; statement_timeout ------------------- 8s (1 row) Time: 0.433 ms -- Following SELECT succeeds because now statement_timeout value is 8 seconds.. SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; ?column? ---------- 1 (1 row) Time: 5006.196 ms (00:05.006) -
Re: BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
Tatsuo Ishii <ishii@sraoss.co.jp> — 2019-10-21T05:02:17Z
If there's no objection, I would like to commit/push the diff. > I admit v11's current behavior is inconstant, but I am not sue going > to back V10's behavior is a good idea. > > With attached patch (against master), SET STATEMENT_TIMEOUT > immediately affects to subsequent commands in the multi statement. I > think this is not only more intuitive than v10's behavior but it meets > the original reporter's expectation. > > SET STATEMENT_TIMEOUT = '10s'; > SET > Time: 0.418 ms > -- SELECT timeout in 1 second. > SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > ERROR: canceling statement due to statement timeout > Time: 1001.107 ms (00:01.001) > > Here are results of test cases attached (statement_timeout.sql). > > \timing > Timing is on. > -- SELECT timeout in 1 second. > SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > psql:/home/t-ishii/tmp/statement_timeout.sql:3: ERROR: canceling statement due to statement timeout > Time: 1001.138 ms (00:01.001) > SET STATEMENT_TIMEOUT = '10s'; > SET > Time: 0.434 ms > -- SELECT timeout in 1 second. > SET STATEMENT_TIMEOUT = '1s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > psql:/home/t-ishii/tmp/statement_timeout.sql:7: ERROR: canceling statement due to statement timeout > Time: 1000.978 ms (00:01.001) > -- This time SELECT succeeds and STATEMENT_TIMEOUT is set to 8 secinds. > SET STATEMENT_TIMEOUT = '8s'\;SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > ?column? > ---------- > 1 > (1 row) > > Time: 5004.886 ms (00:05.005) > SHOW STATEMENT_TIMEOUT; > statement_timeout > ------------------- > 8s > (1 row) > > Time: 0.433 ms > -- Following SELECT succeeds because now statement_timeout value is 8 seconds.. > SELECT * FROM ( WITH test AS ( SELECT pg_sleep(5), 'Billy' as emp_name ) SELECT 1 FROM test ) AS sub; > ?column? > ---------- > 1 > (1 row) > > Time: 5006.196 ms (00:05.006)
-
Re: BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
Tom Lane <tgl@sss.pgh.pa.us> — 2019-10-21T05:03:54Z
Tatsuo Ishii <ishii@sraoss.co.jp> writes: > If there's no objection, I would like to commit/push the diff. I'd like to look at the patch, but I just got back from pgconf.eu and haven't had time yet. regards, tom lane
-
Re: BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
Tom Lane <tgl@sss.pgh.pa.us> — 2019-10-21T23:02:05Z
Tatsuo Ishii <ishii@sraoss.co.jp> writes: >>> tl;dr: I do not think this is buggy in v10. But arguably there's >>> a bug in later branches, and they need to go back to behaving >>> like v10. >> I understand the original reporter's complain. Also I understand Tom's >> complain to v11's behavior. I will look into the v11 (and above) code. > I admit v11's current behavior is inconstant, but I am not sue going > to back V10's behavior is a good idea. > With attached patch (against master), SET STATEMENT_TIMEOUT > immediately affects to subsequent commands in the multi statement. I > think this is not only more intuitive than v10's behavior but it meets > the original reporter's expectation. Hm. So, okay, that is a nicer API probably, but note that it also has the effect that the timeout starts over again for each statement in the string, while before it applied to the string as a whole. Are we okay with that change? (I've not yet looked to see if it's documented anywhere that it works that way...) It's kind of tossing some of the optimization intended by f8e5f156b overboard, since when a timeout is active we'll be doing timeout calculations for each statement in the string. Anyway, granting that we want the definitional change, I still don't like anything about this patch. The proposed test + if (!doing_extended_query_message || + (!stmt_timeout_active && doing_extended_query_message)) is unreadably complicated and repetitive, and it's undocumented, and it makes timeout handling work quite differently in the simple and extended query paths, and it will cause excess timeout calculations (over and above the newly-necessary ones) because it will force a new timeout calculation for each start_xact_command call in the simple query path (yes, we do more than one of those per statement in common cases). Plus it makes the semantics of stmt_timeout_active rather unclear. I think if we want to do this, the way to do it is to add another disable_statement_timeout call while finishing up a non-last query in exec_simple_query, as per 0001 below. That adds no extra overhead unless we have a multi-statement string, and it is much more parallel to the way things are done for extended protocol. However ... as I was looking at this, I realized that I didn't like anything about commit f8e5f156b either. It introduces private state in postgres.c that has to be kept in sync with state in timeout.c. We already found one bug in that (cf be42015fc), and I have little faith that there aren't others, and no faith at all that we won't introduce more later. The right way to manage that, I think, is to extend timeout.c to allow inquiring whether the timeout is active, as per 0002 below, so that timeout.c's state is the single source of truth about this. Maintaining the extra state needed to make this cheap allows some other small simplifications/speedups, too, mainly that we can skip useless searches of the active_timeouts[] array. Not sure what I think about back-patching this. We probably can't back-patch 0001; that's enough of a behavioral change that the cure seems worse than the disease. I'm tempted though to argue that we should back-patch 0002, on the grounds that it prevents possible bugs and should save a few cycles too. regards, tom lane
-
Re: BUG #16035: STATEMENT_TIMEOUT not working when we have single quote usage inside CTE which is used in inner sql
Tom Lane <tgl@sss.pgh.pa.us> — 2019-10-24T18:19:29Z
I wrote: > Tatsuo Ishii <ishii@sraoss.co.jp> writes: >> With attached patch (against master), SET STATEMENT_TIMEOUT >> immediately affects to subsequent commands in the multi statement. I >> think this is not only more intuitive than v10's behavior but it meets >> the original reporter's expectation. > Hm. So, okay, that is a nicer API probably, but note that it also > has the effect that the timeout starts over again for each statement > in the string, while before it applied to the string as a whole. > Are we okay with that change? (I've not yet looked to see if it's > documented anywhere that it works that way...) It's kind of tossing > some of the optimization intended by f8e5f156b overboard, since when > a timeout is active we'll be doing timeout calculations for each > statement in the string. I looked around, and as far as I can tell, there is no detail at all about this in our user-facing docs. I think we should apply a doc patch more or less like the attached. This fails to provide a complete spec of what the behavior used to be, but I don't much care to try to document that 100% exactly. Anyone have an objection to pushing ahead with this for HEAD only? regards, tom lane