summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docs/manual.texi43
-rw-r--r--myisam/mi_check.c110
-rw-r--r--myisam/mi_page.c3
-rw-r--r--myisam/myisamchk.c21
-rw-r--r--mysys/my_winthread.c2
-rw-r--r--sql/ha_myisam.cc66
-rw-r--r--sql/sql_table.cc20
7 files changed, 181 insertions, 84 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi
index 81939e8317a..2d45fa3aeb5 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -9036,9 +9036,9 @@ priority in one thread.
@item --memlock
Lock the @code{mysqld} process in memory. This works only if your system
supports the @code{mlockall()} system call. This may help if you have
-a problem where the opearting system is causing @code{mysqld} to swap on disk.
+a problem where the operating system is causing @code{mysqld} to swap on disk.
-@item --myisam-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP or FORCE.
+@item --myisam-recover [=option[,option...]]] where option is one of DEFAULT, BACKUP, FORCE or QUICK.
If this option is used, @code{mysqld} will on open check if the table is
marked as crashed or if if the table wasn't closed properly
(The last option only works if you are running with @code{--skip-locking}).
@@ -9051,10 +9051,15 @@ The following options affects how the repair works.
@item DEFAULT @tab The same as not giving any option to @code{--myisam-recover}.
@item BACKUP @tab If the data table was changed during recover, save a backup of the @file{table_name.MYD} data file as @file{table_name-datetime.BAK}.
@item FORCE @tab Run recover even if we will loose more than one row from the .MYD file.
+@item QUICK @tab Don't check the rows in the table if there isn't any delete blocks.
@end multitable
-Before a table is automaticly repaired, mysqld will add a note about this
-in the error log.
+Before a table is automaticly repaired, mysqld will add a note about
+this in the error log. If you want to be able to recover from most
+things without user intervention, you should use the options
+@code{BACKUP,FORCE}. This will force a repair of a table even if some rows
+would be deleted, but it will keep the old data file as a backup so that
+you can later examine what happened.
@item --pid-file=path
Path to pid file used by @code{safe_mysqld}.
@@ -21266,7 +21271,7 @@ of both worlds.
@menu
* MyISAM:: MyISAM tables
-* MERGE::
+* MERGE:: MERGE tables
* ISAM:: ISAM tables
* HEAP:: HEAP tables
* BDB:: BDB or Berkeley_db tables
@@ -21378,11 +21383,37 @@ The following options to @code{mysqld} can be used to change the behavior of
@multitable @columnfractions .40 .60
@item @strong{Option} @tab @strong{Meaning}
-@item @code{--myisam-recover} @tab Automatic recover of crashed tables.
+@item @code{--myisam-recover=#} @tab Automatic recover of crashed tables.
@item @code{-O myisam_sort_buffer_size=#} @tab Buffer used when recovering tables.
@item @code{--delay-key-write-for-all-tables} @tab Don't flush key buffers between writes for any MyISAM table
@end multitable
+The automatic recovery is activated if you start mysqld with
+@code{--myisam-recover=#}. @xref{Command-line options}.
+On open, the table is checked if it's marked as crashed or if the open
+count variable for the table is not 0 and you are running with
+@code{--skip-locking}. If either of the above is true the following happens.
+
+@itemize @bullet
+@item
+The table is checked for errors.
+@item
+If we found an error, try to do a fast repair (with sorting and without
+recreating the data file) of the table.
+@item
+If the repair fails because of an error in the data file (for example a
+duplicate key error), we try again, but this time we recreate the data file.
+@item
+If the repair fails, retry once more with the old repair option method
+(write row by row without sorting) which should be able to repair any
+type of error with little disk requirements..
+@end itemize
+
+Note that if you run automatic recover with the @code{BACKUP} option,
+you should have a cron script that automaticly moves file with names
+like @file{tablename-datetime.BAK} from the database directories to a
+backup media.
+
@xref{Command-line options}.
@menu
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index b95767d33cb..e55065b795e 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -1186,7 +1186,7 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
sort_info->dupp++;
if (rep_quick == 1)
{
- param->error_printed=1;
+ param->error_printed=param->retry_without_quick=1;
goto err;
}
continue;
@@ -1218,6 +1218,16 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
param->retry_repair=param->retry_without_quick=1;
goto err;
}
+ if (param->testflag & T_SAFE_REPAIR)
+ {
+ /* Don't repair if we loosed more than one row */
+ if (info->state->records+1 < start_records)
+ {
+ info->state->records=start_records;
+ got_error=1;
+ goto err;
+ }
+ }
if (!rep_quick)
{
@@ -1226,7 +1236,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
info->state->data_file_length=sort_info->filepos;
/* Only whole records */
share->state.split=info->state->records+info->state->del;
- param->out_flag|=O_NEW_DATA; /* Data in new file */
share->state.version=(ulong) time((time_t*) 0); /* Force reopen */
}
else
@@ -1248,6 +1257,21 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
+ if (!got_error)
+ {
+ /* Replace the actual file with the temporary file */
+ if (new_file >= 0)
+ {
+ my_close(new_file,MYF(0));
+ info->dfile=new_file= -1;
+ if (change_to_newfile(share->filename,MI_NAME_DEXT,
+ DATA_TMP_EXT, share->base.raid_chunks,
+ (param->testflag & T_BACKUP_DATA ?
+ MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
+ mi_open_datafile(info,share))
+ got_error=1;
+ }
+ }
if (got_error)
{
if (! param->error_printed)
@@ -1275,7 +1299,8 @@ err:
share->pack.header_length=0;
share->data_file_type=sort_info->new_data_file_type;
}
- share->state.changed|=STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES;
+ share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES |
+ STATE_NOT_ANALYZED);
DBUG_RETURN(got_error);
}
@@ -1454,14 +1479,17 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
flush_key_blocks(info->s->kfile, FLUSH_IGNORE_CHANGED);
/* Put same locks as old file */
- if (lock_file(param,new_file,0L,F_WRLCK,"tempfile",param->temp_filename))
- goto err;
info->s->state.version=(ulong) time((time_t*) 0);
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
VOID(my_close(info->s->kfile,MYF(MY_WME)));
- param->out_flag|=O_NEW_INDEX; /* Data in new file */
+ info->s->kfile = -1;
+ VOID(my_close(new_file,MYF(MY_WME)));
+ if (change_to_newfile(info->s->filename,MI_NAME_IEXT,INDEX_TMP_EXT,0,
+ MYF(0)) ||
+ mi_open_keyfile(info->s))
+ goto err2;
+ _mi_readinfo(info,F_WRLCK,0);
- info->s->kfile=new_file;
info->state->key_file_length=param->new_file_pos;
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
for (key=0 ; key < info->s->base.keys ; key++)
@@ -1474,6 +1502,7 @@ int mi_sort_index(MI_CHECK *param, register MI_INFO *info, my_string name)
err:
VOID(my_close(new_file,MYF(MY_WME)));
+err2:
VOID(my_delete(param->temp_filename,MYF(MY_WME)));
DBUG_RETURN(-1);
} /* sort_index */
@@ -1843,7 +1872,6 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
/* Only whole records */
share->state.split=info->state->records+info->state->del;
share->state.version=(ulong) time((time_t*) 0);
- param->out_flag|=O_NEW_DATA; /* Data in new file */
my_close(info->dfile,MYF(0));
info->dfile=new_file;
share->data_file_type=sort_info->new_data_file_type;
@@ -1910,18 +1938,34 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
memcpy( &share->state.state, info->state, sizeof(*info->state));
err:
+ got_error|= flush_blocks(param,share->kfile);
+ VOID(end_io_cache(&info->rec_cache));
+ if (!got_error)
+ {
+ /* Replace the actual file with the temporary file */
+ if (new_file >= 0)
+ {
+ my_close(new_file,MYF(0));
+ info->dfile=new_file= -1;
+ if (change_to_newfile(share->filename,MI_NAME_DEXT,
+ DATA_TMP_EXT, share->base.raid_chunks,
+ (param->testflag & T_BACKUP_DATA ?
+ MYF(MY_REDEL_MAKE_BACKUP): MYF(0))) ||
+ mi_open_datafile(info,share))
+ got_error=1;
+ }
+ }
if (got_error)
{
if (! param->error_printed)
mi_check_print_error(param,"%d when fixing table",my_errno);
if (new_file >= 0)
{
- VOID(end_io_cache(&info->rec_cache));
VOID(my_close(new_file,MYF(0)));
- VOID(my_raid_delete(param->temp_filename,info->s->base.raid_chunks,
+ VOID(my_raid_delete(param->temp_filename,share->base.raid_chunks,
MYF(MY_WME)));
if (info->dfile == new_file)
- info->dfile=0;
+ info->dfile= -1;
}
mi_mark_crashed_on_repair(info);
}
@@ -1933,7 +1977,6 @@ err:
my_free(sort_info->record,MYF(MY_ALLOW_ZERO_PTR));
my_free(sort_info->buff,MYF(MY_ALLOW_ZERO_PTR));
VOID(end_io_cache(&param->read_cache));
- VOID(end_io_cache(&info->rec_cache));
info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
if (!got_error && (param->testflag & T_UNPACK))
{
@@ -2441,6 +2484,7 @@ static int sort_key_write(SORT_INFO *sort_info, const void *a)
sort_info->key_block->
lastkey),
llbuff2));
+ param->error_printed=param->retry_without_quick=1;
if (sort_info->param->testflag & T_VERBOSE)
_mi_print_key(stdout,sort_info->keyseg,(uchar*) a, USE_WHOLE_KEY);
return (sort_delete_record(param));
@@ -2475,7 +2519,7 @@ static int sort_insert_key(MI_CHECK *param,
my_off_t prev_block)
{
uint a_length,t_length,nod_flag;
- my_off_t filepos;
+ my_off_t filepos,key_file_length;
uchar *anc_buff,*lastkey;
MI_KEY_PARAM s_temp;
MI_INFO *info;
@@ -2526,11 +2570,20 @@ static int sort_insert_key(MI_CHECK *param,
mi_putint(anc_buff,key_block->last_length,nod_flag);
bzero((byte*) anc_buff+key_block->last_length,
sort_info->keyinfo->block_length- key_block->last_length);
+ key_file_length=info->state->key_file_length;
if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR)
- return 1;
- if (my_pwrite(info->s->kfile,(byte*) anc_buff,
- (uint) sort_info->keyinfo->block_length,filepos,
- param->myf_rw))
+ DBUG_RETURN(1);
+
+ /* If we read the page from the key cache, we have to write it back to it */
+ if (key_file_length == info->state->key_file_length)
+ {
+ if (_mi_write_keypage(info, sort_info->keyinfo, filepos,
+ anc_buff))
+ DBUG_RETURN(1);
+ }
+ else if (my_pwrite(info->s->kfile,(byte*) anc_buff,
+ (uint) sort_info->keyinfo->block_length,filepos,
+ param->myf_rw))
DBUG_RETURN(1);
DBUG_DUMP("buff",(byte*) anc_buff,mi_getint(anc_buff));
@@ -2608,7 +2661,7 @@ static int sort_delete_record(MI_CHECK *param)
static int flush_pending_blocks(MI_CHECK *param)
{
uint nod_flag,length;
- my_off_t filepos;
+ my_off_t filepos,key_file_length;
MI_INFO *info;
SORT_KEY_BLOCKS *key_block;
SORT_INFO *sort_info= &param->sort_info;
@@ -2623,18 +2676,27 @@ static int flush_pending_blocks(MI_CHECK *param)
length=mi_getint(key_block->buff);
if (nod_flag)
_mi_kpointer(info,key_block->end_pos,filepos);
- if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR)
- DBUG_RETURN(1);
+ key_file_length=info->state->key_file_length;
bzero((byte*) key_block->buff+length,
sort_info->keyinfo->block_length-length);
- if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
- (uint) sort_info->keyinfo->block_length,filepos,
- param->myf_rw))
+ if ((filepos=_mi_new(info,sort_info->keyinfo)) == HA_OFFSET_ERROR)
+ DBUG_RETURN(1);
+
+ /* If we read the page from the key cache, we have to write it back */
+ if (key_file_length == info->state->key_file_length)
+ {
+ if (_mi_write_keypage(info, sort_info->keyinfo, filepos,
+ key_block->buff))
+ DBUG_RETURN(1);
+ }
+ else if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
+ (uint) sort_info->keyinfo->block_length,filepos,
+ param->myf_rw))
DBUG_RETURN(1);
DBUG_DUMP("buff",(byte*) key_block->buff,length);
nod_flag=1;
}
- info->s->state.key_root[sort_info->key]=filepos; /* Last is root for tree */
+ info->s->state.key_root[sort_info->key]=filepos; /* Last is root for tree */
DBUG_RETURN(0);
} /* flush_pending_blocks */
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index bc0394aedca..f8e2a977754 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -99,6 +99,7 @@ int _mi_dispose(register MI_INFO *info, MI_KEYDEF *keyinfo, my_off_t pos)
my_off_t old_link;
char buff[8];
DBUG_ENTER("_mi_dispose");
+ DBUG_PRINT("enter",("pos: %ld", (long) pos));
old_link=info->s->state.key_del[keyinfo->block_size];
info->s->state.key_del[keyinfo->block_size]=pos;
@@ -141,6 +142,6 @@ my_off_t _mi_new(register MI_INFO *info, MI_KEYDEF *keyinfo)
info->s->state.key_del[keyinfo->block_size]=mi_sizekorr(buff);
}
info->s->state.changed|= STATE_NOT_SORTED_PAGES;
- DBUG_PRINT("exit",("Pos: %d",pos));
+ DBUG_PRINT("exit",("Pos: %ld",(long) pos));
DBUG_RETURN(pos);
} /* _mi_new */
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 26e1699a07c..7d9ba9b7c28 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -481,6 +481,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
File datafile;
char fixed_name[FN_REFLEN];
char llbuff[22],llbuff2[22];
+ my_bool state_updated=0;
MYISAM_SHARE *share;
DBUG_ENTER("myisamchk");
@@ -665,12 +666,20 @@ static int myisamchk(MI_CHECK *param, my_string filename)
(share->state.key_map ||
(rep_quick && !param->keys_in_use && !recreate)) &&
mi_test_if_sort_rep(info, info->state->records, 1))
+ {
error=mi_repair_by_sort(&check_param,info,fixed_name,rep_quick);
+ state_updated=1;
+ }
else if (param->testflag & (T_REP | T_REP_BY_SORT))
error=mi_repair(&check_param, info,fixed_name,rep_quick);
}
if (!error && param->testflag & T_SORT_RECORDS)
{
+ /*
+ The data file is nowadays reopened in the repair code so we should
+ soon remove the following reopen-code
+ */
+#ifndef TO_BE_REMOVED
if (param->out_flag & O_NEW_DATA)
{ /* Change temp file to org file */
VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */
@@ -682,6 +691,7 @@ static int myisamchk(MI_CHECK *param, my_string filename)
param->out_flag&= ~O_NEW_DATA; /* We are using new datafile */
param->read_cache.file=info->dfile;
}
+#endif
if (! error)
{
uint key;
@@ -737,7 +747,11 @@ static int myisamchk(MI_CHECK *param, my_string filename)
{
error|=chk_key(param, info);
if (!error && (param->testflag & (T_STATISTICS | T_AUTO_INC)))
- error=update_state_info(param, info, UPDATE_STAT);
+ error=update_state_info(param, info,
+ ((param->testflag & T_STATISTICS) ?
+ UPDATE_STAT : 0) |
+ ((param->testflag & T_AUTO_INC) ?
+ UPDATE_AUTO_INC : 0));
}
if ((!rep_quick && !error) ||
!(param->testflag & (T_FAST | T_FORCE_CREATE)))
@@ -788,7 +802,8 @@ static int myisamchk(MI_CHECK *param, my_string filename)
error|=update_state_info(param, info,
UPDATE_OPEN_COUNT |
(((param->testflag & (T_REP | T_REP_BY_SORT)) ?
- UPDATE_TIME | UPDATE_STAT : 0) |
+ UPDATE_TIME : 0) |
+ (state_updated ? UPDATE_STAT : 0) |
((param->testflag & T_SORT_RECORDS) ?
UPDATE_SORT : 0)));
VOID(lock_file(param, share->kfile,0L,F_UNLCK,"indexfile",filename));
@@ -1244,7 +1259,7 @@ err:
{
VOID(end_io_cache(&info->rec_cache));
(void) my_close(new_file,MYF(MY_WME));
- (void) my_raid_delete(param->temp_filename, share->base.raid_chunksize,
+ (void) my_raid_delete(param->temp_filename, share->base.raid_chunks,
MYF(MY_WME));
}
if (temp_buff)
diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c
index 2fe56a13baf..a1fb2c76184 100644
--- a/mysys/my_winthread.c
+++ b/mysys/my_winthread.c
@@ -83,7 +83,7 @@ int pthread_create(pthread_t *thread_id, pthread_attr_t *attr,
attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map);
#else
- hThread=(HANDLE)_beginthread(pthread_start,
+ hThread=(HANDLE)_beginthread((void( __cdecl *)(void *)) pthread_start,
attr->dwStackSize ? attr->dwStackSize :
65535, (void*) map);
#endif
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 8be9bc62ba7..639c2dc04a6 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -411,6 +411,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
int error;
if (!file) return HA_ADMIN_INTERNAL_ERROR;
MI_CHECK param;
+ ha_rows start_records;
myisamchk_init(&param);
param.thd = thd;
@@ -420,8 +421,10 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
if (check_opt->quick)
param.opt_rep_quick++;
param.sort_buffer_length= check_opt->sort_buffer_size;
- while ((error=repair(thd,param,0)))
+ start_records=file->state->records;
+ while ((error=repair(thd,param,0)) && param.retry_repair)
{
+ param.retry_repair=0;
if (param.retry_without_quick && param.opt_rep_quick)
{
param.opt_rep_quick=0;
@@ -438,6 +441,14 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
}
break;
}
+ if (!error && start_records != file->state->records)
+ {
+ char llbuff[22],llbuff2[22];
+ sql_print_error("Warning: Found %s of %s rows from %s",
+ llstr(file->state->records, llbuff),
+ llstr(start_records, llbuff2),
+ table->path);
+ }
return error;
}
@@ -461,7 +472,7 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
{
int error=0;
- bool optimize_done= !optimize;
+ bool optimize_done= !optimize, statistics_done=0;
char fixed_name[FN_REFLEN];
const char *old_proc_info=thd->proc_info;
MYISAM_SHARE* share = file->s;
@@ -487,11 +498,13 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
{
param.testflag|= T_STATISTICS; // We get this for free
thd->proc_info="Repair by sorting";
+ statistics_done=1;
error = mi_repair_by_sort(&param, file, fixed_name, param.opt_rep_quick);
}
else
{
thd->proc_info="Repair with keycache";
+ param.testflag &= ~T_REP_BY_SORT;
error= mi_repair(&param, file, fixed_name, param.opt_rep_quick);
}
}
@@ -504,7 +517,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
thd->proc_info="Sorting index";
error=mi_sort_index(&param,file,fixed_name);
}
- if ((param.testflag & T_STATISTICS) &&
+ if (!statistics_done && (param.testflag & T_STATISTICS) &&
(share->state.changed & STATE_NOT_ANALYZED))
{
optimize_done=1;
@@ -525,7 +538,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
if (file->s->base.auto_key)
update_auto_increment_key(&param, file, 1);
error = update_state_info(&param, file,
- UPDATE_TIME |
+ UPDATE_TIME | UPDATE_OPEN_COUNT |
(param.testflag & T_STATISTICS ?
UPDATE_STAT : 0));
info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
@@ -536,48 +549,6 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
mi_mark_crashed(file);
file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
}
- if (!error)
- {
- if (param.out_flag & (O_NEW_DATA | O_NEW_INDEX))
- {
- bool in_auto_repair;
- /*
- We have to close all instances of this file to ensure that we can
- do the rename safely on all operating system and to ensure that
- all threads are using the new version.
- */
- thd->proc_info="renaming file";
- VOID(pthread_mutex_lock(&LOCK_open));
- if (!(in_auto_repair = (table->table_cache_key == 0)))
- {
- if (close_cached_table(thd,table))
- error=1;
- }
- else
- {
- if (param.out_flag & O_NEW_DATA)
- my_close(file->dfile,MYF(0));
- if (param.out_flag & O_NEW_INDEX)
- my_close(file->s->kfile,MYF(0));
- }
- if (param.out_flag & O_NEW_DATA)
- error|=change_to_newfile(fixed_name,MI_NAME_DEXT,
- DATA_TMP_EXT, 0,
- (param.testflag & T_BACKUP_DATA ?
- MYF(MY_REDEL_MAKE_BACKUP): MYF(0)));
- if (param.out_flag & O_NEW_INDEX)
- error|=change_to_newfile(fixed_name,MI_NAME_IEXT,
- INDEX_TMP_EXT, 0, MYF(0));
- if (in_auto_repair)
- {
- if ((param.out_flag & O_NEW_DATA) && mi_open_datafile(file,file->s))
- error=1;
- if ((param.out_flag & O_NEW_DATA) && mi_open_keyfile(file->s))
- error=1;
- }
- VOID(pthread_mutex_unlock(&LOCK_open));
- }
- }
thd->proc_info=old_proc_info;
DBUG_RETURN(error ? HA_ADMIN_FAILED :
!optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
@@ -634,8 +605,7 @@ bool ha_myisam::check_and_repair(THD *thd)
if (mi_is_crashed(file) || check(thd, &check_opt))
{
sql_print_error("Warning: Recovering table: %s",table->path);
- if (check_opt.retry_without_quick)
- check_opt.quick=0;
+ check_opt.quick= !check_opt.retry_without_quick;
check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ?
T_BACKUP_DATA : 0) |
(!(myisam_recover_options & HA_RECOVER_FORCE) ?
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 87c94c22169..e4257f84459 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -889,6 +889,24 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
continue;
}
+ /* Close all instances of the table to allow repair to rename files */
+ if (open_for_modify && table->table->version)
+ {
+ pthread_mutex_lock(&LOCK_open);
+ mysql_lock_abort(thd,table->table);
+ while (remove_table_from_cache(thd, table->table->table_cache_key,
+ table->table->real_name) &&
+ ! thd->killed)
+ {
+ dropping_tables++;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ dropping_tables--;
+ }
+ pthread_mutex_unlock(&LOCK_open);
+ if (thd->killed)
+ goto err;
+ }
+
int result_code = (table->table->file->*operator_func)(thd, check_opt);
packet->length(0);
net_store_data(packet, table_name);
@@ -933,7 +951,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
break;
}
if (fatal_error)
- table->table->flush_version=0; // Force close of table
+ table->table->version=0; // Force close of table
close_thread_tables(thd);
if (my_net_write(&thd->net, (char*) packet->ptr(),
packet->length()))