diff --git a/mysql-test/r/lock_wait_timeout_fractional.result b/mysql-test/r/lock_wait_timeout_fractional.result new file mode 100644 index 00000000..bd81f307 --- /dev/null +++ b/mysql-test/r/lock_wait_timeout_fractional.result @@ -0,0 +1,26 @@ +SET @start_global = @@global.lock_wait_timeout; +SET @start_session = @@session.lock_wait_timeout; +# sub-second timeout fires on MDL contention. +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +# Connection con1 +LOCK TABLES t1 WRITE; +# Connection default +SET @@session.lock_wait_timeout = 0.2; +SET @t0 = NOW(6); +ALTER TABLE t1 ADD COLUMN b INT; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT TIMESTAMPDIFF(MICROSECOND, @t0, NOW(6)) < 500000 AS sub_second_wait; +sub_second_wait +1 +SET @t0 = NOW(6); +LOCK TABLES t1 WRITE; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +SELECT TIMESTAMPDIFF(MICROSECOND, @t0, NOW(6)) < 500000 AS sub_second_wait; +sub_second_wait +1 +# Connection con1 +UNLOCK TABLES; +# Connection default +DROP TABLE t1; +SET @@global.lock_wait_timeout = @start_global; +SET @@session.lock_wait_timeout = @start_session; diff --git a/mysql-test/suite/sys_vars/r/lock_wait_timeout_basic.result b/mysql-test/suite/sys_vars/r/lock_wait_timeout_basic.result index 7d41318b..4859a719 100644 --- a/mysql-test/suite/sys_vars/r/lock_wait_timeout_basic.result +++ b/mysql-test/suite/sys_vars/r/lock_wait_timeout_basic.result @@ -11,12 +11,12 @@ SET @@global.lock_wait_timeout = 100; SET @@global.lock_wait_timeout = DEFAULT; SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 SET @@session.lock_wait_timeout = 200; SET @@session.lock_wait_timeout = DEFAULT; SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -31536000 +31536000.000000 '#--------------------FN_DYNVARS_002_02-------------------------#' SET @@global.lock_wait_timeout = @start_global_value; SELECT @@global.lock_wait_timeout = 31536000; @@ -27,158 +27,168 @@ SELECT @@session.lock_wait_timeout = 31536000; @@session.lock_wait_timeout = 31536000 1 '#--------------------FN_DYNVARS_002_03-------------------------#' +SET @@global.lock_wait_timeout = 0; +SELECT @@global.lock_wait_timeout; +@@global.lock_wait_timeout +0.000000 SET @@global.lock_wait_timeout = 1; SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -1 +1.000000 SET @@global.lock_wait_timeout = 60020; SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -60020 +60020.000000 SET @@global.lock_wait_timeout = 65535; SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -65535 +65535.000000 SET @@global.lock_wait_timeout = 31536000; SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 +SET @@global.lock_wait_timeout = 0.5; +SELECT @@global.lock_wait_timeout; +@@global.lock_wait_timeout +0.500000 +SET @@global.lock_wait_timeout = 0.001; +SELECT @@global.lock_wait_timeout; +@@global.lock_wait_timeout +0.001000 +SET @@global.lock_wait_timeout = 65532.01; +SELECT @@global.lock_wait_timeout; +@@global.lock_wait_timeout +65532.010000 '#--------------------FN_DYNVARS_002_04-------------------------#' +SET @@session.lock_wait_timeout = 0; +SELECT @@session.lock_wait_timeout; +@@session.lock_wait_timeout +0.000000 SET @@session.lock_wait_timeout = 1; SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -1 +1.000000 SET @@session.lock_wait_timeout = 50050; SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -50050 +50050.000000 SET @@session.lock_wait_timeout = 65535; SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -65535 +65535.000000 SET @@session.lock_wait_timeout = 31536000; SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -31536000 +31536000.000000 +SET @@session.lock_wait_timeout = 0.2; +SELECT @@session.lock_wait_timeout; +@@session.lock_wait_timeout +0.200000 +SET @@session.lock_wait_timeout = 1.25; +SELECT @@session.lock_wait_timeout; +@@session.lock_wait_timeout +1.250000 +SET @@session.lock_wait_timeout = 65532.01; +SELECT @@session.lock_wait_timeout; +@@session.lock_wait_timeout +65532.010000 '#------------------FN_DYNVARS_002_05-----------------------#' -SET @@global.lock_wait_timeout = 0; -Warnings: -Warning 1292 Truncated incorrect lock_wait_timeout value: '0' -SELECT @@global.lock_wait_timeout; -@@global.lock_wait_timeout -1 SET @@global.lock_wait_timeout = -1024; Warnings: Warning 1292 Truncated incorrect lock_wait_timeout value: '-1024' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -1 +0.000000 SET @@global.lock_wait_timeout = 31536001; Warnings: Warning 1292 Truncated incorrect lock_wait_timeout value: '31536001' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 SET @@global.lock_wait_timeout = 3153600112; Warnings: Warning 1292 Truncated incorrect lock_wait_timeout value: '3153600112' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 -SET @@global.lock_wait_timeout = 65532.01; -ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' -SELECT @@global.lock_wait_timeout; -@@global.lock_wait_timeout -31536000 +31536000.000000 SET @@global.lock_wait_timeout = ON; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 SET @@global.lock_wait_timeout = OFF; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 SET @@global.lock_wait_timeout = test; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 SET @@global.lock_wait_timeout = " "; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 SET @@global.lock_wait_timeout = ' '; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 -SET @@session.lock_wait_timeout = 0; -Warnings: -Warning 1292 Truncated incorrect lock_wait_timeout value: '0' -SELECT @@session.lock_wait_timeout; -@@session.lock_wait_timeout -1 +31536000.000000 SET @@session.lock_wait_timeout = -2; Warnings: Warning 1292 Truncated incorrect lock_wait_timeout value: '-2' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -1 +0.000000 SET @@session.lock_wait_timeout = 3176990909; Warnings: Warning 1292 Truncated incorrect lock_wait_timeout value: '3176990909' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -31536000 +31536000.000000 SET @@session.lock_wait_timeout = 31536001; Warnings: Warning 1292 Truncated incorrect lock_wait_timeout value: '31536001' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -31536000 +31536000.000000 SET @@session.lock_wait_timeout = -1024; Warnings: Warning 1292 Truncated incorrect lock_wait_timeout value: '-1024' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -1 -SET @@session.lock_wait_timeout = 65532.01; -ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' -SELECT @@session.lock_wait_timeout; -@@session.lock_wait_timeout -1 +0.000000 SET @@session.lock_wait_timeout = ON; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -1 +0.000000 SET @@session.lock_wait_timeout = OFF; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -1 +0.000000 SET @@session.lock_wait_timeout = test; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -1 +0.000000 SET @@session.lock_wait_timeout = ' '; ERROR 42000: Incorrect argument type to variable 'lock_wait_timeout' SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -1 +0.000000 '#------------------FN_DYNVARS_002_06-----------------------#' -SELECT @@global.lock_wait_timeout = VARIABLE_VALUE -FROM performance_schema.global_variables +SELECT @@global.lock_wait_timeout = VARIABLE_VALUE +FROM performance_schema.global_variables WHERE VARIABLE_NAME='lock_wait_timeout'; @@global.lock_wait_timeout = VARIABLE_VALUE 1 '#------------------FN_DYNVARS_002_07-----------------------#' -SELECT @@session.lock_wait_timeout = VARIABLE_VALUE -FROM performance_schema.session_variables +SELECT @@session.lock_wait_timeout = VARIABLE_VALUE +FROM performance_schema.session_variables WHERE VARIABLE_NAME='lock_wait_timeout'; @@session.lock_wait_timeout = VARIABLE_VALUE 1 @@ -186,13 +196,11 @@ WHERE VARIABLE_NAME='lock_wait_timeout'; SET @@global.lock_wait_timeout = TRUE; SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -1 +1.000000 SET @@global.lock_wait_timeout = FALSE; -Warnings: -Warning 1292 Truncated incorrect lock_wait_timeout value: '0' SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -1 +0.000000 '#---------------------FN_DYNVARS_001_09----------------------#' SET @@global.lock_wait_timeout = 10; SET @@session.lock_wait_timeout = 11; @@ -211,7 +219,7 @@ SELECT @@local.lock_wait_timeout = @@session.lock_wait_timeout; SET lock_wait_timeout = 1; SELECT @@lock_wait_timeout; @@lock_wait_timeout -1 +1.000000 SELECT local.lock_wait_timeout; ERROR 42S02: Unknown table 'local' in field list SELECT session.lock_wait_timeout; @@ -221,8 +229,8 @@ ERROR 42S22: Unknown column 'lock_wait_timeout' in 'field list' SET @@global.lock_wait_timeout = @start_global_value; SELECT @@global.lock_wait_timeout; @@global.lock_wait_timeout -31536000 +31536000.000000 SET @@session.lock_wait_timeout = @start_session_value; SELECT @@session.lock_wait_timeout; @@session.lock_wait_timeout -31536000 +31536000.000000 diff --git a/mysql-test/suite/sys_vars/t/lock_wait_timeout_basic.test b/mysql-test/suite/sys_vars/t/lock_wait_timeout_basic.test index d8fa3157..2054bdbb 100644 --- a/mysql-test/suite/sys_vars/t/lock_wait_timeout_basic.test +++ b/mysql-test/suite/sys_vars/t/lock_wait_timeout_basic.test @@ -3,11 +3,11 @@ # Variable Name: lock_wait_timeout # # Scope: GLOBAL & SESSION # # Access Type: Dynamic # -# Data Type: Numeric # -# Default Value: 1 # -# Range: 1 - 31536000 # -# # -# # +# Data Type: Numeric (fractional seconds) # +# Default Value: 31536000 # +# Range: 0 - 31536000 # +# +# # Creation Date: 2010-02-08 # # Author: Jon Olav Hauglid # # # @@ -18,7 +18,7 @@ # * Scope & Access method # # * Data Integrity # # # -# Reference: http://dev.mysql.com/doc/refman/5.5/en/ # +# Reference: http://dev.mysql.com/doc/refman/en/ # # server-system-variables.html#option_mysqld_lock-wait-timeout # # # ################################################################################ @@ -69,6 +69,8 @@ SELECT @@session.lock_wait_timeout = 31536000; # Change the value of lock_wait_timeout to a valid value for GLOBAL Scope # ############################################################################### +SET @@global.lock_wait_timeout = 0; +SELECT @@global.lock_wait_timeout; SET @@global.lock_wait_timeout = 1; SELECT @@global.lock_wait_timeout; SET @@global.lock_wait_timeout = 60020; @@ -77,12 +79,21 @@ SET @@global.lock_wait_timeout = 65535; SELECT @@global.lock_wait_timeout; SET @@global.lock_wait_timeout = 31536000; SELECT @@global.lock_wait_timeout; +# Fractional values are valid. +SET @@global.lock_wait_timeout = 0.5; +SELECT @@global.lock_wait_timeout; +SET @@global.lock_wait_timeout = 0.001; +SELECT @@global.lock_wait_timeout; +SET @@global.lock_wait_timeout = 65532.01; +SELECT @@global.lock_wait_timeout; --echo '#--------------------FN_DYNVARS_002_04-------------------------#' ############################################################################### # Change the value of lock_wait_timeout to a valid value for SESSION Scope # ############################################################################### +SET @@session.lock_wait_timeout = 0; +SELECT @@session.lock_wait_timeout; SET @@session.lock_wait_timeout = 1; SELECT @@session.lock_wait_timeout; SET @@session.lock_wait_timeout = 50050; @@ -91,6 +102,13 @@ SET @@session.lock_wait_timeout = 65535; SELECT @@session.lock_wait_timeout; SET @@session.lock_wait_timeout = 31536000; SELECT @@session.lock_wait_timeout; +# Fractional values are valid. +SET @@session.lock_wait_timeout = 0.2; +SELECT @@session.lock_wait_timeout; +SET @@session.lock_wait_timeout = 1.25; +SELECT @@session.lock_wait_timeout; +SET @@session.lock_wait_timeout = 65532.01; +SELECT @@session.lock_wait_timeout; --echo '#------------------FN_DYNVARS_002_05-----------------------#' @@ -98,8 +116,6 @@ SELECT @@session.lock_wait_timeout; # Change the value of lock_wait_timeout to an invalid value # ################################################################# # for global scope -SET @@global.lock_wait_timeout = 0; -SELECT @@global.lock_wait_timeout; SET @@global.lock_wait_timeout = -1024; SELECT @@global.lock_wait_timeout; SET @@global.lock_wait_timeout = 31536001; @@ -107,9 +123,6 @@ SELECT @@global.lock_wait_timeout; SET @@global.lock_wait_timeout = 3153600112; SELECT @@global.lock_wait_timeout; ---Error ER_WRONG_TYPE_FOR_VAR -SET @@global.lock_wait_timeout = 65532.01; -SELECT @@global.lock_wait_timeout; --Error ER_WRONG_TYPE_FOR_VAR SET @@global.lock_wait_timeout = ON; SELECT @@global.lock_wait_timeout; @@ -127,8 +140,6 @@ SET @@global.lock_wait_timeout = ' '; SELECT @@global.lock_wait_timeout; # for session scope -SET @@session.lock_wait_timeout = 0; -SELECT @@session.lock_wait_timeout; SET @@session.lock_wait_timeout = -2; SELECT @@session.lock_wait_timeout; SET @@session.lock_wait_timeout = 3176990909; @@ -138,9 +149,6 @@ SELECT @@session.lock_wait_timeout; SET @@session.lock_wait_timeout = -1024; SELECT @@session.lock_wait_timeout; ---Error ER_WRONG_TYPE_FOR_VAR -SET @@session.lock_wait_timeout = 65532.01; -SELECT @@session.lock_wait_timeout; --Error ER_WRONG_TYPE_FOR_VAR SET @@session.lock_wait_timeout = ON; SELECT @@session.lock_wait_timeout; @@ -162,8 +170,8 @@ SELECT @@session.lock_wait_timeout; #################################################################### --disable_warnings -SELECT @@global.lock_wait_timeout = VARIABLE_VALUE -FROM performance_schema.global_variables +SELECT @@global.lock_wait_timeout = VARIABLE_VALUE +FROM performance_schema.global_variables WHERE VARIABLE_NAME='lock_wait_timeout'; --enable_warnings @@ -174,8 +182,8 @@ WHERE VARIABLE_NAME='lock_wait_timeout'; #################################################################### --disable_warnings -SELECT @@session.lock_wait_timeout = VARIABLE_VALUE -FROM performance_schema.session_variables +SELECT @@session.lock_wait_timeout = VARIABLE_VALUE +FROM performance_schema.session_variables WHERE VARIABLE_NAME='lock_wait_timeout'; --enable_warnings diff --git a/mysql-test/t/lock_wait_timeout_fractional.test b/mysql-test/t/lock_wait_timeout_fractional.test new file mode 100644 index 00000000..9880659d --- /dev/null +++ b/mysql-test/t/lock_wait_timeout_fractional.test @@ -0,0 +1,45 @@ +################################################################################ +# t/lock_wait_timeout_fractional.test +# +# Bug#114949 (lock_wait_timeout high resolution) +# Verify that the session/global system variable @@lock_wait_timeout accepts +# fractional (sub-second) values, and that an MDL wait actually fires with +# sub-second precision when contention exists. +################################################################################ + +SET @start_global = @@global.lock_wait_timeout; +SET @start_session = @@session.lock_wait_timeout; + +--echo # sub-second timeout fires on MDL contention. +CREATE TABLE t1 (a INT) ENGINE=InnoDB; + +--echo # Connection con1 +connect (con1, localhost, root,,); +LOCK TABLES t1 WRITE; + +--echo # Connection default +connection default; +SET @@session.lock_wait_timeout = 0.2; + +SET @t0 = NOW(6); +--error ER_LOCK_WAIT_TIMEOUT +ALTER TABLE t1 ADD COLUMN b INT; +SELECT TIMESTAMPDIFF(MICROSECOND, @t0, NOW(6)) < 500000 AS sub_second_wait; + +SET @t0 = NOW(6); +--error ER_LOCK_WAIT_TIMEOUT +LOCK TABLES t1 WRITE; +SELECT TIMESTAMPDIFF(MICROSECOND, @t0, NOW(6)) < 500000 AS sub_second_wait; + +--echo # Connection con1 +connection con1; +UNLOCK TABLES; +disconnect con1; + +--echo # Connection default +connection default; +DROP TABLE t1; + +# Restore initial values. +SET @@global.lock_wait_timeout = @start_global; +SET @@session.lock_wait_timeout = @start_session; diff --git a/sql/dd/dictionary.h b/sql/dd/dictionary.h index 9c5c373a..30c4a254 100644 --- a/sql/dd/dictionary.h +++ b/sql/dd/dictionary.h @@ -326,7 +326,7 @@ bool has_exclusive_tablespace_mdl(THD *thd, const char *tablespace_name); [[nodiscard]] bool acquire_exclusive_table_mdl( THD *thd, const char *schema_name, const char *table_name, - unsigned long int lock_wait_timeout, MDL_ticket **out_mdl_ticket); + ulonglong lock_wait_timeout, MDL_ticket **out_mdl_ticket); /** Acquire exclusive metadata lock on the given schema name with diff --git a/sql/dd/impl/dictionary_impl.cc b/sql/dd/impl/dictionary_impl.cc index 9c878869..1367f6e0 100644 --- a/sql/dd/impl/dictionary_impl.cc +++ b/sql/dd/impl/dictionary_impl.cc @@ -414,7 +414,7 @@ bool Dictionary_impl::is_system_view_name(const char *schema_name, static bool acquire_shared_mdl(THD *thd, MDL_key::enum_mdl_namespace lock_namespace, const char *schema_name, const char *table_name, - bool no_wait, ulong lock_wait_timeout, + bool no_wait, ulonglong lock_wait_timeout, enum_mdl_duration lock_duration, MDL_ticket **out_mdl_ticket) { DBUG_TRACE; @@ -439,7 +439,7 @@ static bool acquire_exclusive_mdl(THD *thd, MDL_key::enum_mdl_namespace lock_namespace, const char *schema_name, const char *table_name, bool no_wait, - ulong lock_wait_timeout, + ulonglong lock_wait_timeout, enum_mdl_duration lock_duration, MDL_ticket **out_mdl_ticket) { DBUG_TRACE; @@ -557,7 +557,7 @@ bool acquire_exclusive_table_mdl(THD *thd, const char *schema_name, bool acquire_exclusive_table_mdl(THD *thd, const char *schema_name, const char *table_name, - unsigned long int lock_wait_timeout, + ulonglong lock_wait_timeout, MDL_ticket **out_mdl_ticket) { return acquire_exclusive_mdl(thd, MDL_key::TABLE, schema_name, table_name, false, lock_wait_timeout, MDL_TRANSACTION, diff --git a/sql/lock.cc b/sql/lock.cc index 7cd62133..a3081566 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -794,7 +794,7 @@ bool lock_schema_name(THD *thd, const char *db) { @return false - On Success. */ bool lock_tablespace_names(THD *thd, Tablespace_hash_set *tablespace_set, - ulong lock_wait_timeout, MEM_ROOT *mem_root) { + ulonglong lock_wait_timeout, MEM_ROOT *mem_root) { // Stop if we have nothing to lock if (tablespace_set->empty()) return false; @@ -1013,7 +1013,7 @@ static void print_lock_error(int error, const char *table) { */ bool acquire_shared_global_read_lock(THD *thd, - unsigned long lock_wait_timeout) { + ulonglong lock_wait_timeout) { // If we cannot acquire protection against GRL, err out. if (thd->global_read_lock.can_acquire_protection()) return true; diff --git a/sql/lock.h b/sql/lock.h index 433dae89..547cf4eb 100644 --- a/sql/lock.h +++ b/sql/lock.h @@ -58,13 +58,13 @@ typedef malloc_unordered_set Tablespace_hash_set; // Lock tablespace names. bool lock_tablespace_names(THD *thd, Tablespace_hash_set *tablespace_set, - ulong lock_wait_timeout, MEM_ROOT *mem_root); + ulonglong lock_wait_timeout, MEM_ROOT *mem_root); /* Lock based on stored routine name */ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, const char *db, const char *name); /* Acquire protection against the global read lock. */ -bool acquire_shared_global_read_lock(THD *thd, unsigned long lock_wait_timeout); +bool acquire_shared_global_read_lock(THD *thd, ulonglong lock_wait_timeout); #endif /* LOCK_INCLUDED */ diff --git a/sql/mdl.cc b/sql/mdl.cc index 846b4fd6..d7d364d7 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -3354,7 +3354,7 @@ void MDL_lock::object_lock_notify_conflicting_locks(MDL_context *ctx, @param [in,out] mdl_request Lock request object for lock to be acquired - @param lock_wait_timeout Seconds to wait before timeout. + @param lock_wait_timeout Nanoseconds to wait before timeout. @retval false Success. MDL_request::ticket points to the ticket for the lock. @@ -3399,7 +3399,7 @@ bool MDL_context::acquire_lock(MDL_request *mdl_request, struct timespec abs_timeout; MDL_wait::enum_wait_status wait_status; /* Do some work outside the critical section. */ - set_timespec(&abs_timeout, lock_wait_timeout); + set_timespec_nsec(&abs_timeout, lock_wait_timeout); if (try_acquire_lock_impl(mdl_request, &ticket)) return true; @@ -3623,7 +3623,7 @@ class MDL_request_cmp { @param mdl_requests List of requests for locks to be acquired. - @param lock_wait_timeout Seconds to wait before timeout. + @param lock_wait_timeout Nanoseconds to wait before timeout. @note The list of requests should not contain non-exclusive lock requests. There should not be any acquired locks in the context. @@ -3729,7 +3729,7 @@ bool MDL_context::clone_tickets(const MDL_context *ticket_owner, @param mdl_ticket Lock to upgrade. @param new_type Lock type to upgrade to. - @param lock_wait_timeout Seconds to wait before timeout. + @param lock_wait_timeout Nanoseconds to wait before timeout. @note In case of failure to upgrade lock (e.g. because upgrader was killed) leaves lock in its original state (locked in diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 7b5e75b4..123e92a9 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -13418,6 +13418,9 @@ static int get_options(int *argc_ptr, char ***argv_ptr) { global_system_variables.long_query_time = (ulonglong)(global_system_variables.long_query_time_double * 1e6); + global_system_variables.lock_wait_timeout = + (ulonglong)(global_system_variables.lock_wait_timeout_double * 1e9); + if (opt_short_log_format) opt_specialflag |= SPECIAL_SHORT_LOG_FORMAT; if (Connection_handler_manager::init()) { diff --git a/sql/sql_backup_lock.cc b/sql/sql_backup_lock.cc index f9ad7dbc..a00283db 100644 --- a/sql/sql_backup_lock.cc +++ b/sql/sql_backup_lock.cc @@ -125,7 +125,7 @@ Shared_backup_lock_guard::try_acquire_shared_backup_lock(THD *thd, @param[in] thd Current thread context @param[in] mdl_type Type of metadata lock to acquire for backup @param[in] mdl_duration Duration of metadata lock - @param[in] lock_wait_timeout How many seconds to wait before timeout. + @param[in] lock_wait_timeout How many nanoseconds to wait before timeout. @return Operation status. @retval false Success @@ -134,7 +134,7 @@ Shared_backup_lock_guard::try_acquire_shared_backup_lock(THD *thd, static bool acquire_mdl_for_backup(THD *thd, enum_mdl_type mdl_type, enum_mdl_duration mdl_duration, - ulong lock_wait_timeout) { + ulonglong lock_wait_timeout) { MDL_request mdl_request; assert(mdl_type == MDL_SHARED || mdl_type == MDL_INTENTION_EXCLUSIVE); @@ -174,13 +174,13 @@ void release_backup_lock(THD *thd) { Backup Lock and IX lock should be considered as Shared Backup Lock. */ -bool acquire_exclusive_backup_lock(THD *thd, ulong lock_wait_timeout, +bool acquire_exclusive_backup_lock(THD *thd, ulonglong lock_wait_timeout, bool for_trx) { const enum_mdl_duration duration = (for_trx ? MDL_TRANSACTION : MDL_EXPLICIT); return acquire_mdl_for_backup(thd, MDL_SHARED, duration, lock_wait_timeout); } -bool acquire_shared_backup_lock(THD *thd, ulong lock_wait_timeout, +bool acquire_shared_backup_lock(THD *thd, ulonglong lock_wait_timeout, bool for_trx) { const enum_mdl_duration duration = (for_trx ? MDL_TRANSACTION : MDL_EXPLICIT); return acquire_mdl_for_backup(thd, MDL_INTENTION_EXCLUSIVE, duration, diff --git a/sql/sql_backup_lock.h b/sql/sql_backup_lock.h index f303fac3..ba609b1c 100644 --- a/sql/sql_backup_lock.h +++ b/sql/sql_backup_lock.h @@ -26,6 +26,7 @@ #include +#include "my_inttypes.h" // ulonglong #include "my_sqlcommand.h" // SQLCOM_LOCK_INSTANCE, SQLCOM_UNLOCK_INSTANCE #include "sql/sql_cmd.h" // Sql_cmd @@ -121,7 +122,7 @@ class Shared_backup_lock_guard { Acquire exclusive Backup Lock. @param[in] thd Current thread context - @param[in] lock_wait_timeout How many seconds to wait before timeout. + @param[in] lock_wait_timeout How many nanoseconds to wait before timeout. @param[in] for_trx true if MDL duration is MDL_TRANSACTION false if MDL duration is MDL_EXPLICIT @@ -130,14 +131,14 @@ class Shared_backup_lock_guard { @retval true Failure */ -bool acquire_exclusive_backup_lock(THD *thd, unsigned long lock_wait_timeout, +bool acquire_exclusive_backup_lock(THD *thd, ulonglong lock_wait_timeout, bool for_trx); /** Acquire shared Backup Lock. @param[in] thd Current thread context - @param[in] lock_wait_timeout How many seconds to wait before timeout. + @param[in] lock_wait_timeout How many nanoseconds to wait before timeout. @param[in] for_trx true if MDL duration is MDL_TRANSACTION false if MDL duration is MDL_EXPLICIT @@ -146,7 +147,7 @@ bool acquire_exclusive_backup_lock(THD *thd, unsigned long lock_wait_timeout, @retval true Failure */ -bool acquire_shared_backup_lock(THD *thd, unsigned long lock_wait_timeout, +bool acquire_shared_backup_lock(THD *thd, ulonglong lock_wait_timeout, bool for_trx = true); /** diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 93aba7cd..06359216 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -5523,7 +5523,7 @@ static inline bool is_temporary_table_being_opened(const Table_ref *table) { @param tables_start Start of list of tables on which locks should be acquired. @param tables_end End of list of tables. - @param lock_wait_timeout Seconds to wait before timeout. + @param lock_wait_timeout Nanoseconds to wait before timeout. @param flags Bitmap of flags to modify how the tables will be open, see open_table() description for details. @@ -5533,7 +5533,7 @@ static inline bool is_temporary_table_being_opened(const Table_ref *table) { */ bool get_and_lock_tablespace_names(THD *thd, Table_ref *tables_start, Table_ref *tables_end, - ulong lock_wait_timeout, uint flags) { + ulonglong lock_wait_timeout, uint flags) { // If this is a DISCARD or IMPORT TABLESPACE command (indicated by // the THD:: tablespace_op flag), we skip this phase, because these // commands are only used for file-per-table tablespaces, which we @@ -5648,7 +5648,7 @@ bool get_and_lock_tablespace_names(THD *thd, Table_ref *tables_start, @param tables_start Start of list of tables on which locks should be acquired. @param tables_end End of list of tables. - @param lock_wait_timeout Seconds to wait before timeout. + @param lock_wait_timeout Nanoseconds to wait before timeout. @param flags Bitmap of flags to modify how the tables will be open, see open_table() description for details. @param schema_reqs When non-nullptr, pointer to array in which @@ -5661,7 +5661,7 @@ bool get_and_lock_tablespace_names(THD *thd, Table_ref *tables_start, @retval true Failure (e.g. connection was killed) */ bool lock_table_names(THD *thd, Table_ref *tables_start, Table_ref *tables_end, - ulong lock_wait_timeout, uint flags, + ulonglong lock_wait_timeout, uint flags, Prealloced_array *schema_reqs) { MDL_request_list mdl_requests; Table_ref *table; diff --git a/sql/sql_base.h b/sql/sql_base.h index 820dbe88..b1e047f9 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -278,10 +278,10 @@ bool init_ftfuncs(THD *thd, Query_block *select); int run_before_dml_hook(THD *thd); bool get_and_lock_tablespace_names(THD *thd, Table_ref *tables_start, Table_ref *tables_end, - ulong lock_wait_timeout, uint flags); + ulonglong lock_wait_timeout, uint flags); bool lock_table_names( THD *thd, Table_ref *table_list, Table_ref *table_list_end, - ulong lock_wait_timeout, uint flags, + ulonglong lock_wait_timeout, uint flags, Prealloced_array *schema_reqs = nullptr); bool open_tables(THD *thd, Table_ref **tables, uint *counter, uint flags, Prelocking_strategy *prelocking_strategy); diff --git a/sql/sql_partition_admin.cc b/sql/sql_partition_admin.cc index 70232b90..0265107d 100644 --- a/sql/sql_partition_admin.cc +++ b/sql/sql_partition_admin.cc @@ -585,7 +585,7 @@ bool Sql_cmd_alter_table_repair_partition::execute(THD *thd) { bool Sql_cmd_alter_table_truncate_partition::execute(THD *thd) { int error; - ulong timeout = thd->variables.lock_wait_timeout; + ulonglong timeout = thd->variables.lock_wait_timeout; Table_ref *first_table = thd->lex->query_block->get_table_list(); uint table_counter; Partition_handler *part_handler = nullptr; diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 8ef0199c..649342ee 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -2375,11 +2375,26 @@ static Sys_var_bool Sys_local_infile("local_infile", GLOBAL_VAR(opt_local_infile), CMD_LINE(OPT_ARG), DEFAULT(false)); -static Sys_var_ulong Sys_lock_wait_timeout( +static bool update_cached_lock_wait_timeout(sys_var *, THD *thd, + enum_var_type type) { + if (type == OPT_SESSION) + thd->variables.lock_wait_timeout = static_cast( + thd->variables.lock_wait_timeout_double * 1e9); + else + global_system_variables.lock_wait_timeout = static_cast( + global_system_variables.lock_wait_timeout_double * 1e9); + return false; +} + +static Sys_var_double Sys_lock_wait_timeout( "lock_wait_timeout", - "Timeout in seconds to wait for a lock before returning an error.", - HINT_UPDATEABLE SESSION_VAR(lock_wait_timeout), CMD_LINE(REQUIRED_ARG), - VALID_RANGE(1, LONG_TIMEOUT), DEFAULT(LONG_TIMEOUT), BLOCK_SIZE(1)); + "Timeout in seconds to wait for a lock before returning an error. " + "The argument will be treated as a decimal value with nanosecond " + "precision.", + HINT_UPDATEABLE SESSION_VAR(lock_wait_timeout_double), + CMD_LINE(REQUIRED_ARG), VALID_RANGE(0, LONG_TIMEOUT), + DEFAULT(LONG_TIMEOUT), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(nullptr), + ON_UPDATE(update_cached_lock_wait_timeout)); #ifdef HAVE_MLOCKALL static Sys_var_bool Sys_locked_in_memory( diff --git a/sql/system_variables.h b/sql/system_variables.h index 2271656a..66d91c7c 100644 --- a/sql/system_variables.h +++ b/sql/system_variables.h @@ -240,7 +240,7 @@ struct System_variables { uint cte_max_recursion_depth; ulonglong histogram_generation_max_mem_size; ulong join_buff_size; - ulong lock_wait_timeout; + ulonglong lock_wait_timeout; ulong max_allowed_packet; ulong max_error_count; ulong max_length_for_sort_data; ///< Unused. @@ -345,6 +345,9 @@ struct System_variables { double long_query_time_double; + /* User-facing value of lock_wait_timeout (seconds, fractional). */ + double lock_wait_timeout_double; + bool pseudo_replica_mode; Gtid_specification gtid_next; diff --git a/storage/innobase/dict/dict0dd.cc b/storage/innobase/dict/dict0dd.cc index 55356dcc..4f07e45b 100644 --- a/storage/innobase/dict/dict0dd.cc +++ b/storage/innobase/dict/dict0dd.cc @@ -7033,7 +7033,7 @@ bool dd_tablespace_get_mdl(const char *space_name, MDL_ticket **mdl_ticket, bool trx_duration = foreground; /* Background thread should not block on MDL lock. */ - ulong timeout = foreground ? thd->variables.lock_wait_timeout : 0; + ulonglong timeout = foreground ? thd->variables.lock_wait_timeout : 0; bool result = acquire_shared_backup_lock(thd, timeout, trx_duration); if (!result) { diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 90a96222..a0fd5187 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -5857,14 +5857,15 @@ dberr_t dd_sdi_acquire_exclusive_mdl(THD *thd, space_id_t space_id, snprintf(tbl_buf, sizeof(tbl_buf), "SDI_" SPACE_ID_PF, space_id); - /* Submit a higher than default lock wait timeout, the timeout accepted by - dd::acquire_exclusive_table_mdl is in seconds. */ + /* Submit a higher than default lock wait timeout. The timeout accepted by + dd::acquire_exclusive_table_mdl is in nanoseconds. */ std::chrono::seconds lock_wait_timeout = thd_lock_wait_timeout(thd); if (lock_wait_timeout < std::chrono::hours(27)) { lock_wait_timeout += std::chrono::hours(27); } if (dd::acquire_exclusive_table_mdl( - thd, db_buf, tbl_buf, (unsigned long int)lock_wait_timeout.count(), + thd, db_buf, tbl_buf, + static_cast(lock_wait_timeout.count()) * 1000000000ULL, sdi_mdl)) { /* MDL failure can happen with lower timeout values chosen by user */ diff --git a/storage/ndb/plugin/ha_ndbcluster_binlog.cc b/storage/ndb/plugin/ha_ndbcluster_binlog.cc index 1dee6fe6..39297cc3 100644 --- a/storage/ndb/plugin/ha_ndbcluster_binlog.cc +++ b/storage/ndb/plugin/ha_ndbcluster_binlog.cc @@ -1758,7 +1758,7 @@ class Ndb_schema_event_handler { class Lock_wait_timeout_guard { public: - Lock_wait_timeout_guard(THD *thd, ulong lock_wait_timeout) + Lock_wait_timeout_guard(THD *thd, ulonglong lock_wait_timeout) : m_thd(thd), m_save_lock_wait_timeout(thd->variables.lock_wait_timeout) { m_thd->variables.lock_wait_timeout = lock_wait_timeout; @@ -1770,7 +1770,7 @@ class Ndb_schema_event_handler { private: THD *const m_thd; - ulong m_save_lock_wait_timeout; + ulonglong m_save_lock_wait_timeout; }; // Log error code and message returned from NDB @@ -3774,8 +3774,11 @@ class Ndb_schema_event_handler { thd_ndb_options.set(Thd_ndb::IS_SCHEMA_DIST_PARTICIPANT); // Set the custom lock_wait_timeout for schema distribution - Lock_wait_timeout_guard lwt_guard(m_thd, - opt_ndb_schema_dist_lock_wait_timeout); + // (opt_ndb_schema_dist_lock_wait_timeout is in seconds, convert to ns). + Lock_wait_timeout_guard lwt_guard( + m_thd, + static_cast(opt_ndb_schema_dist_lock_wait_timeout) * + 1000000000ULL); Ndb_schema_op_result schema_op_result; switch (schema_type) { @@ -3887,8 +3890,11 @@ class Ndb_schema_event_handler { thd_ndb_options.set(Thd_ndb::IS_SCHEMA_DIST_PARTICIPANT); // Set the custom lock_wait_timeout for schema distribution - Lock_wait_timeout_guard lwt_guard(m_thd, - opt_ndb_schema_dist_lock_wait_timeout); + // (opt_ndb_schema_dist_lock_wait_timeout is in seconds, convert to ns). + Lock_wait_timeout_guard lwt_guard( + m_thd, + static_cast(opt_ndb_schema_dist_lock_wait_timeout) * + 1000000000ULL); { const SCHEMA_OP_TYPE schema_type = (SCHEMA_OP_TYPE)schema->type; diff --git a/storage/ndb/plugin/ndb_dd_client.cc b/storage/ndb/plugin/ndb_dd_client.cc index fa64aca0..2a07fdd8 100644 --- a/storage/ndb/plugin/ndb_dd_client.cc +++ b/storage/ndb/plugin/ndb_dd_client.cc @@ -125,7 +125,7 @@ bool Ndb_dd_client::mdl_lock_table(const char *schema_name, bool Ndb_dd_client::mdl_lock_schema_exclusive(const char *schema_name, bool custom_lock_wait, - ulong lock_wait_timeout) { + ulonglong lock_wait_timeout) { MDL_request_list mdl_requests; MDL_request schema_request; MDL_request backup_lock_request; @@ -181,7 +181,7 @@ bool Ndb_dd_client::mdl_lock_schema(const char *schema_name) { bool Ndb_dd_client::mdl_lock_logfile_group_exclusive( const char *logfile_group_name, bool custom_lock_wait, - ulong lock_wait_timeout) { + ulonglong lock_wait_timeout) { MDL_request_list mdl_requests; MDL_request logfile_group_request; MDL_request backup_lock_request; @@ -241,7 +241,7 @@ bool Ndb_dd_client::mdl_lock_logfile_group(const char *logfile_group_name, bool Ndb_dd_client::mdl_lock_tablespace_exclusive(const char *tablespace_name, bool custom_lock_wait, - ulong lock_wait_timeout) { + ulonglong lock_wait_timeout) { MDL_request_list mdl_requests; MDL_request tablespace_request; MDL_request backup_lock_request; @@ -302,7 +302,7 @@ bool Ndb_dd_client::mdl_lock_tablespace(const char *tablespace_name, bool Ndb_dd_client::mdl_locks_acquire_exclusive(const char *schema_name, const char *table_name, bool custom_lock_wait, - ulong lock_wait_timeout) { + ulonglong lock_wait_timeout) { MDL_request_list mdl_requests; MDL_request schema_request; MDL_request mdl_request; @@ -344,7 +344,7 @@ bool Ndb_dd_client::mdl_locks_acquire_exclusive(const char *schema_name, } bool Ndb_dd_client::mdl_locks_acquire(MDL_request_list mdl_requests, - ulong lock_wait_timeout) { + ulonglong lock_wait_timeout) { if (m_thd->mdl_context.acquire_locks(&mdl_requests, lock_wait_timeout)) { return false; } diff --git a/storage/ndb/plugin/ndb_dd_client.h b/storage/ndb/plugin/ndb_dd_client.h index 79a05cb6..9701f9b7 100644 --- a/storage/ndb/plugin/ndb_dd_client.h +++ b/storage/ndb/plugin/ndb_dd_client.h @@ -107,12 +107,12 @@ class Ndb_dd_client { @brief Acquire requested locks in list and register acquired lock tickets @param mdl_requests List of MDL requests - @param lock_wait_timeout Seconds to wait before timeout + @param lock_wait_timeout Nanoseconds to wait before timeout @return true if acquired successfully, false if not */ bool mdl_locks_acquire(MDL_request_list mdl_requests, - ulong lock_wait_timeout); + ulonglong lock_wait_timeout); /** @brief Release EXPLICIT locks held by the previous registered tickets */ @@ -144,7 +144,7 @@ class Ndb_dd_client { */ bool mdl_lock_schema_exclusive(const char *schema_name, bool custom_lock_wait = false, - ulong lock_wait_timeout = 0); + ulonglong lock_wait_timeout = 0); /** @brief Acquire IX MDL on the table @@ -170,7 +170,7 @@ class Ndb_dd_client { bool mdl_locks_acquire_exclusive(const char *schema_name, const char *table_name, bool custom_lock_wait = false, - ulong lock_wait_timeout = 0); + ulonglong lock_wait_timeout = 0); /** @brief Acquire IX or SR MDL on the Logfile Group @@ -195,7 +195,7 @@ class Ndb_dd_client { */ bool mdl_lock_logfile_group_exclusive(const char *logfile_group_name, bool custom_lock_wait = false, - ulong lock_wait_timeout = 0); + ulonglong lock_wait_timeout = 0); /** @brief Acquire IX or SR MDL on the tablespace @@ -220,7 +220,7 @@ class Ndb_dd_client { */ bool mdl_lock_tablespace_exclusive(const char *tablespace_name, bool custom_lock_wait = false, - ulong lock_wait_timeout = 0); + ulonglong lock_wait_timeout = 0); // Transaction handling functions void commit();