1
# name : innodb_kill_idle_transaction.patch
3
# maintainer : Yasufumi
6
# Any small change to this file in the main branch
7
# should be done or reviewed by the maintainer!
8
--- a/include/mysql/plugin.h
9
+++ b/include/mysql/plugin.h
12
void thd_set_ha_data(MYSQL_THD thd, const struct handlerton *hton,
15
+int thd_command(const MYSQL_THD thd);
16
+long long thd_start_time(const MYSQL_THD thd);
17
+void thd_kill(MYSQL_THD thd);
18
+#define EXTENDED_FOR_KILLIDLE
23
--- a/include/mysql/plugin.h.pp
24
+++ b/include/mysql/plugin.h.pp
26
void *thd_get_ha_data(const void* thd, const struct handlerton *hton);
27
void thd_set_ha_data(void* thd, const struct handlerton *hton,
29
+int thd_command(const void* thd);
30
+long long thd_start_time(const void* thd);
31
+void thd_kill(void* thd);
32
--- a/sql/sql_class.cc
33
+++ b/sql/sql_class.cc
38
+/* extend for kill session of idle transaction from engine */
40
+int thd_command(const THD* thd)
42
+ return (int) thd->command;
46
+long long thd_start_time(const THD* thd)
48
+ return (long long) thd->start_time;
52
+void thd_kill(THD* thd)
54
+ pthread_mutex_lock(&thd->LOCK_thd_data);
55
+ thd->awake(THD::KILL_CONNECTION);
56
+ pthread_mutex_unlock(&thd->LOCK_thd_data);
60
Implementation of Drop_table_error_handler::handle_error().
61
--- a/storage/innodb_plugin/handler/ha_innodb.cc
62
+++ b/storage/innodb_plugin/handler/ha_innodb.cc
63
@@ -2517,6 +2517,10 @@
65
innobase_commit_concurrency_init_default();
67
+#ifndef EXTENDED_FOR_KILLIDLE
68
+ srv_kill_idle_transaction = 0;
71
/* Since we in this module access directly the fields of a trx
72
struct, and due to different headers and flags it might happen that
73
mutex_t has a different size in this module and in InnoDB
74
@@ -11231,6 +11235,48 @@
78
+/***********************************************************************
79
+functions for kill session of idle transaction */
82
+innobase_thd_is_idle(
83
+/*=================*/
84
+ const void* thd) /*!< in: thread handle (THD*) */
86
+#ifdef EXTENDED_FOR_KILLIDLE
87
+ return(thd_command((const THD*) thd) == COM_SLEEP);
95
+innobase_thd_get_start_time(
96
+/*========================*/
97
+ const void* thd) /*!< in: thread handle (THD*) */
99
+#ifdef EXTENDED_FOR_KILLIDLE
100
+ return((ib_int64_t)thd_start_time((const THD*) thd));
102
+ return(0); /*dummy value*/
112
+#ifdef EXTENDED_FOR_KILLIDLE
113
+ thd_kill((THD*) thd);
120
static SHOW_VAR innodb_status_variables_export[]= {
121
{"Innodb", (char*) &show_innodb_vars, SHOW_FUNC},
122
{NullS, NullS, SHOW_LONG}
123
@@ -11474,6 +11520,15 @@
124
"Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket",
125
NULL, NULL, 500L, 1L, ~0L, 0);
127
+static MYSQL_SYSVAR_LONG(kill_idle_transaction, srv_kill_idle_transaction,
128
+ PLUGIN_VAR_RQCMDARG,
129
+#ifdef EXTENDED_FOR_KILLIDLE
130
+ "If non-zero value, the idle session with transaction which is idle over the value in seconds is killed by InnoDB.",
132
+ "No effect for this build.",
134
+ NULL, NULL, 0, 0, LONG_MAX, 0);
136
static MYSQL_SYSVAR_LONG(file_io_threads, innobase_file_io_threads,
137
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY | PLUGIN_VAR_NOSYSVAR,
138
"Number of file I/O threads in InnoDB.",
139
@@ -11767,6 +11822,7 @@
140
MYSQL_SYSVAR(fast_checksum),
141
MYSQL_SYSVAR(commit_concurrency),
142
MYSQL_SYSVAR(concurrency_tickets),
143
+ MYSQL_SYSVAR(kill_idle_transaction),
144
MYSQL_SYSVAR(data_file_path),
145
MYSQL_SYSVAR(doublewrite_file),
146
MYSQL_SYSVAR(data_home_dir),
147
--- a/storage/innodb_plugin/include/srv0srv.h
148
+++ b/storage/innodb_plugin/include/srv0srv.h
150
extern ulint srv_activity_count;
151
extern ulint srv_fatal_semaphore_wait_threshold;
152
extern ulint srv_dml_needed_delay;
153
+extern lint srv_kill_idle_transaction;
155
extern mutex_t* kernel_mutex_temp;/* mutex protecting the server, trx structs,
156
query threads, and lock table: we allocate
157
--- a/storage/innodb_plugin/include/trx0trx.h
158
+++ b/storage/innodb_plugin/include/trx0trx.h
160
ulint mysql_process_no;/* since in Linux, 'top' reports
161
process id's and not thread id's, we
162
store the process number too */
164
+ ib_int64_t last_stmt_start;
165
/*------------------------------*/
166
ulint n_mysql_tables_in_use; /* number of Innobase tables
167
used in the processing of the current
168
--- a/storage/innodb_plugin/srv/srv0srv.c
169
+++ b/storage/innodb_plugin/srv/srv0srv.c
172
#include "os0sync.h" /* for HAVE_ATOMIC_BUILTINS */
174
+/* prototypes of new functions added to ha_innodb.cc for kill_idle_transaction */
175
+ibool innobase_thd_is_idle(const void* thd);
176
+ib_int64_t innobase_thd_get_start_time(const void* thd);
177
+void innobase_thd_kill(void* thd);
179
/* prototypes for new functions added to ha_innodb.cc */
180
ibool innobase_get_slow_log();
183
/* The following is the maximum allowed duration of a lock wait. */
184
UNIV_INTERN ulint srv_fatal_semaphore_wait_threshold = 600;
187
+UNIV_INTERN lint srv_kill_idle_transaction = 0;
189
/* How much data manipulation language (DML) statements need to be delayed,
190
in microseconds, in order to reduce the lagging of the purge thread. */
191
UNIV_INTERN ulint srv_dml_needed_delay = 0;
192
@@ -2557,6 +2565,36 @@
196
+ if (srv_kill_idle_transaction && trx_sys) {
201
+ mutex_enter(&kernel_mutex);
202
+ trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
204
+ if (trx->conc_state == TRX_ACTIVE
206
+ && innobase_thd_is_idle(trx->mysql_thd)) {
207
+ ib_int64_t start_time; /* as stmt ID */
209
+ start_time = innobase_thd_get_start_time(trx->mysql_thd);
210
+ if (trx->last_stmt_start != start_time) {
211
+ trx->idle_start = now;
212
+ trx->last_stmt_start = start_time;
213
+ } else if (difftime(now, trx->idle_start)
214
+ > srv_kill_idle_transaction) {
215
+ /* kill the session */
216
+ mutex_exit(&kernel_mutex);
217
+ innobase_thd_kill(trx->mysql_thd);
221
+ trx = UT_LIST_GET_NEXT(mysql_trx_list, trx);
223
+ mutex_exit(&kernel_mutex);
226
/* Flush stderr so that a database user gets the output
227
to possible MySQL error file */
229
--- a/storage/innodb_plugin/trx/trx0trx.c
230
+++ b/storage/innodb_plugin/trx/trx0trx.c
232
trx->mysql_relay_log_file_name = "";
233
trx->mysql_relay_log_pos = 0;
235
+ trx->idle_start = 0;
236
+ trx->last_stmt_start = 0;
238
mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO);
242
+++ b/mysql-test/r/percona_innodb_kill_idle_trx.result
244
+DROP TABLE IF EXISTS t1;
246
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
247
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
249
+innodb_kill_idle_transaction 0
250
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
251
+VARIABLE_NAME VARIABLE_VALUE
252
+INNODB_KILL_IDLE_TRANSACTION 0
253
+SET GLOBAL innodb_kill_idle_transaction=1;
254
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
256
+innodb_kill_idle_transaction 1
257
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
258
+VARIABLE_NAME VARIABLE_VALUE
259
+INNODB_KILL_IDLE_TRANSACTION 1
261
+INSERT INTO t1 VALUES (1),(2),(3);
269
+INSERT INTO t1 VALUES (4),(5),(6);
271
+ERROR HY000: MySQL server has gone away
278
+SET GLOBAL innodb_kill_idle_transaction=0;
279
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
281
+innodb_kill_idle_transaction 0
282
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
283
+VARIABLE_NAME VARIABLE_VALUE
284
+INNODB_KILL_IDLE_TRANSACTION 0
286
+++ b/mysql-test/r/percona_innodb_kill_idle_trx_locks.result
288
+DROP TABLE IF EXISTS t1;
290
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
291
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
293
+innodb_kill_idle_transaction 0
294
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
295
+VARIABLE_NAME VARIABLE_VALUE
296
+INNODB_KILL_IDLE_TRANSACTION 0
297
+SET GLOBAL innodb_kill_idle_transaction=5;
298
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
300
+innodb_kill_idle_transaction 5
301
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
302
+VARIABLE_NAME VARIABLE_VALUE
303
+INNODB_KILL_IDLE_TRANSACTION 5
305
+INSERT INTO t1 VALUES (1),(2),(3);
312
+### Locking rows. Lock should be released when idle trx is killed.
314
+SELECT * FROM t1 FOR UPDATE;
326
+SET GLOBAL innodb_kill_idle_transaction=0;
327
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
329
+innodb_kill_idle_transaction 0
330
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';
331
+VARIABLE_NAME VARIABLE_VALUE
332
+INNODB_KILL_IDLE_TRANSACTION 0
334
+++ b/mysql-test/t/percona_innodb_kill_idle_trx.test
336
+--source include/have_innodb.inc
338
+DROP TABLE IF EXISTS t1;
342
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
344
+--source include/percona_innodb_kill_idle_trx_show.inc
345
+SET GLOBAL innodb_kill_idle_transaction=1;
346
+--source include/percona_innodb_kill_idle_trx_show.inc
349
+INSERT INTO t1 VALUES (1),(2),(3);
354
+INSERT INTO t1 VALUES (4),(5),(6);
358
+--error 2006 --error CR_SERVER_GONE_ERROR
362
+SET GLOBAL innodb_kill_idle_transaction=0;
363
+--source include/percona_innodb_kill_idle_trx_show.inc
365
+++ b/mysql-test/t/percona_innodb_kill_idle_trx_locks.test
367
+--source include/have_innodb.inc
369
+DROP TABLE IF EXISTS t1;
373
+CREATE TABLE t1 (a INT) ENGINE=InnoDB;
375
+--source include/percona_innodb_kill_idle_trx_show.inc
376
+SET GLOBAL innodb_kill_idle_transaction=5;
377
+--source include/percona_innodb_kill_idle_trx_show.inc
379
+connect (conn1,localhost,root,,);
383
+INSERT INTO t1 VALUES (1),(2),(3);
387
+--echo ### Locking rows. Lock should be released when idle trx is killed.
389
+SELECT * FROM t1 FOR UPDATE;
396
+SET GLOBAL innodb_kill_idle_transaction=0;
397
+--source include/percona_innodb_kill_idle_trx_show.inc
399
+++ b/mysql-test/include/percona_innodb_kill_idle_trx_show.inc
401
+SHOW GLOBAL VARIABLES LIKE 'innodb_kill_idle_transaction';
402
+SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE VARIABLE_NAME='innodb_kill_idle_transaction';