summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2018-09-11 15:47:50 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2018-09-11 21:32:36 +0300
commit5567a8c936ede50efcdf4a7f898dbaa058106d70 (patch)
tree613a8564a4964c7fbe4d5e3926675c0f093e38de
parent09af00cbde1d62dfda574dee10e5c0fd240c3f7f (diff)
downloadmariadb-git-5567a8c936ede50efcdf4a7f898dbaa058106d70.tar.gz
MDEV-17138 Reduce redo log volume for undo tablespace initialization
Implement a 10.4 redo log format, which extends the 10.3 format by introducing the MLOG_MEMSET record. MLOG_MEMSET: A new redo log record type for filling an area with a byte. mlog_memset(): Write the MLOG_MEMSET record. mlog_parse_nbytes(): Handle MLOG_MEMSET as well. trx_rseg_header_create(): Reduce the redo log volume by making use of mlog_memset() and the zero-initialization that happens inside page allocation. fil_addr_null: Remove. flst_init(): Create a variant that takes a zero-initialized buf_block_t* as a parameter, and only writes the FIL_NULL using mlog_memset(). flst_zero_addr(): A variant of flst_write_addr() that writes a null address using mlog_memset() for the FIL_NULL. The following fixes are replacing some use of MLOG_WRITE_STRING with the more compact MLOG_MEMSET record, or eliminating redundant redo log writes: btr_store_big_rec_extern_fields(): Invoke mlog_memset() for zero-initializing the tail of the ROW_FORMAT=COMPRESSED BLOB page. trx_sysf_create(), trx_rseg_format_upgrade(): Invoke mlog_memset() for zero-initializing the page trailer. fsp_header_init(), trx_rseg_header_create(): Remove redundant zero-initializations.
-rw-r--r--mysql-test/suite/innodb/t/undo_truncate.opt1
-rw-r--r--mysql-test/suite/innodb/t/undo_truncate.test6
-rw-r--r--storage/innobase/btr/btr0btr.cc3
-rw-r--r--storage/innobase/btr/btr0cur.cc16
-rw-r--r--storage/innobase/fil/fil0fil.cc3
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc24
-rw-r--r--storage/innobase/fut/fut0lst.cc4
-rw-r--r--storage/innobase/include/fil0fil.h7
-rw-r--r--storage/innobase/include/fut0lst.h49
-rw-r--r--storage/innobase/include/fut0lst.ic22
-rw-r--r--storage/innobase/include/log0log.h3
-rw-r--r--storage/innobase/include/mtr0log.h20
-rw-r--r--storage/innobase/include/mtr0types.h5
-rw-r--r--storage/innobase/log/log0log.cc4
-rw-r--r--storage/innobase/log/log0recv.cc7
-rw-r--r--storage/innobase/mtr/mtr0log.cc117
-rw-r--r--storage/innobase/srv/srv0start.cc7
-rw-r--r--storage/innobase/trx/trx0rseg.cc38
-rw-r--r--storage/innobase/trx/trx0sys.cc7
19 files changed, 222 insertions, 121 deletions
diff --git a/mysql-test/suite/innodb/t/undo_truncate.opt b/mysql-test/suite/innodb/t/undo_truncate.opt
deleted file mode 100644
index 1c897ab6cfc..00000000000
--- a/mysql-test/suite/innodb/t/undo_truncate.opt
+++ /dev/null
@@ -1 +0,0 @@
---innodb-log-buffer-size=2m
diff --git a/mysql-test/suite/innodb/t/undo_truncate.test b/mysql-test/suite/innodb/t/undo_truncate.test
index 9b91c78e35a..af6ed2b4372 100644
--- a/mysql-test/suite/innodb/t/undo_truncate.test
+++ b/mysql-test/suite/innodb/t/undo_truncate.test
@@ -1,9 +1,5 @@
--source include/have_innodb.inc
-# With 32k, truncation could happen on shutdown after the test,
-# and the mtr.add_suppression() would not filter out the warning.
-# With 64k, no truncation seems to happen.
-# --source include/innodb_page_size.inc
---source include/innodb_page_size_small.inc
+--source include/innodb_page_size.inc
--source include/have_undo_tablespaces.inc
SET @save_undo_logs = @@GLOBAL.innodb_undo_logs;
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 0d191cb9c64..606ab114b2f 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -1237,8 +1237,7 @@ btr_create(
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
- flst_init(block->frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
- mtr);
+ flst_init(block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
} else {
block = fseg_create(space, 0,
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
diff --git a/storage/innobase/btr/btr0cur.cc b/storage/innobase/btr/btr0cur.cc
index 3d8d08573f7..e6b9fc93658 100644
--- a/storage/innobase/btr/btr0cur.cc
+++ b/storage/innobase/btr/btr0cur.cc
@@ -7499,16 +7499,20 @@ btr_store_big_rec_extern_fields(
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
rec_page_no,
MLOG_4BYTES, &mtr);
-
- /* Zero out the unused part of the page. */
- memset(page + page_zip_get_size(page_zip)
- - c_stream.avail_out,
- 0, c_stream.avail_out);
mlog_log_string(page
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
page_zip_get_size(page_zip)
- - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ - FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION
+ - c_stream.avail_out,
&mtr);
+ /* Zero out the unused part of the page. */
+ if (c_stream.avail_out) {
+ mlog_memset(block,
+ page_zip_get_size(page_zip)
+ - c_stream.avail_out,
+ c_stream.avail_out,
+ 0, &mtr);
+ }
/* Copy the page to compressed storage,
because it will be flushed to disk
from there. */
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 9b42caf421f..52c98eadbc4 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -172,9 +172,6 @@ ulint fil_n_pending_tablespace_flushes = 0;
/** Number of files currently open */
ulint fil_n_file_opened = 0;
-/** The null file address */
-const fil_addr_t fil_addr_null = {FIL_NULL, 0};
-
/** The tablespace memory cache. This variable is NULL before the module is
initialized. */
fil_system_t fil_system;
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 1ae32a62c87..b31dea67470 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -730,23 +730,23 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr)
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_ID + block->frame,
space->id, MLOG_4BYTES, mtr);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_NOT_USED + block->frame, 0,
- MLOG_4BYTES, mtr);
+ ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_NOT_USED
+ + block->frame));
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE + block->frame, size,
MLOG_4BYTES, mtr);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + block->frame, 0,
- MLOG_4BYTES, mtr);
+ ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
+ + block->frame));
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + block->frame,
space->flags & ~FSP_FLAGS_MEM_MASK,
MLOG_4BYTES, mtr);
- mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FRAG_N_USED + block->frame, 0,
- MLOG_4BYTES, mtr);
-
- flst_init(FSP_HEADER_OFFSET + FSP_FREE + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_FREE_FRAG + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_FULL_FRAG + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL + block->frame, mtr);
- flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE + block->frame, mtr);
+ ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED
+ + block->frame));
+
+ flst_init(block, FSP_HEADER_OFFSET + FSP_FREE, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_FULL_FRAG, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, mtr);
+ flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE, mtr);
mlog_write_ull(FSP_HEADER_OFFSET + FSP_SEG_ID + block->frame, 1, mtr);
diff --git a/storage/innobase/fut/fut0lst.cc b/storage/innobase/fut/fut0lst.cc
index 3e77165ac31..05474b02cbd 100644
--- a/storage/innobase/fut/fut0lst.cc
+++ b/storage/innobase/fut/fut0lst.cc
@@ -58,8 +58,8 @@ flst_add_to_empty(
flst_write_addr(base + FLST_LAST, node_addr, mtr);
/* Set prev and next fields of node to add */
- flst_write_addr(node + FLST_PREV, fil_addr_null, mtr);
- flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr);
+ flst_zero_addr(node + FLST_PREV, mtr);
+ flst_zero_addr(node + FLST_NEXT, mtr);
/* Update len of base node */
mlog_write_ulint(base + FLST_LEN, 1, MLOG_4BYTES, mtr);
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 947d9d1c860..43234bb80c6 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -366,19 +366,12 @@ typedef byte fil_faddr_t; /*!< 'type' definition in C: an address
#define FIL_ADDR_BYTE 4U /* then comes 2-byte byte offset within page*/
#define FIL_ADDR_SIZE 6U /* address size is 6 bytes */
-#ifndef UNIV_INNOCHECKSUM
-
/** File space address */
struct fil_addr_t {
ulint page; /*!< page number within a space */
ulint boffset; /*!< byte offset within the page */
};
-/** The null file address */
-extern const fil_addr_t fil_addr_null;
-
-#endif /* !UNIV_INNOCHECKSUM */
-
/** The byte offsets on a file page for various variables @{ */
#define FIL_PAGE_SPACE_OR_CHKSUM 0 /*!< in < MySQL-4.0.14 space id the
page belongs to (== 0) but in later
diff --git a/storage/innobase/include/fut0lst.h b/storage/innobase/include/fut0lst.h
index bff4a92f381..d38b450085c 100644
--- a/storage/innobase/include/fut0lst.h
+++ b/storage/innobase/include/fut0lst.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 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
@@ -28,11 +29,8 @@ Created 11/28/1995 Heikki Tuuri
#ifndef UNIV_INNOCHECKSUM
-#include "univ.i"
-
-#include "fil0fil.h"
-#include "mtr0mtr.h"
-
+#include "fut0fut.h"
+#include "mtr0log.h"
/* The C 'types' of base node and list node: these should be used to
write self-documenting code. Of course, the sizeof macro cannot be
@@ -49,6 +47,47 @@ typedef byte flst_node_t;
#define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE)
#ifndef UNIV_INNOCHECKSUM
+/* We define the field offsets of a node for the list */
+#define FLST_PREV 0 /* 6-byte address of the previous list element;
+ the page part of address is FIL_NULL, if no
+ previous element */
+#define FLST_NEXT FIL_ADDR_SIZE /* 6-byte address of the next
+ list element; the page part of address
+ is FIL_NULL, if no next element */
+
+/* We define the field offsets of a base node for the list */
+#define FLST_LEN 0 /* 32-bit list length field */
+#define FLST_FIRST 4 /* 6-byte address of the first element
+ of the list; undefined if empty list */
+#define FLST_LAST (4 + FIL_ADDR_SIZE) /* 6-byte address of the
+ last element of the list; undefined
+ if empty list */
+
+/** Initialize a zero-initialized list base node.
+@param[in,out] block file page
+@param[in] ofs byte offset of the list base node
+@param[in,out] mtr mini-transaction */
+inline void flst_init(buf_block_t* block, uint16_t ofs, mtr_t* mtr)
+{
+ ut_ad(0 == mach_read_from_2(FLST_LEN + ofs + block->frame));
+ ut_ad(0 == mach_read_from_2(FLST_FIRST + FIL_ADDR_BYTE + ofs
+ + block->frame));
+ ut_ad(0 == mach_read_from_2(FLST_LAST + FIL_ADDR_BYTE + ofs
+ + block->frame));
+ compile_time_assert(FIL_NULL == 0xffU * 0x1010101U);
+ mlog_memset(block, FLST_FIRST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
+ mlog_memset(block, FLST_LAST + FIL_ADDR_PAGE + ofs, 4, 0xff, mtr);
+}
+
+/** Write a null file address.
+@param[in,out] faddr file address to be zeroed otu
+@param[in,out] mtr mini-transaction */
+inline void flst_zero_addr(fil_faddr_t* faddr, mtr_t* mtr)
+{
+ mlog_memset(faddr + FIL_ADDR_PAGE, 4, 0xff, mtr);
+ mlog_write_ulint(faddr + FIL_ADDR_BYTE, 0, MLOG_2BYTES, mtr);
+}
+
/********************************************************************//**
Initializes a list base node. */
UNIV_INLINE
diff --git a/storage/innobase/include/fut0lst.ic b/storage/innobase/include/fut0lst.ic
index 5c9a9ca94c1..3a978b8f75a 100644
--- a/storage/innobase/include/fut0lst.ic
+++ b/storage/innobase/include/fut0lst.ic
@@ -23,26 +23,8 @@ File-based list utilities
Created 11/28/1995 Heikki Tuuri
***********************************************************************/
-#include "fut0fut.h"
-#include "mtr0log.h"
#include "buf0buf.h"
-/* We define the field offsets of a node for the list */
-#define FLST_PREV 0 /* 6-byte address of the previous list element;
- the page part of address is FIL_NULL, if no
- previous element */
-#define FLST_NEXT FIL_ADDR_SIZE /* 6-byte address of the next
- list element; the page part of address
- is FIL_NULL, if no next element */
-
-/* We define the field offsets of a base node for the list */
-#define FLST_LEN 0 /* 32-bit list length field */
-#define FLST_FIRST 4 /* 6-byte address of the first element
- of the list; undefined if empty list */
-#define FLST_LAST (4 + FIL_ADDR_SIZE) /* 6-byte address of the
- last element of the list; undefined
- if empty list */
-
/********************************************************************//**
Writes a file address. */
UNIV_INLINE
@@ -101,8 +83,8 @@ flst_init(
| MTR_MEMO_PAGE_SX_FIX));
mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
- flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr);
- flst_write_addr(base + FLST_LAST, fil_addr_null, mtr);
+ flst_zero_addr(base + FLST_FIRST, mtr);
+ flst_zero_addr(base + FLST_LAST, mtr);
}
/** Get the length of a list.
diff --git a/storage/innobase/include/log0log.h b/storage/innobase/include/log0log.h
index a1de00791b5..7cf0e839ef7 100644
--- a/storage/innobase/include/log0log.h
+++ b/storage/innobase/include/log0log.h
@@ -481,6 +481,7 @@ MariaDB 10.2.18 and later will use the 10.3 format, but LOG_HEADER_SUBFORMAT
1 instead of 0. MariaDB 10.3 will use subformat 0 (5.7-style TRUNCATE) or 2
(MDEV-13564 backup-friendly TRUNCATE). */
#define LOG_HEADER_FORMAT_10_3 103
+#define LOG_HEADER_FORMAT_10_4 104
/** The MariaDB 10.4.0 log format (only with innodb_encrypt_log=ON) */
#define LOG_HEADER_FORMAT_ENC_10_4 (104U | 1U << 31)
/** Encrypted MariaDB redo log */
@@ -552,7 +553,7 @@ struct log_t{
struct files {
/** number of files */
ulint n_files;
- /** format of the redo log: e.g., LOG_HEADER_FORMAT_10_3 */
+ /** format of the redo log: e.g., LOG_HEADER_FORMAT_10_4 */
uint32_t format;
/** redo log subformat: 0 with separately logged TRUNCATE,
2 with fully redo-logged TRUNCATE (1 in MariaDB 10.2) */
diff --git a/storage/innobase/include/mtr0log.h b/storage/innobase/include/mtr0log.h
index d6b32374c42..01502aa104d 100644
--- a/storage/innobase/include/mtr0log.h
+++ b/storage/innobase/include/mtr0log.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 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
@@ -72,6 +73,23 @@ mlog_log_string(
byte* ptr, /*!< in: pointer written to */
ulint len, /*!< in: string length */
mtr_t* mtr); /*!< in: mini-transaction handle */
+
+/** Initialize a string of bytes.
+@param[in,out] b buffer page
+@param[in] ofs byte offset from block->frame
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void
+mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr);
+
+/** Initialize a string of bytes.
+@param[in,out] byte byte address
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr);
+
/********************************************************//**
Writes initial part of a log record consisting of one-byte item
type and four-byte space and page numbers. */
@@ -189,7 +207,7 @@ mlog_parse_initial_log_record(
ulint* space, /*!< out: space id */
ulint* page_no);/*!< out: page number */
/********************************************************//**
-Parses a log record written by mlog_write_ulint or mlog_write_ull.
+Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset.
@return parsed record end, NULL if not a complete record */
byte*
mlog_parse_nbytes(
diff --git a/storage/innobase/include/mtr0types.h b/storage/innobase/include/mtr0types.h
index d88a31c96a3..39ed707267d 100644
--- a/storage/innobase/include/mtr0types.h
+++ b/storage/innobase/include/mtr0types.h
@@ -228,8 +228,11 @@ enum mlog_id_t {
of a ROW_FORMAT=COMPRESSED table */
MLOG_ZIP_WRITE_TRX_ID = 62,
+ /** initialize a page with a string of identical bytes */
+ MLOG_MEMSET = 63,
+
/** biggest value (used in assertions) */
- MLOG_BIGGEST_TYPE = MLOG_ZIP_WRITE_TRX_ID,
+ MLOG_BIGGEST_TYPE = MLOG_MEMSET,
/** log record for writing/updating crypt data of
a tablespace */
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index bb8afdbe6ef..204f0a6917d 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -665,7 +665,7 @@ void log_t::files::create(ulint n_files)
this->n_files= n_files;
format= srv_encrypt_log
- ? LOG_HEADER_FORMAT_ENC_10_4 : LOG_HEADER_FORMAT_10_3;
+ ? LOG_HEADER_FORMAT_ENC_10_4 : LOG_HEADER_FORMAT_10_4;
subformat= 2;
file_size= srv_log_file_size;
lsn= LOG_START_LSN;
@@ -698,7 +698,7 @@ log_file_header_flush(
ut_ad(log_write_mutex_own());
ut_ad(!recv_no_log_write);
ut_a(nth_file < log_sys.log.n_files);
- ut_ad(log_sys.log.format == LOG_HEADER_FORMAT_10_3
+ ut_ad(log_sys.log.format == LOG_HEADER_FORMAT_10_4
|| log_sys.log.format == LOG_HEADER_FORMAT_ENC_10_4);
buf = log_sys.log.file_header_bufs[nth_file];
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 5669ad10553..5a42f9db206 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -1087,7 +1087,8 @@ recv_find_max_checkpoint(ulint* max_field)
case LOG_HEADER_FORMAT_10_2 | LOG_HEADER_FORMAT_ENCRYPTED:
case LOG_HEADER_FORMAT_10_3:
case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED:
- case LOG_HEADER_FORMAT_ENC_10_4:
+ case LOG_HEADER_FORMAT_10_4:
+ case LOG_HEADER_FORMAT_10_4 | LOG_HEADER_FORMAT_ENCRYPTED:
break;
default:
ib::error() << "Unsupported redo log format."
@@ -1257,6 +1258,7 @@ parse_log:
break;
#endif /* UNIV_LOG_LSN_DEBUG */
case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
+ case MLOG_MEMSET:
#ifdef UNIV_DEBUG
if (page && page_type == FIL_PAGE_TYPE_ALLOCATED
&& end_ptr >= ptr + 2) {
@@ -3848,6 +3850,9 @@ static const char* get_mlog_string(mlog_id_t type)
case MLOG_TRUNCATE:
return("MLOG_TRUNCATE");
+ case MLOG_MEMSET:
+ return("MLOG_MEMSET");
+
case MLOG_FILE_WRITE_CRYPT_DATA:
return("MLOG_FILE_WRITE_CRYPT_DATA");
}
diff --git a/storage/innobase/mtr/mtr0log.cc b/storage/innobase/mtr/mtr0log.cc
index 6baf1f06bf9..c9a6de8c902 100644
--- a/storage/innobase/mtr/mtr0log.cc
+++ b/storage/innobase/mtr/mtr0log.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 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
@@ -121,7 +121,7 @@ mlog_parse_initial_log_record(
}
/********************************************************//**
-Parses a log record written by mlog_write_ulint or mlog_write_ull.
+Parses a log record written by mlog_write_ulint, mlog_write_ull, mlog_memset.
@return parsed record end, NULL if not a complete record or a corrupt record */
byte*
mlog_parse_nbytes(
@@ -137,29 +137,43 @@ mlog_parse_nbytes(
ulint val;
ib_uint64_t dval;
- ut_a(type <= MLOG_8BYTES);
+ ut_ad(type <= MLOG_8BYTES || type == MLOG_MEMSET);
ut_a(!page || !page_zip
|| !fil_page_index_page_check(page));
if (end_ptr < ptr + 2) {
-
- return(NULL);
+ return NULL;
}
offset = mach_read_from_2(ptr);
ptr += 2;
- if (offset >= srv_page_size) {
- recv_sys->found_corrupt_log = TRUE;
-
- return(NULL);
+ if (UNIV_UNLIKELY(offset >= srv_page_size)) {
+ goto corrupt;
}
- if (type == MLOG_8BYTES) {
+ switch (type) {
+ case MLOG_MEMSET:
+ if (end_ptr < ptr + 3) {
+ return NULL;
+ }
+ val = mach_read_from_2(ptr);
+ ptr += 2;
+ if (UNIV_UNLIKELY(offset + val > srv_page_size)) {
+ goto corrupt;
+ }
+ if (page) {
+ memset(page + offset, *ptr, val);
+ if (page_zip) {
+ memset(static_cast<page_zip_des_t*>(page_zip)
+ ->data + offset, *ptr, val);
+ }
+ }
+ return const_cast<byte*>(++ptr);
+ case MLOG_8BYTES:
dval = mach_u64_parse_compressed(&ptr, end_ptr);
if (ptr == NULL) {
-
- return(NULL);
+ return NULL;
}
if (page) {
@@ -171,14 +185,13 @@ mlog_parse_nbytes(
mach_write_to_8(page + offset, dval);
}
- return(const_cast<byte*>(ptr));
+ return const_cast<byte*>(ptr);
+ default:
+ val = mach_parse_compressed(&ptr, end_ptr);
}
- val = mach_parse_compressed(&ptr, end_ptr);
-
if (ptr == NULL) {
-
- return(NULL);
+ return NULL;
}
switch (type) {
@@ -221,11 +234,11 @@ mlog_parse_nbytes(
break;
default:
corrupt:
- recv_sys->found_corrupt_log = TRUE;
+ recv_sys->found_corrupt_log = true;
ptr = NULL;
}
- return(const_cast<byte*>(ptr));
+ return const_cast<byte*>(ptr);
}
/********************************************************//**
@@ -409,6 +422,72 @@ mlog_parse_string(
return(ptr + len);
}
+/** Initialize a string of bytes.
+@param[in,out] b buffer page
+@param[in] ofs byte offset from block->frame
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void
+mlog_memset(buf_block_t* b, ulint ofs, ulint len, byte val, mtr_t* mtr)
+{
+ ut_ad(len);
+ ut_ad(ofs <= ulint(srv_page_size));
+ ut_ad(ofs + len <= ulint(srv_page_size));
+ memset(ofs + b->frame, val, len);
+
+ mtr->set_modified();
+ switch (mtr->get_log_mode()) {
+ case MTR_LOG_NONE:
+ case MTR_LOG_NO_REDO:
+ return;
+ case MTR_LOG_SHORT_INSERTS:
+ ut_ad(0);
+ /* fall through */
+ case MTR_LOG_ALL:
+ break;
+ }
+
+ byte* l = mtr->get_log()->open(11 + 2 + 2 + 1);
+ l = mlog_write_initial_log_record_low(
+ MLOG_MEMSET, b->page.id.space(), b->page.id.page_no(), l, mtr);
+ mach_write_to_2(l, ofs);
+ mach_write_to_2(l + 2, len);
+ l[4] = val;
+ mlog_close(mtr, l + 5);
+}
+
+/** Initialize a string of bytes.
+@param[in,out] byte byte address
+@param[in] len length of the data to write
+@param[in] val the data byte to write
+@param[in,out] mtr mini-transaction */
+void mlog_memset(byte* b, ulint len, byte val, mtr_t* mtr)
+{
+ ut_ad(len);
+ ut_ad(page_offset(b) + len <= ulint(srv_page_size));
+ memset(b, val, len);
+
+ mtr->set_modified();
+ switch (mtr->get_log_mode()) {
+ case MTR_LOG_NONE:
+ case MTR_LOG_NO_REDO:
+ return;
+ case MTR_LOG_SHORT_INSERTS:
+ ut_ad(0);
+ /* fall through */
+ case MTR_LOG_ALL:
+ break;
+ }
+
+ byte* l = mtr->get_log()->open(11 + 2 + 2 + 1);
+ l = mlog_write_initial_log_record_fast(b, MLOG_MEMSET, l, mtr);
+ mach_write_to_2(l, page_offset(b));
+ mach_write_to_2(l + 2, len);
+ l[4] = val;
+ mlog_close(mtr, l + 5);
+}
+
/********************************************************//**
Opens a buffer for mlog, writes the initial log record and,
if needed, the field lengths of an index.
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index f87fd2c370c..4b488c9f648 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1249,9 +1249,8 @@ srv_prepare_to_delete_redo_log_files(
{
ib::info info;
if (srv_log_file_size == 0
- || (log_sys.log.format != LOG_HEADER_FORMAT_10_3
- && log_sys.log.format
- != LOG_HEADER_FORMAT_ENC_10_4)) {
+ || (log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED)
+ != LOG_HEADER_FORMAT_10_4) {
info << "Upgrading redo log: ";
} else if (n_files != srv_n_log_files
|| srv_log_file_size
@@ -2062,7 +2061,7 @@ files_checked:
&& log_sys.log.format
== (srv_encrypt_log
? LOG_HEADER_FORMAT_ENC_10_4
- : LOG_HEADER_FORMAT_10_3)
+ : LOG_HEADER_FORMAT_10_4)
&& log_sys.log.subformat == 2) {
/* No need to add or remove encryption,
upgrade, downgrade, or resize. */
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 199a1b69f0b..bfa49b88d1d 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -253,12 +253,10 @@ void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr)
mlog_write_ulint(rseg_format, 0, MLOG_4BYTES, mtr);
/* Clear also possible garbage at the end of the page. Old
InnoDB versions did not initialize unused parts of pages. */
- byte* b = rseg_header + TRX_RSEG_MAX_TRX_ID + 8;
- ulint len = srv_page_size
- - (FIL_PAGE_DATA_END
- + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8);
- memset(b, 0, len);
- mlog_log_string(b, len, mtr);
+ mlog_memset(TRX_RSEG_MAX_TRX_ID + 8 + rseg_header,
+ srv_page_size
+ - (FIL_PAGE_DATA_END
+ + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8), 0, mtr);
}
/** Create a rollback segment header.
@@ -274,8 +272,6 @@ trx_rseg_header_create(
buf_block_t* sys_header,
mtr_t* mtr)
{
- ulint page_no;
- trx_rsegf_t* rsegf;
buf_block_t* block;
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
@@ -292,25 +288,17 @@ trx_rseg_header_create(
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
- page_no = block->page.id.page_no();
-
- /* Get the rollback segment file page */
- rsegf = trx_rsegf_get_new(space->id, page_no, mtr);
-
- mlog_write_ulint(rsegf + TRX_RSEG_FORMAT, 0, MLOG_4BYTES, mtr);
+ ut_ad(0 == mach_read_from_4(TRX_RSEG_FORMAT + TRX_RSEG
+ + block->frame));
+ ut_ad(0 == mach_read_from_4(TRX_RSEG_HISTORY_SIZE + TRX_RSEG
+ + block->frame));
/* Initialize the history list */
-
- mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
- flst_init(rsegf + TRX_RSEG_HISTORY, mtr);
+ flst_init(block, TRX_RSEG_HISTORY + TRX_RSEG, mtr);
/* Reset the undo log slots */
- for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) {
- /* FIXME: This is generating a lot of redo log.
- Why not just let it remain zero-initialized,
- and adjust trx_rsegf_undo_find_free() and friends? */
- trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
- }
+ mlog_memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG,
+ TRX_RSEG_N_SLOTS * 4, 0xff, mtr);
if (sys_header) {
/* Add the rollback segment info to the free slot in
@@ -325,10 +313,10 @@ trx_rseg_header_create(
+ TRX_SYS_RSEG_PAGE_NO
+ rseg_id * TRX_SYS_RSEG_SLOT_SIZE
+ sys_header->frame,
- page_no, MLOG_4BYTES, mtr);
+ block->page.id.page_no(), MLOG_4BYTES, mtr);
}
- return(page_no);
+ return block->page.id.page_no();
}
/** Free a rollback segment in memory. */
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index b01595e313d..003a2e70f93 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -195,10 +195,9 @@ trx_sysf_create(
ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END));
/* Initialize all of the page. This part used to be uninitialized. */
- memset(ptr, 0, srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr));
-
- mlog_log_string(TRX_SYS + page, srv_page_size - FIL_PAGE_DATA_END
- - TRX_SYS, mtr);
+ mlog_memset(block, ptr - page,
+ srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr),
+ 0, mtr);
/* Create the first rollback segment in the SYSTEM tablespace */
slot_no = trx_sys_rseg_find_free(block);