Commit e6bdb11f authored by unknown's avatar unknown

Use LOGREC_REDO_NEW_ROW_HEAD and LOGREC_REDO_NEW_ROW_TAIL when writing to a new page

This makes REDO safer as we then know when it's safe to ignore HA_ERR_WRONG_CRC from page cache
Removed not used logged data for LOGREC_UNDO_ROW_DELETE and LOGREC_UNDO_ROW_UPDATE


storage/maria/ma_blockrec.c:
  Use LOGREC_REDO_NEW_ROW_HEAD and LOGREC_REDO_NEW_ROW_TAIL when writing to a new page
  This makes REDO safer as we then know when it's safe to ignore HA_ERR_WRONG_CRC from page cache
storage/maria/ma_blockrec.h:
  Fixed prototype
storage/maria/ma_key_recover.c:
  Removed not used logged data for LOGREC_UNDO_ROW_DELETE and LOGREC_UNDO_ROW_UPDATE
storage/maria/ma_loghandler.c:
  Use LOGREC_REDO_NEW_ROW_HEAD and LOGREC_REDO_NEW_ROW_TAIL when writing to a new page
storage/maria/ma_loghandler.h:
  Added LOGREC_REDO_NEW_ROW_HEAD and LOGREC_REDO_NEW_ROW_TAIL
storage/maria/ma_recovery.c:
  Added support for LOGREC_REDO_NEW_ROW_HEAD and LOGREC_REDO_NEW_ROW_TAIL
parent 7e7c534b
...@@ -1777,7 +1777,9 @@ static my_bool write_tail(MARIA_HA *info, ...@@ -1777,7 +1777,9 @@ static my_bool write_tail(MARIA_HA *info,
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) row_pos.data; log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) row_pos.data;
log_array[TRANSLOG_INTERNAL_PARTS + 1].length= length; log_array[TRANSLOG_INTERNAL_PARTS + 1].length= length;
if (translog_write_record(&lsn, LOGREC_REDO_INSERT_ROW_TAIL, if (translog_write_record(&lsn,
(block_is_read ? LOGREC_REDO_INSERT_ROW_TAIL :
LOGREC_REDO_NEW_ROW_TAIL),
info->trn, info, sizeof(log_data) + length, info->trn, info, sizeof(log_data) + length,
TRANSLOG_INTERNAL_PARTS + 2, log_array, TRANSLOG_INTERNAL_PARTS + 2, log_array,
log_data, NULL)) log_data, NULL))
...@@ -2830,7 +2832,11 @@ static my_bool write_block_record(MARIA_HA *info, ...@@ -2830,7 +2832,11 @@ static my_bool write_block_record(MARIA_HA *info,
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data); log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) row_pos->data; log_array[TRANSLOG_INTERNAL_PARTS + 1].str= (char*) row_pos->data;
log_array[TRANSLOG_INTERNAL_PARTS + 1].length= head_length; log_array[TRANSLOG_INTERNAL_PARTS + 1].length= head_length;
if (translog_write_record(&lsn, LOGREC_REDO_INSERT_ROW_HEAD, info->trn, if (translog_write_record(&lsn,
head_block_is_read ?
LOGREC_REDO_INSERT_ROW_HEAD :
LOGREC_REDO_NEW_ROW_HEAD,
info->trn,
info, sizeof(log_data) + head_length, info, sizeof(log_data) + head_length,
TRANSLOG_INTERNAL_PARTS + 2, log_array, TRANSLOG_INTERNAL_PARTS + 2, log_array,
log_data, NULL)) log_data, NULL))
...@@ -5721,17 +5727,22 @@ my_bool write_hook_for_file_id(enum translog_record_type type ...@@ -5721,17 +5727,22 @@ my_bool write_hook_for_file_id(enum translog_record_type type
***************************************************************************/ ***************************************************************************/
/* /*
Apply LOGREC_REDO_INSERT_ROW_HEAD & LOGREC_REDO_INSERT_ROW_TAIL Apply changes to head and tail pages
SYNOPSIS SYNOPSIS
_ma_apply_redo_insert_row_head_or_tail() _ma_apply_redo_insert_row_head_or_tail()
info Maria handler info Maria handler
lsn LSN to put on page lsn LSN to put on page
page_type HEAD_PAGE or TAIL_PAGE page_type HEAD_PAGE or TAIL_PAGE
new_page True if this is first entry on page
header Header (without FILEID) header Header (without FILEID)
data Data to be put on page data Data to be put on page
data_length Length of data data_length Length of data
NOTE
Handles LOGREC_REDO_INSERT_ROW_HEAD, LOGREC_REDO_INSERT_ROW_TAIL
LOGREC_REDO_NEW_ROW_HEAD and LOGREC_REDO_NEW_ROW_TAIL
RETURN RETURN
0 ok 0 ok
# Error number # Error number
...@@ -5739,6 +5750,7 @@ my_bool write_hook_for_file_id(enum translog_record_type type ...@@ -5739,6 +5750,7 @@ my_bool write_hook_for_file_id(enum translog_record_type type
uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
uint page_type, uint page_type,
my_bool new_page,
const uchar *header, const uchar *header,
const uchar *data, const uchar *data,
size_t data_length) size_t data_length)
...@@ -5783,8 +5795,8 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -5783,8 +5795,8 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
unlock_method= PAGECACHE_LOCK_WRITE; unlock_method= PAGECACHE_LOCK_WRITE;
unpin_method= PAGECACHE_PIN; unpin_method= PAGECACHE_PIN;
DBUG_ASSERT(rownr == 0); DBUG_ASSERT(rownr == 0 && new_page);
if (rownr != 0) if (rownr != 0 || !new_page)
goto crashed_file; goto crashed_file;
buff= info->keyread_buff; buff= info->keyread_buff;
...@@ -5808,8 +5820,8 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -5808,8 +5820,8 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
if (!buff) if (!buff)
{ {
/* Skip errors when reading outside of file and uninitialized pages */ /* Skip errors when reading outside of file and uninitialized pages */
if (my_errno != HA_ERR_FILE_TOO_SHORT && if (!new_page || (my_errno != HA_ERR_FILE_TOO_SHORT &&
my_errno != HA_ERR_WRONG_CRC) my_errno != HA_ERR_WRONG_CRC))
goto err; goto err;
/* Create new page */ /* Create new page */
buff= pagecache_block_link_to_buffer(page_link.link); buff= pagecache_block_link_to_buffer(page_link.link);
...@@ -5834,8 +5846,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -5834,8 +5846,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
This is a page that has been freed before and now should be This is a page that has been freed before and now should be
changed to new type. changed to new type.
*/ */
if (((buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != BLOB_PAGE && if (!new_page)
(buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) != UNALLOCATED_PAGE))
goto crashed_file; goto crashed_file;
make_empty_page(info, buff, page_type, 0); make_empty_page(info, buff, page_type, 0);
empty_space= block_size - PAGE_HEADER_SIZE - PAGE_SUFFIX_SIZE; empty_space= block_size - PAGE_HEADER_SIZE - PAGE_SUFFIX_SIZE;
...@@ -5850,6 +5861,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, ...@@ -5850,6 +5861,7 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
uint max_entry= (uint) buff[DIR_COUNT_OFFSET]; uint max_entry= (uint) buff[DIR_COUNT_OFFSET];
uint length; uint length;
DBUG_ASSERT(!new_page);
dir= dir_entry_pos(buff, block_size, rownr); dir= dir_entry_pos(buff, block_size, rownr);
empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET);
......
...@@ -222,6 +222,7 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data, ...@@ -222,6 +222,7 @@ void _ma_print_bitmap(MARIA_FILE_BITMAP *bitmap, uchar *data,
uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn,
uint page_type, uint page_type,
my_bool new_page,
const uchar *header, const uchar *header,
const uchar *data, const uchar *data,
size_t data_length); size_t data_length);
......
...@@ -119,21 +119,6 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn, ...@@ -119,21 +119,6 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn,
page_store(log_pos + KEY_NR_STORE_SIZE, page); page_store(log_pos + KEY_NR_STORE_SIZE, page);
log_pos+= KEY_NR_STORE_SIZE + PAGE_STORE_SIZE; log_pos+= KEY_NR_STORE_SIZE + PAGE_STORE_SIZE;
} }
if (undo_type == LOGREC_UNDO_ROW_DELETE ||
undo_type == LOGREC_UNDO_ROW_UPDATE)
{
/*
We need to store position to the row that was inserted to be
able to regenerate keys
*/
MARIA_RECORD_POS rowid= info->cur_row.lastpos;
ulonglong page= ma_recordpos_to_page(rowid);
uint dir_entry= ma_recordpos_to_dir_entry(rowid);
page_store(log_pos, page);
dirpos_store(log_pos+ PAGE_STORE_SIZE, dir_entry);
log_pos+= PAGE_STORE_SIZE + DIRPOS_STORE_SIZE;
}
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data; log_array[TRANSLOG_INTERNAL_PARTS + 0].str= (char*) log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data); log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data);
......
...@@ -403,10 +403,17 @@ static LOG_DESC INIT_LOGREC_REDO_INSERT_ROW_TAIL= ...@@ -403,10 +403,17 @@ static LOG_DESC INIT_LOGREC_REDO_INSERT_ROW_TAIL=
write_hook_for_redo, NULL, 0, write_hook_for_redo, NULL, 0,
"redo_insert_row_tail", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL}; "redo_insert_row_tail", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL};
/* Use this entry next time we need to add a new entry */ static LOG_DESC INIT_LOGREC_REDO_NEW_ROW_HEAD=
static LOG_DESC INIT_LOGREC_REDO_NOT_USED= {LOGRECTYPE_VARIABLE_LENGTH, 0,
{LOGRECTYPE_VARIABLE_LENGTH, 0, 8, NULL, write_hook_for_redo, NULL, 0, FILEID_STORE_SIZE + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE, NULL,
"redo_insert_row_blob", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL}; write_hook_for_redo, NULL, 0,
"redo_new_row_head", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL};
static LOG_DESC INIT_LOGREC_REDO_NEW_ROW_TAIL=
{LOGRECTYPE_VARIABLE_LENGTH, 0,
FILEID_STORE_SIZE + PAGE_STORE_SIZE + DIRPOS_STORE_SIZE, NULL,
write_hook_for_redo, NULL, 0,
"redo_new_row_tail", LOGREC_NOT_LAST_IN_GROUP, NULL, NULL};
static LOG_DESC INIT_LOGREC_REDO_INSERT_ROW_BLOBS= static LOG_DESC INIT_LOGREC_REDO_INSERT_ROW_BLOBS=
{LOGRECTYPE_VARIABLE_LENGTH, 0, FILEID_STORE_SIZE, NULL, {LOGRECTYPE_VARIABLE_LENGTH, 0, FILEID_STORE_SIZE, NULL,
...@@ -594,8 +601,10 @@ void translog_table_init() ...@@ -594,8 +601,10 @@ void translog_table_init()
INIT_LOGREC_REDO_INSERT_ROW_HEAD; INIT_LOGREC_REDO_INSERT_ROW_HEAD;
log_record_type_descriptor[LOGREC_REDO_INSERT_ROW_TAIL]= log_record_type_descriptor[LOGREC_REDO_INSERT_ROW_TAIL]=
INIT_LOGREC_REDO_INSERT_ROW_TAIL; INIT_LOGREC_REDO_INSERT_ROW_TAIL;
log_record_type_descriptor[LOGREC_REDO_NOT_USED]= log_record_type_descriptor[LOGREC_REDO_NEW_ROW_HEAD]=
INIT_LOGREC_REDO_NOT_USED; INIT_LOGREC_REDO_NEW_ROW_HEAD;
log_record_type_descriptor[LOGREC_REDO_NEW_ROW_TAIL]=
INIT_LOGREC_REDO_NEW_ROW_TAIL;
log_record_type_descriptor[LOGREC_REDO_INSERT_ROW_BLOBS]= log_record_type_descriptor[LOGREC_REDO_INSERT_ROW_BLOBS]=
INIT_LOGREC_REDO_INSERT_ROW_BLOBS; INIT_LOGREC_REDO_INSERT_ROW_BLOBS;
log_record_type_descriptor[LOGREC_REDO_PURGE_ROW_HEAD]= log_record_type_descriptor[LOGREC_REDO_PURGE_ROW_HEAD]=
......
...@@ -105,7 +105,8 @@ enum translog_record_type ...@@ -105,7 +105,8 @@ enum translog_record_type
LOGREC_RESERVED_FOR_CHUNKS23= 0, LOGREC_RESERVED_FOR_CHUNKS23= 0,
LOGREC_REDO_INSERT_ROW_HEAD, LOGREC_REDO_INSERT_ROW_HEAD,
LOGREC_REDO_INSERT_ROW_TAIL, LOGREC_REDO_INSERT_ROW_TAIL,
LOGREC_REDO_NOT_USED, /* Reserver for next tag */ LOGREC_REDO_NEW_ROW_HEAD,
LOGREC_REDO_NEW_ROW_TAIL,
LOGREC_REDO_INSERT_ROW_BLOBS, LOGREC_REDO_INSERT_ROW_BLOBS,
LOGREC_REDO_PURGE_ROW_HEAD, LOGREC_REDO_PURGE_ROW_HEAD,
LOGREC_REDO_PURGE_ROW_TAIL, LOGREC_REDO_PURGE_ROW_TAIL,
......
...@@ -88,7 +88,9 @@ prototype_redo_exec_hook(INCOMPLETE_LOG); ...@@ -88,7 +88,9 @@ prototype_redo_exec_hook(INCOMPLETE_LOG);
prototype_redo_exec_hook_dummy(INCOMPLETE_GROUP); prototype_redo_exec_hook_dummy(INCOMPLETE_GROUP);
prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD); prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD);
prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL); prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL);
prototype_redo_exec_hook(REDO_INSERT_ROW_BLOBS); prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD);
prototype_redo_exec_hook(REDO_NEW_ROW_TAIL);
prototype_redo_exec_hook(REDO_NEW_ROW_BLOBS);
prototype_redo_exec_hook(REDO_PURGE_ROW_HEAD); prototype_redo_exec_hook(REDO_PURGE_ROW_HEAD);
prototype_redo_exec_hook(REDO_PURGE_ROW_TAIL); prototype_redo_exec_hook(REDO_PURGE_ROW_TAIL);
prototype_redo_exec_hook(REDO_FREE_HEAD_OR_TAIL); prototype_redo_exec_hook(REDO_FREE_HEAD_OR_TAIL);
...@@ -1312,6 +1314,10 @@ end: ...@@ -1312,6 +1314,10 @@ end:
return error; return error;
} }
/*
NOTE
This is called for REDO_INSERT_ROW_HEAD and READ_NEW_ROW_HEAD
*/
prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD) prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD)
{ {
...@@ -1353,6 +1359,8 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD) ...@@ -1353,6 +1359,8 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_HEAD)
buff= log_record_buffer.str; buff= log_record_buffer.str;
if (_ma_apply_redo_insert_row_head_or_tail(info, current_group_end_lsn, if (_ma_apply_redo_insert_row_head_or_tail(info, current_group_end_lsn,
HEAD_PAGE, HEAD_PAGE,
(rec->type ==
LOGREC_REDO_NEW_ROW_HEAD),
buff + FILEID_STORE_SIZE, buff + FILEID_STORE_SIZE,
buff + buff +
FILEID_STORE_SIZE + FILEID_STORE_SIZE +
...@@ -1368,6 +1376,10 @@ end: ...@@ -1368,6 +1376,10 @@ end:
return error; return error;
} }
/*
NOTE
This is called for REDO_INSERT_ROW_TAIL and READ_NEW_ROW_TAIL
*/
prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL) prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL)
{ {
...@@ -1388,6 +1400,8 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL) ...@@ -1388,6 +1400,8 @@ prototype_redo_exec_hook(REDO_INSERT_ROW_TAIL)
buff= log_record_buffer.str; buff= log_record_buffer.str;
if (_ma_apply_redo_insert_row_head_or_tail(info, current_group_end_lsn, if (_ma_apply_redo_insert_row_head_or_tail(info, current_group_end_lsn,
TAIL_PAGE, TAIL_PAGE,
(rec->type ==
LOGREC_REDO_NEW_ROW_TAIL),
buff + FILEID_STORE_SIZE, buff + FILEID_STORE_SIZE,
buff + buff +
FILEID_STORE_SIZE + FILEID_STORE_SIZE +
...@@ -2189,6 +2203,9 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply) ...@@ -2189,6 +2203,9 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply)
#define install_redo_exec_hook(R) \ #define install_redo_exec_hook(R) \
log_record_type_descriptor[LOGREC_ ## R].record_execute_in_redo_phase= \ log_record_type_descriptor[LOGREC_ ## R].record_execute_in_redo_phase= \
exec_REDO_LOGREC_ ## R; exec_REDO_LOGREC_ ## R;
#define install_redo_exec_hook_shared(R,S) \
log_record_type_descriptor[LOGREC_ ## R].record_execute_in_redo_phase= \
exec_REDO_LOGREC_ ## S;
#define install_undo_exec_hook(R) \ #define install_undo_exec_hook(R) \
log_record_type_descriptor[LOGREC_ ## R].record_execute_in_undo_phase= \ log_record_type_descriptor[LOGREC_ ## R].record_execute_in_undo_phase= \
exec_UNDO_LOGREC_ ## R; exec_UNDO_LOGREC_ ## R;
...@@ -2226,6 +2243,10 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply) ...@@ -2226,6 +2243,10 @@ static int run_redo_phase(LSN lsn, enum maria_apply_log_way apply)
install_undo_exec_hook(UNDO_KEY_INSERT); install_undo_exec_hook(UNDO_KEY_INSERT);
install_undo_exec_hook(UNDO_KEY_DELETE); install_undo_exec_hook(UNDO_KEY_DELETE);
install_undo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT); install_undo_exec_hook(UNDO_KEY_DELETE_WITH_ROOT);
/* REDO_NEW_ROW_HEAD shares entry with REDO_INSERT_ROW_HEAD */
install_redo_exec_hook_shared(REDO_NEW_ROW_HEAD, REDO_INSERT_ROW_HEAD);
/* REDO_NEW_ROW_TAIL shares entry with REDO_INSERT_ROW_TAIL */
install_redo_exec_hook_shared(REDO_NEW_ROW_TAIL, REDO_INSERT_ROW_TAIL);
current_group_end_lsn= LSN_IMPOSSIBLE; current_group_end_lsn= LSN_IMPOSSIBLE;
#ifndef DBUG_OFF #ifndef DBUG_OFF
...@@ -2612,6 +2633,8 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const ...@@ -2612,6 +2633,8 @@ static MARIA_HA *get_MARIA_HA_from_REDO_record(const
case LOGREC_REDO_INSERT_ROW_TAIL: case LOGREC_REDO_INSERT_ROW_TAIL:
case LOGREC_REDO_PURGE_ROW_HEAD: case LOGREC_REDO_PURGE_ROW_HEAD:
case LOGREC_REDO_PURGE_ROW_TAIL: case LOGREC_REDO_PURGE_ROW_TAIL:
case LOGREC_REDO_NEW_ROW_HEAD:
case LOGREC_REDO_NEW_ROW_TAIL:
llstr(page, llbuf); llstr(page, llbuf);
tprint(tracef, " For page %s of table of short id %u", llbuf, sid); tprint(tracef, " For page %s of table of short id %u", llbuf, sid);
break; break;
......
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