Commit ecd3ff9f authored by Sergey Vojtovich's avatar Sergey Vojtovich

MDEV-6089 - MySQL WL#7305 "Improve MDL scalability by using lock-free hash"

Removed MDL map partitions. Won't be needed when this MDEV is implemented.
parent 903160ef
...@@ -264,8 +264,8 @@ select * from information_schema.metadata_lock_info; ...@@ -264,8 +264,8 @@ select * from information_schema.metadata_lock_info;
THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Global read lock # MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Global read lock
# MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock test t1 # MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock test t1
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock mysqltest2
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock test # MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock test
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock mysqltest2
# MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock mysqltest2 t2 # MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock mysqltest2 t2
create or replace table test.t1; create or replace table test.t1;
ERROR 42000: A table must have at least 1 column ERROR 42000: A table must have at least 1 column
...@@ -291,8 +291,8 @@ select * from information_schema.metadata_lock_info; ...@@ -291,8 +291,8 @@ select * from information_schema.metadata_lock_info;
THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME THREAD_ID LOCK_MODE LOCK_DURATION LOCK_TYPE TABLE_SCHEMA TABLE_NAME
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Global read lock # MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Global read lock
# MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock test t1 # MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock test t1
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock mysqltest2
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock test # MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock test
# MDL_INTENTION_EXCLUSIVE MDL_EXPLICIT Schema metadata lock mysqltest2
# MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock mysqltest2 t2 # MDL_SHARED_NO_READ_WRITE MDL_EXPLICIT Table metadata lock mysqltest2 t2
create or replace table test.t1 (a int) select 1 as 'a', 2 as 'a'; create or replace table test.t1 (a int) select 1 as 'a', 2 as 'a';
ERROR 42S21: Duplicate column name 'a' ERROR 42S21: Duplicate column name 'a'
......
...@@ -454,7 +454,7 @@ The following options may be given as the first argument: ...@@ -454,7 +454,7 @@ The following options may be given as the first argument:
--metadata-locks-cache-size=# --metadata-locks-cache-size=#
Unused Unused
--metadata-locks-hash-instances=# --metadata-locks-hash-instances=#
Number of metadata locks hash instances Unused
--min-examined-row-limit=# --min-examined-row-limit=#
Don't write queries to slow log that examine fewer rows Don't write queries to slow log that examine fewer rows
than that than that
......
...@@ -500,7 +500,7 @@ ...@@ -500,7 +500,7 @@
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED +VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Number of metadata locks hash instances VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1 NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1024 NUMERIC_MAX_VALUE 1024
@@ -1987,7 +1987,7 @@ @@ -1987,7 +1987,7 @@
......
...@@ -2002,7 +2002,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME ...@@ -2002,7 +2002,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8 DEFAULT_VALUE 8
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Number of metadata locks hash instances VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1 NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1024 NUMERIC_MAX_VALUE 1024
NUMERIC_BLOCK_SIZE 1 NUMERIC_BLOCK_SIZE 1
......
...@@ -500,7 +500,7 @@ ...@@ -500,7 +500,7 @@
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
-VARIABLE_TYPE BIGINT UNSIGNED -VARIABLE_TYPE BIGINT UNSIGNED
+VARIABLE_TYPE INT UNSIGNED +VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Number of metadata locks hash instances VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1 NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1024 NUMERIC_MAX_VALUE 1024
@@ -2183,7 +2183,7 @@ @@ -2183,7 +2183,7 @@
......
...@@ -2170,7 +2170,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME ...@@ -2170,7 +2170,7 @@ GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 8 DEFAULT_VALUE 8
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT Number of metadata locks hash instances VARIABLE_COMMENT Unused
NUMERIC_MIN_VALUE 1 NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1024 NUMERIC_MAX_VALUE 1024
NUMERIC_BLOCK_SIZE 1 NUMERIC_BLOCK_SIZE 1
......
...@@ -111,39 +111,9 @@ void MDL_key::init_psi_keys() ...@@ -111,39 +111,9 @@ void MDL_key::init_psi_keys()
static bool mdl_initialized= 0; static bool mdl_initialized= 0;
/**
A partition in a collection of all MDL locks.
MDL_map is partitioned for scalability reasons.
Maps MDL_key to MDL_lock instances.
*/
class MDL_map_partition
{
public:
MDL_map_partition();
~MDL_map_partition();
inline MDL_lock *find_or_insert(const MDL_key *mdl_key);
unsigned long get_lock_owner(const MDL_key *key);
inline void remove(MDL_lock *lock);
private:
bool move_from_hash_to_lock_mutex(MDL_lock *lock);
/** A partition of all acquired locks in the server. */
HASH m_locks;
/* Protects access to m_locks hash. */
mysql_mutex_t m_mutex;
friend int mdl_iterate(int (*)(MDL_ticket *, void *), void *);
};
/**
Start-up parameter for the number of partitions of the MDL_lock hash.
*/
ulong mdl_locks_hash_partitions;
/** /**
A collection of all MDL locks. A singleton, A collection of all MDL locks. A singleton,
there is only one instance of the map in the server. there is only one instance of the map in the server.
Contains instances of MDL_map_partition
*/ */
class MDL_map class MDL_map
...@@ -155,8 +125,11 @@ public: ...@@ -155,8 +125,11 @@ public:
unsigned long get_lock_owner(const MDL_key *key); unsigned long get_lock_owner(const MDL_key *key);
void remove(MDL_lock *lock); void remove(MDL_lock *lock);
private: private:
/** Array of partitions where the locks are actually stored. */ bool move_from_hash_to_lock_mutex(MDL_lock *lock);
Dynamic_array<MDL_map_partition *> m_partitions; /** All acquired locks in the server. */
HASH m_locks;
/* Protects access to m_locks hash. */
mysql_mutex_t m_mutex;
/** Pre-allocated MDL_lock object for GLOBAL namespace. */ /** Pre-allocated MDL_lock object for GLOBAL namespace. */
MDL_lock *m_global_lock; MDL_lock *m_global_lock;
/** Pre-allocated MDL_lock object for COMMIT namespace. */ /** Pre-allocated MDL_lock object for COMMIT namespace. */
...@@ -405,8 +378,7 @@ public: ...@@ -405,8 +378,7 @@ public:
bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx, bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx,
bool ignore_lock_priority) const; bool ignore_lock_priority) const;
inline static MDL_lock *create(const MDL_key *key, inline static MDL_lock *create(const MDL_key *key);
MDL_map_partition *map_part);
inline unsigned long get_lock_owner() const; inline unsigned long get_lock_owner() const;
...@@ -435,14 +407,13 @@ public: ...@@ -435,14 +407,13 @@ public:
public: public:
MDL_lock(const MDL_key *key_arg, MDL_map_partition *map_part) MDL_lock(const MDL_key *key_arg)
: key(key_arg), : key(key_arg),
m_hog_lock_count(0), m_hog_lock_count(0),
m_ref_usage(0), m_ref_usage(0),
m_ref_release(0), m_ref_release(0),
m_is_destroyed(FALSE), m_is_destroyed(FALSE),
m_version(0), m_version(0)
m_map_part(map_part)
{ {
mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock); mysql_prlock_init(key_MDL_lock_rwlock, &m_rwlock);
} }
...@@ -455,17 +426,17 @@ public: ...@@ -455,17 +426,17 @@ public:
public: public:
/** /**
These three members are used to make it possible to separate These three members are used to make it possible to separate
the MDL_map_partition::m_mutex mutex and MDL_lock::m_rwlock in the MDL_map::m_mutex mutex and MDL_lock::m_rwlock in
MDL_map::find_or_insert() for increased scalability. MDL_map::find_or_insert() for increased scalability.
The 'm_is_destroyed' member is only set by destroyers that The 'm_is_destroyed' member is only set by destroyers that
have both the MDL_map_partition::m_mutex and MDL_lock::m_rwlock, thus have both the MDL_map::m_mutex and MDL_lock::m_rwlock, thus
holding any of the mutexes is sufficient to read it. holding any of the mutexes is sufficient to read it.
The 'm_ref_usage; is incremented under protection by The 'm_ref_usage; is incremented under protection by
MDL_map_partition::m_mutex, but when 'm_is_destroyed' is set to TRUE, this MDL_map::m_mutex, but when 'm_is_destroyed' is set to TRUE, this
member is moved to be protected by the MDL_lock::m_rwlock. member is moved to be protected by the MDL_lock::m_rwlock.
This means that the MDL_map::find_or_insert() which only This means that the MDL_map::find_or_insert() which only
holds the MDL_lock::m_rwlock can compare it to 'm_ref_release' holds the MDL_lock::m_rwlock can compare it to 'm_ref_release'
without acquiring MDL_map_partition::m_mutex again and if equal without acquiring MDL_map::m_mutex again and if equal
it can also destroy the lock object safely. it can also destroy the lock object safely.
The 'm_ref_release' is incremented under protection by The 'm_ref_release' is incremented under protection by
MDL_lock::m_rwlock. MDL_lock::m_rwlock.
...@@ -480,23 +451,19 @@ public: ...@@ -480,23 +451,19 @@ public:
/** /**
We use the same idea and an additional version counter to support We use the same idea and an additional version counter to support
caching of unused MDL_lock object for further re-use. caching of unused MDL_lock object for further re-use.
This counter is incremented while holding both MDL_map_partition::m_mutex This counter is incremented while holding both MDL_map::m_mutex
and MDL_lock::m_rwlock locks each time when a MDL_lock is moved from and MDL_lock::m_rwlock locks each time when a MDL_lock is moved from
the partitioned hash to the paritioned unused objects list (or destroyed). the hash to the unused objects list (or destroyed).
A thread, which has found a MDL_lock object for the key in the hash A thread, which has found a MDL_lock object for the key in the hash
and then released the MDL_map_partition::m_mutex before acquiring the and then released the MDL_map::m_mutex before acquiring the
MDL_lock::m_rwlock, can determine that this object was moved to the MDL_lock::m_rwlock, can determine that this object was moved to the
unused objects list (or destroyed) while it held no locks by comparing unused objects list (or destroyed) while it held no locks by comparing
the version value which it read while holding the MDL_map_partition::m_mutex the version value which it read while holding the MDL_map::m_mutex
with the value read after acquiring the MDL_lock::m_rwlock. with the value read after acquiring the MDL_lock::m_rwlock.
Note that since it takes several years to overflow this counter such Note that since it takes several years to overflow this counter such
theoretically possible overflows should not have any practical effects. theoretically possible overflows should not have any practical effects.
*/ */
ulonglong m_version; ulonglong m_version;
/**
Partition of MDL_map where the lock is stored.
*/
MDL_map_partition *m_map_part;
}; };
...@@ -509,8 +476,8 @@ public: ...@@ -509,8 +476,8 @@ public:
class MDL_scoped_lock : public MDL_lock class MDL_scoped_lock : public MDL_lock
{ {
public: public:
MDL_scoped_lock(const MDL_key *key_arg, MDL_map_partition *map_part) MDL_scoped_lock(const MDL_key *key_arg)
: MDL_lock(key_arg, map_part) : MDL_lock(key_arg)
{ } { }
virtual const bitmap_t *incompatible_granted_types_bitmap() const virtual const bitmap_t *incompatible_granted_types_bitmap() const
...@@ -550,8 +517,8 @@ private: ...@@ -550,8 +517,8 @@ private:
class MDL_object_lock : public MDL_lock class MDL_object_lock : public MDL_lock
{ {
public: public:
MDL_object_lock(const MDL_key *key_arg, MDL_map_partition *map_part) MDL_object_lock(const MDL_key *key_arg)
: MDL_lock(key_arg, map_part) : MDL_lock(key_arg)
{ } { }
virtual const bitmap_t *incompatible_granted_types_bitmap() const virtual const bitmap_t *incompatible_granted_types_bitmap() const
...@@ -660,7 +627,7 @@ static inline int mdl_iterate_lock(MDL_lock *lock, ...@@ -660,7 +627,7 @@ static inline int mdl_iterate_lock(MDL_lock *lock,
int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg) int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg)
{ {
DYNAMIC_ARRAY locks; DYNAMIC_ARRAY locks;
uint i, j; uint i;
int res; int res;
DBUG_ENTER("mdl_iterate"); DBUG_ENTER("mdl_iterate");
...@@ -670,30 +637,26 @@ int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg) ...@@ -670,30 +637,26 @@ int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg)
my_init_dynamic_array(&locks, sizeof(MDL_lock*), 512, 1, MYF(0)); my_init_dynamic_array(&locks, sizeof(MDL_lock*), 512, 1, MYF(0));
for (i= 0; i < mdl_locks.m_partitions.elements(); i++)
{
MDL_map_partition *part= mdl_locks.m_partitions.at(i);
/* Collect all locks first */ /* Collect all locks first */
mysql_mutex_lock(&part->m_mutex); mysql_mutex_lock(&mdl_locks.m_mutex);
if (allocate_dynamic(&locks, part->m_locks.records)) if (allocate_dynamic(&locks, mdl_locks.m_locks.records))
{ {
res= 1; res= 1;
mysql_mutex_unlock(&part->m_mutex); mysql_mutex_unlock(&mdl_locks.m_mutex);
break; goto end;
} }
reset_dynamic(&locks); for (i= 0; i < mdl_locks.m_locks.records; i++)
for (j= 0; j < part->m_locks.records; j++)
{ {
MDL_lock *lock= (MDL_lock*) my_hash_element(&part->m_locks, j); MDL_lock *lock= (MDL_lock*) my_hash_element(&mdl_locks.m_locks, i);
lock->m_ref_usage++; lock->m_ref_usage++;
insert_dynamic(&locks, &lock); insert_dynamic(&locks, &lock);
} }
mysql_mutex_unlock(&part->m_mutex); mysql_mutex_unlock(&mdl_locks.m_mutex);
/* Now show them */ /* Now show them */
for (j= 0; j < locks.elements; j++) for (i= 0; i < locks.elements; i++)
{ {
MDL_lock *lock= (MDL_lock*) *dynamic_element(&locks, j, MDL_lock**); MDL_lock *lock= (MDL_lock*) *dynamic_element(&locks, i, MDL_lock**);
res= mdl_iterate_lock(lock, callback, arg); res= mdl_iterate_lock(lock, callback, arg);
mysql_prlock_wrlock(&lock->m_rwlock); mysql_prlock_wrlock(&lock->m_rwlock);
...@@ -708,30 +671,12 @@ int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg) ...@@ -708,30 +671,12 @@ int mdl_iterate(int (*callback)(MDL_ticket *ticket, void *arg), void *arg)
if (res) if (res)
break; break;
} }
} end:
delete_dynamic(&locks); delete_dynamic(&locks);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
/** Initialize the container for all MDL locks. */
void MDL_map::init()
{
MDL_key global_lock_key(MDL_key::GLOBAL, "", "");
MDL_key commit_lock_key(MDL_key::COMMIT, "", "");
m_global_lock= MDL_lock::create(&global_lock_key, NULL);
m_commit_lock= MDL_lock::create(&commit_lock_key, NULL);
for (uint i= 0; i < mdl_locks_hash_partitions; i++)
{
MDL_map_partition *part= new (std::nothrow) MDL_map_partition();
m_partitions.append(part);
}
}
my_hash_value_type mdl_hash_function(CHARSET_INFO *cs, my_hash_value_type mdl_hash_function(CHARSET_INFO *cs,
const uchar *key, size_t length) const uchar *key, size_t length)
{ {
...@@ -740,14 +685,20 @@ my_hash_value_type mdl_hash_function(CHARSET_INFO *cs, ...@@ -740,14 +685,20 @@ my_hash_value_type mdl_hash_function(CHARSET_INFO *cs,
} }
/** Initialize the partition in the container with all MDL locks. */ /** Initialize the container for all MDL locks. */
MDL_map_partition::MDL_map_partition() void MDL_map::init()
{ {
MDL_key global_lock_key(MDL_key::GLOBAL, "", "");
MDL_key commit_lock_key(MDL_key::COMMIT, "", "");
m_global_lock= MDL_lock::create(&global_lock_key);
m_commit_lock= MDL_lock::create(&commit_lock_key);
mysql_mutex_init(key_MDL_map_mutex, &m_mutex, NULL); mysql_mutex_init(key_MDL_map_mutex, &m_mutex, NULL);
my_hash_init2(&m_locks, 0, &my_charset_bin, 16 /* FIXME */, 0, 0, my_hash_init2(&m_locks, 0, &my_charset_bin, 16 /* FIXME */, 0, 0,
mdl_locks_key, mdl_hash_function, 0, 0); mdl_locks_key, mdl_hash_function, 0, 0);
}; }
/** /**
...@@ -760,21 +711,6 @@ void MDL_map::destroy() ...@@ -760,21 +711,6 @@ void MDL_map::destroy()
MDL_lock::destroy(m_global_lock); MDL_lock::destroy(m_global_lock);
MDL_lock::destroy(m_commit_lock); MDL_lock::destroy(m_commit_lock);
while (m_partitions.elements() > 0)
{
MDL_map_partition *part= m_partitions.pop();
delete part;
}
}
/**
Destroy the partition in container for all MDL locks.
@pre It must be empty.
*/
MDL_map_partition::~MDL_map_partition()
{
DBUG_ASSERT(!m_locks.records); DBUG_ASSERT(!m_locks.records);
mysql_mutex_destroy(&m_mutex); mysql_mutex_destroy(&m_mutex);
my_hash_free(&m_locks); my_hash_free(&m_locks);
...@@ -816,26 +752,6 @@ MDL_lock* MDL_map::find_or_insert(const MDL_key *mdl_key) ...@@ -816,26 +752,6 @@ MDL_lock* MDL_map::find_or_insert(const MDL_key *mdl_key)
return lock; return lock;
} }
uint part_id= mdl_key->hash_value() % mdl_locks_hash_partitions;
MDL_map_partition *part= m_partitions.at(part_id);
return part->find_or_insert(mdl_key);
}
/**
Find MDL_lock object corresponding to the key and hash value in
MDL_map partition, create it if it does not exist.
@retval non-NULL - Success. MDL_lock instance for the key with
locked MDL_lock::m_rwlock.
@retval NULL - Failure (OOM).
*/
MDL_lock* MDL_map_partition::find_or_insert(const MDL_key *mdl_key)
{
MDL_lock *lock;
retry: retry:
mysql_mutex_lock(&m_mutex); mysql_mutex_lock(&m_mutex);
if (!(lock= (MDL_lock*) my_hash_search_using_hash_value(&m_locks, if (!(lock= (MDL_lock*) my_hash_search_using_hash_value(&m_locks,
...@@ -847,7 +763,7 @@ retry: ...@@ -847,7 +763,7 @@ retry:
No lock object found so we need to create a new one No lock object found so we need to create a new one
or reuse an existing unused object. or reuse an existing unused object.
*/ */
lock= MDL_lock::create(mdl_key, this); lock= MDL_lock::create(mdl_key);
if (!lock || my_hash_insert(&m_locks, (uchar*)lock)) if (!lock || my_hash_insert(&m_locks, (uchar*)lock))
{ {
MDL_lock::destroy(lock); MDL_lock::destroy(lock);
...@@ -864,7 +780,7 @@ retry: ...@@ -864,7 +780,7 @@ retry:
/** /**
Release MDL_map_partition::m_mutex mutex and lock MDL_lock::m_rwlock for lock Release MDL_map::m_mutex mutex and lock MDL_lock::m_rwlock for lock
object from the hash. Handle situation when object was released object from the hash. Handle situation when object was released
while we held no locks. while we held no locks.
...@@ -873,7 +789,7 @@ retry: ...@@ -873,7 +789,7 @@ retry:
should re-try looking up MDL_lock object in the hash. should re-try looking up MDL_lock object in the hash.
*/ */
bool MDL_map_partition::move_from_hash_to_lock_mutex(MDL_lock *lock) bool MDL_map::move_from_hash_to_lock_mutex(MDL_lock *lock)
{ {
ulonglong version; ulonglong version;
...@@ -882,7 +798,7 @@ bool MDL_map_partition::move_from_hash_to_lock_mutex(MDL_lock *lock) ...@@ -882,7 +798,7 @@ bool MDL_map_partition::move_from_hash_to_lock_mutex(MDL_lock *lock)
/* /*
We increment m_ref_usage which is a reference counter protected by We increment m_ref_usage which is a reference counter protected by
MDL_map_partition::m_mutex under the condition it is present in the hash MDL_map::m_mutex under the condition it is present in the hash
and m_is_destroyed is FALSE. and m_is_destroyed is FALSE.
*/ */
lock->m_ref_usage++; lock->m_ref_usage++;
...@@ -957,21 +873,6 @@ MDL_map::get_lock_owner(const MDL_key *mdl_key) ...@@ -957,21 +873,6 @@ MDL_map::get_lock_owner(const MDL_key *mdl_key)
} }
else else
{ {
uint part_id= mdl_key->hash_value() % mdl_locks_hash_partitions;
MDL_map_partition *part= m_partitions.at(part_id);
res= part->get_lock_owner(mdl_key);
}
return res;
}
unsigned long
MDL_map_partition::get_lock_owner(const MDL_key *mdl_key)
{
MDL_lock *lock;
unsigned long res= 0;
mysql_mutex_lock(&m_mutex); mysql_mutex_lock(&m_mutex);
lock= (MDL_lock*) my_hash_search_using_hash_value(&m_locks, lock= (MDL_lock*) my_hash_search_using_hash_value(&m_locks,
mdl_key->hash_value(), mdl_key->hash_value(),
...@@ -980,7 +881,7 @@ MDL_map_partition::get_lock_owner(const MDL_key *mdl_key) ...@@ -980,7 +881,7 @@ MDL_map_partition::get_lock_owner(const MDL_key *mdl_key)
if (lock) if (lock)
res= lock->get_lock_owner(); res= lock->get_lock_owner();
mysql_mutex_unlock(&m_mutex); mysql_mutex_unlock(&m_mutex);
}
return res; return res;
} }
...@@ -1004,24 +905,12 @@ void MDL_map::remove(MDL_lock *lock) ...@@ -1004,24 +905,12 @@ void MDL_map::remove(MDL_lock *lock)
return; return;
} }
lock->m_map_part->remove(lock);
}
/**
Destroy MDL_lock object belonging to specific MDL_map
partition or delegate this responsibility to whatever
thread that holds the last outstanding reference to it.
*/
void MDL_map_partition::remove(MDL_lock *lock)
{
mysql_mutex_lock(&m_mutex); mysql_mutex_lock(&m_mutex);
my_hash_delete(&m_locks, (uchar*) lock); my_hash_delete(&m_locks, (uchar*) lock);
/* /*
To let threads holding references to the MDL_lock object know that it was To let threads holding references to the MDL_lock object know that it was
moved to the list of unused objects or destroyed, we increment the version moved to the list of unused objects or destroyed, we increment the version
counter under protection of both MDL_map_partition::m_mutex and counter under protection of both MDL_map::m_mutex and
MDL_lock::m_rwlock locks. This allows us to read the version value while MDL_lock::m_rwlock locks. This allows us to read the version value while
having either one of those locks. having either one of those locks.
*/ */
...@@ -1033,8 +922,8 @@ void MDL_map_partition::remove(MDL_lock *lock) ...@@ -1033,8 +922,8 @@ void MDL_map_partition::remove(MDL_lock *lock)
has the responsibility to release it. has the responsibility to release it.
Setting of m_is_destroyed to TRUE while holding _both_ Setting of m_is_destroyed to TRUE while holding _both_
MDL_map_partition::m_mutex and MDL_lock::m_rwlock mutexes transfers MDL_map::m_mutex and MDL_lock::m_rwlock mutexes transfers
the protection of m_ref_usage from MDL_map_partition::m_mutex to the protection of m_ref_usage from MDL_map::m_mutex to
MDL_lock::m_rwlock while removal of the object from the hash MDL_lock::m_rwlock while removal of the object from the hash
(and cache of unused objects) makes it read-only. Therefore (and cache of unused objects) makes it read-only. Therefore
whoever acquires MDL_lock::m_rwlock next will see the most up whoever acquires MDL_lock::m_rwlock next will see the most up
...@@ -1153,17 +1042,16 @@ void MDL_request::init(const MDL_key *key_arg, ...@@ -1153,17 +1042,16 @@ void MDL_request::init(const MDL_key *key_arg,
@note Also chooses an MDL_lock descendant appropriate for object namespace. @note Also chooses an MDL_lock descendant appropriate for object namespace.
*/ */
inline MDL_lock *MDL_lock::create(const MDL_key *mdl_key, inline MDL_lock *MDL_lock::create(const MDL_key *mdl_key)
MDL_map_partition *map_part)
{ {
switch (mdl_key->mdl_namespace()) switch (mdl_key->mdl_namespace())
{ {
case MDL_key::GLOBAL: case MDL_key::GLOBAL:
case MDL_key::SCHEMA: case MDL_key::SCHEMA:
case MDL_key::COMMIT: case MDL_key::COMMIT:
return new (std::nothrow) MDL_scoped_lock(mdl_key, map_part); return new (std::nothrow) MDL_scoped_lock(mdl_key);
default: default:
return new (std::nothrow) MDL_object_lock(mdl_key, map_part); return new (std::nothrow) MDL_object_lock(mdl_key);
} }
} }
......
...@@ -981,14 +981,6 @@ extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd); ...@@ -981,14 +981,6 @@ extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd);
extern "C" int thd_is_connected(MYSQL_THD thd); extern "C" int thd_is_connected(MYSQL_THD thd);
/*
Start-up parameter for the number of partitions of the hash
containing all the MDL_lock objects and a constant for
its default value.
*/
extern ulong mdl_locks_hash_partitions;
static const ulong MDL_LOCKS_HASH_PARTITIONS_DEFAULT = 8;
/* /*
Metadata locking subsystem tries not to grant more than Metadata locking subsystem tries not to grant more than
max_write_lock_count high-prio, strong locks successively, max_write_lock_count high-prio, strong locks successively,
......
...@@ -1410,10 +1410,11 @@ static Sys_var_ulong Sys_metadata_locks_cache_size( ...@@ -1410,10 +1410,11 @@ static Sys_var_ulong Sys_metadata_locks_cache_size(
VALID_RANGE(1, 1024*1024), DEFAULT(1024), VALID_RANGE(1, 1024*1024), DEFAULT(1024),
BLOCK_SIZE(1)); BLOCK_SIZE(1));
static ulong mdl_locks_hash_partitions;
static Sys_var_ulong Sys_metadata_locks_hash_instances( static Sys_var_ulong Sys_metadata_locks_hash_instances(
"metadata_locks_hash_instances", "Number of metadata locks hash instances", "metadata_locks_hash_instances", "Unused",
READ_ONLY GLOBAL_VAR(mdl_locks_hash_partitions), CMD_LINE(REQUIRED_ARG), READ_ONLY GLOBAL_VAR(mdl_locks_hash_partitions), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1, 1024), DEFAULT(MDL_LOCKS_HASH_PARTITIONS_DEFAULT), VALID_RANGE(1, 1024), DEFAULT(8),
BLOCK_SIZE(1)); BLOCK_SIZE(1));
/* /*
......
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