mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-22 16:43:03 +01:00
160 lines
6.8 KiB
Plaintext
160 lines
6.8 KiB
Plaintext
Timeouts for running SQL statements.
|
|
|
|
Author:
|
|
Vlad Khorsun <hvlad@users.sf.net>
|
|
|
|
|
|
Description:
|
|
|
|
The feature allows to set timeout for SQL statement, i.e. it allows to automatically
|
|
stop execution of SQL statement when it running longer than given timeout value.
|
|
|
|
The feature could be useful for:
|
|
- database administrators get instrument to limit heavy queries from consuming too
|
|
much resources
|
|
- application developers could use statement timeout when creating\debugging complex
|
|
queries with unknown in advance execution time
|
|
- testers could use statement timeout to detect long running queries and ensure finite
|
|
run time of the test suites
|
|
- and so on
|
|
|
|
From the end user point of view feature have following details:
|
|
- when statement starts execution (or cursor is opened), engine starts special timer
|
|
- fetch doesn't reset timer
|
|
- timer is stopped when statement execution finished (or last record is fetched)
|
|
- when timer is fired
|
|
- if statement execution is active, it stops at closest possible moment
|
|
- if statement is not active currently (between fetches, for example), it is marked
|
|
as cancelled and next fetch will actually break execution and returns with error
|
|
- timeout value could be set:
|
|
- at database level, by setting value in firebird.conf (or databases.conf) by database
|
|
administrator
|
|
scope - all statements in all connections
|
|
units - seconds
|
|
- at connection level, using API and\or new SQL statement (see below)
|
|
scope - all statements at given connection
|
|
units - up to milliseconds
|
|
- at statement level, using API
|
|
scope - given statement
|
|
units - milliseconds
|
|
- effective value of timeout is evaluated every time statement starts execution
|
|
(or cursor is opened) as:
|
|
- if not set at statement level, look at connection level
|
|
- if not set at connection level, look at database level
|
|
- in any case can't be greater than value set at database level
|
|
i.e. value of statement timeout could be overriden by application developer at lower
|
|
scope but it can't relax limit set by DBA (in config)
|
|
- zero timeout means no timeout, i.e. timer will not start
|
|
- while statement timeout is set in milliseconds at API level, we can't promise
|
|
absolute precision. With big load it could be less precise. The only guarantee
|
|
is that timeout will not fire before specified moment.
|
|
- if statement execution is cancelled due to timeout, then API call returns error
|
|
isc_cancelled with secondary error code specifying exact reason:
|
|
- isc_cfg_stmt_timeout: Config level timeout expired
|
|
- isc_att_stmt_timeout: Attachment level timeout expired
|
|
- isc_req_stmt_timeout: Statement level timeout expired
|
|
- statement timeout is ignored for all internal queries issued by engine itself
|
|
- statement timeout is ignored for DDL statements
|
|
- client application could wait more time than set by timeout value if engine
|
|
need to undo many actions due to statement cancellation
|
|
- when engine run EXECUTE STATEMENT statement, it pass rest of currently active timeout
|
|
to the new statement. If external (remote) engine doesn't support statement timeouts,
|
|
local engine silently ignores corresponding error
|
|
- when engine acquires some lock of lock manager, it could lower value of lock timeout
|
|
using rest of the currently active statement timeout, if possible. Due to lock manager
|
|
internals rest of statement timeout will be rounded up to the whole seconds.
|
|
|
|
|
|
Support at configuration level (firebird.conf and\or databases.conf)
|
|
|
|
New setting "StatementTimeout": set number of seconds after which statement execution
|
|
will be automatically cancelled by the engine. Zero means no timeout is set.
|
|
Per-database configurable. Type: integer. Default value is 0.
|
|
|
|
|
|
Support at API level
|
|
|
|
- get\set statement execution timeout at connection level, milliseconds:
|
|
interface Attachment
|
|
uint getStatementTimeout(Status status);
|
|
void setStatementTimeout(Status status, uint timeOut);
|
|
|
|
- get\set statement execution timeout at statement level, milliseconds:
|
|
interface Statement
|
|
uint getTimeout(Status status);
|
|
void setTimeout(Status status, uint timeOut);
|
|
|
|
- set statement execution timeout at statement level using ISC API, milliseconds:
|
|
|
|
ISC_STATUS ISC_EXPORT fb_dsql_set_timeout(ISC_STATUS*, isc_stmt_handle*, ISC_ULONG);
|
|
|
|
- get statement execution timeout at config and\or connection level is possible
|
|
using isc_database_info() API with new info tags:
|
|
- fb_info_statement_timeout_db
|
|
- fb_info_statement_timeout_att
|
|
|
|
- get statement execution timeout at statement level is possible using isc_dsql_info()
|
|
API with new info tags:
|
|
- isc_info_sql_stmt_timeout_user timeout value of given statement
|
|
- isc_info_sql_stmt_timeout_run actual timeout value of given statement
|
|
evaluated considering values set at config, connection and statement levels, see
|
|
"effective value of timeout" above. Valid only when timeout timer is running, i.e.
|
|
for currently executed statements.
|
|
|
|
Remote client implementation notes:
|
|
- Attachment::setStatementTimeout() issued "SET STATEMENT TIMEOUT" SQL statement
|
|
- Attachment::getStatementTimeout() calls isc_database_info() with
|
|
fb_info_statement_timeout_att tag
|
|
- Statement::setTimeout() save timeout value given and pass it with op_execute
|
|
and op_execute2 packets
|
|
- Statement::getTimeout() returns saved timeout value
|
|
- fb_dsql_set_timeout() is a wrapper over Statement::setTimeout()
|
|
|
|
If remote server doesn't support statement timeouts (protocol version less than 16):
|
|
- "set" functions will return isc_wish_list error
|
|
- "get" functions will return zero and set isc_wish_list error
|
|
- "info" functions will return isc_info_error tag in info buffer (as usual).
|
|
|
|
|
|
Support in SQL
|
|
|
|
- New SQL statement allows to set set statement execution timeout at connection level:
|
|
|
|
SET STATEMENT TIMEOUT <value> [HOUR | MINUTE | SECOND | MILLISECOND]
|
|
|
|
if timepart is not set, default is SECOND.
|
|
This statement could run outside of transaction control and immediately effective.
|
|
|
|
- Context variables
|
|
|
|
Context 'SYSTEM' have new variable: 'STATEMENT_TIMEOUT'. It contains current value of
|
|
statement execution timeout that was set at connection level, or zero, if timeout was
|
|
not set.
|
|
|
|
- Monitoring tables
|
|
|
|
MON$ATTACHMENTS
|
|
MON$STATEMENT_TIMEOUT Connection level statement timeout
|
|
|
|
MON$STATEMENTS
|
|
MON$STATEMENT_TIMEOUT Statement level statement timeout
|
|
MON$STATEMENT_TIMER Timeout timer expiration time
|
|
|
|
|
|
MON$STATEMENT_TIMEOUT contains timeout values set at connection\statement level,
|
|
in milliseconds. Zero, if timeout is not set.
|
|
|
|
MON$STATEMENT_TIMER contains NULL value if timeout was not set or if timer is not
|
|
running.
|
|
|
|
|
|
Support in ISQL tool
|
|
|
|
New ISQL command is introduced:
|
|
|
|
SET LOCAL_TIMEOUT <int>
|
|
|
|
It allows to set statement execution timeout (in milliseconds) for the next statement.
|
|
After statement execution it automatically reset to zero.
|
|
|