Commit 082e0b95 authored by Dmitry Lenev's avatar Dmitry Lenev

Fix for bug#12695572 - "IMPROVE MDL PERFORMANCE IN PRE-VISTA

BY CACHING OR REDUCING CREATEEVENT CALLS".
 
5.5 versions of MySQL server performed worse than 5.1 versions 
under single-connection workload in autocommit mode on Windows XP.
 
Part of this slowdown can be attributed to overhead associated
with constant creation/destruction of MDL_lock objects in the MDL
subsystem. The problem is that creation/destruction of these
objects causes creation and destruction of associated
synchronization primitives, which are expensive on Windows XP.
 
This patch tries to alleviate this problem by introducing a cache
of unused MDL_object_lock objects. Instead of destroying such
objects we put them into the cache and then reuse with a new
key when creation of a new object is requested.

To limit the size of this cache, a new --metadata-locks-cache-size
start-up parameter was introduced.

mysql-test/r/mysqld--help-notwin.result:
  Updated test after adding --metadata-locks-cache-size
  parameter.
mysql-test/r/mysqld--help-win.result:
  Updated test after adding --metadata-locks-cache-size
  parameter.
mysql-test/suite/sys_vars/r/metadata_locks_cache_size_basic.result:
  Added test coverage for newly introduced --metadata_locks_cache_size
  start-up parameter and corresponding global read-only variable.
mysql-test/suite/sys_vars/t/metadata_locks_cache_size_basic-master.opt:
  Added test coverage for newly introduced --metadata_locks_cache_size
  start-up parameter and corresponding global read-only variable.
mysql-test/suite/sys_vars/t/metadata_locks_cache_size_basic.test:
  Added test coverage for newly introduced --metadata_locks_cache_size
  start-up parameter and corresponding global read-only variable.
sql/mdl.cc:
  Introduced caching of unused MDL_object_lock objects, in order to
  avoid costs associated with constant creation and destruction of
  such objects in single-connection workloads run in autocommit mode.
  Such costs can be pretty high on systems where creation and 
  destruction of synchronization primitives require a system call 
  (e.g. Windows XP).
   
  To implement this cache,a list of unused MDL_object_lock instances 
  was added to MDL_map object. Instead of being destroyed 
  MDL_object_lock instances are put into this list and re-used later 
  when creation of a new instance is required. Also added 
  MDL_lock::m_version counter to allow threads having outstanding 
  references to an MDL_object_lock instance to notice that it has 
  been moved to the unused objects list.
   
  Added a global variable for a start-up parameter that limits
  the size of the unused objects list.
   
  Note that we don't cache MDL_scoped_lock objects since they
  are supposed to be created only during execution of DDL 
  statements and therefore should not affect performance much.
sql/mdl.h:
  Added a global variable for start-up parameter that limits the
  size of the unused MDL_object_lock objects list and constant
  for its default value.
sql/sql_plist.h:
  Added I_P_List<>::pop_front() function.
sql/sys_vars.cc:
  Introduced --metadata-locks-cache-size start-up parameter
  for specifying size of the cache of unused MDL_object_lock
  objects.
parent b6c0ed99
......@@ -336,6 +336,8 @@ The following options may be given as the first argument:
After this many write locks, allow some read locks to run
in between
--memlock Lock mysqld in memory.
--metadata-locks-cache-size=#
Size of unused metadata locks cache
--min-examined-row-limit=#
Don't write queries to slow log that examine fewer rows
than that
......@@ -844,6 +846,7 @@ max-tmp-tables 32
max-user-connections 0
max-write-lock-count 18446744073709551615
memlock FALSE
metadata-locks-cache-size 1024
min-examined-row-limit 0
multi-range-count 256
myisam-block-size 1024
......
......@@ -335,6 +335,8 @@ The following options may be given as the first argument:
After this many write locks, allow some read locks to run
in between
--memlock Lock mysqld in memory.
--metadata-locks-cache-size=#
Size of unused metadata locks cache
--min-examined-row-limit=#
Don't write queries to slow log that examine fewer rows
than that
......@@ -847,6 +849,7 @@ max-tmp-tables 32
max-user-connections 0
max-write-lock-count 18446744073709551615
memlock FALSE
metadata-locks-cache-size 1024
min-examined-row-limit 0
multi-range-count 256
myisam-block-size 1024
......
#
# Check that the paremeter is correctly set by start-up
# option (.opt file sets it to 256 while default is 1024).
select @@global.metadata_locks_cache_size = 256;
@@global.metadata_locks_cache_size = 256
1
#
# Check that variable is read only
#
set @@global.metadata_locks_cache_size= 1024;
ERROR HY000: Variable 'metadata_locks_cache_size' is a read only variable
select @@global.metadata_locks_cache_size = 256;
@@global.metadata_locks_cache_size = 256
1
#
# And only GLOBAL
#
select @@session.metadata_locks_cache_size;
ERROR HY000: Variable 'metadata_locks_cache_size' is a GLOBAL variable
set @@session.metadata_locks_cache_size= 1024;
ERROR HY000: Variable 'metadata_locks_cache_size' is a read only variable
#
# Basic test coverage for --metadata-locks-cache-size startup
# parameter and corresponding read-only global @@metadata_locks_cache_size
# variable.
#
--echo #
--echo # Check that the paremeter is correctly set by start-up
--echo # option (.opt file sets it to 256 while default is 1024).
select @@global.metadata_locks_cache_size = 256;
--echo #
--echo # Check that variable is read only
--echo #
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set @@global.metadata_locks_cache_size= 1024;
select @@global.metadata_locks_cache_size = 256;
--echo #
--echo # And only GLOBAL
--echo #
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.metadata_locks_cache_size;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set @@session.metadata_locks_cache_size= 1024;
This diff is collapsed.
......@@ -851,4 +851,12 @@ extern "C" void thd_exit_cond(MYSQL_THD thd, const char *old_msg);
extern mysql_mutex_t LOCK_open;
#endif
/*
Start-up parameter for the maximum size of the unused MDL_lock objects cache
and a constant for its default value.
*/
extern ulong mdl_locks_cache_size;
static const ulong MDL_LOCKS_CACHE_SIZE_DEFAULT = 1024;
#endif
......@@ -128,6 +128,15 @@ public:
}
inline T* front() { return m_first; }
inline const T *front() const { return m_first; }
inline T* pop_front()
{
T *result= front();
if (result)
remove(result);
return result;
}
void swap(I_P_List<T, B, C> &rhs)
{
swap_variables(T *, m_first, rhs.m_first);
......
......@@ -1156,6 +1156,12 @@ static Sys_var_ulonglong Sys_max_heap_table_size(
VALID_RANGE(16384, (ulonglong)~(intptr)0), DEFAULT(16*1024*1024),
BLOCK_SIZE(1024));
static Sys_var_ulong Sys_metadata_locks_cache_size(
"metadata_locks_cache_size", "Size of unused metadata locks cache",
READ_ONLY GLOBAL_VAR(mdl_locks_cache_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1, 1024*1024), DEFAULT(MDL_LOCKS_CACHE_SIZE_DEFAULT),
BLOCK_SIZE(1));
static Sys_var_ulong Sys_pseudo_thread_id(
"pseudo_thread_id",
"This variable is for internal server use",
......
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