summaryrefslogtreecommitdiff
path: root/sql/sql_cache.cc
diff options
context:
space:
mode:
authorunknown <konstantin@mysql.com>2006-01-04 17:35:30 +0300
committerunknown <konstantin@mysql.com>2006-01-04 17:35:30 +0300
commitaf13158ab844d131e8b7c41c4a50a93e3f6c83c0 (patch)
tree12c607d43ac445a9f67b581d304e538eea483b50 /sql/sql_cache.cc
parentf23188b137e5194d851972e7d3b1982a33d0b4ca (diff)
downloadmariadb-git-af13158ab844d131e8b7c41c4a50a93e3f6c83c0.tar.gz
A fix for Bug#7209 "Client error with "Access Denied" on updates
when high concurrency": remove HASH::current_record and make it an external search parameter, so that it can not be the cause of a race condition under high concurrent load. The bug was in a race condition in table_hash_search, when column_priv_hash.current_record was overwritten simultaneously by multiple threads, causing the search for a suitable grant record to fail. No test case as the bug is repeatable only under concurrent load. include/hash.h: - remove current_record from HASH, instead modify hash_first, hash_next to accept HASH_SEARCH_STATE as an IN/OUT parameter mysys/hash.c: - remove HASH::current_record - change declarations of functions that use HASH in read-only mode to accept const HASH * instead of HASH *. - implement hash_search; move the old implementation of hash_search to hash_first mysys/testhash.c: - adjust the test case to changed function declarations sql/lock.cc: - adjust to changed declarations of hash_search, hash_next sql/sql_acl.cc: - adjust to changed declarations of hash_search, hash_next sql/sql_base.cc: - adjust to changed declarations of hash_search, hash_nex sql/sql_cache.cc: - adjust to a changed declaration of hash_replace
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r--sql/sql_cache.cc10
1 files changed, 6 insertions, 4 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index b40257511f7..457478e90db 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -2873,6 +2873,7 @@ my_bool Query_cache::move_by_type(byte **border,
}
case Query_cache_block::TABLE:
{
+ HASH_SEARCH_STATE record_idx;
DBUG_PRINT("qcache", ("block 0x%lx TABLE", (ulong) block));
if (*border == 0)
break;
@@ -2890,7 +2891,7 @@ my_bool Query_cache::move_by_type(byte **border,
byte *key;
uint key_length;
key=query_cache_table_get_key((byte*) block, &key_length, 0);
- hash_search(&tables, (byte*) key, key_length);
+ hash_first(&tables, (byte*) key, key_length, &record_idx);
block->destroy();
new_block->init(len);
@@ -2924,7 +2925,7 @@ my_bool Query_cache::move_by_type(byte **border,
/* Fix pointer to table name */
new_block->table()->table(new_block->table()->db() + tablename_offset);
/* Fix hash to point at moved block */
- hash_replace(&tables, tables.current_record, (byte*) new_block);
+ hash_replace(&tables, &record_idx, (byte*) new_block);
DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
len, (ulong) new_block, (ulong) *border));
@@ -2932,6 +2933,7 @@ my_bool Query_cache::move_by_type(byte **border,
}
case Query_cache_block::QUERY:
{
+ HASH_SEARCH_STATE record_idx;
DBUG_PRINT("qcache", ("block 0x%lx QUERY", (ulong) block));
if (*border == 0)
break;
@@ -2949,7 +2951,7 @@ my_bool Query_cache::move_by_type(byte **border,
byte *key;
uint key_length;
key=query_cache_query_get_key((byte*) block, &key_length, 0);
- hash_search(&queries, (byte*) key, key_length);
+ hash_first(&queries, (byte*) key, key_length, &record_idx);
// Move table of used tables
memmove((char*) new_block->table(0), (char*) block->table(0),
ALIGN_SIZE(n_tables*sizeof(Query_cache_block_table)));
@@ -3017,7 +3019,7 @@ my_bool Query_cache::move_by_type(byte **border,
net->query_cache_query= (gptr) new_block;
}
/* Fix hash to point at moved block */
- hash_replace(&queries, queries.current_record, (byte*) new_block);
+ hash_replace(&queries, &record_idx, (byte*) new_block);
DBUG_PRINT("qcache", ("moved %lu bytes to 0x%lx, new gap at 0x%lx",
len, (ulong) new_block, (ulong) *border));
break;