Commit 5567a8c9 authored by Marko Mäkelä's avatar Marko Mäkelä

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.
parent 09af00cb
--source include/have_innodb.inc --source include/have_innodb.inc
# With 32k, truncation could happen on shutdown after the test, --source include/innodb_page_size.inc
# 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/have_undo_tablespaces.inc --source include/have_undo_tablespaces.inc
SET @save_undo_logs = @@GLOBAL.innodb_undo_logs; SET @save_undo_logs = @@GLOBAL.innodb_undo_logs;
......
...@@ -1237,8 +1237,7 @@ btr_create( ...@@ -1237,8 +1237,7 @@ btr_create(
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW); buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
flst_init(block->frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, flst_init(block, PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
mtr);
} else { } else {
block = fseg_create(space, 0, block = fseg_create(space, 0,
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr); PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
......
...@@ -7499,16 +7499,20 @@ btr_store_big_rec_extern_fields( ...@@ -7499,16 +7499,20 @@ btr_store_big_rec_extern_fields(
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4, + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4,
rec_page_no, rec_page_no,
MLOG_4BYTES, &mtr); 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 mlog_log_string(page
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
page_zip_get_size(page_zip) 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); &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, /* Copy the page to compressed storage,
because it will be flushed to disk because it will be flushed to disk
from there. */ from there. */
......
...@@ -172,9 +172,6 @@ ulint fil_n_pending_tablespace_flushes = 0; ...@@ -172,9 +172,6 @@ ulint fil_n_pending_tablespace_flushes = 0;
/** Number of files currently open */ /** Number of files currently open */
ulint fil_n_file_opened = 0; 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 /** The tablespace memory cache. This variable is NULL before the module is
initialized. */ initialized. */
fil_system_t fil_system; fil_system_t fil_system;
......
...@@ -730,23 +730,23 @@ void fsp_header_init(fil_space_t* space, ulint size, mtr_t* mtr) ...@@ -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, mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_ID + block->frame,
space->id, MLOG_4BYTES, mtr); space->id, MLOG_4BYTES, mtr);
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_NOT_USED + block->frame, 0, ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_NOT_USED
MLOG_4BYTES, mtr); + block->frame));
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE + block->frame, size, mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SIZE + block->frame, size,
MLOG_4BYTES, mtr); MLOG_4BYTES, mtr);
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FREE_LIMIT + block->frame, 0, ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FREE_LIMIT
MLOG_4BYTES, mtr); + block->frame));
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + block->frame, mlog_write_ulint(FSP_HEADER_OFFSET + FSP_SPACE_FLAGS + block->frame,
space->flags & ~FSP_FLAGS_MEM_MASK, space->flags & ~FSP_FLAGS_MEM_MASK,
MLOG_4BYTES, mtr); MLOG_4BYTES, mtr);
mlog_write_ulint(FSP_HEADER_OFFSET + FSP_FRAG_N_USED + block->frame, 0, ut_ad(0 == mach_read_from_4(FSP_HEADER_OFFSET + FSP_FRAG_N_USED
MLOG_4BYTES, mtr); + block->frame));
flst_init(FSP_HEADER_OFFSET + FSP_FREE + block->frame, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_FREE, mtr);
flst_init(FSP_HEADER_OFFSET + FSP_FREE_FRAG + block->frame, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_FREE_FRAG, mtr);
flst_init(FSP_HEADER_OFFSET + FSP_FULL_FRAG + block->frame, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_FULL_FRAG, mtr);
flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL + block->frame, mtr); flst_init(block, FSP_HEADER_OFFSET + FSP_SEG_INODES_FULL, mtr);
flst_init(FSP_HEADER_OFFSET + FSP_SEG_INODES_FREE + block->frame, 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); mlog_write_ull(FSP_HEADER_OFFSET + FSP_SEG_ID + block->frame, 1, mtr);
......
...@@ -58,8 +58,8 @@ flst_add_to_empty( ...@@ -58,8 +58,8 @@ flst_add_to_empty(
flst_write_addr(base + FLST_LAST, node_addr, mtr); flst_write_addr(base + FLST_LAST, node_addr, mtr);
/* Set prev and next fields of node to add */ /* Set prev and next fields of node to add */
flst_write_addr(node + FLST_PREV, fil_addr_null, mtr); flst_zero_addr(node + FLST_PREV, mtr);
flst_write_addr(node + FLST_NEXT, fil_addr_null, mtr); flst_zero_addr(node + FLST_NEXT, mtr);
/* Update len of base node */ /* Update len of base node */
mlog_write_ulint(base + FLST_LEN, 1, MLOG_4BYTES, mtr); mlog_write_ulint(base + FLST_LEN, 1, MLOG_4BYTES, mtr);
......
...@@ -366,19 +366,12 @@ typedef byte fil_faddr_t; /*!< 'type' definition in C: an address ...@@ -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_BYTE 4U /* then comes 2-byte byte offset within page*/
#define FIL_ADDR_SIZE 6U /* address size is 6 bytes */ #define FIL_ADDR_SIZE 6U /* address size is 6 bytes */
#ifndef UNIV_INNOCHECKSUM
/** File space address */ /** File space address */
struct fil_addr_t { struct fil_addr_t {
ulint page; /*!< page number within a space */ ulint page; /*!< page number within a space */
ulint boffset; /*!< byte offset within the page */ 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 @{ */ /** 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 #define FIL_PAGE_SPACE_OR_CHKSUM 0 /*!< in < MySQL-4.0.14 space id the
page belongs to (== 0) but in later page belongs to (== 0) but in later
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -28,11 +29,8 @@ Created 11/28/1995 Heikki Tuuri ...@@ -28,11 +29,8 @@ Created 11/28/1995 Heikki Tuuri
#ifndef UNIV_INNOCHECKSUM #ifndef UNIV_INNOCHECKSUM
#include "univ.i" #include "fut0fut.h"
#include "mtr0log.h"
#include "fil0fil.h"
#include "mtr0mtr.h"
/* The C 'types' of base node and list node: these should be used to /* 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 write self-documenting code. Of course, the sizeof macro cannot be
...@@ -49,6 +47,47 @@ typedef byte flst_node_t; ...@@ -49,6 +47,47 @@ typedef byte flst_node_t;
#define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE) #define FLST_NODE_SIZE (2 * FIL_ADDR_SIZE)
#ifndef UNIV_INNOCHECKSUM #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. */ Initializes a list base node. */
UNIV_INLINE UNIV_INLINE
......
...@@ -23,26 +23,8 @@ File-based list utilities ...@@ -23,26 +23,8 @@ File-based list utilities
Created 11/28/1995 Heikki Tuuri Created 11/28/1995 Heikki Tuuri
***********************************************************************/ ***********************************************************************/
#include "fut0fut.h"
#include "mtr0log.h"
#include "buf0buf.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. */ Writes a file address. */
UNIV_INLINE UNIV_INLINE
...@@ -101,8 +83,8 @@ flst_init( ...@@ -101,8 +83,8 @@ flst_init(
| MTR_MEMO_PAGE_SX_FIX)); | MTR_MEMO_PAGE_SX_FIX));
mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr); mlog_write_ulint(base + FLST_LEN, 0, MLOG_4BYTES, mtr);
flst_write_addr(base + FLST_FIRST, fil_addr_null, mtr); flst_zero_addr(base + FLST_FIRST, mtr);
flst_write_addr(base + FLST_LAST, fil_addr_null, mtr); flst_zero_addr(base + FLST_LAST, mtr);
} }
/** Get the length of a list. /** Get the length of a list.
......
...@@ -481,6 +481,7 @@ MariaDB 10.2.18 and later will use the 10.3 format, but LOG_HEADER_SUBFORMAT ...@@ -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 1 instead of 0. MariaDB 10.3 will use subformat 0 (5.7-style TRUNCATE) or 2
(MDEV-13564 backup-friendly TRUNCATE). */ (MDEV-13564 backup-friendly TRUNCATE). */
#define LOG_HEADER_FORMAT_10_3 103 #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) */ /** The MariaDB 10.4.0 log format (only with innodb_encrypt_log=ON) */
#define LOG_HEADER_FORMAT_ENC_10_4 (104U | 1U << 31) #define LOG_HEADER_FORMAT_ENC_10_4 (104U | 1U << 31)
/** Encrypted MariaDB redo log */ /** Encrypted MariaDB redo log */
...@@ -552,7 +553,7 @@ struct log_t{ ...@@ -552,7 +553,7 @@ struct log_t{
struct files { struct files {
/** number of files */ /** number of files */
ulint n_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; uint32_t format;
/** redo log subformat: 0 with separately logged TRUNCATE, /** redo log subformat: 0 with separately logged TRUNCATE,
2 with fully redo-logged TRUNCATE (1 in MariaDB 10.2) */ 2 with fully redo-logged TRUNCATE (1 in MariaDB 10.2) */
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2014, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -72,6 +73,23 @@ mlog_log_string( ...@@ -72,6 +73,23 @@ mlog_log_string(
byte* ptr, /*!< in: pointer written to */ byte* ptr, /*!< in: pointer written to */
ulint len, /*!< in: string length */ ulint len, /*!< in: string length */
mtr_t* mtr); /*!< in: mini-transaction handle */ 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 Writes initial part of a log record consisting of one-byte item
type and four-byte space and page numbers. */ type and four-byte space and page numbers. */
...@@ -189,7 +207,7 @@ mlog_parse_initial_log_record( ...@@ -189,7 +207,7 @@ mlog_parse_initial_log_record(
ulint* space, /*!< out: space id */ ulint* space, /*!< out: space id */
ulint* page_no);/*!< out: page number */ 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 */ @return parsed record end, NULL if not a complete record */
byte* byte*
mlog_parse_nbytes( mlog_parse_nbytes(
......
...@@ -228,8 +228,11 @@ enum mlog_id_t { ...@@ -228,8 +228,11 @@ enum mlog_id_t {
of a ROW_FORMAT=COMPRESSED table */ of a ROW_FORMAT=COMPRESSED table */
MLOG_ZIP_WRITE_TRX_ID = 62, MLOG_ZIP_WRITE_TRX_ID = 62,
/** initialize a page with a string of identical bytes */
MLOG_MEMSET = 63,
/** biggest value (used in assertions) */ /** 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 /** log record for writing/updating crypt data of
a tablespace */ a tablespace */
......
...@@ -665,7 +665,7 @@ void log_t::files::create(ulint n_files) ...@@ -665,7 +665,7 @@ void log_t::files::create(ulint n_files)
this->n_files= n_files; this->n_files= n_files;
format= srv_encrypt_log 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; subformat= 2;
file_size= srv_log_file_size; file_size= srv_log_file_size;
lsn= LOG_START_LSN; lsn= LOG_START_LSN;
...@@ -698,7 +698,7 @@ log_file_header_flush( ...@@ -698,7 +698,7 @@ log_file_header_flush(
ut_ad(log_write_mutex_own()); ut_ad(log_write_mutex_own());
ut_ad(!recv_no_log_write); ut_ad(!recv_no_log_write);
ut_a(nth_file < log_sys.log.n_files); 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); || log_sys.log.format == LOG_HEADER_FORMAT_ENC_10_4);
buf = log_sys.log.file_header_bufs[nth_file]; buf = log_sys.log.file_header_bufs[nth_file];
......
...@@ -1087,7 +1087,8 @@ recv_find_max_checkpoint(ulint* max_field) ...@@ -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_2 | LOG_HEADER_FORMAT_ENCRYPTED:
case LOG_HEADER_FORMAT_10_3: case LOG_HEADER_FORMAT_10_3:
case LOG_HEADER_FORMAT_10_3 | LOG_HEADER_FORMAT_ENCRYPTED: 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; break;
default: default:
ib::error() << "Unsupported redo log format." ib::error() << "Unsupported redo log format."
...@@ -1257,6 +1258,7 @@ recv_parse_or_apply_log_rec_body( ...@@ -1257,6 +1258,7 @@ recv_parse_or_apply_log_rec_body(
break; break;
#endif /* UNIV_LOG_LSN_DEBUG */ #endif /* UNIV_LOG_LSN_DEBUG */
case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES: case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
case MLOG_MEMSET:
#ifdef UNIV_DEBUG #ifdef UNIV_DEBUG
if (page && page_type == FIL_PAGE_TYPE_ALLOCATED if (page && page_type == FIL_PAGE_TYPE_ALLOCATED
&& end_ptr >= ptr + 2) { && end_ptr >= ptr + 2) {
...@@ -3848,6 +3850,9 @@ static const char* get_mlog_string(mlog_id_t type) ...@@ -3848,6 +3850,9 @@ static const char* get_mlog_string(mlog_id_t type)
case MLOG_TRUNCATE: case MLOG_TRUNCATE:
return("MLOG_TRUNCATE"); return("MLOG_TRUNCATE");
case MLOG_MEMSET:
return("MLOG_MEMSET");
case MLOG_FILE_WRITE_CRYPT_DATA: case MLOG_FILE_WRITE_CRYPT_DATA:
return("MLOG_FILE_WRITE_CRYPT_DATA"); return("MLOG_FILE_WRITE_CRYPT_DATA");
} }
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 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 the terms of the GNU General Public License as published by the Free Software
...@@ -121,7 +121,7 @@ mlog_parse_initial_log_record( ...@@ -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 */ @return parsed record end, NULL if not a complete record or a corrupt record */
byte* byte*
mlog_parse_nbytes( mlog_parse_nbytes(
...@@ -137,29 +137,43 @@ mlog_parse_nbytes( ...@@ -137,29 +137,43 @@ mlog_parse_nbytes(
ulint val; ulint val;
ib_uint64_t dval; ib_uint64_t dval;
ut_a(type <= MLOG_8BYTES); ut_ad(type <= MLOG_8BYTES || type == MLOG_MEMSET);
ut_a(!page || !page_zip ut_a(!page || !page_zip
|| !fil_page_index_page_check(page)); || !fil_page_index_page_check(page));
if (end_ptr < ptr + 2) { if (end_ptr < ptr + 2) {
return NULL;
return(NULL);
} }
offset = mach_read_from_2(ptr); offset = mach_read_from_2(ptr);
ptr += 2; ptr += 2;
if (offset >= srv_page_size) { if (UNIV_UNLIKELY(offset >= srv_page_size)) {
recv_sys->found_corrupt_log = TRUE; goto corrupt;
return(NULL);
} }
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); dval = mach_u64_parse_compressed(&ptr, end_ptr);
if (ptr == NULL) { if (ptr == NULL) {
return NULL;
return(NULL);
} }
if (page) { if (page) {
...@@ -171,14 +185,13 @@ mlog_parse_nbytes( ...@@ -171,14 +185,13 @@ mlog_parse_nbytes(
mach_write_to_8(page + offset, dval); 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) { if (ptr == NULL) {
return NULL;
return(NULL);
} }
switch (type) { switch (type) {
...@@ -221,11 +234,11 @@ mlog_parse_nbytes( ...@@ -221,11 +234,11 @@ mlog_parse_nbytes(
break; break;
default: default:
corrupt: corrupt:
recv_sys->found_corrupt_log = TRUE; recv_sys->found_corrupt_log = true;
ptr = NULL; ptr = NULL;
} }
return(const_cast<byte*>(ptr)); return const_cast<byte*>(ptr);
} }
/********************************************************//** /********************************************************//**
...@@ -409,6 +422,72 @@ mlog_parse_string( ...@@ -409,6 +422,72 @@ mlog_parse_string(
return(ptr + len); 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, Opens a buffer for mlog, writes the initial log record and,
if needed, the field lengths of an index. if needed, the field lengths of an index.
......
...@@ -1249,9 +1249,8 @@ srv_prepare_to_delete_redo_log_files( ...@@ -1249,9 +1249,8 @@ srv_prepare_to_delete_redo_log_files(
{ {
ib::info info; ib::info info;
if (srv_log_file_size == 0 if (srv_log_file_size == 0
|| (log_sys.log.format != LOG_HEADER_FORMAT_10_3 || (log_sys.log.format & ~LOG_HEADER_FORMAT_ENCRYPTED)
&& log_sys.log.format != LOG_HEADER_FORMAT_10_4) {
!= LOG_HEADER_FORMAT_ENC_10_4)) {
info << "Upgrading redo log: "; info << "Upgrading redo log: ";
} else if (n_files != srv_n_log_files } else if (n_files != srv_n_log_files
|| srv_log_file_size || srv_log_file_size
...@@ -2062,7 +2061,7 @@ dberr_t srv_start(bool create_new_db) ...@@ -2062,7 +2061,7 @@ dberr_t srv_start(bool create_new_db)
&& log_sys.log.format && log_sys.log.format
== (srv_encrypt_log == (srv_encrypt_log
? LOG_HEADER_FORMAT_ENC_10_4 ? LOG_HEADER_FORMAT_ENC_10_4
: LOG_HEADER_FORMAT_10_3) : LOG_HEADER_FORMAT_10_4)
&& log_sys.log.subformat == 2) { && log_sys.log.subformat == 2) {
/* No need to add or remove encryption, /* No need to add or remove encryption,
upgrade, downgrade, or resize. */ upgrade, downgrade, or resize. */
......
...@@ -253,12 +253,10 @@ void trx_rseg_format_upgrade(trx_rsegf_t* rseg_header, mtr_t* mtr) ...@@ -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); mlog_write_ulint(rseg_format, 0, MLOG_4BYTES, mtr);
/* Clear also possible garbage at the end of the page. Old /* Clear also possible garbage at the end of the page. Old
InnoDB versions did not initialize unused parts of pages. */ InnoDB versions did not initialize unused parts of pages. */
byte* b = rseg_header + TRX_RSEG_MAX_TRX_ID + 8; mlog_memset(TRX_RSEG_MAX_TRX_ID + 8 + rseg_header,
ulint len = srv_page_size srv_page_size
- (FIL_PAGE_DATA_END - (FIL_PAGE_DATA_END
+ TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8); + TRX_RSEG + TRX_RSEG_MAX_TRX_ID + 8), 0, mtr);
memset(b, 0, len);
mlog_log_string(b, len, mtr);
} }
/** Create a rollback segment header. /** Create a rollback segment header.
...@@ -274,8 +272,6 @@ trx_rseg_header_create( ...@@ -274,8 +272,6 @@ trx_rseg_header_create(
buf_block_t* sys_header, buf_block_t* sys_header,
mtr_t* mtr) mtr_t* mtr)
{ {
ulint page_no;
trx_rsegf_t* rsegf;
buf_block_t* block; buf_block_t* block;
ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK)); ut_ad(mtr_memo_contains(mtr, &space->latch, MTR_MEMO_X_LOCK));
...@@ -292,25 +288,17 @@ trx_rseg_header_create( ...@@ -292,25 +288,17 @@ trx_rseg_header_create(
buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW); buf_block_dbg_add_level(block, SYNC_RSEG_HEADER_NEW);
page_no = block->page.id.page_no(); ut_ad(0 == mach_read_from_4(TRX_RSEG_FORMAT + TRX_RSEG
+ block->frame));
/* Get the rollback segment file page */ ut_ad(0 == mach_read_from_4(TRX_RSEG_HISTORY_SIZE + TRX_RSEG
rsegf = trx_rsegf_get_new(space->id, page_no, mtr); + block->frame));
mlog_write_ulint(rsegf + TRX_RSEG_FORMAT, 0, MLOG_4BYTES, mtr);
/* Initialize the history list */ /* Initialize the history list */
flst_init(block, TRX_RSEG_HISTORY + TRX_RSEG, mtr);
mlog_write_ulint(rsegf + TRX_RSEG_HISTORY_SIZE, 0, MLOG_4BYTES, mtr);
flst_init(rsegf + TRX_RSEG_HISTORY, mtr);
/* Reset the undo log slots */ /* Reset the undo log slots */
for (ulint i = 0; i < TRX_RSEG_N_SLOTS; i++) { mlog_memset(block, TRX_RSEG_UNDO_SLOTS + TRX_RSEG,
/* FIXME: This is generating a lot of redo log. TRX_RSEG_N_SLOTS * 4, 0xff, mtr);
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);
}
if (sys_header) { if (sys_header) {
/* Add the rollback segment info to the free slot in /* Add the rollback segment info to the free slot in
...@@ -325,10 +313,10 @@ trx_rseg_header_create( ...@@ -325,10 +313,10 @@ trx_rseg_header_create(
+ TRX_SYS_RSEG_PAGE_NO + TRX_SYS_RSEG_PAGE_NO
+ rseg_id * TRX_SYS_RSEG_SLOT_SIZE + rseg_id * TRX_SYS_RSEG_SLOT_SIZE
+ sys_header->frame, + 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. */ /** Free a rollback segment in memory. */
......
...@@ -195,10 +195,9 @@ trx_sysf_create( ...@@ -195,10 +195,9 @@ trx_sysf_create(
ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END)); ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END));
/* Initialize all of the page. This part used to be uninitialized. */ /* 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_memset(block, ptr - page,
srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr),
mlog_log_string(TRX_SYS + page, srv_page_size - FIL_PAGE_DATA_END 0, mtr);
- TRX_SYS, mtr);
/* Create the first rollback segment in the SYSTEM tablespace */ /* Create the first rollback segment in the SYSTEM tablespace */
slot_no = trx_sys_rseg_find_free(block); slot_no = trx_sys_rseg_find_free(block);
......
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