MDEV-11418 - AliSQL: [Feature] Issue#1 KILL IDLE TRANSACTIONS
Terminate idle transactions safely in server layer by setting up socket timeout parameter. Percona provides another patch to resolve similar problem, but it calls server layer's callback in InnoDB plugin to close THD, which crashes in some testcases. See https://bugs.launchpad.net/percona-server/+bug/901060 for more detailed information. 1. export parameter trx_idle_timeout to handle all kinds of transactions, the priority is highest 2. export parameter trx_readonly_idle_timeout to handle read-only transactions 3. export parameter trx_changes_idle_timeout to handle read-write transactions
This commit is contained in:
parent
8026cd6202
commit
af22a70df9
@ -58,7 +58,6 @@ int thd_connection_has_data(THD *thd);
|
||||
void thd_set_net_read_write(THD *thd, uint val);
|
||||
uint thd_get_net_read_write(THD *thd);
|
||||
void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var);
|
||||
ulong thd_get_net_wait_timeout(THD *thd);
|
||||
my_socket thd_get_fd(THD *thd);
|
||||
int thd_store_globals(THD* thd);
|
||||
|
||||
|
@ -271,6 +271,15 @@ The following options may be given as the first argument:
|
||||
height-balanced.
|
||||
--host-cache-size=# How many host names should be cached to avoid resolving.
|
||||
(Automatically configured unless set explicitly)
|
||||
--idle-readonly-transaction-timeout=#
|
||||
The number of seconds the server waits for read-only idle
|
||||
transaction
|
||||
--idle-readwrite-transaction-timeout=#
|
||||
The number of seconds the server waits for read-write
|
||||
idle transaction
|
||||
--idle-transaction-timeout=#
|
||||
The number of seconds the server waits for idle
|
||||
transaction
|
||||
--ignore-builtin-innodb
|
||||
Disable initialization of builtin InnoDB plugin
|
||||
--ignore-db-dirs=name
|
||||
@ -1259,6 +1268,9 @@ help TRUE
|
||||
histogram-size 0
|
||||
histogram-type SINGLE_PREC_HB
|
||||
host-cache-size 279
|
||||
idle-readonly-transaction-timeout 0
|
||||
idle-readwrite-transaction-timeout 0
|
||||
idle-transaction-timeout 0
|
||||
ignore-builtin-innodb FALSE
|
||||
ignore-db-dirs
|
||||
init-connect
|
||||
|
51
mysql-test/r/transaction_timeout.result
Normal file
51
mysql-test/r/transaction_timeout.result
Normal file
@ -0,0 +1,51 @@
|
||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||
# Test idle_transaction_timeout
|
||||
connect c0,localhost,root,,test,,;
|
||||
SHOW VARIABLES LIKE 'idle_%transaction_timeout';
|
||||
Variable_name Value
|
||||
idle_readonly_transaction_timeout 0
|
||||
idle_readwrite_transaction_timeout 0
|
||||
idle_transaction_timeout 0
|
||||
SET autocommit=0;
|
||||
SET idle_transaction_timeout=1;
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
SELECT * FROM t1;
|
||||
Got one of the listed errors
|
||||
disconnect c0;
|
||||
# Test idle_readonly_transaction_timeout
|
||||
connect c1,localhost,root,,test,,;
|
||||
SHOW VARIABLES LIKE 'idle_%transaction_timeout';
|
||||
Variable_name Value
|
||||
idle_readonly_transaction_timeout 0
|
||||
idle_readwrite_transaction_timeout 0
|
||||
idle_transaction_timeout 0
|
||||
SET autocommit=0;
|
||||
SET idle_readonly_transaction_timeout=1;
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
SELECT * FROM t1;
|
||||
Got one of the listed errors
|
||||
disconnect c1;
|
||||
# Test idle_readwrite_transaction_timeout
|
||||
connect c2,localhost,root,,test,,;
|
||||
SHOW VARIABLES LIKE 'idle_%transaction_timeout';
|
||||
Variable_name Value
|
||||
idle_readonly_transaction_timeout 0
|
||||
idle_readwrite_transaction_timeout 0
|
||||
idle_transaction_timeout 0
|
||||
SET autocommit=0;
|
||||
SET idle_readwrite_transaction_timeout=1;
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
SELECT * FROM t1;
|
||||
a
|
||||
INSERT INTO t1 VALUES (1);
|
||||
SELECT * FROM t1;
|
||||
Got one of the listed errors
|
||||
disconnect c2;
|
||||
connection default;
|
||||
DROP TABLE t1;
|
@ -1213,6 +1213,48 @@ NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT NULL
|
||||
VARIABLE_NAME IDLE_READONLY_TRANSACTION_TIMEOUT
|
||||
SESSION_VALUE 0
|
||||
GLOBAL_VALUE 0
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE SESSION
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of seconds the server waits for read-only idle transaction
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 31536000
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME IDLE_READWRITE_TRANSACTION_TIMEOUT
|
||||
SESSION_VALUE 0
|
||||
GLOBAL_VALUE 0
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE SESSION
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of seconds the server waits for read-write idle transaction
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 31536000
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME IDLE_TRANSACTION_TIMEOUT
|
||||
SESSION_VALUE 0
|
||||
GLOBAL_VALUE 0
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE SESSION
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of seconds the server waits for idle transaction
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 31536000
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME IGNORE_BUILTIN_INNODB
|
||||
SESSION_VALUE NULL
|
||||
GLOBAL_VALUE OFF
|
||||
|
@ -1325,6 +1325,48 @@ NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT NULL
|
||||
VARIABLE_NAME IDLE_READONLY_TRANSACTION_TIMEOUT
|
||||
SESSION_VALUE 0
|
||||
GLOBAL_VALUE 0
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE SESSION
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of seconds the server waits for read-only idle transaction
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 31536000
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME IDLE_READWRITE_TRANSACTION_TIMEOUT
|
||||
SESSION_VALUE 0
|
||||
GLOBAL_VALUE 0
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE SESSION
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of seconds the server waits for read-write idle transaction
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 31536000
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME IDLE_TRANSACTION_TIMEOUT
|
||||
SESSION_VALUE 0
|
||||
GLOBAL_VALUE 0
|
||||
GLOBAL_VALUE_ORIGIN COMPILE-TIME
|
||||
DEFAULT_VALUE 0
|
||||
VARIABLE_SCOPE SESSION
|
||||
VARIABLE_TYPE INT UNSIGNED
|
||||
VARIABLE_COMMENT The number of seconds the server waits for idle transaction
|
||||
NUMERIC_MIN_VALUE 0
|
||||
NUMERIC_MAX_VALUE 31536000
|
||||
NUMERIC_BLOCK_SIZE 1
|
||||
ENUM_VALUE_LIST NULL
|
||||
READ_ONLY NO
|
||||
COMMAND_LINE_ARGUMENT REQUIRED
|
||||
VARIABLE_NAME IGNORE_BUILTIN_INNODB
|
||||
SESSION_VALUE NULL
|
||||
GLOBAL_VALUE OFF
|
||||
|
54
mysql-test/t/transaction_timeout.test
Normal file
54
mysql-test/t/transaction_timeout.test
Normal file
@ -0,0 +1,54 @@
|
||||
--source include/no_protocol.inc
|
||||
--source include/have_innodb.inc
|
||||
--source include/not_embedded.inc
|
||||
|
||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||
|
||||
--echo # Test idle_transaction_timeout
|
||||
connect (c0,localhost,root,,test,,);
|
||||
SHOW VARIABLES LIKE 'idle_%transaction_timeout';
|
||||
SET autocommit=0;
|
||||
SET idle_transaction_timeout=1;
|
||||
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
sleep 2;
|
||||
|
||||
--error 2006,2013
|
||||
SELECT * FROM t1;
|
||||
disconnect c0;
|
||||
|
||||
--echo # Test idle_readonly_transaction_timeout
|
||||
connect (c1,localhost,root,,test,,);
|
||||
SHOW VARIABLES LIKE 'idle_%transaction_timeout';
|
||||
SET autocommit=0;
|
||||
SET idle_readonly_transaction_timeout=1;
|
||||
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
sleep 2;
|
||||
|
||||
--error 2006,2013 # Gone away
|
||||
SELECT * FROM t1;
|
||||
disconnect c1;
|
||||
|
||||
--echo # Test idle_readwrite_transaction_timeout
|
||||
connect (c2,localhost,root,,test,,);
|
||||
SHOW VARIABLES LIKE 'idle_%transaction_timeout';
|
||||
SET autocommit=0;
|
||||
SET idle_readwrite_transaction_timeout=1;
|
||||
|
||||
BEGIN;
|
||||
SELECT * FROM t1;
|
||||
sleep 2;
|
||||
|
||||
SELECT * FROM t1;
|
||||
INSERT INTO t1 VALUES (1);
|
||||
sleep 2;
|
||||
|
||||
--error 2006, 2013 # Gone away
|
||||
SELECT * FROM t1;
|
||||
disconnect c2;
|
||||
|
||||
connection default;
|
||||
DROP TABLE t1;
|
@ -1476,7 +1476,7 @@ struct THD_TRANS
|
||||
bool trans_did_wait() const {
|
||||
return (m_unsafe_rollback_flags & DID_WAIT) != 0;
|
||||
}
|
||||
|
||||
bool is_trx_read_write() const;
|
||||
};
|
||||
|
||||
|
||||
@ -1576,6 +1576,16 @@ private:
|
||||
};
|
||||
|
||||
|
||||
inline bool THD_TRANS::is_trx_read_write() const
|
||||
{
|
||||
Ha_trx_info *ha_info;
|
||||
for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
|
||||
if (ha_info->is_trx_read_write())
|
||||
return TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
|
||||
ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
|
||||
|
||||
|
@ -695,6 +695,10 @@ typedef struct system_variables
|
||||
my_bool session_track_state_change;
|
||||
|
||||
ulong threadpool_priority;
|
||||
|
||||
uint idle_transaction_timeout;
|
||||
uint idle_readonly_transaction_timeout;
|
||||
uint idle_readwrite_transaction_timeout;
|
||||
} SV;
|
||||
|
||||
/**
|
||||
@ -4287,6 +4291,29 @@ public:
|
||||
current_linfo= 0;
|
||||
mysql_mutex_unlock(&LOCK_thread_count);
|
||||
}
|
||||
|
||||
|
||||
uint get_net_wait_timeout()
|
||||
{
|
||||
if (in_active_multi_stmt_transaction())
|
||||
{
|
||||
if (transaction.all.is_trx_read_write())
|
||||
{
|
||||
if (variables.idle_readwrite_transaction_timeout > 0)
|
||||
return variables.idle_readwrite_transaction_timeout;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (variables.idle_readonly_transaction_timeout > 0)
|
||||
return variables.idle_readonly_transaction_timeout;
|
||||
}
|
||||
|
||||
if (variables.idle_transaction_timeout > 0)
|
||||
return variables.idle_transaction_timeout;
|
||||
}
|
||||
|
||||
return variables.net_wait_timeout;
|
||||
}
|
||||
};
|
||||
|
||||
inline void add_to_active_threads(THD *thd)
|
||||
|
@ -1210,8 +1210,8 @@ bool do_command(THD *thd)
|
||||
the client, the connection is closed or "net_wait_timeout"
|
||||
number of seconds has passed.
|
||||
*/
|
||||
if(!thd->skip_wait_timeout)
|
||||
my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
|
||||
if (!thd->skip_wait_timeout)
|
||||
my_net_set_read_timeout(net, thd->get_net_wait_timeout());
|
||||
|
||||
/*
|
||||
XXX: this code is here only to clear possible errors of init_connect.
|
||||
|
@ -3519,6 +3519,27 @@ static Sys_var_ulong Sys_net_wait_timeout(
|
||||
VALID_RANGE(1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
|
||||
DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1));
|
||||
|
||||
static Sys_var_uint Sys_idle_transaction_timeout(
|
||||
"idle_transaction_timeout",
|
||||
"The number of seconds the server waits for idle transaction",
|
||||
SESSION_VAR(idle_transaction_timeout), CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
|
||||
DEFAULT(0), BLOCK_SIZE(1));
|
||||
|
||||
static Sys_var_uint Sys_idle_readonly_transaction_timeout(
|
||||
"idle_readonly_transaction_timeout",
|
||||
"The number of seconds the server waits for read-only idle transaction",
|
||||
SESSION_VAR(idle_readonly_transaction_timeout), CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
|
||||
DEFAULT(0), BLOCK_SIZE(1));
|
||||
|
||||
static Sys_var_uint Sys_idle_readwrite_transaction_timeout(
|
||||
"idle_readwrite_transaction_timeout",
|
||||
"The number of seconds the server waits for read-write idle transaction",
|
||||
SESSION_VAR(idle_readwrite_transaction_timeout), CMD_LINE(REQUIRED_ARG),
|
||||
VALID_RANGE(0, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
|
||||
DEFAULT(0), BLOCK_SIZE(1));
|
||||
|
||||
static Sys_var_plugin Sys_default_storage_engine(
|
||||
"default_storage_engine", "The default storage engine for new tables",
|
||||
SESSION_VAR(table_plugin), NO_CMD_LINE,
|
||||
|
@ -199,7 +199,7 @@ void tp_callback(TP_connection *c)
|
||||
c->priority= get_priority(c);
|
||||
|
||||
/* Read next command from client. */
|
||||
c->set_io_timeout(thd->variables.net_wait_timeout);
|
||||
c->set_io_timeout(thd->get_net_wait_timeout());
|
||||
c->state= TP_STATE_IDLE;
|
||||
if (c->start_io())
|
||||
goto error;
|
||||
|
Loading…
x
Reference in New Issue
Block a user