Commit c13f4091 authored by Jan Lindström's avatar Jan Lindström

MDEV-8815: InnoDB should refuse to start if crash recovery fails instead of asserting

Added error handling to crash recovery so that we stop instead of
asserting.
parent a4e59020
...@@ -275,7 +275,7 @@ recv_sys_var_init(void); ...@@ -275,7 +275,7 @@ recv_sys_var_init(void);
Empties the hash table of stored log records, applying them to appropriate Empties the hash table of stored log records, applying them to appropriate
pages. */ pages. */
UNIV_INTERN UNIV_INTERN
void dberr_t
recv_apply_hashed_log_recs( recv_apply_hashed_log_recs(
/*=======================*/ /*=======================*/
ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are
......
...@@ -442,9 +442,10 @@ recv_sys_init( ...@@ -442,9 +442,10 @@ recv_sys_init(
} }
/********************************************************//** /********************************************************//**
Empties the hash table when it has been fully processed. */ Empties the hash table when it has been fully processed.
@return DB_SUCCESS when successfull or DB_ERROR when fails. */
static static
void dberr_t
recv_sys_empty_hash(void) recv_sys_empty_hash(void)
/*=====================*/ /*=====================*/
{ {
...@@ -458,13 +459,15 @@ recv_sys_empty_hash(void) ...@@ -458,13 +459,15 @@ recv_sys_empty_hash(void)
" log records on it %lu\n", " log records on it %lu\n",
(ulong) recv_sys->n_addrs, (ulong) recv_sys->n_addrs,
(ulong) recv_max_parsed_page_no); (ulong) recv_max_parsed_page_no);
ut_error; return DB_ERROR;
} }
hash_table_free(recv_sys->addr_hash); hash_table_free(recv_sys->addr_hash);
mem_heap_empty(recv_sys->heap); mem_heap_empty(recv_sys->heap);
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512); recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512);
return DB_SUCCESS;
} }
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
...@@ -1779,9 +1782,10 @@ recv_read_in_area( ...@@ -1779,9 +1782,10 @@ recv_read_in_area(
/*******************************************************************//** /*******************************************************************//**
Empties the hash table of stored log records, applying them to appropriate Empties the hash table of stored log records, applying them to appropriate
pages. */ pages.
@return DB_SUCCESS when successfull or DB_ERROR when fails. */
UNIV_INTERN UNIV_INTERN
void dberr_t
recv_apply_hashed_log_recs( recv_apply_hashed_log_recs(
/*=======================*/ /*=======================*/
ibool allow_ibuf) /*!< in: if TRUE, also ibuf operations are ibool allow_ibuf) /*!< in: if TRUE, also ibuf operations are
...@@ -1798,6 +1802,7 @@ recv_apply_hashed_log_recs( ...@@ -1798,6 +1802,7 @@ recv_apply_hashed_log_recs(
ulint i; ulint i;
ibool has_printed = FALSE; ibool has_printed = FALSE;
mtr_t mtr; mtr_t mtr;
dberr_t err = DB_SUCCESS;
loop: loop:
mutex_enter(&(recv_sys->mutex)); mutex_enter(&(recv_sys->mutex));
...@@ -1931,13 +1936,15 @@ loop: ...@@ -1931,13 +1936,15 @@ loop:
recv_sys->apply_log_recs = FALSE; recv_sys->apply_log_recs = FALSE;
recv_sys->apply_batch_on = FALSE; recv_sys->apply_batch_on = FALSE;
recv_sys_empty_hash(); err = recv_sys_empty_hash();
if (has_printed) { if (has_printed) {
fprintf(stderr, "InnoDB: Apply batch completed\n"); fprintf(stderr, "InnoDB: Apply batch completed\n");
} }
mutex_exit(&(recv_sys->mutex)); mutex_exit(&(recv_sys->mutex));
return err;
} }
#else /* !UNIV_HOTBACKUP */ #else /* !UNIV_HOTBACKUP */
/*******************************************************************//** /*******************************************************************//**
...@@ -2258,7 +2265,6 @@ recv_report_corrupt_log( ...@@ -2258,7 +2265,6 @@ recv_report_corrupt_log(
if (!srv_force_recovery) { if (!srv_force_recovery) {
fputs("InnoDB: Set innodb_force_recovery" fputs("InnoDB: Set innodb_force_recovery"
" to ignore this error.\n", stderr); " to ignore this error.\n", stderr);
ut_error;
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -2281,9 +2287,11 @@ static ...@@ -2281,9 +2287,11 @@ static
ibool ibool
recv_parse_log_recs( recv_parse_log_recs(
/*================*/ /*================*/
ibool store_to_hash) /*!< in: TRUE if the records should be stored ibool store_to_hash, /*!< in: TRUE if the records should be stored
to the hash table; this is set to FALSE if just to the hash table; this is set to FALSE if just
debug checking is needed */ debug checking is needed */
dberr_t* err) /*!< out: DB_SUCCESS if successfull,
DB_ERROR if parsing fails. */
{ {
byte* ptr; byte* ptr;
byte* end_ptr; byte* end_ptr;
...@@ -2392,7 +2400,8 @@ loop: ...@@ -2392,7 +2400,8 @@ loop:
(ulint) type, space, (ulint) type, space,
(char*)(body + 2)); (char*)(body + 2));
ut_error; *err = DB_ERROR;
return(FALSE);
} }
} }
#endif #endif
...@@ -2688,17 +2697,18 @@ recv_scan_log_recs( ...@@ -2688,17 +2697,18 @@ recv_scan_log_recs(
if (log_crypt_block_maybe_encrypted(log_block, if (log_crypt_block_maybe_encrypted(log_block,
&log_crypt_err)) { &log_crypt_err)) {
/* Log block maybe encrypted */ /* Log block maybe encrypted finish processing*/
log_crypt_print_error(log_crypt_err); log_crypt_print_error(log_crypt_err);
*err = DB_ERROR; *err = DB_ERROR;
return (TRUE); return (TRUE);
} }
/* Crash if we encounter a garbage log block */ /* Stop if we encounter a garbage log block */
if (!srv_force_recovery) { if (!srv_force_recovery) {
fputs("InnoDB: Set innodb_force_recovery" fputs("InnoDB: Set innodb_force_recovery"
" to ignore this error.\n", stderr); " to ignore this error.\n", stderr);
ut_error; *err = DB_ERROR;
return (TRUE);
} }
break; break;
...@@ -2736,7 +2746,8 @@ recv_scan_log_recs( ...@@ -2736,7 +2746,8 @@ recv_scan_log_recs(
/* This is not really an error, but currently /* This is not really an error, but currently
we stop here in the debug version: */ we stop here in the debug version: */
ut_error; *err = DB_ERROR;
return (TRUE);
#endif #endif
break; break;
} }
...@@ -2802,7 +2813,8 @@ recv_scan_log_recs( ...@@ -2802,7 +2813,8 @@ recv_scan_log_recs(
" innodb_force_recovery" " innodb_force_recovery"
" to ignore this error.\n", " to ignore this error.\n",
stderr); stderr);
ut_error; *err = DB_ERROR;
return (TRUE);
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -2844,7 +2856,11 @@ recv_scan_log_recs( ...@@ -2844,7 +2856,11 @@ recv_scan_log_recs(
if (more_data && !recv_sys->found_corrupt_log) { if (more_data && !recv_sys->found_corrupt_log) {
/* Try to parse more log records */ /* Try to parse more log records */
recv_parse_log_recs(store_to_hash); recv_parse_log_recs(store_to_hash, err);
if (*err != DB_SUCCESS) {
return (TRUE);
}
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
if (store_to_hash if (store_to_hash
...@@ -2856,7 +2872,12 @@ recv_scan_log_recs( ...@@ -2856,7 +2872,12 @@ recv_scan_log_recs(
log yet: they would be produced by ibuf log yet: they would be produced by ibuf
operations */ operations */
recv_apply_hashed_log_recs(FALSE); *err = recv_apply_hashed_log_recs(FALSE);
if (*err != DB_SUCCESS) {
/* Finish processing because of error */
return (TRUE);
}
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -3174,7 +3195,7 @@ recv_recovery_from_checkpoint_start_func( ...@@ -3174,7 +3195,7 @@ recv_recovery_from_checkpoint_start_func(
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
lsn_t old_scanned_lsn = recv_sys->scanned_lsn; lsn_t old_scanned_lsn = recv_sys->scanned_lsn;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
dberr_t err; dberr_t err = DB_SUCCESS;
recv_group_scan_log_recs(group, &contiguous_lsn, recv_group_scan_log_recs(group, &contiguous_lsn,
&group_scanned_lsn, &err); &group_scanned_lsn, &err);
...@@ -3276,7 +3297,7 @@ recv_recovery_from_checkpoint_start_func( ...@@ -3276,7 +3297,7 @@ recv_recovery_from_checkpoint_start_func(
/* No harm in trying to do RO access. */ /* No harm in trying to do RO access. */
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
ut_error; return (DB_READ_ONLY);
} }
return(DB_ERROR); return(DB_ERROR);
......
...@@ -312,7 +312,7 @@ recv_sys_var_init(void); ...@@ -312,7 +312,7 @@ recv_sys_var_init(void);
Empties the hash table of stored log records, applying them to appropriate Empties the hash table of stored log records, applying them to appropriate
pages. */ pages. */
UNIV_INTERN UNIV_INTERN
void dberr_t
recv_apply_hashed_log_recs( recv_apply_hashed_log_recs(
/*=======================*/ /*=======================*/
ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are ibool allow_ibuf); /*!< in: if TRUE, also ibuf operations are
......
...@@ -446,9 +446,10 @@ recv_sys_init( ...@@ -446,9 +446,10 @@ recv_sys_init(
} }
/********************************************************//** /********************************************************//**
Empties the hash table when it has been fully processed. */ Empties the hash table when it has been fully processed.
@return DB_SUCCESS when successfull or DB_ERROR when fails. */
static static
void dberr_t
recv_sys_empty_hash(void) recv_sys_empty_hash(void)
/*=====================*/ /*=====================*/
{ {
...@@ -462,13 +463,15 @@ recv_sys_empty_hash(void) ...@@ -462,13 +463,15 @@ recv_sys_empty_hash(void)
" log records on it %lu\n", " log records on it %lu\n",
(ulong) recv_sys->n_addrs, (ulong) recv_sys->n_addrs,
(ulong) recv_max_parsed_page_no); (ulong) recv_max_parsed_page_no);
ut_error; return DB_ERROR;
} }
hash_table_free(recv_sys->addr_hash); hash_table_free(recv_sys->addr_hash);
mem_heap_empty(recv_sys->heap); mem_heap_empty(recv_sys->heap);
recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512); recv_sys->addr_hash = hash_create(buf_pool_get_curr_size() / 512);
return DB_SUCCESS;
} }
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
...@@ -1847,9 +1850,10 @@ recv_read_in_area( ...@@ -1847,9 +1850,10 @@ recv_read_in_area(
/*******************************************************************//** /*******************************************************************//**
Empties the hash table of stored log records, applying them to appropriate Empties the hash table of stored log records, applying them to appropriate
pages. */ pages.
@return DB_SUCCESS when successfull or DB_ERROR when fails. */
UNIV_INTERN UNIV_INTERN
void dberr_t
recv_apply_hashed_log_recs( recv_apply_hashed_log_recs(
/*=======================*/ /*=======================*/
ibool allow_ibuf) /*!< in: if TRUE, also ibuf operations are ibool allow_ibuf) /*!< in: if TRUE, also ibuf operations are
...@@ -1866,6 +1870,7 @@ recv_apply_hashed_log_recs( ...@@ -1866,6 +1870,7 @@ recv_apply_hashed_log_recs(
ulint i; ulint i;
ibool has_printed = FALSE; ibool has_printed = FALSE;
mtr_t mtr; mtr_t mtr;
dberr_t err = DB_SUCCESS;
loop: loop:
mutex_enter(&(recv_sys->mutex)); mutex_enter(&(recv_sys->mutex));
...@@ -1999,13 +2004,15 @@ loop: ...@@ -1999,13 +2004,15 @@ loop:
recv_sys->apply_log_recs = FALSE; recv_sys->apply_log_recs = FALSE;
recv_sys->apply_batch_on = FALSE; recv_sys->apply_batch_on = FALSE;
recv_sys_empty_hash(); err = recv_sys_empty_hash();
if (has_printed) { if (has_printed) {
fprintf(stderr, "InnoDB: Apply batch completed\n"); fprintf(stderr, "InnoDB: Apply batch completed\n");
} }
mutex_exit(&(recv_sys->mutex)); mutex_exit(&(recv_sys->mutex));
return err;
} }
#else /* !UNIV_HOTBACKUP */ #else /* !UNIV_HOTBACKUP */
/*******************************************************************//** /*******************************************************************//**
...@@ -2328,7 +2335,6 @@ recv_report_corrupt_log( ...@@ -2328,7 +2335,6 @@ recv_report_corrupt_log(
if (!srv_force_recovery) { if (!srv_force_recovery) {
fputs("InnoDB: Set innodb_force_recovery" fputs("InnoDB: Set innodb_force_recovery"
" to ignore this error.\n", stderr); " to ignore this error.\n", stderr);
ut_error;
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -2351,9 +2357,11 @@ static ...@@ -2351,9 +2357,11 @@ static
ibool ibool
recv_parse_log_recs( recv_parse_log_recs(
/*================*/ /*================*/
ibool store_to_hash) /*!< in: TRUE if the records should be stored ibool store_to_hash, /*!< in: TRUE if the records should be stored
to the hash table; this is set to FALSE if just to the hash table; this is set to FALSE if just
debug checking is needed */ debug checking is needed */
dberr_t* err) /*!< out: DB_SUCCESS if successfull,
DB_ERROR if parsing fails. */
{ {
byte* ptr; byte* ptr;
byte* end_ptr; byte* end_ptr;
...@@ -2462,7 +2470,8 @@ loop: ...@@ -2462,7 +2470,8 @@ loop:
(ulint) type, space, (ulint) type, space,
(char*)(body + 2)); (char*)(body + 2));
ut_error; *err = DB_ERROR;
return(FALSE);
} }
} }
#endif #endif
...@@ -2758,17 +2767,18 @@ recv_scan_log_recs( ...@@ -2758,17 +2767,18 @@ recv_scan_log_recs(
if (log_crypt_block_maybe_encrypted(log_block, if (log_crypt_block_maybe_encrypted(log_block,
&log_crypt_err)) { &log_crypt_err)) {
/* Log block maybe encrypted */ /* Log block maybe encrypted finish processing*/
log_crypt_print_error(log_crypt_err); log_crypt_print_error(log_crypt_err);
*err = DB_ERROR; *err = DB_ERROR;
return (TRUE); return (TRUE);
} }
/* Crash if we encounter a garbage log block */ /* Stop if we encounter a garbage log block */
if (!srv_force_recovery) { if (!srv_force_recovery) {
fputs("InnoDB: Set innodb_force_recovery" fputs("InnoDB: Set innodb_force_recovery"
" to ignore this error.\n", stderr); " to ignore this error.\n", stderr);
ut_error; *err = DB_ERROR;
return (TRUE);
} }
break; break;
...@@ -2806,7 +2816,8 @@ recv_scan_log_recs( ...@@ -2806,7 +2816,8 @@ recv_scan_log_recs(
/* This is not really an error, but currently /* This is not really an error, but currently
we stop here in the debug version: */ we stop here in the debug version: */
ut_error; *err = DB_ERROR;
return (TRUE);
#endif #endif
break; break;
} }
...@@ -2872,7 +2883,8 @@ recv_scan_log_recs( ...@@ -2872,7 +2883,8 @@ recv_scan_log_recs(
" innodb_force_recovery" " innodb_force_recovery"
" to ignore this error.\n", " to ignore this error.\n",
stderr); stderr);
ut_error; *err = DB_ERROR;
return (TRUE);
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -2914,7 +2926,11 @@ recv_scan_log_recs( ...@@ -2914,7 +2926,11 @@ recv_scan_log_recs(
if (more_data && !recv_sys->found_corrupt_log) { if (more_data && !recv_sys->found_corrupt_log) {
/* Try to parse more log records */ /* Try to parse more log records */
recv_parse_log_recs(store_to_hash); recv_parse_log_recs(store_to_hash, err);
if (*err != DB_SUCCESS) {
return (TRUE);
}
#ifndef UNIV_HOTBACKUP #ifndef UNIV_HOTBACKUP
if (store_to_hash if (store_to_hash
...@@ -2926,7 +2942,12 @@ recv_scan_log_recs( ...@@ -2926,7 +2942,12 @@ recv_scan_log_recs(
log yet: they would be produced by ibuf log yet: they would be produced by ibuf
operations */ operations */
recv_apply_hashed_log_recs(FALSE); *err = recv_apply_hashed_log_recs(FALSE);
if (*err != DB_SUCCESS) {
/* Finish processing because of error */
return (TRUE);
}
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
...@@ -3267,7 +3288,7 @@ recv_recovery_from_checkpoint_start_func( ...@@ -3267,7 +3288,7 @@ recv_recovery_from_checkpoint_start_func(
#ifdef UNIV_LOG_ARCHIVE #ifdef UNIV_LOG_ARCHIVE
lsn_t old_scanned_lsn = recv_sys->scanned_lsn; lsn_t old_scanned_lsn = recv_sys->scanned_lsn;
#endif /* UNIV_LOG_ARCHIVE */ #endif /* UNIV_LOG_ARCHIVE */
dberr_t err; dberr_t err = DB_SUCCESS;
recv_group_scan_log_recs(group, &contiguous_lsn, recv_group_scan_log_recs(group, &contiguous_lsn,
&group_scanned_lsn, &err); &group_scanned_lsn, &err);
...@@ -3369,7 +3390,7 @@ recv_recovery_from_checkpoint_start_func( ...@@ -3369,7 +3390,7 @@ recv_recovery_from_checkpoint_start_func(
/* No harm in trying to do RO access. */ /* No harm in trying to do RO access. */
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
ut_error; return (DB_READ_ONLY);
} }
return(DB_ERROR); return(DB_ERROR);
......
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