Commit 6bef652d authored by Vladislav Vaintroub's avatar Vladislav Vaintroub

MDEV-4409 - Fix deadlock in MySQL key cache code, that can happen if there is...

MDEV-4409 - Fix deadlock in MySQL key cache code, that can happen if there is a key cache resize running in parallel with an update.

If there is a key cache resize,a  thread writing to key cache, will pause waiting  until resize finishes. However this thread is won't be woken, because resize does not  signaling waiters anymore. This is a regression introduced in WL#86(segmented MyISAM key cache)
The fix is to unconditionally release  threads waiting on resize_queue when resize  finishes, as in pre-WL#86 code.
parent 762d3cb8
...@@ -651,8 +651,7 @@ err: ...@@ -651,8 +651,7 @@ err:
SYNOPSIS SYNOPSIS
prepare_resize_simple_key_cache() prepare_resize_simple_key_cache()
keycache pointer to the control block of a simple key cache keycache pointer to the control block of a simple key cache
with_resize_queue <=> resize queue is used
release_lock <=> release the key cache lock before return release_lock <=> release the key cache lock before return
DESCRIPTION DESCRIPTION
...@@ -660,10 +659,8 @@ err: ...@@ -660,10 +659,8 @@ err:
this it destroys the key cache calling end_simple_key_cache. The function this it destroys the key cache calling end_simple_key_cache. The function
takes the parameter keycache as a pointer to the control block takes the parameter keycache as a pointer to the control block
structure of the type SIMPLE_KEY_CACHE_CB for this key cache. structure of the type SIMPLE_KEY_CACHE_CB for this key cache.
The parameter with_resize_queue determines weather the resize queue is The parameter release_lock says whether the key cache lock must be
involved (MySQL server never uses this queue). The parameter release_lock released before return from the function.
says weather the key cache lock must be released before return from
the function.
RETURN VALUE RETURN VALUE
0 - on success, 0 - on success,
...@@ -677,7 +674,6 @@ err: ...@@ -677,7 +674,6 @@ err:
static static
int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
my_bool with_resize_queue,
my_bool release_lock) my_bool release_lock)
{ {
int res= 0; int res= 0;
...@@ -692,7 +688,7 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -692,7 +688,7 @@ int prepare_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
one resizer only. In set_var.cc keycache->in_init is used to block one resizer only. In set_var.cc keycache->in_init is used to block
multiple attempts. multiple attempts.
*/ */
while (with_resize_queue && keycache->in_resize) while (keycache->in_resize)
{ {
/* purecov: begin inspected */ /* purecov: begin inspected */
wait_on_queue(&keycache->resize_queue, &keycache->cache_lock); wait_on_queue(&keycache->resize_queue, &keycache->cache_lock);
...@@ -759,8 +755,7 @@ finish: ...@@ -759,8 +755,7 @@ finish:
SYNOPSIS SYNOPSIS
finish_resize_simple_key_cache() finish_resize_simple_key_cache()
keycache pointer to the control block of a simple key cache keycache pointer to the control block of a simple key cache
with_resize_queue <=> resize queue is used
acquire_lock <=> acquire the key cache lock at start acquire_lock <=> acquire the key cache lock at start
DESCRIPTION DESCRIPTION
...@@ -769,9 +764,7 @@ finish: ...@@ -769,9 +764,7 @@ finish:
keycache as a pointer to the control block structure of the type keycache as a pointer to the control block structure of the type
SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag SIMPLE_KEY_CACHE_CB for this key cache. The function sets the flag
in_resize in this structure to FALSE. in_resize in this structure to FALSE.
The parameter with_resize_queue determines weather the resize queue The parameter acquire_lock says whether the key cache lock must be
is involved (MySQL server never uses this queue).
The parameter acquire_lock says weather the key cache lock must be
acquired at the start of the function. acquired at the start of the function.
RETURN VALUE RETURN VALUE
...@@ -785,7 +778,6 @@ finish: ...@@ -785,7 +778,6 @@ finish:
static static
void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
my_bool with_resize_queue,
my_bool acquire_lock) my_bool acquire_lock)
{ {
DBUG_ENTER("finish_resize_simple_key_cache"); DBUG_ENTER("finish_resize_simple_key_cache");
...@@ -801,11 +793,10 @@ void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, ...@@ -801,11 +793,10 @@ void finish_resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache,
*/ */
keycache->in_resize= 0; keycache->in_resize= 0;
if (with_resize_queue)
{ /* Signal waiting threads. */
/* Signal waiting threads. */ release_whole_queue(&keycache->resize_queue);
release_whole_queue(&keycache->resize_queue);
}
keycache_pthread_mutex_unlock(&keycache->cache_lock); keycache_pthread_mutex_unlock(&keycache->cache_lock);
...@@ -872,7 +863,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_ ...@@ -872,7 +863,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_
We do not lose the cache_lock and will release it only at the end of We do not lose the cache_lock and will release it only at the end of
this function. this function.
*/ */
if (prepare_resize_simple_key_cache(keycache, 1, 0)) if (prepare_resize_simple_key_cache(keycache, 0))
goto finish; goto finish;
/* The following will work even if use_mem is 0 */ /* The following will work even if use_mem is 0 */
...@@ -880,7 +871,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_ ...@@ -880,7 +871,7 @@ int resize_simple_key_cache(SIMPLE_KEY_CACHE_CB *keycache, uint key_cache_block_
division_limit, age_threshold); division_limit, age_threshold);
finish: finish:
finish_resize_simple_key_cache(keycache, 1, 0); finish_resize_simple_key_cache(keycache, 0);
DBUG_RETURN(blocks); DBUG_RETURN(blocks);
} }
...@@ -5279,7 +5270,7 @@ int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, ...@@ -5279,7 +5270,7 @@ int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
} }
for (i= 0; i < partitions; i++) for (i= 0; i < partitions; i++)
{ {
err|= prepare_resize_simple_key_cache(keycache->partition_array[i], 0, 1); err|= prepare_resize_simple_key_cache(keycache->partition_array[i], 1);
} }
if (!err) if (!err)
blocks= init_partitioned_key_cache(keycache, key_cache_block_size, blocks= init_partitioned_key_cache(keycache, key_cache_block_size,
...@@ -5288,7 +5279,7 @@ int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache, ...@@ -5288,7 +5279,7 @@ int resize_partitioned_key_cache(PARTITIONED_KEY_CACHE_CB *keycache,
{ {
for (i= 0; i < partitions; i++) for (i= 0; i < partitions; i++)
{ {
finish_resize_simple_key_cache(keycache->partition_array[i], 0, 1); finish_resize_simple_key_cache(keycache->partition_array[i], 1);
} }
} }
DBUG_RETURN(blocks); DBUG_RETURN(blocks);
......
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