From 3cfd578ea7efa50805d2a069e6e180331ba41358 Mon Sep 17 00:00:00 2001 From: "svoj@mysql.com/april.(none)" <> Date: Tue, 5 Dec 2006 18:44:14 +0400 Subject: [PATCH] BUG#23526 - show table status reports incorrect values for MyISAM tables This problem could happen when show table status get outdated copy of TABLE object from table cache. MyISAM updates state info when external_lock() method is called. Though I_S does not lock a table to avoid deadlocks. If I_S opens a table which is in a table cache it will likely get outdated state info copy. In this case shared state copy is more recent than local copy. This problem is fixed by correctly restoring myisam state info pointer back to original value, that is to shared state. Affects MyISAM only. No good deterministic test case for this fix. --- include/thr_lock.h | 1 + myisam/mi_locking.c | 9 +++++++++ myisam/mi_open.c | 1 + myisam/myisamdef.h | 1 + mysys/thr_lock.c | 12 ++++++++++-- 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/thr_lock.h b/include/thr_lock.h index 251d8e7c9cf..d34358d5a6b 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -122,6 +122,7 @@ typedef struct st_thr_lock { void (*get_status)(void*, int); /* When one gets a lock */ void (*copy_status)(void*,void*); void (*update_status)(void*); /* Before release of write */ + void (*restore_status)(void*); /* Before release of read */ my_bool (*check_status)(void *); } THR_LOCK; diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index 36b793363c5..ee776128eb8 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -326,6 +326,15 @@ void mi_update_status(void* param) } } + +void mi_restore_status(void *param) +{ + MI_INFO *info= (MI_INFO*) param; + info->state= &info->s->state.state; + info->append_insert_at_end= 0; +} + + void mi_copy_status(void* to,void *from) { ((MI_INFO*) to)->state= &((MI_INFO*) from)->save_state; diff --git a/myisam/mi_open.c b/myisam/mi_open.c index bf20eb3f270..1f7dd23f148 100644 --- a/myisam/mi_open.c +++ b/myisam/mi_open.c @@ -505,6 +505,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) share->lock.get_status=mi_get_status; share->lock.copy_status=mi_copy_status; share->lock.update_status=mi_update_status; + share->lock.restore_status= mi_restore_status; share->lock.check_status=mi_check_status; } } diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h index 12e2c8e4bec..14f4570771a 100644 --- a/myisam/myisamdef.h +++ b/myisam/myisamdef.h @@ -732,6 +732,7 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b, my_bool null_are_equal); void mi_get_status(void* param, int concurrent_insert); void mi_update_status(void* param); +void mi_restore_status(void* param); void mi_copy_status(void* to,void *from); my_bool mi_check_status(void* param); void mi_disable_non_unique_index(MI_INFO *info, ha_rows rows); diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 66848b94651..58b55583c5f 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -758,8 +758,16 @@ void thr_unlock(THR_LOCK_DATA *data) } else lock->write.last=data->prev; - if (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock->update_status) - (*lock->update_status)(data->status_param); + if (lock_type >= TL_WRITE_CONCURRENT_INSERT) + { + if (lock->update_status) + (*lock->update_status)(data->status_param); + } + else + { + if (lock->restore_status) + (*lock->restore_status)(data->status_param); + } if (lock_type == TL_READ_NO_INSERT) lock->read_no_write_count--; data->type=TL_UNLOCK; /* Mark unlocked */