summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/encryption/r/innodb_encrypt_log_corruption.result14
-rw-r--r--mysql-test/suite/innodb/r/log_corruption.result14
-rw-r--r--mysql-test/suite/innodb/t/log_corruption.test31
-rw-r--r--storage/innobase/include/mtr0types.h14
-rw-r--r--storage/innobase/include/trx0rec.h19
-rw-r--r--storage/innobase/include/trx0undo.h28
-rw-r--r--storage/innobase/log/log0recv.cc104
-rw-r--r--storage/innobase/srv/srv0start.cc11
-rw-r--r--storage/innobase/trx/trx0rec.cc61
-rw-r--r--storage/innobase/trx/trx0undo.cc84
10 files changed, 283 insertions, 97 deletions
diff --git a/mysql-test/suite/encryption/r/innodb_encrypt_log_corruption.result b/mysql-test/suite/encryption/r/innodb_encrypt_log_corruption.result
index 6eb92aedeb7..afba16db42c 100644
--- a/mysql-test/suite/encryption/r/innodb_encrypt_log_corruption.result
+++ b/mysql-test/suite/encryption/r/innodb_encrypt_log_corruption.result
@@ -40,14 +40,15 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
-FOUND 1 /InnoDB: Upgrade after a crash is not supported\. The redo log was created with malicious intentions, or perhaps, and it appears corrupted\./ in mysqld.1.err
+FOUND 1 /InnoDB: Invalid log block checksum. block: 2372 checkpoint no: 1 expected: 3362026715 found: 144444122/ in mysqld.1.err
+FOUND 1 /InnoDB: Missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\./ in mysqld.1.err
# same, but with current-version header
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
-FOUND 1 /InnoDB: Invalid log block checksum. block: 2372 checkpoint no: 1 expected: 3362026715 found: 144444122/ in mysqld.1.err
-FOUND 1 /InnoDB: Missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\./ in mysqld.1.err
+FOUND 2 /InnoDB: Invalid log block checksum. block: 2372 checkpoint no: 1 expected: 3362026715 found: 144444122/ in mysqld.1.err
+FOUND 2 /InnoDB: Missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\./ in mysqld.1.err
# --innodb-force-recovery=6 (skip the entire redo log)
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
@@ -98,6 +99,13 @@ WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
NOT FOUND /InnoDB: Missing MLOG_FILE_NAME or MLOG_FILE_DELETE before MLOG_CHECKPOINT for tablespace 42$/ in mysqld.1.err
+# Clean 10.2 redo log
+SELECT * FROM INFORMATION_SCHEMA.ENGINES
+WHERE engine = 'innodb'
+AND support IN ('YES', 'DEFAULT', 'ENABLED');
+ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
+InnoDB YES Supports transactions, row-level locking, foreign keys and encryption for tables YES YES YES
+FOUND 1 /InnoDB: Upgrading redo log:/ in mysqld.1.err
# Minimal MariaDB 10.1.21 encrypted redo log
SELECT COUNT(*) `1` FROM INFORMATION_SCHEMA.ENGINES WHERE engine='innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
diff --git a/mysql-test/suite/innodb/r/log_corruption.result b/mysql-test/suite/innodb/r/log_corruption.result
index 35b7b00ead6..903dc7f6cf4 100644
--- a/mysql-test/suite/innodb/r/log_corruption.result
+++ b/mysql-test/suite/innodb/r/log_corruption.result
@@ -40,14 +40,15 @@ SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
-FOUND 1 /InnoDB: Upgrade after a crash is not supported\. The redo log was created with malicious intentions, or perhaps, and it appears corrupted\./ in mysqld.1.err
+FOUND 1 /InnoDB: Invalid log block checksum. block: 2372 checkpoint no: 1 expected: 3362026715 found: 144444122/ in mysqld.1.err
+FOUND 1 /InnoDB: Missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\./ in mysqld.1.err
# same, but with current-version header
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
-FOUND 1 /InnoDB: Invalid log block checksum. block: 2372 checkpoint no: 1 expected: 3362026715 found: 144444122/ in mysqld.1.err
-FOUND 1 /InnoDB: Missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\./ in mysqld.1.err
+FOUND 2 /InnoDB: Invalid log block checksum. block: 2372 checkpoint no: 1 expected: 3362026715 found: 144444122/ in mysqld.1.err
+FOUND 2 /InnoDB: Missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\./ in mysqld.1.err
# --innodb-force-recovery=6 (skip the entire redo log)
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
@@ -98,6 +99,13 @@ WHERE engine = 'innodb'
AND support IN ('YES', 'DEFAULT', 'ENABLED');
ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
NOT FOUND /InnoDB: Missing MLOG_FILE_NAME or MLOG_FILE_DELETE before MLOG_CHECKPOINT for tablespace 42$/ in mysqld.1.err
+# Clean 10.2 redo log
+SELECT * FROM INFORMATION_SCHEMA.ENGINES
+WHERE engine = 'innodb'
+AND support IN ('YES', 'DEFAULT', 'ENABLED');
+ENGINE SUPPORT COMMENT TRANSACTIONS XA SAVEPOINTS
+InnoDB YES Supports transactions, row-level locking, foreign keys and encryption for tables YES YES YES
+FOUND 1 /InnoDB: Upgrading redo log:/ in mysqld.1.err
# Minimal MariaDB 10.1.21 encrypted redo log
SELECT * FROM INFORMATION_SCHEMA.ENGINES
WHERE engine = 'innodb'
diff --git a/mysql-test/suite/innodb/t/log_corruption.test b/mysql-test/suite/innodb/t/log_corruption.test
index 3bf68cab4cc..0d699cebb8f 100644
--- a/mysql-test/suite/innodb/t/log_corruption.test
+++ b/mysql-test/suite/innodb/t/log_corruption.test
@@ -204,7 +204,9 @@ EOF
--source include/start_mysqld.inc
eval $check_no_innodb;
--source include/shutdown_mysqld.inc
-let SEARCH_PATTERN=InnoDB: Upgrade after a crash is not supported\. The redo log was created with malicious intentions, or perhaps, and it appears corrupted\.;
+let SEARCH_PATTERN=InnoDB: Invalid log block checksum. block: 2372 checkpoint no: 1 expected: 3362026715 found: 144444122;
+--source include/search_pattern_in_file.inc
+let SEARCH_PATTERN=InnoDB: Missing MLOG_CHECKPOINT between the checkpoint 1213964 and the end 1213952\.;
--source include/search_pattern_in_file.inc
--echo # same, but with current-version header
@@ -339,8 +341,9 @@ perl;
die unless open OUT, "+<", "$ENV{bugdir}/ib_logfile0";
binmode OUT;
# header block
-print OUT pack("Nx[5]nx[5]", 103, 0x1286), "MariaDB 10.3.1";
-print OUT pack("x[478]N", 0x85021a0f);
+print OUT pack("Nx[5]nx[5]", 1, 0x1286);
+print OUT "ibbackup was here!!!1!";
+print OUT pack("x[470]N", 0x52b54540);
# invalid (all-zero) checkpoint page 1 and an empty log page
print OUT chr(0) x 1024;
# valid checkpoint block 2
@@ -364,6 +367,28 @@ eval $check_no_innodb;
--let SEARCH_PATTERN= InnoDB: Missing MLOG_FILE_NAME or MLOG_FILE_DELETE before MLOG_CHECKPOINT for tablespace 42\$
--source include/search_pattern_in_file.inc
+--echo # Clean 10.2 redo log
+perl;
+die unless open OUT, "+<", "$ENV{bugdir}/ib_logfile0";
+binmode OUT;
+die unless seek(OUT, 0x800, 0);
+print OUT pack("H*", "800009440022000c00000001");
+# dummy padding (MLOG_DUMMY_RECORD)
+print OUT " " x 6;
+# MLOG_CHECKPOINT record
+print OUT pack("CNN", 56, 0, 0x12860c);
+# padding (MLOG_DUMMY_RECORD) and block checksum
+print OUT " " x 481, pack("N", 0xe9b21b7b);
+close OUT or die;
+EOF
+
+--let $restart_parameters= $dirs --innodb-force-recovery=5 --innodb-log-file-size=1m
+--source include/start_mysqld.inc
+eval $check_no_innodb;
+--source include/shutdown_mysqld.inc
+--let SEARCH_PATTERN= InnoDB: Upgrading redo log:
+--source include/search_pattern_in_file.inc
+
--echo # Minimal MariaDB 10.1.21 encrypted redo log
perl;
die unless open OUT, "+<", "$ENV{bugdir}/ib_logfile0";
diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h
index 9b0e19d100f..94d904e8efd 100644
--- a/storage/innobase/include/mtr0types.h
+++ b/storage/innobase/include/mtr0types.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2015, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -100,6 +100,18 @@ enum mlog_id_t {
/** Create an index page */
MLOG_PAGE_CREATE = 19,
+ /** insert an undo log record (used in MariaDB 10.2) */
+ MLOG_UNDO_INSERT = 20,
+
+ /** erase an undo log page end (used in MariaDB 10.2) */
+ MLOG_UNDO_ERASE_END = 21,
+
+ /** initialize a page in an undo log (used in MariaDB 10.2) */
+ MLOG_UNDO_INIT = 22,
+
+ /** reuse an insert undo log header (used in MariaDB 10.2) */
+ MLOG_UNDO_HDR_REUSE = 24,
+
/** create an undo log header */
MLOG_UNDO_HDR_CREATE = 25,
diff --git a/storage/innobase/include/trx0rec.h b/storage/innobase/include/trx0rec.h
index 8d5f271dd9b..1f89846d516 100644
--- a/storage/innobase/include/trx0rec.h
+++ b/storage/innobase/include/trx0rec.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -243,6 +243,23 @@ trx_undo_prev_version_build(
into this function by purge thread or not.
And if we read "after image" of undo log */
+/** Parse MLOG_UNDO_INSERT for crash-upgrade from MariaDB 10.2.
+@param[in] ptr log record
+@param[in] end_ptr end of log record buffer
+@param[in,out] page page or NULL
+@return end of log record
+@retval NULL if the log record is incomplete */
+byte*
+trx_undo_parse_add_undo_rec(
+ const byte* ptr,
+ const byte* end_ptr,
+ page_t* page);
+/** Erase the unused undo log page end.
+@param[in,out] undo_page undo log page
+@return whether the page contained something */
+bool
+trx_undo_erase_page_end(page_t* undo_page);
+
/** Read from an undo log record a non-virtual column value.
@param[in,out] ptr pointer to remaining part of the undo record
@param[in,out] field stored field
diff --git a/storage/innobase/include/trx0undo.h b/storage/innobase/include/trx0undo.h
index b51484a61cb..cd7cdca28ca 100644
--- a/storage/innobase/include/trx0undo.h
+++ b/storage/innobase/include/trx0undo.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -315,6 +315,32 @@ bool
trx_undo_truncate_tablespace(
undo::Truncate* undo_trunc);
+/** Parse MLOG_UNDO_INIT for crash-upgrade from MariaDB 10.2.
+@param[in] ptr log record
+@param[in] end_ptr end of log record buffer
+@param[in,out] page page or NULL
+@param[in,out] mtr mini-transaction
+@return end of log record
+@retval NULL if the log record is incomplete */
+byte*
+trx_undo_parse_page_init(
+ const byte* ptr,
+ const byte* end_ptr,
+ page_t* page,
+ mtr_t* mtr);
+/** Parse MLOG_UNDO_HDR_REUSE for crash-upgrade from MariaDB 10.2.
+@param[in] ptr redo log record
+@param[in] end_ptr end of log buffer
+@param[in,out] page undo page or NULL
+@param[in,out] mtr mini-transaction
+@return end of log record or NULL */
+byte*
+trx_undo_parse_page_header_reuse(
+ const byte* ptr,
+ const byte* end_ptr,
+ page_t* page,
+ mtr_t* mtr);
+
/** Parse the redo log entry of an undo log page header create.
@param[in] ptr redo log record
@param[in] end_ptr end of log buffer
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index a4db6d078df..92373afbeff 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -2,7 +2,7 @@
Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2013, 2017, MariaDB Corporation.
+Copyright (c) 2013, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -902,58 +902,6 @@ recv_log_format_0_recover(lsn_t lsn)
return(DB_SUCCESS);
}
-/** Determine if a redo log from MySQL 5.7.9/MariaDB 10.2.2 is clean.
-@return error code
-@retval DB_SUCCESS if the redo log is clean
-@retval DB_CORRUPTION if the redo log is corrupted
-@retval DB_ERROR if the redo log is not empty */
-static
-dberr_t
-recv_log_recover_10_2()
-{
- log_group_t* group = &log_sys->log;
- const lsn_t lsn = group->lsn;
- const lsn_t source_offset = log_group_calc_lsn_offset(lsn, group);
- const ulint page_no
- = (ulint) (source_offset / univ_page_size.physical());
- byte* buf = log_sys->buf;
-
- fil_io(IORequestLogRead, true,
- page_id_t(SRV_LOG_SPACE_FIRST_ID, page_no),
- univ_page_size,
- (ulint) ((source_offset & ~(OS_FILE_LOG_BLOCK_SIZE - 1))
- % univ_page_size.physical()),
- OS_FILE_LOG_BLOCK_SIZE, buf, NULL);
-
- if (log_block_calc_checksum(buf) != log_block_get_checksum(buf)) {
- return(DB_CORRUPTION);
- }
-
- if (group->is_encrypted()) {
- log_crypt(buf, lsn, OS_FILE_LOG_BLOCK_SIZE, true);
- }
-
- /* On a clean shutdown, the redo log will be logically empty
- after the checkpoint lsn. */
-
- if (log_block_get_data_len(buf)
- != (source_offset & (OS_FILE_LOG_BLOCK_SIZE - 1))) {
- return(DB_ERROR);
- }
-
- /* Mark the redo log for upgrading. */
- srv_log_file_size = 0;
- recv_sys->parse_start_lsn = recv_sys->recovered_lsn
- = recv_sys->scanned_lsn
- = recv_sys->mlog_checkpoint_lsn = lsn;
- log_sys->last_checkpoint_lsn = log_sys->next_checkpoint_lsn
- = log_sys->lsn = log_sys->write_lsn
- = log_sys->current_flush_lsn = log_sys->flushed_to_disk_lsn
- = lsn;
- log_sys->next_checkpoint_no = 0;
- return(DB_SUCCESS);
-}
-
/** Find the latest checkpoint in the log header.
@param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2
@return error code or DB_SUCCESS */
@@ -1063,20 +1011,6 @@ recv_find_max_checkpoint(ulint* max_field)
return(DB_ERROR);
}
- switch (group->format) {
- case LOG_HEADER_FORMAT_10_2:
- case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED:
- dberr_t err = recv_log_recover_10_2();
- if (err != DB_SUCCESS) {
- ib::error()
- << "Upgrade after a crash is not supported."
- " The redo log was created with " << creator
- << (err == DB_ERROR
- ? "." : ", and it appears corrupted.");
- }
- return(err);
- }
-
return(DB_SUCCESS);
}
@@ -1394,6 +1328,25 @@ parse_log:
page_parse_create(block, type == MLOG_COMP_PAGE_CREATE_RTREE,
true);
break;
+ case MLOG_UNDO_INSERT:
+ ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG);
+ ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page);
+ break;
+ case MLOG_UNDO_ERASE_END:
+ if (page) {
+ ut_ad(page_type == FIL_PAGE_UNDO_LOG);
+ trx_undo_erase_page_end(page);
+ }
+ break;
+ case MLOG_UNDO_INIT:
+ /* Allow anything in page_type when creating a page. */
+ ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_UNDO_HDR_REUSE:
+ ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG);
+ ptr = trx_undo_parse_page_header_reuse(ptr, end_ptr, page,
+ mtr);
+ break;
case MLOG_UNDO_HDR_CREATE:
ut_ad(!page || page_type == FIL_PAGE_UNDO_LOG);
ptr = trx_undo_parse_page_header(ptr, end_ptr, page, mtr);
@@ -3176,10 +3129,7 @@ recv_recovery_from_checkpoint_start(lsn_t flush_lsn)
err = recv_find_max_checkpoint(&max_cp_field);
- if (err != DB_SUCCESS
- || (log_sys->log.format != LOG_HEADER_FORMAT_3_23
- && (log_sys->log.format & ~LOG_HEADER_FORMAT_ENCRYPTED)
- != LOG_HEADER_FORMAT_CURRENT)) {
+ if (err != DB_SUCCESS) {
srv_start_lsn = recv_sys->recovered_lsn = log_sys->lsn;
log_mutex_exit();
@@ -3620,6 +3570,18 @@ get_mlog_string(mlog_id_t type)
case MLOG_PAGE_CREATE:
return("MLOG_PAGE_CREATE");
+ case MLOG_UNDO_INSERT:
+ return("MLOG_UNDO_INSERT");
+
+ case MLOG_UNDO_ERASE_END:
+ return("MLOG_UNDO_ERASE_END");
+
+ case MLOG_UNDO_INIT:
+ return("MLOG_UNDO_INIT");
+
+ case MLOG_UNDO_HDR_REUSE:
+ return("MLOG_UNDO_HDR_REUSE");
+
case MLOG_UNDO_HDR_CREATE:
return("MLOG_UNDO_HDR_CREATE");
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index 9135f2e19f7..4f508c149e9 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1405,7 +1405,10 @@ srv_prepare_to_delete_redo_log_files(
{
ib::info info;
- if (srv_log_file_size == 0) {
+ if (srv_log_file_size == 0
+ || (log_sys->log.format
+ & ~LOG_HEADER_FORMAT_ENCRYPTED)
+ != LOG_HEADER_FORMAT_CURRENT) {
info << "Upgrading redo log: ";
} else if (n_files != srv_n_log_files
|| srv_log_file_size
@@ -2350,7 +2353,11 @@ files_checked:
/* Leave the redo log alone. */
} else if (srv_log_file_size_requested == srv_log_file_size
&& srv_n_log_files_found == srv_n_log_files
- && log_sys->is_encrypted() == srv_encrypt_log) {
+ && log_sys->log.format
+ == (srv_encrypt_log
+ ? LOG_HEADER_FORMAT_CURRENT
+ | LOG_HEADER_FORMAT_ENCRYPTED
+ : LOG_HEADER_FORMAT_CURRENT)) {
/* No need to upgrade or resize the redo log. */
} else {
/* Prepare to delete the old redo log files */
diff --git a/storage/innobase/trx/trx0rec.cc b/storage/innobase/trx/trx0rec.cc
index a2c49342537..86fe7758626 100644
--- a/storage/innobase/trx/trx0rec.cc
+++ b/storage/innobase/trx/trx0rec.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -76,6 +76,49 @@ trx_undof_page_add_undo_rec_log(
mlog_log_string(undo_page + old_free, new_free - old_free, mtr);
}
+/** Parse MLOG_UNDO_INSERT for crash-upgrade from MariaDB 10.2.
+@param[in] ptr log record
+@param[in] end_ptr end of log record buffer
+@param[in,out] page page or NULL
+@return end of log record
+@retval NULL if the log record is incomplete */
+byte*
+trx_undo_parse_add_undo_rec(
+ const byte* ptr,
+ const byte* end_ptr,
+ page_t* page)
+{
+ ulint len;
+
+ if (end_ptr < ptr + 2) {
+
+ return(NULL);
+ }
+
+ len = mach_read_from_2(ptr);
+ ptr += 2;
+
+ if (end_ptr < ptr + len) {
+
+ return(NULL);
+ }
+
+ if (page) {
+ ulint first_free = mach_read_from_2(page + TRX_UNDO_PAGE_HDR
+ + TRX_UNDO_PAGE_FREE);
+ byte* rec = page + first_free;
+
+ mach_write_to_2(rec, first_free + 4 + len);
+ mach_write_to_2(rec + 2 + len, first_free);
+
+ mach_write_to_2(page + TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE,
+ first_free + 4 + len);
+ memcpy(rec + 2, ptr, len);
+ }
+
+ return(const_cast<byte*>(ptr + len));
+}
+
/**********************************************************************//**
Calculates the free space left for extending an undo log record.
@return bytes left */
@@ -1758,15 +1801,11 @@ trx_undo_rec_get_partial_row(
return(const_cast<byte*>(ptr));
}
-/***********************************************************************//**
-Erases the unused undo log page end.
-@return TRUE if the page contained something, FALSE if it was empty */
-static MY_ATTRIBUTE((nonnull))
-ibool
-trx_undo_erase_page_end(
-/*====================*/
- page_t* undo_page, /*!< in/out: undo page whose end to erase */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+/** Erase the unused undo log page end.
+@param[in,out] undo_page undo log page
+@return whether the page contained something */
+bool
+trx_undo_erase_page_end(page_t* undo_page)
{
ulint first_free;
@@ -1993,7 +2032,7 @@ trx_undo_report_row_operation(
version the replicate page constructed using the log
records stays identical to the original page */
- if (!trx_undo_erase_page_end(undo_page, &mtr)) {
+ if (!trx_undo_erase_page_end(undo_page)) {
/* The record did not fit on an empty
undo page. Discard the freshly allocated
page and return an error. */
diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc
index 1340d19aee8..49c1ab15fe8 100644
--- a/storage/innobase/trx/trx0undo.cc
+++ b/storage/innobase/trx/trx0undo.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2017, MariaDB Corporation.
+Copyright (c) 2014, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@@ -309,6 +309,88 @@ trx_undo_get_first_rec(
/*============== UNDO LOG FILE COPY CREATION AND FREEING ==================*/
+/** Parse MLOG_UNDO_INIT for crash-upgrade from MariaDB 10.2.
+@param[in] ptr log record
+@param[in] end_ptr end of log record buffer
+@param[in,out] page page or NULL
+@param[in,out] mtr mini-transaction
+@return end of log record
+@retval NULL if the log record is incomplete */
+byte*
+trx_undo_parse_page_init(
+ const byte* ptr,
+ const byte* end_ptr,
+ page_t* page,
+ mtr_t* mtr)
+{
+ ulint type = mach_parse_compressed(&ptr, end_ptr);
+
+ if (!ptr) {
+ } else if (type != 1 && type != 2) {
+ recv_sys->found_corrupt_log = true;
+ } else if (page) {
+ mach_write_to_2(FIL_PAGE_TYPE + page, FIL_PAGE_UNDO_LOG);
+ mach_write_to_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE + page,
+ type);
+ mach_write_to_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_START + page,
+ TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
+ mach_write_to_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_FREE + page,
+ TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_HDR_SIZE);
+ }
+
+ return(const_cast<byte*>(ptr));
+}
+
+/** Parse MLOG_UNDO_HDR_REUSE for crash-upgrade from MariaDB 10.2.
+@param[in] ptr redo log record
+@param[in] end_ptr end of log buffer
+@param[in,out] page undo log page or NULL
+@param[in,out] mtr mini-transaction
+@return end of log record or NULL */
+byte*
+trx_undo_parse_page_header_reuse(
+ const byte* ptr,
+ const byte* end_ptr,
+ page_t* undo_page,
+ mtr_t* mtr)
+{
+ trx_id_t trx_id = mach_u64_parse_compressed(&ptr, end_ptr);
+
+ if (!ptr || !undo_page) {
+ return(const_cast<byte*>(ptr));
+ }
+
+ compile_time_assert(TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE
+ + TRX_UNDO_LOG_XA_HDR_SIZE
+ < UNIV_PAGE_SIZE_MIN - 100);
+
+ const ulint new_free = TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE
+ + TRX_UNDO_LOG_OLD_HDR_SIZE;
+
+ /* Insert undo data is not needed after commit: we may free all
+ the space on the page */
+
+ ut_ad(mach_read_from_2(TRX_UNDO_PAGE_HDR + TRX_UNDO_PAGE_TYPE
+ + undo_page)
+ == TRX_UNDO_INSERT);
+
+ byte* page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
+ mach_write_to_2(page_hdr + TRX_UNDO_PAGE_START, new_free);
+ mach_write_to_2(page_hdr + TRX_UNDO_PAGE_FREE, new_free);
+ mach_write_to_2(TRX_UNDO_SEG_HDR + TRX_UNDO_STATE + undo_page,
+ TRX_UNDO_ACTIVE);
+
+ byte* log_hdr = undo_page + TRX_UNDO_SEG_HDR + TRX_UNDO_SEG_HDR_SIZE;
+
+ mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
+ mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
+
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
+ mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
+
+ return(const_cast<byte*>(ptr));
+}
+
/********************************************************************//**
Initializes the fields in an undo log segment page. */
static