Commit 3655cefc authored by Monty's avatar Monty

MDEV-33813 ERROR 1021 (HY000): Disk full (./org/test1.MAI); waiting for someone to free some space

Fixed that internal temporary tables are not waiting for freed disk space.

Other things:
- 'kill id' will now kill a query waiting for free disk space instantly.
  Before it could take up to 60 seconds for the kill would be noticed.
- Fixed that sorting one index is not using MY_WAIT_IF_FULL for temp files.
- Fixed bug where share->write_flag set MY_WAIT_IF_FULL for temp files.

It is quite hard to do a test case for this. Instead I tested all
combinations interactively.
parent 33af5575
......@@ -652,6 +652,7 @@ extern size_t my_fwrite(FILE *stream,const uchar *Buffer,size_t Count,
myf MyFlags);
extern my_off_t my_fseek(FILE *stream,my_off_t pos,int whence,myf MyFlags);
extern my_off_t my_ftell(FILE *stream,myf MyFlags);
extern void (*my_sleep_for_space)(unsigned int seconds);
/* implemented in my_memmem.c */
extern void *my_memmem(const void *haystack, size_t haystacklen,
......
......@@ -112,6 +112,13 @@ void init_glob_errs()
}
#endif
static void my_space_sleep(uint seconds)
{
sleep(seconds);
}
void (*my_sleep_for_space)(uint seconds)= my_space_sleep;
void wait_for_free_space(const char *filename, int errors)
{
if (errors == 0)
......@@ -123,7 +130,7 @@ void wait_for_free_space(const char *filename, int errors)
MYF(ME_BELL | ME_ERROR_LOG | ME_WARNING),
MY_WAIT_FOR_USER_TO_FIX_PANIC,
MY_WAIT_GIVE_USER_A_MESSAGE * MY_WAIT_FOR_USER_TO_FIX_PANIC );
(void) sleep(MY_WAIT_FOR_USER_TO_FIX_PANIC);
my_sleep_for_space(MY_WAIT_FOR_USER_TO_FIX_PANIC);
}
const char **get_global_errmsgs(int nr __attribute__((unused)))
......
......@@ -4880,6 +4880,9 @@ static int init_server_components()
error_handler_hook= my_message_sql;
proc_info_hook= set_thd_stage_info;
/* Set up hook to handle disk full */
my_sleep_for_space= mariadb_sleep_for_space;
/*
Print source revision hash, as one of the first lines, if not the
first in error log, for troubleshooting and debugging purposes
......@@ -9216,6 +9219,7 @@ PSI_stage_info stage_user_lock= { 0, "User lock", 0};
PSI_stage_info stage_user_sleep= { 0, "User sleep", 0};
PSI_stage_info stage_verifying_table= { 0, "Verifying table", 0};
PSI_stage_info stage_waiting_for_delay_list= { 0, "Waiting for delay_list", 0};
PSI_stage_info stage_waiting_for_disk_space= {0, "Waiting for someone to free space", 0};
PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log= { 0, "Waiting for GTID to be written to binary log", 0};
PSI_stage_info stage_waiting_for_handler_insert= { 0, "Waiting for handler insert", 0};
PSI_stage_info stage_waiting_for_handler_lock= { 0, "Waiting for handler lock", 0};
......
......@@ -644,6 +644,7 @@ extern PSI_stage_info stage_user_sleep;
extern PSI_stage_info stage_verifying_table;
extern PSI_stage_info stage_waiting_for_ddl;
extern PSI_stage_info stage_waiting_for_delay_list;
extern PSI_stage_info stage_waiting_for_disk_space;
extern PSI_stage_info stage_waiting_for_flush;
extern PSI_stage_info stage_waiting_for_gtid_to_be_written_to_binary_log;
extern PSI_stage_info stage_waiting_for_handler_insert;
......
......@@ -8323,6 +8323,34 @@ wait_for_commit::unregister_wait_for_prior_commit2()
mysql_mutex_unlock(&LOCK_wait_commit);
}
/*
Wait # seconds or until someone sends a signal (through kill)
Note that this must have same prototype as my_sleep_for_space()
*/
C_MODE_START
void mariadb_sleep_for_space(unsigned int seconds)
{
THD *thd= current_thd;
PSI_stage_info old_stage;
if (!thd)
{
sleep(seconds);
return;
}
mysql_mutex_lock(&thd->LOCK_wakeup_ready);
thd->ENTER_COND(&thd->COND_wakeup_ready, &thd->LOCK_wakeup_ready,
&stage_waiting_for_disk_space, &old_stage);
if (!thd->killed)
mysql_cond_wait(&thd->COND_wakeup_ready, &thd->LOCK_wakeup_ready);
thd->EXIT_COND(&old_stage);
return;
}
C_MODE_END
bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
ulonglong incr)
......
......@@ -8185,6 +8185,9 @@ extern THD_list server_threads;
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps,
uint field_count);
C_MODE_START
void mariadb_sleep_for_space(unsigned int seconds);
C_MODE_END
#endif /* MYSQL_SERVER */
#endif /* SQL_CLASS_INCLUDED */
......@@ -3390,7 +3390,7 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
length= page.size;
bzero(buff+length,keyinfo->block_length-length);
if (write_page(share, new_file, buff, keyinfo->block_length,
new_page_pos, MYF(MY_NABP | MY_WAIT_IF_FULL)))
new_page_pos, MYF(MY_NABP | MY_WAIT_IF_FULL) & param->myf_rw))
{
_ma_check_print_error(param,"Can't write indexblock, error: %d",my_errno);
goto err;
......
......@@ -601,6 +601,20 @@ uint _ma_file_callback_to_id(void *callback_data)
return share ? share->id : 0;
}
/*
Disable MY_WAIT_IF_FULL flag for temporary tables
Temporary tables does not have MY_WAIT_IF_FULL in share->write_flags
*/
uint _ma_write_flags_callback(void *callback_data, myf flags)
{
MARIA_SHARE *share= (MARIA_SHARE*) callback_data;
if (share)
flags&= ~(~share->write_flag & MY_WAIT_IF_FULL);
return flags;
}
/**
@brief flushes the data and/or index file of a table
......
......@@ -172,7 +172,6 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share,
mysql_mutex_lock(&share->intern_lock);
info.read_record= share->read_record;
share->reopen++;
share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
if (share->options & HA_OPTION_READ_ONLY_DATA)
{
info.lock_type=F_RDLCK;
......@@ -987,6 +986,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags,
share->options|= HA_OPTION_READ_ONLY_DATA;
share->is_log_table= FALSE;
share->write_flag=MYF(MY_NABP | MY_WAIT_IF_FULL);
if (open_flags & HA_OPEN_TMP_TABLE || share->options & HA_OPTION_TMP_TABLE)
{
share->options|= HA_OPTION_TMP_TABLE;
......
......@@ -687,6 +687,8 @@ static my_bool pagecache_fwrite(PAGECACHE *pagecache,
/* FIXME: ENGINE=Aria occasionally writes uninitialized data */
__msan_unpoison(args.page, pagecache->block_size);
#endif
/* Reset MY_WAIT_IF_FULL for temporary tables */
flags= _ma_write_flags_callback(filedesc->callback_data, flags);
res= (int)my_pwrite(filedesc->file, args.page, pagecache->block_size,
((my_off_t) pageno << pagecache->shift), flags);
(*filedesc->post_write_hook)(res, &args);
......
......@@ -1745,6 +1745,7 @@ extern my_bool ma_yield_and_check_if_killed(MARIA_HA *info, int inx);
extern my_bool ma_killed_standalone(MARIA_HA *);
extern uint _ma_file_callback_to_id(void *callback_data);
extern uint _ma_write_flags_callback(void *callback_data, myf flags);
extern void free_maria_share(MARIA_SHARE *share);
static inline void unmap_file(MARIA_HA *info __attribute__((unused)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment