Commit 4d6c1573 authored by marko's avatar marko

branches/zip: Make innodb_lock_wait_timeout a settable session variable

(Bug #36285, rb://9).

innodb-index.test, innodb-index.result: Set innodb_lock_wait_timeout as
a session variable instead of relying on the global value.

innodb-index-master.opt: Remove.

innodb-timeout.test: Test that setting the innodb_lock_wait_timeout
works as advertised.

thd_lock_wait_timeout(): New function, to retrieve the lock wait timeout
for a given MySQL client connection (thd), or the global value (thd==NULL).

srv_lock_wait_timeout, innobase_lock_wait_timeout: Remove.

Replace MYSQL_SYSVAR_LONG(lock_wait_timeout)
with MYSQL_THDVAR_ULONG(lock_wait_timeout).  
parent dd5c8747
2008-10-03 The InnoDB Team
* mysql-test/innodb-index.test, mysql-test/innodb-index.result,
mysql-test/innodb-timeout.test, mysql-test/innodb-timeout.result,
srv/srv0srv.c, include/srv0srv.h,
handler/ha_innodb.cc, include/ha_prototypes.h:
Make innodb_lock_wait_timeout a settable session variable.
This fixes MySQL Bug #36285.
2008-09-19 The InnoDB Team 2008-09-19 The InnoDB Team
* os/os0proc.c: * os/os0proc.c:
......
...@@ -128,8 +128,8 @@ static const long AUTOINC_NO_LOCKING = 2; ...@@ -128,8 +128,8 @@ static const long AUTOINC_NO_LOCKING = 2;
static long innobase_mirrored_log_groups, innobase_log_files_in_group, static long innobase_mirrored_log_groups, innobase_log_files_in_group,
innobase_log_buffer_size, innobase_log_buffer_size,
innobase_additional_mem_pool_size, innobase_file_io_threads, innobase_additional_mem_pool_size, innobase_file_io_threads,
innobase_lock_wait_timeout, innobase_force_recovery, innobase_force_recovery, innobase_open_files,
innobase_open_files, innobase_autoinc_lock_mode; innobase_autoinc_lock_mode;
static long long innobase_buffer_pool_size, innobase_log_file_size; static long long innobase_buffer_pool_size, innobase_log_file_size;
...@@ -318,6 +318,10 @@ static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG, ...@@ -318,6 +318,10 @@ static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
"Use strict mode when evaluating create options.", "Use strict mode when evaluating create options.",
NULL, NULL, FALSE); NULL, NULL, FALSE);
static MYSQL_THDVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG,
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
static handler *innobase_create_handler(handlerton *hton, static handler *innobase_create_handler(handlerton *hton,
TABLE_SHARE *table, TABLE_SHARE *table,
...@@ -674,6 +678,21 @@ thd_is_strict( ...@@ -674,6 +678,21 @@ thd_is_strict(
return(THDVAR((THD*) thd, strict_mode)); return(THDVAR((THD*) thd, strict_mode));
} }
/**********************************************************************
Returns the lock wait timeout for the current connection. */
extern "C" UNIV_INTERN
ulong
thd_lock_wait_timeout(
/*==================*/
/* out: the lock wait timeout, in seconds */
void* thd) /* in: thread handle (THD*), or NULL to query
the global innodb_lock_wait_timeout */
{
/* According to <mysql/plugin.h>, passing thd == NULL
returns the global value of the session variable. */
return(THDVAR((THD*) thd, lock_wait_timeout));
}
/************************************************************************ /************************************************************************
Obtain the InnoDB transaction of a MySQL thread. */ Obtain the InnoDB transaction of a MySQL thread. */
inline inline
...@@ -1936,7 +1955,6 @@ innobase_init( ...@@ -1936,7 +1955,6 @@ innobase_init(
srv_n_file_io_threads = (ulint) innobase_file_io_threads; srv_n_file_io_threads = (ulint) innobase_file_io_threads;
srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
srv_force_recovery = (ulint) innobase_force_recovery; srv_force_recovery = (ulint) innobase_force_recovery;
srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite; srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
...@@ -9361,11 +9379,6 @@ static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery, ...@@ -9361,11 +9379,6 @@ static MYSQL_SYSVAR_LONG(force_recovery, innobase_force_recovery,
"Helps to save your data in case the disk image of the database becomes corrupt.", "Helps to save your data in case the disk image of the database becomes corrupt.",
NULL, NULL, 0, 0, 6, 0); NULL, NULL, 0, 0, 6, 0);
static MYSQL_SYSVAR_LONG(lock_wait_timeout, innobase_lock_wait_timeout,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back.",
NULL, NULL, 50, 1, 1024 * 1024 * 1024, 0);
static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size, static MYSQL_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"The size of the buffer which InnoDB uses to write log to the log files on disk.", "The size of the buffer which InnoDB uses to write log to the log files on disk.",
......
...@@ -215,5 +215,15 @@ thd_is_strict( ...@@ -215,5 +215,15 @@ thd_is_strict(
/* out: true if thd is in strict mode */ /* out: true if thd is in strict mode */
void* thd); /* in: thread handle (THD*) */ void* thd); /* in: thread handle (THD*) */
/**********************************************************************
Returns the lock wait timeout for the current connection. */
ulong
thd_lock_wait_timeout(
/*==================*/
/* out: the lock wait timeout, in seconds */
void* thd); /* in: thread handle (THD*), or NULL to query
the global innodb_lock_wait_timeout */
#endif #endif
#endif #endif
...@@ -107,8 +107,6 @@ extern ibool srv_archive_recovery; ...@@ -107,8 +107,6 @@ extern ibool srv_archive_recovery;
extern dulint srv_archive_recovery_limit_lsn; extern dulint srv_archive_recovery_limit_lsn;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
extern ulint srv_lock_wait_timeout;
extern char* srv_file_flush_method_str; extern char* srv_file_flush_method_str;
extern ulint srv_unix_file_flush_method; extern ulint srv_unix_file_flush_method;
extern ulint srv_win_file_flush_method; extern ulint srv_win_file_flush_method;
......
...@@ -847,10 +847,12 @@ create table t2(a int, b varchar(255), primary key(a,b)) engine=innodb; ...@@ -847,10 +847,12 @@ create table t2(a int, b varchar(255), primary key(a,b)) engine=innodb;
insert into t2 select a,left(b,255) from t1; insert into t2 select a,left(b,255) from t1;
drop table t1; drop table t1;
rename table t2 to t1; rename table t2 to t1;
set innodb_lock_wait_timeout=1;
begin; begin;
select a from t1 limit 1 for update; select a from t1 limit 1 for update;
a a
22 22
set innodb_lock_wait_timeout=1;
create index t1ba on t1 (b,a); create index t1ba on t1 (b,a);
ERROR HY000: Lock wait timeout exceeded; try restarting transaction ERROR HY000: Lock wait timeout exceeded; try restarting transaction
commit; commit;
......
...@@ -304,10 +304,12 @@ rename table t2 to t1; ...@@ -304,10 +304,12 @@ rename table t2 to t1;
connect (a,localhost,root,,); connect (a,localhost,root,,);
connect (b,localhost,root,,); connect (b,localhost,root,,);
connection a; connection a;
set innodb_lock_wait_timeout=1;
begin; begin;
# Obtain an IX lock on the table # Obtain an IX lock on the table
select a from t1 limit 1 for update; select a from t1 limit 1 for update;
connection b; connection b;
set innodb_lock_wait_timeout=1;
# This would require an S lock on the table, conflicting with the IX lock. # This would require an S lock on the table, conflicting with the IX lock.
--error ER_LOCK_WAIT_TIMEOUT --error ER_LOCK_WAIT_TIMEOUT
create index t1ba on t1 (b,a); create index t1ba on t1 (b,a);
......
set global innodb_lock_wait_timeout=42;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
42
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
1
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
42
set global innodb_lock_wait_timeout=347;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
42
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
1
select @@innodb_lock_wait_timeout;
@@innodb_lock_wait_timeout
347
create table t1(a int primary key)engine=innodb;
begin;
insert into t1 values(1),(2),(3);
select * from t1 for update;
commit;
a
1
2
3
begin;
insert into t1 values(4);
select * from t1 for update;
commit;
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
drop table t1;
set global innodb_lock_wait_timeout=50;
-- source include/have_innodb.inc
let $timeout=`select @@innodb_lock_wait_timeout`;
set global innodb_lock_wait_timeout=42;
connect (a,localhost,root,,);
connect (b,localhost,root,,);
connection a;
select @@innodb_lock_wait_timeout;
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
connection b;
select @@innodb_lock_wait_timeout;
set global innodb_lock_wait_timeout=347;
select @@innodb_lock_wait_timeout;
set innodb_lock_wait_timeout=1;
select @@innodb_lock_wait_timeout;
connect (c,localhost,root,,);
connection c;
select @@innodb_lock_wait_timeout;
connection default;
disconnect c;
connection a;
create table t1(a int primary key)engine=innodb;
begin;
insert into t1 values(1),(2),(3);
connection b;
--send
select * from t1 for update;
connection a;
commit;
connection b;
reap;
connection a;
begin;
insert into t1 values(4);
connection b;
--send
select * from t1 for update;
connection a;
sleep 2;
commit;
connection b;
--error ER_LOCK_WAIT_TIMEOUT
reap;
drop table t1;
connection default;
disconnect a;
disconnect b;
eval set global innodb_lock_wait_timeout=$timeout;
...@@ -154,8 +154,6 @@ UNIV_INTERN ibool srv_archive_recovery = 0; ...@@ -154,8 +154,6 @@ UNIV_INTERN ibool srv_archive_recovery = 0;
UNIV_INTERN ib_uint64_t srv_archive_recovery_limit_lsn; UNIV_INTERN ib_uint64_t srv_archive_recovery_limit_lsn;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
UNIV_INTERN ulint srv_lock_wait_timeout = 1024 * 1024 * 1024;
/* This parameter is used to throttle the number of insert buffers that are /* This parameter is used to throttle the number of insert buffers that are
merged in a batch. By increasing this parameter on a faster disk you can merged in a batch. By increasing this parameter on a faster disk you can
possibly reduce the number of I/O operations performed to complete the possibly reduce the number of I/O operations performed to complete the
...@@ -1377,6 +1375,7 @@ srv_suspend_mysql_thread( ...@@ -1377,6 +1375,7 @@ srv_suspend_mysql_thread(
ulint diff_time; ulint diff_time;
ulint sec; ulint sec;
ulint ms; ulint ms;
ulong lock_wait_timeout;
ut_ad(!mutex_own(&kernel_mutex)); ut_ad(!mutex_own(&kernel_mutex));
...@@ -1515,8 +1514,14 @@ srv_suspend_mysql_thread( ...@@ -1515,8 +1514,14 @@ srv_suspend_mysql_thread(
mutex_exit(&kernel_mutex); mutex_exit(&kernel_mutex);
if (srv_lock_wait_timeout < 100000000 /* InnoDB system transactions (such as the purge, and
&& wait_time > (double)srv_lock_wait_timeout) { incomplete transactions that are being rolled back after crash
recovery) will use the global value of
innodb_lock_wait_timeout, because trx->mysql_thd == NULL. */
lock_wait_timeout = thd_lock_wait_timeout(trx->mysql_thd);
if (lock_wait_timeout < 100000000
&& wait_time > (double) lock_wait_timeout) {
trx->error_state = DB_LOCK_WAIT_TIMEOUT; trx->error_state = DB_LOCK_WAIT_TIMEOUT;
} }
...@@ -1966,12 +1971,19 @@ srv_lock_timeout_and_monitor_thread( ...@@ -1966,12 +1971,19 @@ srv_lock_timeout_and_monitor_thread(
slot = srv_mysql_table + i; slot = srv_mysql_table + i;
if (slot->in_use) { if (slot->in_use) {
trx_t* trx;
ulong lock_wait_timeout;
some_waits = TRUE; some_waits = TRUE;
wait_time = ut_difftime(ut_time(), slot->suspend_time); wait_time = ut_difftime(ut_time(), slot->suspend_time);
if (srv_lock_wait_timeout < 100000000 trx = thr_get_trx(slot->thr);
&& (wait_time > (double) srv_lock_wait_timeout lock_wait_timeout = thd_lock_wait_timeout(
trx->mysql_thd);
if (lock_wait_timeout < 100000000
&& (wait_time > (double) lock_wait_timeout
|| wait_time < 0)) { || wait_time < 0)) {
/* Timeout exceeded or a wrap-around in system /* Timeout exceeded or a wrap-around in system
...@@ -1981,10 +1993,9 @@ srv_lock_timeout_and_monitor_thread( ...@@ -1981,10 +1993,9 @@ srv_lock_timeout_and_monitor_thread(
possible that the lock has already been possible that the lock has already been
granted: in that case do nothing */ granted: in that case do nothing */
if (thr_get_trx(slot->thr)->wait_lock) { if (trx->wait_lock) {
lock_cancel_waiting_and_release( lock_cancel_waiting_and_release(
thr_get_trx(slot->thr) trx->wait_lock);
->wait_lock);
} }
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment