mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Fixes for automatic recover of MyISAM tables
Docs/manual.texi: Update of automatic recover of MyISAM tables myisam/mi_check.c: Let the repair function rename files; This made the rest of the recover code simpler. myisam/mi_page.c: More debug information myisam/myisamchk.c: Addapt to new mi_check code; Fixed bug when a recover on RAID tables where aborted. mysys/my_winthread.c: Portability fix sql/ha_myisam.cc: Fix for automatic recover sql/sql_table.cc: Close all instances of table before running recover / optimize
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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(¶m->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= ¶m->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 */
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(¶m);
|
||||
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 ¶m, 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 ¶m, 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(¶m, file, fixed_name, param.opt_rep_quick);
|
||||
}
|
||||
else
|
||||
{
|
||||
thd->proc_info="Repair with keycache";
|
||||
param.testflag &= ~T_REP_BY_SORT;
|
||||
error= mi_repair(¶m, file, fixed_name, param.opt_rep_quick);
|
||||
}
|
||||
}
|
||||
@@ -504,7 +517,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK ¶m, bool optimize)
|
||||
thd->proc_info="Sorting index";
|
||||
error=mi_sort_index(¶m,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 ¶m, bool optimize)
|
||||
if (file->s->base.auto_key)
|
||||
update_auto_increment_key(¶m, file, 1);
|
||||
error = update_state_info(¶m, 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 ¶m, 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) ?
|
||||
|
||||
@@ -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()))
|
||||
|
||||
Reference in New Issue
Block a user