Skip to content

Commit 68d6a67

Browse files
AliSQLAliSQL
authored andcommitted
[Feature] Issue#1 KILL IDLE TRANSACTIONS
Description: ------------ 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
1 parent 958add0 commit 68d6a67

8 files changed

Lines changed: 334 additions & 1 deletion

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
SHOW VARIABLES LIKE 'trx%idle_timeout';
2+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;

mysql-test/r/mysqld--help-notwin.result

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,15 @@ The following options may be given as the first argument:
10141014
--transaction-read-only
10151015
Default transaction access mode. True if transactions are
10161016
read-only.
1017+
--trx-changes-idle-timeout=#
1018+
The number of seconds the server waits for not-readonly
1019+
idle transaction
1020+
--trx-idle-timeout=#
1021+
The number of seconds the server waits for idle
1022+
transaction
1023+
--trx-readonly-idle-timeout=#
1024+
The number of seconds the server waits for readonly idle
1025+
transaction
10171026
--updatable-views-with-limit=name
10181027
YES = Don't issue an error message (warning only) if a
10191028
VIEW without presence of a key of the underlying table is
@@ -1320,6 +1329,9 @@ transaction-alloc-block-size 8192
13201329
transaction-isolation REPEATABLE-READ
13211330
transaction-prealloc-size 4096
13221331
transaction-read-only FALSE
1332+
trx-changes-idle-timeout 0
1333+
trx-idle-timeout 0
1334+
trx-readonly-idle-timeout 0
13231335
updatable-views-with-limit YES
13241336
validate-user-plugins TRUE
13251337
verbose TRUE
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
DROP TABLE IF EXISTS t1;
2+
SET autocommit=0;
3+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
4+
SHOW VARIABLES LIKE 'trx%idle_timeout';
5+
Variable_name Value
6+
trx_changes_idle_timeout 0
7+
trx_idle_timeout 0
8+
trx_readonly_idle_timeout 0
9+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
10+
VARIABLE_NAME VARIABLE_VALUE
11+
TRX_CHANGES_IDLE_TIMEOUT 0
12+
TRX_IDLE_TIMEOUT 0
13+
TRX_READONLY_IDLE_TIMEOUT 0
14+
SET trx_idle_timeout=1;
15+
SHOW VARIABLES LIKE 'trx%idle_timeout';
16+
Variable_name Value
17+
trx_changes_idle_timeout 0
18+
trx_idle_timeout 1
19+
trx_readonly_idle_timeout 0
20+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
21+
VARIABLE_NAME VARIABLE_VALUE
22+
TRX_CHANGES_IDLE_TIMEOUT 0
23+
TRX_IDLE_TIMEOUT 1
24+
TRX_READONLY_IDLE_TIMEOUT 0
25+
BEGIN;
26+
INSERT INTO t1 VALUES (1),(2),(3);
27+
COMMIT;
28+
SELECT * FROM t1;
29+
a
30+
1
31+
2
32+
3
33+
BEGIN;
34+
INSERT INTO t1 VALUES (4),(5),(6);
35+
SELECT * FROM t1;
36+
ERROR HY000: MySQL server has gone away
37+
SELECT * FROM t1;
38+
a
39+
1
40+
2
41+
3
42+
DROP TABLE t1;
43+
SET trx_idle_timeout=0;
44+
SHOW VARIABLES LIKE 'trx%idle_timeout';
45+
Variable_name Value
46+
trx_changes_idle_timeout 0
47+
trx_idle_timeout 0
48+
trx_readonly_idle_timeout 0
49+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
50+
VARIABLE_NAME VARIABLE_VALUE
51+
TRX_CHANGES_IDLE_TIMEOUT 0
52+
TRX_IDLE_TIMEOUT 0
53+
TRX_READONLY_IDLE_TIMEOUT 0
54+
DROP TABLE IF EXISTS t1;
55+
SET autocommit=0;
56+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
57+
SHOW VARIABLES LIKE 'trx%idle_timeout';
58+
Variable_name Value
59+
trx_changes_idle_timeout 0
60+
trx_idle_timeout 0
61+
trx_readonly_idle_timeout 0
62+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
63+
VARIABLE_NAME VARIABLE_VALUE
64+
TRX_CHANGES_IDLE_TIMEOUT 0
65+
TRX_IDLE_TIMEOUT 0
66+
TRX_READONLY_IDLE_TIMEOUT 0
67+
SET trx_readonly_idle_timeout=1;
68+
SHOW VARIABLES LIKE 'trx%idle_timeout';
69+
Variable_name Value
70+
trx_changes_idle_timeout 0
71+
trx_idle_timeout 0
72+
trx_readonly_idle_timeout 1
73+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
74+
VARIABLE_NAME VARIABLE_VALUE
75+
TRX_CHANGES_IDLE_TIMEOUT 0
76+
TRX_IDLE_TIMEOUT 0
77+
TRX_READONLY_IDLE_TIMEOUT 1
78+
BEGIN;
79+
INSERT INTO t1 VALUES (1),(2),(3);
80+
SELECT * FROM t1;
81+
a
82+
1
83+
2
84+
3
85+
COMMIT;
86+
SELECT * FROM t1;
87+
a
88+
1
89+
2
90+
3
91+
SELECT * FROM t1;
92+
ERROR HY000: MySQL server has gone away
93+
SELECT * FROM t1;
94+
a
95+
1
96+
2
97+
3
98+
DROP TABLE t1;
99+
SET trx_readonly_idle_timeout=0;
100+
SHOW VARIABLES LIKE 'trx%idle_timeout';
101+
Variable_name Value
102+
trx_changes_idle_timeout 0
103+
trx_idle_timeout 0
104+
trx_readonly_idle_timeout 0
105+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
106+
VARIABLE_NAME VARIABLE_VALUE
107+
TRX_CHANGES_IDLE_TIMEOUT 0
108+
TRX_IDLE_TIMEOUT 0
109+
TRX_READONLY_IDLE_TIMEOUT 0
110+
DROP TABLE IF EXISTS t1;
111+
SET autocommit=0;
112+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
113+
SHOW VARIABLES LIKE 'trx%idle_timeout';
114+
Variable_name Value
115+
trx_changes_idle_timeout 0
116+
trx_idle_timeout 0
117+
trx_readonly_idle_timeout 0
118+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
119+
VARIABLE_NAME VARIABLE_VALUE
120+
TRX_CHANGES_IDLE_TIMEOUT 0
121+
TRX_IDLE_TIMEOUT 0
122+
TRX_READONLY_IDLE_TIMEOUT 0
123+
SET trx_changes_idle_timeout=1;
124+
SHOW VARIABLES LIKE 'trx%idle_timeout';
125+
Variable_name Value
126+
trx_changes_idle_timeout 1
127+
trx_idle_timeout 0
128+
trx_readonly_idle_timeout 0
129+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
130+
VARIABLE_NAME VARIABLE_VALUE
131+
TRX_CHANGES_IDLE_TIMEOUT 1
132+
TRX_IDLE_TIMEOUT 0
133+
TRX_READONLY_IDLE_TIMEOUT 0
134+
BEGIN;
135+
INSERT INTO t1 VALUES (1),(2),(3);
136+
SELECT * FROM t1;
137+
a
138+
1
139+
2
140+
3
141+
COMMIT;
142+
SELECT * FROM t1;
143+
a
144+
1
145+
2
146+
3
147+
SELECT * FROM t1;
148+
a
149+
1
150+
2
151+
3
152+
INSERT INTO t1 VALUES (4),(5),(6);
153+
SELECT * FROM t1;
154+
ERROR HY000: MySQL server has gone away
155+
DROP TABLE t1;
156+
SET trx_changes_idle_timeout=0;
157+
SHOW VARIABLES LIKE 'trx%idle_timeout';
158+
Variable_name Value
159+
trx_changes_idle_timeout 0
160+
trx_idle_timeout 0
161+
trx_readonly_idle_timeout 0
162+
SELECT * FROM INFORMATION_SCHEMA.SESSION_VARIABLES WHERE VARIABLE_NAME LIKE 'trx%idle_timeout' order by VARIABLE_NAME;
163+
VARIABLE_NAME VARIABLE_VALUE
164+
TRX_CHANGES_IDLE_TIMEOUT 0
165+
TRX_IDLE_TIMEOUT 0
166+
TRX_READONLY_IDLE_TIMEOUT 0
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# Test Case For Kill All Transactions
2+
--source include/have_innodb.inc
3+
if (`SELECT $SP_PROTOCOL + $CURSOR_PROTOCOL + $VIEW_PROTOCOL <= 0
4+
AND $PS_PROTOCOL <> 0`)
5+
{
6+
--skip Needn't ps-protocol
7+
}
8+
9+
--disable_warnings
10+
DROP TABLE IF EXISTS t1;
11+
--enable_warnings
12+
13+
SET autocommit=0;
14+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
15+
16+
--source include/server_kill_idle_trx_show.inc
17+
SET trx_idle_timeout=1;
18+
--source include/server_kill_idle_trx_show.inc
19+
20+
BEGIN;
21+
INSERT INTO t1 VALUES (1),(2),(3);
22+
COMMIT;
23+
SELECT * FROM t1;
24+
25+
BEGIN;
26+
INSERT INTO t1 VALUES (4),(5),(6);
27+
sleep 3;
28+
29+
--enable_reconnect
30+
--error 2006 --error CR_SERVER_GONE_ERROR
31+
SELECT * FROM t1;
32+
SELECT * FROM t1;
33+
DROP TABLE t1;
34+
SET trx_idle_timeout=0;
35+
--source include/server_kill_idle_trx_show.inc
36+
37+
# Test Case For Kill Read-Only Transaction
38+
--source include/have_innodb.inc
39+
--disable_warnings
40+
DROP TABLE IF EXISTS t1;
41+
--enable_warnings
42+
43+
SET autocommit=0;
44+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
45+
46+
--source include/server_kill_idle_trx_show.inc
47+
SET trx_readonly_idle_timeout=1;
48+
--source include/server_kill_idle_trx_show.inc
49+
50+
BEGIN;
51+
INSERT INTO t1 VALUES (1),(2),(3);
52+
SELECT * FROM t1;
53+
COMMIT;
54+
SELECT * FROM t1;
55+
56+
sleep 3;
57+
58+
--enable_reconnect
59+
--error 2006 --error CR_SERVER_GONE_ERROR
60+
SELECT * FROM t1;
61+
SELECT * FROM t1;
62+
DROP TABLE t1;
63+
SET trx_readonly_idle_timeout=0;
64+
--source include/server_kill_idle_trx_show.inc
65+
66+
# Test Case For Kill Changes Transaction
67+
--source include/have_innodb.inc
68+
--disable_warnings
69+
DROP TABLE IF EXISTS t1;
70+
--enable_warnings
71+
72+
SET autocommit=0;
73+
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
74+
75+
--source include/server_kill_idle_trx_show.inc
76+
SET trx_changes_idle_timeout=1;
77+
--source include/server_kill_idle_trx_show.inc
78+
79+
BEGIN;
80+
INSERT INTO t1 VALUES (1),(2),(3);
81+
SELECT * FROM t1;
82+
COMMIT;
83+
SELECT * FROM t1;
84+
85+
sleep 3;
86+
87+
SELECT * FROM t1;
88+
INSERT INTO t1 VALUES (4),(5),(6);
89+
sleep 3;
90+
--enable_reconnect
91+
--error 2006 --error CR_SERVER_GONE_ERROR
92+
SELECT * FROM t1;
93+
DROP TABLE t1;
94+
SET trx_changes_idle_timeout=0;
95+
--source include/server_kill_idle_trx_show.inc

mysql-test/suite/sys_vars/r/all_vars.result

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,11 @@ RDS_THREADS_RUNNING_CTL_MODE
3030
RDS_THREADS_RUNNING_CTL_MODE
3131
RDS_THREADS_RUNNING_HIGH_WATERMARK
3232
RDS_THREADS_RUNNING_HIGH_WATERMARK
33+
TRX_CHANGES_IDLE_TIMEOUT
34+
TRX_CHANGES_IDLE_TIMEOUT
35+
TRX_IDLE_TIMEOUT
36+
TRX_IDLE_TIMEOUT
37+
TRX_READONLY_IDLE_TIMEOUT
38+
TRX_READONLY_IDLE_TIMEOUT
3339
drop table t1;
3440
drop table t2;

sql/sql_class.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,9 @@ typedef struct system_variables
474474
ulong net_retry_count;
475475
ulong net_wait_timeout;
476476
ulong net_write_timeout;
477+
ulong trx_idle_timeout;
478+
ulong trx_readonly_idle_timeout;
479+
ulong trx_changes_idle_timeout;
477480
ulong optimizer_prune_level;
478481
ulong optimizer_search_depth;
479482
ulong preload_buff_size;
@@ -1218,6 +1221,15 @@ class Ha_trx_info
12181221
uchar m_flags;
12191222
};
12201223

1224+
inline int ha_check_trx_read_only(Ha_trx_info *ha_list)
1225+
{
1226+
Ha_trx_info *ha_info;
1227+
for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
1228+
if (ha_info->is_trx_read_write())
1229+
return FALSE;
1230+
return TRUE;
1231+
}
1232+
12211233
struct st_savepoint {
12221234
struct st_savepoint *prev;
12231235
char *name;

sql/sql_parse.cc

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -927,7 +927,26 @@ bool do_command(THD *thd)
927927
the client, the connection is closed or "net_wait_timeout"
928928
number of seconds has passed.
929929
*/
930-
my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
930+
THD_TRANS *trans= &thd->transaction.all;
931+
Ha_trx_info *ha_info= trans->ha_list;
932+
bool is_trx_read_only= ha_check_trx_read_only(ha_info);
933+
if (thd->in_active_multi_stmt_transaction())
934+
{
935+
if (thd->variables.trx_idle_timeout > 0)
936+
{
937+
my_net_set_read_timeout(net, thd->variables.trx_idle_timeout);
938+
} else if ((thd->variables.trx_readonly_idle_timeout > 0) && is_trx_read_only)
939+
{
940+
my_net_set_read_timeout(net, thd->variables.trx_readonly_idle_timeout);
941+
} else if ((thd->variables.trx_changes_idle_timeout > 0) && !is_trx_read_only)
942+
{
943+
my_net_set_read_timeout(net, thd->variables.trx_changes_idle_timeout);
944+
} else {
945+
my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
946+
}
947+
} else {
948+
my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
949+
}
931950

932951
/*
933952
XXX: this code is here only to clear possible errors of init_connect.

sql/sys_vars.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3137,6 +3137,27 @@ static Sys_var_ulong Sys_net_wait_timeout(
31373137
VALID_RANGE(1, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
31383138
DEFAULT(NET_WAIT_TIMEOUT), BLOCK_SIZE(1));
31393139

3140+
static Sys_var_ulong Sys_trx_idle_timeout(
3141+
"trx_idle_timeout",
3142+
"The number of seconds the server waits for idle transaction",
3143+
SESSION_VAR(trx_idle_timeout), CMD_LINE(REQUIRED_ARG),
3144+
VALID_RANGE(0, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
3145+
DEFAULT(0), BLOCK_SIZE(1));
3146+
3147+
static Sys_var_ulong Sys_trx_readonly_idle_timeout(
3148+
"trx_readonly_idle_timeout",
3149+
"The number of seconds the server waits for readonly idle transaction",
3150+
SESSION_VAR(trx_readonly_idle_timeout), CMD_LINE(REQUIRED_ARG),
3151+
VALID_RANGE(0, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
3152+
DEFAULT(0), BLOCK_SIZE(1));
3153+
3154+
static Sys_var_ulong Sys_trx_changes_idle_timeout(
3155+
"trx_changes_idle_timeout",
3156+
"The number of seconds the server waits for not-readonly idle transaction",
3157+
SESSION_VAR(trx_changes_idle_timeout), CMD_LINE(REQUIRED_ARG),
3158+
VALID_RANGE(0, IF_WIN(INT_MAX32/1000, LONG_TIMEOUT)),
3159+
DEFAULT(0), BLOCK_SIZE(1));
3160+
31403161
static Sys_var_plugin Sys_default_storage_engine(
31413162
"default_storage_engine", "The default storage engine for new tables",
31423163
SESSION_VAR(table_plugin), NO_CMD_LINE,

0 commit comments

Comments
 (0)