1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-01 03:47:19 +03:00

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.
This commit is contained in:
konstantin@mysql.com
2006-01-04 17:35:30 +03:00
parent ec753efd43
commit f7d6fa6f17
7 changed files with 79 additions and 50 deletions

View File

@ -799,6 +799,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
reg1 TABLE *table;
char key[MAX_DBKEY_LENGTH];
uint key_length;
HASH_SEARCH_STATE state;
DBUG_ENTER("open_table");
/* find a unused table in the open table cache */
@ -863,9 +864,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
/* close handler tables which are marked for flush */
mysql_ha_flush(thd, (TABLE_LIST*) NULL, MYSQL_HA_REOPEN_ON_USAGE, TRUE);
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length,
&state);
table && table->in_use ;
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length,
&state))
{
if (table->version != refresh_version)
{
@ -1236,12 +1239,14 @@ bool table_is_used(TABLE *table, bool wait_for_name_lock)
{
do
{
HASH_SEARCH_STATE state;
char *key= table->table_cache_key;
uint key_length=table->key_length;
for (TABLE *search=(TABLE*) hash_search(&open_cache,
(byte*) key,key_length) ;
for (TABLE *search= (TABLE*) hash_first(&open_cache, (byte*) key,
key_length, &state);
search ;
search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
search= (TABLE*) hash_next(&open_cache, (byte*) key,
key_length, &state))
{
if (search->locked_by_flush ||
search->locked_by_name && wait_for_name_lock ||
@ -2958,11 +2963,14 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table_name,
key_length=(uint) (strmov(strmov(key,db)+1,table_name)-key)+1;
for (;;)
{
HASH_SEARCH_STATE state;
result= signalled= 0;
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
for (table= (TABLE*) hash_first(&open_cache, (byte*) key, key_length,
&state);
table;
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
table= (TABLE*) hash_next(&open_cache, (byte*) key, key_length,
&state))
{
THD *in_use;
table->version=0L; /* Free when thread is ready */