Fixed recovery problem in Aria where bitmap had wrong information after recovery.
LP#619731: Aria recovery corruption "Page 1: Row: 1 has an extent with wrong information in bitmap storage/maria/ma_bitmap.c: Don't send broadcast if no one is waiting for it storage/maria/ma_blockrec.c: Don't update bitmap if the page is not in the dirty_page list (or LSN is after checkpoint start) Fixes the case where we have in the log redo_free_block followed by another redo entry for the same page which is ignored. Also fixed that _ma_apply_redo_insert_row_blobs() doesn't update the bitmap in similar circumstances. storage/maria/ma_blockrec.h: Updated prototype storage/maria/ma_check.c: Added printing of bitmap information if used with maria_chk -vvv (for debugging) storage/maria/ma_recovery.c: Updated call parameters to _ma_apply_redo_free_blocks().
This commit is contained in:
parent
427c6c78de
commit
1e0b42d91f
@ -399,7 +399,8 @@ my_bool _ma_bitmap_flush_all(MARIA_SHARE *share)
|
||||
become false, wake them up.
|
||||
*/
|
||||
DBUG_PRINT("info", ("bitmap flusher waking up others"));
|
||||
pthread_cond_broadcast(&bitmap->bitmap_cond);
|
||||
if (bitmap->flush_all_requested)
|
||||
pthread_cond_broadcast(&bitmap->bitmap_cond);
|
||||
}
|
||||
pthread_mutex_unlock(&bitmap->bitmap_lock);
|
||||
DBUG_RETURN(res);
|
||||
@ -465,7 +466,8 @@ void _ma_bitmap_unlock(MARIA_SHARE *share)
|
||||
bitmap->flush_all_requested--;
|
||||
bitmap->non_flushable= 0;
|
||||
pthread_mutex_unlock(&bitmap->bitmap_lock);
|
||||
pthread_cond_broadcast(&bitmap->bitmap_cond);
|
||||
if (bitmap->flush_all_requested > 0)
|
||||
pthread_cond_broadcast(&bitmap->bitmap_cond);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -6485,7 +6485,13 @@ err:
|
||||
@param info Maria handler
|
||||
@param header Header (without FILEID)
|
||||
|
||||
@note It marks the pages free in the bitmap
|
||||
Mark the pages free in the bitmap.
|
||||
|
||||
We have to check against _ma_redo_not_needed_for_page()
|
||||
to guard against the case where we first clear a block and after
|
||||
that insert new data into the blocks. If we would unconditionally
|
||||
clear the bitmap here, future changes would be ignored for the page
|
||||
if it's not in the dirty list (ie, it would be flushed).
|
||||
|
||||
@return Operation status
|
||||
@retval 0 OK
|
||||
@ -6494,19 +6500,25 @@ err:
|
||||
|
||||
uint _ma_apply_redo_free_blocks(MARIA_HA *info,
|
||||
LSN lsn __attribute__((unused)),
|
||||
LSN redo_lsn,
|
||||
const uchar *header)
|
||||
{
|
||||
MARIA_SHARE *share= info->s;
|
||||
uint ranges;
|
||||
uint16 sid;
|
||||
DBUG_ENTER("_ma_apply_redo_free_blocks");
|
||||
|
||||
share->state.changed|= (STATE_CHANGED | STATE_NOT_ZEROFILLED |
|
||||
STATE_NOT_MOVABLE);
|
||||
|
||||
sid= fileid_korr(header);
|
||||
header+= FILEID_STORE_SIZE;
|
||||
ranges= pagerange_korr(header);
|
||||
header+= PAGERANGE_STORE_SIZE;
|
||||
DBUG_ASSERT(ranges > 0);
|
||||
|
||||
/** @todo leave bitmap lock to the bitmap code... */
|
||||
pthread_mutex_lock(&share->bitmap.bitmap_lock);
|
||||
while (ranges--)
|
||||
{
|
||||
my_bool res;
|
||||
@ -6523,18 +6535,22 @@ uint _ma_apply_redo_free_blocks(MARIA_HA *info,
|
||||
|
||||
DBUG_PRINT("info", ("page: %lu pages: %u", (long) page, page_range));
|
||||
|
||||
/** @todo leave bitmap lock to the bitmap code... */
|
||||
pthread_mutex_lock(&share->bitmap.bitmap_lock);
|
||||
res= _ma_bitmap_reset_full_page_bits(info, &share->bitmap, start_page,
|
||||
page_range);
|
||||
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
|
||||
if (res)
|
||||
for ( ; page_range-- ; start_page++)
|
||||
{
|
||||
_ma_mark_file_crashed(share);
|
||||
DBUG_ASSERT(0);
|
||||
DBUG_RETURN(res);
|
||||
if (_ma_redo_not_needed_for_page(sid, redo_lsn, start_page, FALSE))
|
||||
continue;
|
||||
res= _ma_bitmap_reset_full_page_bits(info, &share->bitmap, start_page,
|
||||
1);
|
||||
if (res)
|
||||
{
|
||||
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
|
||||
_ma_mark_file_crashed(share);
|
||||
DBUG_ASSERT(0);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
@ -6764,7 +6780,7 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info,
|
||||
PAGECACHE_LOCK_WRITE_UNLOCK,
|
||||
PAGECACHE_UNPIN, LSN_IMPOSSIBLE,
|
||||
LSN_IMPOSSIBLE, 0, FALSE);
|
||||
continue;
|
||||
goto fix_bitmap;
|
||||
}
|
||||
DBUG_ASSERT((found_page_type == (uchar) BLOB_PAGE) ||
|
||||
(found_page_type == (uchar) UNALLOCATED_PAGE));
|
||||
@ -6799,14 +6815,16 @@ uint _ma_apply_redo_insert_row_blobs(MARIA_HA *info,
|
||||
unlock_method, unpin_method,
|
||||
PAGECACHE_WRITE_DELAY, 0, LSN_IMPOSSIBLE))
|
||||
goto err;
|
||||
}
|
||||
|
||||
fix_bitmap:
|
||||
/** @todo leave bitmap lock to the bitmap code... */
|
||||
pthread_mutex_lock(&share->bitmap.bitmap_lock);
|
||||
res= _ma_bitmap_set_full_page_bits(info, &share->bitmap, start_page,
|
||||
page_range);
|
||||
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
|
||||
if (res)
|
||||
goto err;
|
||||
pthread_mutex_lock(&share->bitmap.bitmap_lock);
|
||||
res= _ma_bitmap_set_full_page_bits(info, &share->bitmap, page,
|
||||
1);
|
||||
pthread_mutex_unlock(&share->bitmap.bitmap_lock);
|
||||
if (res)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
*first_page= first_page2;
|
||||
|
@ -235,7 +235,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
|
||||
uint _ma_apply_redo_purge_row_head_or_tail(MARIA_HA *info, LSN lsn,
|
||||
uint page_type,
|
||||
const uchar *header);
|
||||
uint _ma_apply_redo_free_blocks(MARIA_HA *info, LSN lsn,
|
||||
uint _ma_apply_redo_free_blocks(MARIA_HA *info, LSN lsn, LSN rec_lsn,
|
||||
const uchar *header);
|
||||
uint _ma_apply_redo_free_head_or_tail(MARIA_HA *info, LSN lsn,
|
||||
const uchar *header);
|
||||
|
@ -100,6 +100,9 @@ static my_bool _ma_flush_table_files_before_swap(HA_CHECK *param,
|
||||
static TrID max_trid_in_system(void);
|
||||
static void _ma_check_print_not_visible_error(HA_CHECK *param, TrID used_trid);
|
||||
void retry_if_quick(MARIA_SORT_PARAM *param, int error);
|
||||
static void print_bitmap_description(MARIA_SHARE *share,
|
||||
pgcache_page_no_t page,
|
||||
uchar *buff);
|
||||
|
||||
|
||||
/* Initialize check param with default values */
|
||||
@ -1842,6 +1845,8 @@ static int check_block_record(HA_CHECK *param, MARIA_HA *info, int extend,
|
||||
}
|
||||
param->used+= block_size;
|
||||
param->link_used+= block_size;
|
||||
if (param->verbose > 2)
|
||||
print_bitmap_description(share, page, bitmap_buff);
|
||||
continue;
|
||||
}
|
||||
/* Skip pages marked as empty in bitmap */
|
||||
@ -2177,12 +2182,17 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
|
||||
llstr(param->del_length, llbuff2));
|
||||
printf("Empty space: %12s Linkdata: %10s\n",
|
||||
llstr(param->empty, llbuff),llstr(param->link_used, llbuff2));
|
||||
if (param->lost)
|
||||
printf("Lost space: %12s", llstr(param->lost, llbuff));
|
||||
if (param->max_found_trid)
|
||||
if (share->data_file_type == BLOCK_RECORD)
|
||||
{
|
||||
printf("Max trans. id: %11s\n",
|
||||
llstr(param->max_found_trid, llbuff));
|
||||
printf("Full pages: %12s Tail count: %12s\n",
|
||||
llstr(param->full_page_count, llbuff),
|
||||
llstr(param->tail_count, llbuff2));
|
||||
printf("Lost space: %12s\n", llstr(param->lost, llbuff));
|
||||
if (param->max_found_trid)
|
||||
{
|
||||
printf("Max trans. id: %11s\n",
|
||||
llstr(param->max_found_trid, llbuff));
|
||||
}
|
||||
}
|
||||
}
|
||||
my_free(record,MYF(0));
|
||||
@ -6799,3 +6809,46 @@ void retry_if_quick(MARIA_SORT_PARAM *sort_param, int error)
|
||||
param->testflag|=T_RETRY_WITHOUT_QUICK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Print information about bitmap page */
|
||||
|
||||
static void print_bitmap_description(MARIA_SHARE *share,
|
||||
pgcache_page_no_t page,
|
||||
uchar *bitmap_data)
|
||||
{
|
||||
uchar *pos, *end;
|
||||
MARIA_FILE_BITMAP *bitmap= &share->bitmap;
|
||||
uint count=0, dot_printed= 0;
|
||||
char buff[80], last[80];
|
||||
|
||||
printf("Bitmap page %lu\n", (ulong) page);
|
||||
page++;
|
||||
last[0]=0;
|
||||
for (pos= bitmap_data, end= pos+ bitmap->used_size ; pos < end ; pos+= 6)
|
||||
{
|
||||
ulonglong bits= uint6korr(pos); /* 6 bytes = 6*8/3= 16 patterns */
|
||||
uint i;
|
||||
|
||||
for (i= 0; i < 16 ; i++, bits>>= 3)
|
||||
{
|
||||
if (count > 60)
|
||||
{
|
||||
buff[count]= 0;
|
||||
if (strcmp(buff, last))
|
||||
{
|
||||
memcpy(last, buff, count+1);
|
||||
printf("%8lu: %s\n", (ulong) page - count, buff);
|
||||
dot_printed= 0;
|
||||
}
|
||||
else if (!(dot_printed++))
|
||||
printf("...\n");
|
||||
count= 0;
|
||||
}
|
||||
buff[count++]= '0' + (uint) (bits & 7);
|
||||
page++;
|
||||
}
|
||||
}
|
||||
buff[count]= 0;
|
||||
printf("%8lu: %s\n", (ulong) page - count, buff);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
|
@ -1643,8 +1643,8 @@ prototype_redo_exec_hook(REDO_FREE_BLOCKS)
|
||||
}
|
||||
|
||||
buff= log_record_buffer.str;
|
||||
if (_ma_apply_redo_free_blocks(info, current_group_end_lsn,
|
||||
buff + FILEID_STORE_SIZE))
|
||||
if (_ma_apply_redo_free_blocks(info, current_group_end_lsn, rec->lsn,
|
||||
buff))
|
||||
goto end;
|
||||
error= 0;
|
||||
end:
|
||||
@ -3015,10 +3015,11 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const
|
||||
page= page_korr(rec->header + FILEID_STORE_SIZE);
|
||||
llstr(page, llbuf);
|
||||
break;
|
||||
case LOGREC_REDO_FREE_BLOCKS:
|
||||
/*
|
||||
For REDO_FREE_BLOCKS, no need to look at dirty pages list: it does not
|
||||
read data pages, only reads/modifies bitmap page(s) which is cheap.
|
||||
We are checking against the dirty pages in _ma_apply_redo_free_blocks()
|
||||
*/
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user