summaryrefslogtreecommitdiff
path: root/innobase/log/log0recv.c
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/log/log0recv.c')
-rw-r--r--innobase/log/log0recv.c225
1 files changed, 148 insertions, 77 deletions
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index c1ceb9791f2..5fd5ab863df 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -57,6 +57,16 @@ ibool recv_needed_recovery = FALSE;
ibool recv_lsn_checks_on = FALSE;
+/* There are two conditions under which we scan the logs, the first
+is normal startup and the second is when we do a recovery from an
+archive.
+This flag is set if we are doing a scan from the last checkpoint during
+startup. If we find log entries that were written after the last checkpoint
+we know that the server was not cleanly shutdown. We must then initialize
+the crash recovery environment before attempting to store these entries in
+the log hash table. */
+ibool recv_log_scan_is_startup_type = FALSE;
+
/* If the following is TRUE, the buffer pool file pages must be invalidated
after recovery and no ibuf operations are allowed; this becomes TRUE if
the log record hash table becomes too full, and log records must be merged
@@ -99,6 +109,16 @@ the recovery failed and the database may be corrupt. */
dulint recv_max_page_lsn;
+/* prototypes */
+
+/***********************************************************
+Initialize crash recovery environment. Can be called iff
+recv_needed_recovery == FALSE. */
+static
+void
+recv_init_crash_recovery(void);
+/*===========================*/
+
/************************************************************
Creates the recovery system. */
@@ -2438,6 +2458,23 @@ recv_scan_log_recs(
if (ut_dulint_cmp(scanned_lsn, recv_sys->scanned_lsn) > 0) {
+ /* We have found more entries. If this scan is
+ of startup type, we must initiate crash recovery
+ environment before parsing these log records. */
+
+ if (recv_log_scan_is_startup_type
+ && !recv_needed_recovery) {
+
+ fprintf(stderr,
+ "InnoDB: Log scan progressed"
+ " past the checkpoint lsn %lu %lu\n",
+ (ulong) ut_dulint_get_high(
+ recv_sys->scanned_lsn),
+ (ulong) ut_dulint_get_low(
+ recv_sys->scanned_lsn));
+ recv_init_crash_recovery();
+ }
+
/* We were able to find more log data: add it to the
parsing buffer if parse_start_lsn is already
non-zero */
@@ -2557,6 +2594,48 @@ recv_group_scan_log_recs(
#endif /* UNIV_DEBUG */
}
+/***********************************************************
+Initialize crash recovery environment. Can be called iff
+recv_needed_recovery == FALSE. */
+static
+void
+recv_init_crash_recovery(void)
+/*==========================*/
+{
+ ut_a(!recv_needed_recovery);
+
+ recv_needed_recovery = TRUE;
+
+ ut_print_timestamp(stderr);
+
+ fprintf(stderr,
+ " InnoDB: Database was not"
+ " shut down normally!\n"
+ "InnoDB: Starting crash recovery.\n");
+
+ fprintf(stderr,
+ "InnoDB: Reading tablespace information"
+ " from the .ibd files...\n");
+
+ fil_load_single_table_tablespaces();
+
+ /* If we are using the doublewrite method, we will
+ check if there are half-written pages in data files,
+ and restore them from the doublewrite buffer if
+ possible */
+
+ if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
+
+ fprintf(stderr,
+ "InnoDB: Restoring possible"
+ " half-written data pages from"
+ " the doublewrite\n"
+ "InnoDB: buffer...\n");
+ trx_sys_doublewrite_init_or_restore_pages(TRUE);
+ }
+
+}
+
/************************************************************
Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function
@@ -2681,72 +2760,6 @@ recv_recovery_from_checkpoint_start(
recv_sys->recovered_lsn = checkpoint_lsn;
srv_start_lsn = checkpoint_lsn;
-
- /* NOTE: we always do a 'recovery' at startup, but only if
- there is something wrong we will print a message to the
- user about recovery: */
-
- if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) != 0
- || ut_dulint_cmp(checkpoint_lsn, min_flushed_lsn) != 0) {
-
- if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn)
- < 0) {
- fprintf(stderr,
-"InnoDB: ##########################################################\n"
-"InnoDB: WARNING!\n"
-"InnoDB: The log sequence number in ibdata files is higher\n"
-"InnoDB: than the log sequence number in the ib_logfiles! Are you sure\n"
-"InnoDB: you are using the right ib_logfiles to start up the database?\n"
-"InnoDB: Log sequence number in ib_logfiles is %lu %lu, log\n"
-"InnoDB: sequence numbers stamped to ibdata file headers are between\n"
-"InnoDB: %lu %lu and %lu %lu.\n"
-"InnoDB: ##########################################################\n",
- (ulong) ut_dulint_get_high(checkpoint_lsn),
- (ulong) ut_dulint_get_low(checkpoint_lsn),
- (ulong) ut_dulint_get_high(min_flushed_lsn),
- (ulong) ut_dulint_get_low(min_flushed_lsn),
- (ulong) ut_dulint_get_high(max_flushed_lsn),
- (ulong) ut_dulint_get_low(max_flushed_lsn));
- }
-
- recv_needed_recovery = TRUE;
-
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
-" InnoDB: Database was not shut down normally!\n"
-"InnoDB: Starting crash recovery.\n");
-
- fprintf(stderr,
-"InnoDB: Reading tablespace information from the .ibd files...\n");
-
- fil_load_single_table_tablespaces();
-
- /* If we are using the doublewrite method, we will
- check if there are half-written pages in data files,
- and restore them from the doublewrite buffer if
- possible */
-
- if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
-
- fprintf(stderr,
-"InnoDB: Restoring possible half-written data pages from the doublewrite\n"
-"InnoDB: buffer...\n");
- trx_sys_doublewrite_init_or_restore_pages(
- TRUE);
- }
-
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
-" InnoDB: Starting log scan based on checkpoint at\n"
-"InnoDB: log sequence number %lu %lu.\n",
- (ulong) ut_dulint_get_high(checkpoint_lsn),
- (ulong) ut_dulint_get_low(checkpoint_lsn));
- } else {
- /* Init the doublewrite buffer memory structure */
- trx_sys_doublewrite_init_or_restore_pages(FALSE);
- }
}
contiguous_lsn = ut_dulint_align_down(recv_sys->scanned_lsn,
@@ -2798,7 +2811,9 @@ recv_recovery_from_checkpoint_start(
group = UT_LIST_GET_NEXT(log_groups, group);
}
- while (group) {
+ /* Set the flag to publish that we are doing startup scan. */
+ recv_log_scan_is_startup_type = (type == LOG_CHECKPOINT);
+ while (group) {
old_scanned_lsn = recv_sys->scanned_lsn;
recv_group_scan_log_recs(group, &contiguous_lsn,
@@ -2819,6 +2834,69 @@ recv_recovery_from_checkpoint_start(
group = UT_LIST_GET_NEXT(log_groups, group);
}
+ /* Done with startup scan. Clear the flag. */
+ recv_log_scan_is_startup_type = FALSE;
+ if (type == LOG_CHECKPOINT) {
+ /* NOTE: we always do a 'recovery' at startup, but only if
+ there is something wrong we will print a message to the
+ user about recovery: */
+
+ if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn) != 0
+ || ut_dulint_cmp(checkpoint_lsn, min_flushed_lsn) != 0) {
+
+ if (ut_dulint_cmp(checkpoint_lsn, max_flushed_lsn)
+ < 0) {
+ fprintf(stderr,
+ "InnoDB: #########################"
+ "#################################\n"
+ "InnoDB: "
+ "WARNING!\n"
+ "InnoDB: The log sequence number"
+ " in ibdata files is higher\n"
+ "InnoDB: than the log sequence number"
+ " in the ib_logfiles! Are you sure\n"
+ "InnoDB: you are using the right"
+ " ib_logfiles to start up"
+ " the database?\n"
+ "InnoDB: Log sequence number in"
+ " ib_logfiles is %lu %lu, log\n"
+ "InnoDB: sequence numbers stamped"
+ " to ibdata file headers are between\n"
+ "InnoDB: %lu %lu and %lu %lu.\n"
+ "InnoDB: #########################"
+ "#################################\n",
+ (ulong) ut_dulint_get_high(
+ checkpoint_lsn),
+ (ulong) ut_dulint_get_low(
+ checkpoint_lsn),
+ (ulong) ut_dulint_get_high(
+ min_flushed_lsn),
+ (ulong) ut_dulint_get_low(
+ min_flushed_lsn),
+ (ulong) ut_dulint_get_high(
+ max_flushed_lsn),
+ (ulong) ut_dulint_get_low(
+ max_flushed_lsn));
+
+
+ }
+
+ if (!recv_needed_recovery) {
+ fprintf(stderr,
+ "InnoDB: The log sequence number"
+ " in ibdata files does not match\n"
+ "InnoDB: the log sequence number"
+ " in the ib_logfiles!\n");
+ recv_init_crash_recovery();
+ }
+
+ }
+ if (!recv_needed_recovery) {
+ /* Init the doublewrite buffer memory structure */
+ trx_sys_doublewrite_init_or_restore_pages(FALSE);
+ }
+ }
+
/* We currently have only one log group */
if (ut_dulint_cmp(group_scanned_lsn, checkpoint_lsn) < 0) {
ut_print_timestamp(stderr);
@@ -2871,16 +2949,9 @@ recv_recovery_from_checkpoint_start(
recv_synchronize_groups(up_to_date_group);
if (!recv_needed_recovery) {
- if (ut_dulint_cmp(checkpoint_lsn, recv_sys->recovered_lsn)
- != 0) {
- fprintf(stderr,
-"InnoDB: Warning: we did not need to do crash recovery, but log scan\n"
-"InnoDB: progressed past the checkpoint lsn %lu %lu up to lsn %lu %lu\n",
- (ulong) ut_dulint_get_high(checkpoint_lsn),
- (ulong) ut_dulint_get_low(checkpoint_lsn),
- (ulong) ut_dulint_get_high(recv_sys->recovered_lsn),
- (ulong) ut_dulint_get_low(recv_sys->recovered_lsn));
- }
+ ut_a(ut_dulint_cmp(checkpoint_lsn,
+ recv_sys->recovered_lsn) == 0);
+
} else {
srv_start_lsn = recv_sys->recovered_lsn;
}