Commit 2b0c4476 authored by unknown's avatar unknown
Browse files

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:
  Added restore_status, that will be called prior to release a
  read lock.
myisam/mi_locking.c:
  Added mi_restore_status, that will be called prior to release a
  read lock. This function is intended to set myisam state pointer
  back to original value, that is to shared state.
myisam/mi_open.c:
  Added restore_status, that will be called prior to release a
  read lock.
myisam/myisamdef.h:
  Added mi_restore_status, that will be called prior to release a
  read lock.
mysys/thr_lock.c:
  Call restore_status if we have lock with priority lower than
  TL_WRITE_CONCURRENT_INSERT.
parent d337e90e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;

+9 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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;
      }
    }
+1 −0
Original line number Diff line number Diff line
@@ -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);
+10 −2
Original line number Diff line number Diff line
@@ -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)
  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 */