Skip to content

Commit

Permalink
Port v5.1 SysVar: innodb_deadlock_detect
Browse files Browse the repository at this point in the history
Summary:
Add innodb_deadlock_detect to disable deadlock detection on row locks.

This is set to 1 by default.

When set to 0, row lock wait timeouts will break deadlocks.

This is done to avoid the performance hit from deadlock detection.

The detection code holds kernel_mutex when making checks which prevents
anything else from making progress.

Test Plan: Follow-up diff includes mtr using this, it passes.  Jenkins

Reviewers: chip

Reviewed By: chip
  • Loading branch information
steaphangreene committed Apr 19, 2013
1 parent 24b3d11 commit dbc3c69
Show file tree
Hide file tree
Showing 6 changed files with 171 additions and 1 deletion.
92 changes: 92 additions & 0 deletions mysql-test/suite/sys_vars/r/innodb_deadlock_detect_basic.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
SET @start_global_value = @@global.innodb_deadlock_detect;
SELECT @start_global_value;
@start_global_value
1
Valid values are 'ON' and 'OFF'
select @@global.innodb_deadlock_detect in (0, 1);
@@global.innodb_deadlock_detect in (0, 1)
1
select @@global.innodb_deadlock_detect;
@@global.innodb_deadlock_detect
1
select @@session.innodb_deadlock_detect;
ERROR HY000: Variable 'innodb_deadlock_detect' is a GLOBAL variable
show global variables like 'innodb_deadlock_detect';
Variable_name Value
innodb_deadlock_detect ON
show session variables like 'innodb_deadlock_detect';
Variable_name Value
innodb_deadlock_detect ON
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
set global innodb_deadlock_detect='OFF';
select @@global.innodb_deadlock_detect;
@@global.innodb_deadlock_detect
0
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT OFF
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT OFF
set @@global.innodb_deadlock_detect=1;
select @@global.innodb_deadlock_detect;
@@global.innodb_deadlock_detect
1
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
set global innodb_deadlock_detect=0;
select @@global.innodb_deadlock_detect;
@@global.innodb_deadlock_detect
0
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT OFF
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT OFF
set @@global.innodb_deadlock_detect='ON';
select @@global.innodb_deadlock_detect;
@@global.innodb_deadlock_detect
1
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
set session innodb_deadlock_detect='OFF';
ERROR HY000: Variable 'innodb_deadlock_detect' is a GLOBAL variable and should be set with SET GLOBAL
set @@session.innodb_deadlock_detect='ON';
ERROR HY000: Variable 'innodb_deadlock_detect' is a GLOBAL variable and should be set with SET GLOBAL
set global innodb_deadlock_detect=1.1;
ERROR 42000: Incorrect argument type to variable 'innodb_deadlock_detect'
set global innodb_deadlock_detect=1e1;
ERROR 42000: Incorrect argument type to variable 'innodb_deadlock_detect'
set global innodb_deadlock_detect=2;
ERROR 42000: Variable 'innodb_deadlock_detect' can't be set to the value of '2'
NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643)
set global innodb_deadlock_detect=-3;
select @@global.innodb_deadlock_detect;
@@global.innodb_deadlock_detect
1
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
VARIABLE_NAME VARIABLE_VALUE
INNODB_DEADLOCK_DETECT ON
set global innodb_deadlock_detect='AUTO';
ERROR 42000: Variable 'innodb_deadlock_detect' can't be set to the value of 'AUTO'
SET @@global.innodb_deadlock_detect = @start_global_value;
SELECT @@global.innodb_deadlock_detect;
@@global.innodb_deadlock_detect
1
65 changes: 65 additions & 0 deletions mysql-test/suite/sys_vars/t/innodb_deadlock_detect_basic.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--source include/have_innodb.inc

SET @start_global_value = @@global.innodb_deadlock_detect;
SELECT @start_global_value;

#
# exists as global only
#
--echo Valid values are 'ON' and 'OFF'
select @@global.innodb_deadlock_detect in (0, 1);
select @@global.innodb_deadlock_detect;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.innodb_deadlock_detect;
show global variables like 'innodb_deadlock_detect';
show session variables like 'innodb_deadlock_detect';
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';

#
# show that it's writable
#
set global innodb_deadlock_detect='OFF';
select @@global.innodb_deadlock_detect;
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
set @@global.innodb_deadlock_detect=1;
select @@global.innodb_deadlock_detect;
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
set global innodb_deadlock_detect=0;
select @@global.innodb_deadlock_detect;
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
set @@global.innodb_deadlock_detect='ON';
select @@global.innodb_deadlock_detect;
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
--error ER_GLOBAL_VARIABLE
set session innodb_deadlock_detect='OFF';
--error ER_GLOBAL_VARIABLE
set @@session.innodb_deadlock_detect='ON';

#
# incorrect types
#
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_deadlock_detect=1.1;
--error ER_WRONG_TYPE_FOR_VAR
set global innodb_deadlock_detect=1e1;
--error ER_WRONG_VALUE_FOR_VAR
set global innodb_deadlock_detect=2;
--echo NOTE: The following should fail with ER_WRONG_VALUE_FOR_VAR (BUG#50643)
set global innodb_deadlock_detect=-3;
select @@global.innodb_deadlock_detect;
select * from information_schema.global_variables where variable_name='innodb_deadlock_detect';
select * from information_schema.session_variables where variable_name='innodb_deadlock_detect';
--error ER_WRONG_VALUE_FOR_VAR
set global innodb_deadlock_detect='AUTO';

#
# Cleanup
#

SET @@global.innodb_deadlock_detect = @start_global_value;
SELECT @@global.innodb_deadlock_detect;
7 changes: 7 additions & 0 deletions storage/innobase/handler/ha_innodb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16183,6 +16183,12 @@ static MYSQL_SYSVAR_ULONG(
1000000, 0); /* Maximum value */
#endif /* HAVE_ATOMIC_BUILTINS */

static MYSQL_SYSVAR_BOOL(deadlock_detect, srv_deadlock_detect,
PLUGIN_VAR_OPCMDARG,
"Detect deadlocks when locks are acquired. Without this the row lock wait"
" timeout resolves deadlock.",
NULL, NULL, TRUE);

static MYSQL_SYSVAR_ULONG(thread_sleep_delay, srv_thread_sleep_delay,
PLUGIN_VAR_RQCMDARG,
"Time of innodb thread sleeping before joining InnoDB queue (usec). "
Expand Down Expand Up @@ -16558,6 +16564,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(limit_optimistic_insert_debug),
MYSQL_SYSVAR(trx_purge_view_update_only_debug),
#endif /* UNIV_DEBUG */
MYSQL_SYSVAR(deadlock_detect),
MYSQL_SYSVAR(fake_changes),
MYSQL_SYSVAR(fake_changes_locks),
NULL
Expand Down
3 changes: 3 additions & 0 deletions storage/innobase/include/srv0srv.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ extern ulong srv_auto_extend_increment;

extern ibool srv_created_new_raw;

/* Detect deadlocks on lock wait */
extern my_bool srv_deadlock_detect;

/** Maximum number of srv_n_log_files, or innodb_log_files_in_group */
#define SRV_N_LOG_FILES_MAX 100
extern ulong srv_n_log_files;
Expand Down
2 changes: 1 addition & 1 deletion storage/innobase/lock/lock0lock.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1924,7 +1924,7 @@ lock_rec_enqueue_waiting(

trx_mutex_enter(trx);

if (victim_trx_id != 0) {
if (srv_deadlock_detect && victim_trx_id != 0) {

ut_ad(victim_trx_id == trx->id);

Expand Down
3 changes: 3 additions & 0 deletions storage/innobase/srv/srv0conc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ we could get a deadlock. Value of 0 will disable the concurrency check. */

UNIV_INTERN ulong srv_thread_concurrency = 0;

/* When != 0, detect deadlocks for row-lock waits */
UNIV_INTERN my_bool srv_deadlock_detect = 1;

#ifndef HAVE_ATOMIC_BUILTINS

/** This mutex protects srv_conc data structures */
Expand Down

5 comments on commit dbc3c69

@zhaiwx1987
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

srv_deadlock_detect here didn't prevent deadlock detect and lock_deadlock_check_and_resolve was still called

@steaphan-fb-com
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you provide more details? If you can post the full circumstances to reproduce this issue, we will try to take a look when next we get a chance (but no promises).

@zhaiwx1987
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,

I just read the related code in file lock0lock.cc.

quoted code in lock0lock.cc:

1927 trx_mutex_exit(trx);
1928
1929 victim_trx_id = lock_deadlock_check_and_resolve(lock, trx);
1930
1931 trx_mutex_enter(trx);
1932
1933 if (srv_deadlock_detect && victim_trx_id != 0) {
1934

@steaphan-fb-com
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you're right. This feature was incorrectly ported. We'll fix it. Thanks!

@steaphan-fb-com
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be fixed now, in this commit:

eb621d9

Thanks!

Please sign in to comment.