diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2018-09-11 15:47:50 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2018-09-11 21:32:36 +0300 |
commit | 5567a8c936ede50efcdf4a7f898dbaa058106d70 (patch) | |
tree | 613a8564a4964c7fbe4d5e3926675c0f093e38de | |
parent | 09af00cbde1d62dfda574dee10e5c0fd240c3f7f (diff) | |
download | mariadb-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.opt | 1 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/undo_truncate.test | 6 | ||||
-rw-r--r-- | storage/innobase/btr/btr0btr.cc | 3 | ||||
-rw-r--r-- | storage/innobase/btr/btr0cur.cc | 16 | ||||
-rw-r--r-- | storage/innobase/fil/fil0fil.cc | 3 | ||||
-rw-r--r-- | storage/innobase/fsp/fsp0fsp.cc | 24 | ||||
-rw-r--r-- | storage/innobase/fut/fut0lst.cc | 4 | ||||
-rw-r--r-- | storage/innobase/include/fil0fil.h | 7 | ||||
-rw-r--r-- | storage/innobase/include/fut0lst.h | 49 | ||||
-rw-r--r-- | storage/innobase/include/fut0lst.ic | 22 | ||||
-rw-r--r-- | storage/innobase/include/log0log.h | 3 | ||||
-rw-r--r-- | storage/innobase/include/mtr0log.h | 20 | ||||
-rw-r--r-- | storage/innobase/include/mtr0types.h | 5 | ||||
-rw-r--r-- | storage/innobase/log/log0log.cc | 4 | ||||
-rw-r--r-- | storage/innobase/log/log0recv.cc | 7 | ||||
-rw-r--r-- | storage/innobase/mtr/mtr0log.cc | 117 | ||||
-rw-r--r-- | storage/innobase/srv/srv0start.cc | 7 | ||||
-rw-r--r-- | storage/innobase/trx/trx0rseg.cc | 38 | ||||
-rw-r--r-- | storage/innobase/trx/trx0sys.cc | 7 |
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); |