Commit 5f08a831 authored by istruewing@chilla.local's avatar istruewing@chilla.local
Browse files

Bug#8283 - OPTIMIZE TABLE causes data loss

OPTIMIZE TABLE with myisam_repair_threads > 1 performs a non-quick 
parallel repair. This means that it does not only rebuild all 
indexes, but also the data file.

Non-quick parallel repair works so that there is one thread per 
index. The first of the threads rebuilds also the new data file.

The problem was that all threads shared the read io cache on the
old data file. If there were holes (deleted records) in the table,
the first thread skipped them, writing only contiguous, non-deleted
records to the new data file. Then it built the new index so that
its entries pointed to the correct record positions. But the other
threads didn't know the new record positions, but put the positions
from the old data file into the index.

The new design is so that there is a shared io cache which is filled
by the first thread (the data file writer) with the new contiguous
records and read by the other threads. Now they know the new record
positions.

Another problem was that for the parallel repair of compressed
tables a common bit_buff and rec_buff was used. I changed it so
that thread specific buffers are used for parallel repair.

A similar problem existed for checksum calculation. I made this
multi-thread safe too.
parent fadbdf27
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -325,12 +325,18 @@ typedef int (*IO_CACHE_CALLBACK)(struct st_io_cache*);
#ifdef THREAD
typedef struct st_io_cache_share
{
  /* to sync on reads into buffer */
  pthread_mutex_t mutex;
  pthread_cond_t  cond;
  int             count, total;
  /* actual IO_CACHE that filled the buffer */
  struct st_io_cache *active;
  pthread_mutex_t       mutex;           /* To sync on reads into buffer. */
  pthread_cond_t        cond;            /* To wait for signals. */
  pthread_cond_t        cond_writer;     /* For a synchronized writer. */
  /* Offset in file corresponding to the first byte of buffer. */
  my_off_t              pos_in_file;
  /* If a synchronized write cache is the source of the data. */
  struct st_io_cache    *source_cache;
  byte                  *buffer;         /* The read buffer. */
  byte                  *read_end;       /* Behind last valid byte of buffer. */
  int                   running_threads; /* threads not in lock. */
  int                   total_threads;   /* threads sharing the cache. */
  int                   error;           /* Last error. */
#ifdef NOT_YET_IMPLEMENTED
  /* whether the structure should be free'd */
  my_bool alloced;
@@ -672,8 +678,8 @@ extern void setup_io_cache(IO_CACHE* info);
extern int _my_b_read(IO_CACHE *info,byte *Buffer,uint Count);
#ifdef THREAD
extern int _my_b_read_r(IO_CACHE *info,byte *Buffer,uint Count);
extern void init_io_cache_share(IO_CACHE *info,
				IO_CACHE_SHARE *s, uint num_threads);
extern void init_io_cache_share(IO_CACHE *read_cache, IO_CACHE_SHARE *cshare,
                                IO_CACHE *write_cache, uint num_threads);
extern void remove_io_thread(IO_CACHE *info);
#endif
extern int _my_b_seq_read(IO_CACHE *info,byte *Buffer,uint Count);
+1 −1
Original line number Diff line number Diff line
@@ -345,7 +345,7 @@ typedef struct st_mi_check_param
  uint testflag, key_cache_block_size;
  uint8 language;
  my_bool using_global_keycache, opt_lock_memory, opt_follow_links;
  my_bool retry_repair, force_sort, calc_checksum;
  my_bool retry_repair, force_sort;
  char temp_filename[FN_REFLEN],*isam_file_name;
  MY_TMPDIR *tmpdir;
  int tmpfile_createflag;
+257 −49

File changed.

Preview size limit exceeded, changes collapsed.

+4 −1
Original line number Diff line number Diff line
@@ -201,7 +201,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
	 ((open_flags & HA_OPEN_ABORT_IF_CRASHED) &&
	  (my_disable_locking && share->state.open_count))))
    {
      DBUG_PRINT("error",("Table is marked as crashed"));
      DBUG_PRINT("error",("Table is marked as crashed. open_flags: %u  "
                          "changed: %u  open_count: %u  !locking: %d",
                          open_flags, share->state.changed,
                          share->state.open_count, my_disable_locking));
      my_errno=((share->state.changed & STATE_CRASHED_ON_REPAIR) ?
		HA_ERR_CRASHED_ON_REPAIR : HA_ERR_CRASHED_ON_USAGE);
      goto err;
+44 −32

File changed.

Preview size limit exceeded, changes collapsed.

Loading