summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-06-08 12:45:08 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-06-08 12:45:08 +0300
commit2d8fdfbde5d5d32df64bacfaa7574ecf83b0bc03 (patch)
treecea7cfc27b7f5c3c9d116a82330fef01350b08f4 /storage
parentc4cbc7a8807250d2d5b5938b218fd9c423a0b30a (diff)
parentfbeb9489cd7d6ad859a49ae5ab8f876f3d988470 (diff)
downloadmariadb-git-2d8fdfbde5d5d32df64bacfaa7574ecf83b0bc03.tar.gz
Merge 10.1 into 10.2
Replace have_innodb_zip.inc with innodb_page_size_small.inc.
Diffstat (limited to 'storage')
-rw-r--r--storage/innobase/btr/btr0btr.cc37
-rw-r--r--storage/innobase/buf/buf0buf.cc90
-rw-r--r--storage/innobase/buf/buf0dblwr.cc61
-rw-r--r--storage/innobase/dict/dict0crea.cc7
-rw-r--r--storage/innobase/fil/fil0crypt.cc44
-rw-r--r--storage/innobase/fil/fil0fil.cc25
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc24
-rw-r--r--storage/innobase/fsp/fsp0sysspace.cc11
-rw-r--r--storage/innobase/include/buf0dblwr.h9
-rw-r--r--storage/innobase/include/fsp0fsp.h14
-rw-r--r--storage/innobase/include/trx0rseg.h7
-rw-r--r--storage/innobase/include/trx0trx.h2
-rw-r--r--storage/innobase/srv/srv0srv.cc2
-rw-r--r--storage/innobase/srv/srv0start.cc19
-rw-r--r--storage/innobase/trx/trx0rseg.cc4
-rw-r--r--storage/xtradb/btr/btr0btr.cc47
-rw-r--r--storage/xtradb/buf/buf0buf.cc117
-rw-r--r--storage/xtradb/buf/buf0dblwr.cc74
-rw-r--r--storage/xtradb/fil/fil0crypt.cc34
-rw-r--r--storage/xtradb/fil/fil0fil.cc318
-rw-r--r--storage/xtradb/fsp/fsp0fsp.cc24
-rw-r--r--storage/xtradb/handler/ha_innodb.cc11
-rw-r--r--storage/xtradb/include/buf0dblwr.h16
-rw-r--r--storage/xtradb/include/fil0fil.h53
-rw-r--r--storage/xtradb/include/fsp0fsp.h14
-rw-r--r--storage/xtradb/include/log0recv.h36
-rw-r--r--storage/xtradb/include/trx0rseg.h11
-rw-r--r--storage/xtradb/include/trx0trx.h21
-rw-r--r--storage/xtradb/log/log0log.cc9
-rw-r--r--storage/xtradb/log/log0recv.cc52
-rw-r--r--storage/xtradb/srv/srv0srv.cc2
-rw-r--r--storage/xtradb/srv/srv0start.cc191
-rw-r--r--storage/xtradb/trx/trx0rseg.cc31
-rw-r--r--storage/xtradb/trx/trx0trx.cc3
34 files changed, 722 insertions, 698 deletions
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index 3d778c49012..d0fcd68c677 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -1133,9 +1133,7 @@ btr_create(
const btr_create_t* btr_redo_create_info,
mtr_t* mtr)
{
- ulint page_no;
buf_block_t* block;
- buf_frame_t* frame;
page_t* page;
page_zip_des_t* page_zip;
@@ -1170,33 +1168,28 @@ btr_create(
+ IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_TREE_ROOT_PAGE_NO,
FSP_UP, mtr);
- ut_ad(block->page.id.page_no() == IBUF_TREE_ROOT_PAGE_NO);
- } else {
- block = fseg_create(space, 0,
- PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
- }
- if (block == NULL) {
-
- return(FIL_NULL);
- }
+ if (block == NULL) {
+ return(FIL_NULL);
+ }
- page_no = block->page.id.page_no();
- frame = buf_block_get_frame(block);
+ ut_ad(block->page.id.page_no() == IBUF_TREE_ROOT_PAGE_NO);
- if (type & DICT_IBUF) {
- /* It is an insert buffer tree: initialize the free list */
buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
- ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
-
- flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
+ flst_init(block->frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ mtr);
} else {
- /* It is a non-ibuf tree: create a file segment for leaf
- pages */
+ block = fseg_create(space, 0,
+ PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
+
+ if (block == NULL) {
+ return(FIL_NULL);
+ }
+
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
- if (!fseg_create(space, page_no,
+ if (!fseg_create(space, block->page.id.page_no(),
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
segment before return. */
@@ -1287,7 +1280,7 @@ btr_create(
ut_ad(page_get_max_insert_size(page, 2) > 2 * BTR_PAGE_MAX_REC_SIZE);
- return(page_no);
+ return(block->page.id.page_no());
}
/** Free a B-tree except the root page. The root page MUST be freed after
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index 168225c5484..8d6d95a020e 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -3872,14 +3872,25 @@ buf_zip_decompress(
{
const byte* frame = block->page.zip.data;
ulint size = page_zip_get_size(&block->page.zip);
+ /* The tablespace will not be found if this function is called
+ during IMPORT. */
+ fil_space_t* space = fil_space_acquire_for_io(block->page.id.space());
+ const unsigned key_version = mach_read_from_4(
+ frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+ fil_space_crypt_t* crypt_data = space ? space->crypt_data : NULL;
+ const bool encrypted = crypt_data
+ && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED
+ && (!crypt_data->is_default_encryption()
+ || srv_encrypt_tables);
ut_ad(block->page.size.is_compressed());
ut_a(block->page.id.space() != 0);
if (UNIV_UNLIKELY(check && !page_zip_verify_checksum(frame, size))) {
- ib::error() << "Compressed page checksum mismatch "
- << block->page.id << "): stored: "
+ ib::error() << "Compressed page checksum mismatch for "
+ << (space ? space->chain.start->name : "")
+ << block->page.id << ": stored: "
<< mach_read_from_4(frame + FIL_PAGE_SPACE_OR_CHKSUM)
<< ", crc32: "
<< page_zip_calc_checksum(
@@ -3895,7 +3906,7 @@ buf_zip_decompress(
<< page_zip_calc_checksum(
frame, size, SRV_CHECKSUM_ALGORITHM_NONE);
- return(FALSE);
+ goto err_exit;
}
switch (fil_page_get_type(frame)) {
@@ -3903,15 +3914,16 @@ buf_zip_decompress(
case FIL_PAGE_RTREE:
if (page_zip_decompress(&block->page.zip,
block->frame, TRUE)) {
+ if (space) {
+ fil_space_release_for_io(space);
+ }
return(TRUE);
}
- ib::error() << "Unable to decompress space "
- << block->page.id.space()
- << " page " << block->page.id.page_no();
-
- return(FALSE);
-
+ ib::error() << "Unable to decompress "
+ << (space ? space->chain.start->name : "")
+ << block->page.id;
+ goto err_exit;
case FIL_PAGE_TYPE_ALLOCATED:
case FIL_PAGE_INODE:
case FIL_PAGE_IBUF_BITMAP:
@@ -3921,11 +3933,31 @@ buf_zip_decompress(
case FIL_PAGE_TYPE_ZBLOB2:
/* Copy to uncompressed storage. */
memcpy(block->frame, frame, block->page.size.physical());
+ if (space) {
+ fil_space_release_for_io(space);
+ }
+
return(TRUE);
}
ib::error() << "Unknown compressed page type "
- << fil_page_get_type(frame);
+ << fil_page_get_type(frame)
+ << " in " << (space ? space->chain.start->name : "")
+ << block->page.id;
+
+err_exit:
+ if (encrypted) {
+ ib::info() << "Row compressed page could be encrypted"
+ " with key_version " << key_version;
+ block->page.encrypted = true;
+ dict_set_encrypted_by_space(block->page.id.space());
+ } else {
+ dict_set_corrupted_by_space(block->page.id.space());
+ }
+
+ if (space) {
+ fil_space_release_for_io(space);
+ }
return(FALSE);
}
@@ -4526,12 +4558,21 @@ got_block:
/* Decompress the page while not holding
buf_pool->mutex or block->mutex. */
- /* Page checksum verification is already done when
- the page is read from disk. Hence page checksum
- verification is not necessary when decompressing the page. */
{
- bool success = buf_zip_decompress(block, FALSE);
- ut_a(success);
+ bool success = buf_zip_decompress(block, TRUE);
+
+ if (!success) {
+ buf_pool_mutex_enter(buf_pool);
+ buf_page_mutex_enter(fix_block);
+ buf_block_set_io_fix(fix_block, BUF_IO_NONE);
+ buf_page_mutex_exit(fix_block);
+
+ --buf_pool->n_pend_unzip;
+ buf_block_unfix(fix_block);
+ buf_pool_mutex_exit(buf_pool);
+ rw_lock_x_unlock(&fix_block->lock);
+ return NULL;
+ }
}
if (!recv_no_ibuf_operations) {
@@ -4634,19 +4675,12 @@ got_block:
goto loop;
}
- ib::info() << "innodb_change_buffering_debug evict "
- << page_id;
-
return(NULL);
}
buf_page_mutex_enter(fix_block);
if (buf_flush_page_try(buf_pool, fix_block)) {
-
- ib::info() << "innodb_change_buffering_debug flush "
- << page_id;
-
guess = fix_block;
goto loop;
@@ -5563,15 +5597,11 @@ buf_page_create(
memset(frame + FIL_PAGE_NEXT, 0xff, 4);
mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
- /* These 8 bytes are also repurposed for PageIO compression and must
- be reset when the frame is assigned to a new page id. See fil0fil.h.
-
-
- FIL_PAGE_FILE_FLUSH_LSN is used on the following pages:
+ /* FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION is only used on the
+ following pages:
(1) The first page of the InnoDB system tablespace (page 0:0)
- (2) FIL_RTREE_SPLIT_SEQ_NUM on R-tree pages .
-
- Therefore we don't transparently compress such pages. */
+ (2) FIL_RTREE_SPLIT_SEQ_NUM on R-tree pages
+ (3) key_version on encrypted pages (not page 0:0) */
memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
diff --git a/storage/innobase/buf/buf0dblwr.cc b/storage/innobase/buf/buf0dblwr.cc
index 3113424a894..b770e8483d9 100644
--- a/storage/innobase/buf/buf0dblwr.cc
+++ b/storage/innobase/buf/buf0dblwr.cc
@@ -162,11 +162,11 @@ buf_dblwr_init(
ut_zalloc_nokey(buf_size * sizeof(void*)));
}
-/****************************************************************//**
-Creates the doublewrite buffer to a new InnoDB installation. The header of the
-doublewrite buffer is placed on the trx system header page.
-@return true if successful, false if not. */
-MY_ATTRIBUTE((warn_unused_result))
+/** Create the doublewrite buffer if the doublewrite buffer header
+is not present in the TRX_SYS page.
+@return whether the operation succeeded
+@retval true if the doublewrite buffer exists or was created
+@retval false if the creation failed (too small first data file) */
bool
buf_dblwr_create()
{
@@ -181,12 +181,11 @@ buf_dblwr_create()
if (buf_dblwr) {
/* Already inited */
-
return(true);
}
start_again:
- mtr_start(&mtr);
+ mtr.start();
buf_dblwr_being_created = TRUE;
doublewrite = buf_dblwr_get(&mtr);
@@ -198,33 +197,49 @@ start_again:
buf_dblwr_init(doublewrite);
- mtr_commit(&mtr);
+ mtr.commit();
buf_dblwr_being_created = FALSE;
return(true);
- }
+ } else {
+ fil_space_t* space = fil_space_acquire(TRX_SYS_SPACE);
+ const bool fail = UT_LIST_GET_FIRST(space->chain)->size
+ < 3 * FSP_EXTENT_SIZE;
+ fil_space_release(space);
- ib::info() << "Doublewrite buffer not found: creating new";
+ if (fail) {
+ goto too_small;
+ }
+ }
block2 = fseg_create(TRX_SYS_SPACE, TRX_SYS_PAGE_NO,
TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_FSEG, &mtr);
- /* fseg_create acquires a second latch on the page,
- therefore we must declare it: */
-
- buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
-
if (block2 == NULL) {
- ib::error() << "Cannot create doublewrite buffer: you must"
- " increase your tablespace size."
- " Cannot continue operation.";
-
- /* The mini-transaction did not write anything yet;
- we merely failed to allocate a page. */
+too_small:
+ ib::error()
+ << "Cannot create doublewrite buffer: "
+ "the first file in innodb_data_file_path"
+ " must be at least "
+ << (3 * (FSP_EXTENT_SIZE * UNIV_PAGE_SIZE) >> 20)
+ << "M.";
mtr.commit();
return(false);
}
+ ib::info() << "Doublewrite buffer not found: creating new";
+
+ /* FIXME: After this point, the doublewrite buffer creation
+ is not atomic. The doublewrite buffer should not exist in
+ the InnoDB system tablespace file in the first place.
+ It could be located in separate optional file(s) in a
+ user-specified location. */
+
+ /* fseg_create acquires a second latch on the page,
+ therefore we must declare it: */
+
+ buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
+
fseg_header = doublewrite + TRX_SYS_DOUBLEWRITE_FSEG;
prev_page_no = 0;
@@ -516,6 +531,10 @@ buf_dblwr_process()
byte* unaligned_read_buf;
recv_dblwr_t& recv_dblwr = recv_sys->dblwr;
+ if (!buf_dblwr) {
+ return;
+ }
+
unaligned_read_buf = static_cast<byte*>(
ut_malloc_nokey(2 * UNIV_PAGE_SIZE));
diff --git a/storage/innobase/dict/dict0crea.cc b/storage/innobase/dict/dict0crea.cc
index 1b5b6ff3850..128f661b618 100644
--- a/storage/innobase/dict/dict0crea.cc
+++ b/storage/innobase/dict/dict0crea.cc
@@ -460,14 +460,9 @@ dict_build_tablespace_for_table(
mtr_start(&mtr);
mtr.set_named_space(table->space);
- bool ret = fsp_header_init(table->space,
- FIL_IBD_FILE_INITIAL_SIZE,
- &mtr);
+ fsp_header_init(table->space, FIL_IBD_FILE_INITIAL_SIZE, &mtr);
mtr_commit(&mtr);
- if (!ret) {
- return(DB_ERROR);
- }
} else {
ut_ad(dict_tf_get_rec_format(table->flags)
!= REC_FORMAT_COMPRESSED);
diff --git a/storage/innobase/fil/fil0crypt.cc b/storage/innobase/fil/fil0crypt.cc
index 0026e6e2735..5cfacc5bcd8 100644
--- a/storage/innobase/fil/fil0crypt.cc
+++ b/storage/innobase/fil/fil0crypt.cc
@@ -831,7 +831,7 @@ fil_space_decrypt(
Calculate post encryption checksum
@param[in] page_size page size
@param[in] dst_frame Block where checksum is calculated
-@return page checksum or BUF_NO_CHECKSUM_MAGIC
+@return page checksum
not needed. */
UNIV_INTERN
uint32_t
@@ -839,34 +839,11 @@ fil_crypt_calculate_checksum(
const page_size_t& page_size,
const byte* dst_frame)
{
- uint32_t checksum = 0;
- srv_checksum_algorithm_t algorithm =
- static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
-
- if (!page_size.is_compressed()) {
- switch (algorithm) {
- case SRV_CHECKSUM_ALGORITHM_CRC32:
- case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- checksum = buf_calc_page_crc32(dst_frame);
- break;
- case SRV_CHECKSUM_ALGORITHM_INNODB:
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
- checksum = (ib_uint32_t) buf_calc_page_new_checksum(
- dst_frame);
- break;
- case SRV_CHECKSUM_ALGORITHM_NONE:
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
- checksum = BUF_NO_CHECKSUM_MAGIC;
- break;
- /* no default so the compiler will emit a warning
- * if new enum is added and not handled here */
- }
- } else {
- checksum = page_zip_calc_checksum(dst_frame, page_size.physical(),
- algorithm);
- }
-
- return checksum;
+ /* For encrypted tables we use only crc32 and strict_crc32 */
+ return page_size.is_compressed()
+ ? page_zip_calc_checksum(dst_frame, page_size.physical(),
+ SRV_CHECKSUM_ALGORITHM_CRC32)
+ : buf_calc_page_crc32(dst_frame);
}
/***********************************************************************/
@@ -2492,15 +2469,8 @@ fil_space_verify_crypt_checksum(
return false;
}
- srv_checksum_algorithm_t algorithm =
- static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
- /* If no checksum is used, can't continue checking. */
- if (algorithm == SRV_CHECKSUM_ALGORITHM_NONE) {
- return(true);
- }
-
/* Read stored post encryption checksum. */
- ib_uint32_t checksum = mach_read_from_4(
+ uint32_t checksum = mach_read_from_4(
page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4);
/* Declare empty pages non-corrupted */
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index 966c160f4bd..72358e7628b 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -4282,12 +4282,14 @@ fil_ibd_open(
df_default.close();
tablespaces_found--;
}
+
if (df_dict.is_open() && !df_dict.is_valid()) {
df_dict.close();
/* Leave dict.filepath so that SYS_DATAFILES
can be corrected below. */
tablespaces_found--;
}
+
if (df_remote.is_open() && !df_remote.is_valid()) {
df_remote.close();
tablespaces_found--;
@@ -5151,23 +5153,16 @@ fil_report_invalid_page_access(
ulint len, /*!< in: I/O length */
bool is_read) /*!< in: I/O type */
{
- ib::error()
- << "Trying to access page number " << block_offset << " in"
+ ib::fatal()
+ << "Trying to " << (is_read ? "read" : "write")
+ << " page number " << block_offset << " in"
" space " << space_id << ", space name " << space_name << ","
" which is outside the tablespace bounds. Byte offset "
- << byte_offset << ", len " << len << ", i/o type " <<
- (is_read ? "read" : "write")
- << ". If you get this error at mysqld startup, please check"
- " that your my.cnf matches the ibdata files that you have in"
- " the MySQL server.";
-
- ib::error() << "Server exits"
-#ifdef UNIV_DEBUG
- << " at " << __FILE__ << "[" << __LINE__ << "]"
-#endif
- << ".";
-
- _exit(1);
+ << byte_offset << ", len " << len <<
+ (space_id == 0 && !srv_was_started
+ ? "Please check that the configuration matches"
+ " the InnoDB system tablespace location (ibdata files)"
+ : "");
}
/** Reads or writes data. This operation could be asynchronous (aio).
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index 57b6c8de825..467fbbd557d 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -690,17 +690,12 @@ fsp_header_init_fields(
flags);
}
-/** Initializes the space header of a new created space and creates also the
-insert buffer tree root if space == 0.
+/** Initialize a tablespace header.
@param[in] space_id space id
@param[in] size current size in blocks
-@param[in,out] mtr min-transaction
-@return true on success, otherwise false. */
-bool
-fsp_header_init(
- ulint space_id,
- ulint size,
- mtr_t* mtr)
+@param[in,out] mtr mini-transaction */
+void
+fsp_header_init(ulint space_id, ulint size, mtr_t* mtr)
{
fsp_header_t* header;
buf_block_t* block;
@@ -752,19 +747,9 @@ fsp_header_init(
fsp_fill_free_list(!is_system_tablespace(space_id),
space, header, mtr);
- if (space_id == srv_sys_space.space_id()) {
- if (btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
- 0, univ_page_size, DICT_IBUF_ID_MIN + space_id,
- dict_ind_redundant, NULL, mtr) == FIL_NULL) {
- return(false);
- }
- }
-
if (space->crypt_data) {
space->crypt_data->write_page0(space, page, mtr);
}
-
- return(true);
}
/**********************************************************************//**
@@ -2096,7 +2081,6 @@ fseg_create_general(
inode = fsp_alloc_seg_inode(space, space_header, mtr);
if (inode == NULL) {
-
goto funct_exit;
}
diff --git a/storage/innobase/fsp/fsp0sysspace.cc b/storage/innobase/fsp/fsp0sysspace.cc
index 974140fe565..fa0203586fb 100644
--- a/storage/innobase/fsp/fsp0sysspace.cc
+++ b/storage/innobase/fsp/fsp0sysspace.cc
@@ -834,17 +834,6 @@ SysTablespace::check_file_spec(
}
}
- /* We assume doublewirte blocks in the first data file. */
- if (err == DB_SUCCESS && *create_new_db
- && begin->m_size < TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 3) {
- ib::error() << "The " << name() << " data file "
- << "'" << begin->name() << "' must be at least "
- << TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * 3 * UNIV_PAGE_SIZE
- / (1024 * 1024) << " MB";
-
- err = DB_ERROR;
- }
-
return(err);
}
diff --git a/storage/innobase/include/buf0dblwr.h b/storage/innobase/include/buf0dblwr.h
index ef522be4d9a..598609e2be4 100644
--- a/storage/innobase/include/buf0dblwr.h
+++ b/storage/innobase/include/buf0dblwr.h
@@ -38,10 +38,11 @@ extern buf_dblwr_t* buf_dblwr;
/** Set to TRUE when the doublewrite buffer is being created */
extern ibool buf_dblwr_being_created;
-/****************************************************************//**
-Creates the doublewrite buffer to a new InnoDB installation. The header of the
-doublewrite buffer is placed on the trx system header page.
-@return true if successful, false if not. */
+/** Create the doublewrite buffer if the doublewrite buffer header
+is not present in the TRX_SYS page.
+@return whether the operation succeeded
+@retval true if the doublewrite buffer exists or was created
+@retval false if the creation failed (too small first data file) */
MY_ATTRIBUTE((warn_unused_result))
bool
buf_dblwr_create();
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index f6fee72300c..63fc211c88d 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -397,18 +397,12 @@ fsp_header_init_fields(
ulint space_id, /*!< in: space id */
ulint flags); /*!< in: tablespace flags (FSP_SPACE_FLAGS):
0, or table->flags if newer than COMPACT */
-
-/** Initializes the space header of a new created space and creates also the
-insert buffer tree root if space == 0.
+/** Initialize a tablespace header.
@param[in] space_id space id
@param[in] size current size in blocks
-@param[in,out] mtr min-transaction
-@return true on success, otherwise false. */
-bool
-fsp_header_init(
- ulint space_id,
- ulint size,
- mtr_t* mtr);
+@param[in,out] mtr mini-transaction */
+void
+fsp_header_init(ulint space_id, ulint size, mtr_t* mtr);
/**********************************************************************//**
Increases the space size field of a space. */
diff --git a/storage/innobase/include/trx0rseg.h b/storage/innobase/include/trx0rseg.h
index 4c162526384..3078aa8faf1 100644
--- a/storage/innobase/include/trx0rseg.h
+++ b/storage/innobase/include/trx0rseg.h
@@ -110,9 +110,12 @@ void
trx_rseg_mem_free(trx_rseg_t* rseg);
/** Create a persistent rollback segment.
-@param[in] space_id system or undo tablespace id */
+@param[in] space_id system or undo tablespace id
+@return pointer to new rollback segment
+@retval NULL on failure */
trx_rseg_t*
-trx_rseg_create(ulint space_id);
+trx_rseg_create(ulint space_id)
+ MY_ATTRIBUTE((warn_unused_result));
/** Create the temporary rollback segments. */
void
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h
index 75753b53467..6274dec9f9d 100644
--- a/storage/innobase/include/trx0trx.h
+++ b/storage/innobase/include/trx0trx.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2016, 2017, MariaDB Corporation.
+Copyright (c) 2015, 2017, 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
diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc
index 06ed058f18e..56aa5626450 100644
--- a/storage/innobase/srv/srv0srv.cc
+++ b/storage/innobase/srv/srv0srv.cc
@@ -2537,7 +2537,7 @@ suspend_thread:
case SRV_SHUTDOWN_CLEANUP:
if (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP
&& srv_fast_shutdown < 2) {
- srv_shutdown(srv_fast_shutdown == 1);
+ srv_shutdown(srv_fast_shutdown == 0);
}
srv_suspend_thread(slot);
my_thread_end();
diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc
index c89a11d821b..99843719008 100644
--- a/storage/innobase/srv/srv0start.cc
+++ b/storage/innobase/srv/srv0start.cc
@@ -1334,7 +1334,7 @@ srv_init_abort_low(
dberr_t err)
{
if (create_new_db) {
- ib::error() << "InnoDB Database creation was aborted"
+ ib::error() << "Database creation was aborted"
#ifdef UNIV_DEBUG
" at " << innobase_basename(file) << "[" << line << "]"
#endif /* UNIV_DEBUG */
@@ -2131,14 +2131,24 @@ files_checked:
mtr_start(&mtr);
- bool ret = fsp_header_init(0, sum_of_new_sizes, &mtr);
+ fsp_header_init(0, sum_of_new_sizes, &mtr);
+
+ compile_time_assert(TRX_SYS_SPACE == 0);
+ compile_time_assert(IBUF_SPACE_ID == 0);
+
+ ulint ibuf_root = btr_create(
+ DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
+ 0, univ_page_size, DICT_IBUF_ID_MIN,
+ dict_ind_redundant, NULL, &mtr);
mtr_commit(&mtr);
- if (!ret) {
+ if (ibuf_root == FIL_NULL) {
return(srv_init_abort(DB_ERROR));
}
+ ut_ad(ibuf_root == IBUF_TREE_ROOT_PAGE_NO);
+
/* To maintain backward compatibility we create only
the first rollback segment before the double write buffer.
All the remaining rollback segments will be created later,
@@ -2286,7 +2296,7 @@ files_checked:
const ulint sum_of_data_file_sizes
= srv_sys_space.get_sum_of_sizes();
/* Compare the system tablespace file size to what is
- stored in FSP_SIZE. In open_or_create_data_files()
+ stored in FSP_SIZE. In srv_sys_space.open_or_create()
we already checked that the file sizes match the
innodb_data_file_path specification. */
if (srv_read_only_mode
@@ -2393,7 +2403,6 @@ files_checked:
}
}
-
/* Validate a few system page types that were left
uninitialized by older versions of MySQL. */
if (!high_level_read_only) {
diff --git a/storage/innobase/trx/trx0rseg.cc b/storage/innobase/trx/trx0rseg.cc
index 663566cf26f..b48f3e18f1b 100644
--- a/storage/innobase/trx/trx0rseg.cc
+++ b/storage/innobase/trx/trx0rseg.cc
@@ -263,7 +263,9 @@ trx_rseg_array_init()
}
/** Create a persistent rollback segment.
-@param[in] space_id system or undo tablespace id */
+@param[in] space_id system or undo tablespace id
+@return pointer to new rollback segment
+@retval NULL on failure */
trx_rseg_t*
trx_rseg_create(ulint space_id)
{
diff --git a/storage/xtradb/btr/btr0btr.cc b/storage/xtradb/btr/btr0btr.cc
index d84c93f8b3e..e66599e206d 100644
--- a/storage/xtradb/btr/btr0btr.cc
+++ b/storage/xtradb/btr/btr0btr.cc
@@ -2,7 +2,7 @@
Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2014, 2017, MariaDB Corporation
+Copyright (c) 2014, 2017, 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
@@ -1703,9 +1703,7 @@ btr_create(
dict_index_t* index, /*!< in: index */
mtr_t* mtr) /*!< in: mini-transaction handle */
{
- ulint page_no;
buf_block_t* block;
- buf_frame_t* frame;
page_t* page;
page_zip_des_t* page_zip;
@@ -1720,6 +1718,10 @@ btr_create(
space, 0,
IBUF_HEADER + IBUF_TREE_SEG_HEADER, mtr);
+ if (ibuf_hdr_block == NULL) {
+ return(FIL_NULL);
+ }
+
buf_block_dbg_add_level(
ibuf_hdr_block, SYNC_IBUF_TREE_NODE_NEW);
@@ -1733,7 +1735,17 @@ btr_create(
+ IBUF_HEADER + IBUF_TREE_SEG_HEADER,
IBUF_TREE_ROOT_PAGE_NO,
FSP_UP, mtr);
+
+ if (block == NULL) {
+ return(FIL_NULL);
+ }
+
ut_ad(buf_block_get_page_no(block) == IBUF_TREE_ROOT_PAGE_NO);
+
+ buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
+
+ flst_init(block->frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
+ mtr);
} else {
#ifdef UNIV_BLOB_DEBUG
if ((type & DICT_CLUSTERED) && !index->blobs) {
@@ -1745,34 +1757,19 @@ btr_create(
#endif /* UNIV_BLOB_DEBUG */
block = fseg_create(space, 0,
PAGE_HEADER + PAGE_BTR_SEG_TOP, mtr);
- }
- if (block == NULL) {
-
- return(FIL_NULL);
- }
-
- page_no = buf_block_get_page_no(block);
- frame = buf_block_get_frame(block);
-
- if (type & DICT_IBUF) {
- /* It is an insert buffer tree: initialize the free list */
- buf_block_dbg_add_level(block, SYNC_IBUF_TREE_NODE_NEW);
-
- ut_ad(page_no == IBUF_TREE_ROOT_PAGE_NO);
+ if (block == NULL) {
+ return(FIL_NULL);
+ }
- flst_init(frame + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST, mtr);
- } else {
- /* It is a non-ibuf tree: create a file segment for leaf
- pages */
buf_block_dbg_add_level(block, SYNC_TREE_NODE_NEW);
- if (!fseg_create(space, page_no,
+ if (!fseg_create(space, buf_block_get_page_no(block),
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
segment before return. */
- btr_free_root(space, zip_size, page_no, mtr);
-
+ btr_free_root(space, zip_size,
+ buf_block_get_page_no(block), mtr);
return(FIL_NULL);
}
@@ -1816,7 +1813,7 @@ btr_create(
ut_ad(page_get_max_insert_size(page, 2) > 2 * BTR_PAGE_MAX_REC_SIZE);
- return(page_no);
+ return(buf_block_get_page_no(block));
}
/************************************************************//**
diff --git a/storage/xtradb/buf/buf0buf.cc b/storage/xtradb/buf/buf0buf.cc
index 4678b0eb6a8..290712e52af 100644
--- a/storage/xtradb/buf/buf0buf.cc
+++ b/storage/xtradb/buf/buf0buf.cc
@@ -86,6 +86,15 @@ bool
buf_page_decrypt_after_read(buf_page_t* bpage, fil_space_t* space)
MY_ATTRIBUTE((nonnull));
+/********************************************************************//**
+Mark a table with the specified space pointed by bpage->space corrupted.
+Also remove the bpage from LRU list.
+@param[in,out] bpage Block */
+static
+void
+buf_mark_space_corrupt(
+ buf_page_t* bpage);
+
/* prototypes for new functions added to ha_innodb.cc */
trx_t* innobase_get_trx();
@@ -2541,17 +2550,26 @@ buf_zip_decompress(
{
const byte* frame = block->page.zip.data;
ulint size = page_zip_get_size(&block->page.zip);
+ /* Space is not found if this function is called during IMPORT */
+ fil_space_t* space = fil_space_acquire_for_io(block->page.space);
+ const unsigned key_version = mach_read_from_4(frame +
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+ fil_space_crypt_t* crypt_data = space ? space->crypt_data : NULL;
+ const bool encrypted = crypt_data
+ && crypt_data->type != CRYPT_SCHEME_UNENCRYPTED
+ && (!crypt_data->is_default_encryption()
+ || srv_encrypt_tables);
ut_ad(buf_block_get_zip_size(block));
ut_a(buf_block_get_space(block) != 0);
if (UNIV_UNLIKELY(check && !page_zip_verify_checksum(frame, size))) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: compressed page checksum mismatch"
- " (space %u page %u): stored: %lu, crc32: %lu "
- "innodb: %lu, none: %lu\n",
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Compressed page checksum mismatch"
+ " for %s [%u:%u]: stored: " ULINTPF ", crc32: " ULINTPF
+ " innodb: " ULINTPF ", none: " ULINTPF ".",
+ space ? space->chain.start->name : "N/A",
block->page.space, block->page.offset,
mach_read_from_4(frame + FIL_PAGE_SPACE_OR_CHKSUM),
page_zip_calc_checksum(frame, size,
@@ -2560,22 +2578,28 @@ buf_zip_decompress(
SRV_CHECKSUM_ALGORITHM_INNODB),
page_zip_calc_checksum(frame, size,
SRV_CHECKSUM_ALGORITHM_NONE));
- return(FALSE);
+ goto err_exit;
}
switch (fil_page_get_type(frame)) {
- case FIL_PAGE_INDEX:
+ case FIL_PAGE_INDEX: {
+
if (page_zip_decompress(&block->page.zip,
block->frame, TRUE)) {
+ if (space) {
+ fil_space_release_for_io(space);
+ }
return(TRUE);
}
- fprintf(stderr,
- "InnoDB: unable to decompress space %u page %u\n",
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Unable to decompress space %s [%u:%u]",
+ space ? space->chain.start->name : "N/A",
block->page.space,
block->page.offset);
- return(FALSE);
+ goto err_exit;
+ }
case FIL_PAGE_TYPE_ALLOCATED:
case FIL_PAGE_INODE:
case FIL_PAGE_IBUF_BITMAP:
@@ -2586,14 +2610,36 @@ buf_zip_decompress(
/* Copy to uncompressed storage. */
memcpy(block->frame, frame,
buf_block_get_zip_size(block));
+
+ if (space) {
+ fil_space_release_for_io(space);
+ }
+
return(TRUE);
}
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: unknown compressed page"
- " type %lu\n",
- fil_page_get_type(frame));
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Unknown compressed page in %s [%u:%u]"
+ " type %s [" ULINTPF "].",
+ space ? space->chain.start->name : "N/A",
+ block->page.space, block->page.offset,
+ fil_get_page_type_name(fil_page_get_type(frame)), fil_page_get_type(frame));
+
+err_exit:
+ if (encrypted) {
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Row compressed page could be encrypted with key_version %u.",
+ key_version);
+ block->page.encrypted = true;
+ dict_set_encrypted_by_space(block->page.space);
+ } else {
+ dict_set_corrupted_by_space(block->page.space);
+ }
+
+ if (space) {
+ fil_space_release_for_io(space);
+ }
+
return(FALSE);
}
@@ -3076,9 +3122,9 @@ loop:
}
ib_logf(IB_LOG_LEVEL_FATAL, "Unable"
- " to read tablespace %lu page no"
- " %lu into the buffer pool after"
- " %lu attempts"
+ " to read tablespace " ULINTPF " page no "
+ ULINTPF " into the buffer pool after "
+ ULINTPF " attempts."
" The most probable cause"
" of this error may be that the"
" table has been corrupted."
@@ -3291,12 +3337,21 @@ got_block:
/* Decompress the page while not holding
any buf_pool or block->mutex. */
- /* Page checksum verification is already done when
- the page is read from disk. Hence page checksum
- verification is not necessary when decompressing the page. */
{
- bool success = buf_zip_decompress(block, FALSE);
- ut_a(success);
+ bool success = buf_zip_decompress(block, TRUE);
+
+ if (!success) {
+ buf_block_mutex_enter(fix_block);
+ buf_block_set_io_fix(fix_block, BUF_IO_NONE);
+ buf_block_mutex_exit(fix_block);
+
+ os_atomic_decrement_ulint(&buf_pool->n_pend_unzip, 1);
+ rw_lock_x_unlock(&fix_block->lock);
+ mutex_enter(&buf_pool->LRU_list_mutex);
+ buf_block_unfix(fix_block);
+ mutex_exit(&buf_pool->LRU_list_mutex);
+ return NULL;
+ }
}
if (!recv_no_ibuf_operations) {
@@ -3394,16 +3449,10 @@ got_block:
goto loop;
}
- fprintf(stderr,
- "innodb_change_buffering_debug evict %u %u\n",
- (unsigned) space, (unsigned) offset);
return(NULL);
}
if (buf_flush_page_try(buf_pool, fix_block)) {
- fprintf(stderr,
- "innodb_change_buffering_debug flush %u %u\n",
- (unsigned) space, (unsigned) offset);
guess = fix_block;
goto loop;
}
@@ -4374,11 +4423,11 @@ buf_page_create(
memset(frame + FIL_PAGE_NEXT, 0xff, 4);
mach_write_to_2(frame + FIL_PAGE_TYPE, FIL_PAGE_TYPE_ALLOCATED);
- /* Reset to zero the file flush lsn field in the page; if the first
- page of an ibdata file is 'created' in this function into the buffer
- pool then we lose the original contents of the file flush lsn stamp.
- Then InnoDB could in a crash recovery print a big, false, corruption
- warning if the stamp contains an lsn bigger than the ib_logfile lsn. */
+ /* FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION is only used on the
+ following pages:
+ (1) The first page of the InnoDB system tablespace (page 0:0)
+ (2) FIL_RTREE_SPLIT_SEQ_NUM on R-tree pages
+ (3) key_version on encrypted pages (not page 0:0) */
memset(frame + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION, 0, 8);
diff --git a/storage/xtradb/buf/buf0dblwr.cc b/storage/xtradb/buf/buf0dblwr.cc
index c0c52deb57f..49371f9a6f1 100644
--- a/storage/xtradb/buf/buf0dblwr.cc
+++ b/storage/xtradb/buf/buf0dblwr.cc
@@ -175,13 +175,14 @@ buf_dblwr_init(
mem_zalloc(buf_size * sizeof(void*)));
}
-/****************************************************************//**
-Creates the doublewrite buffer to a new InnoDB installation. The header of the
-doublewrite buffer is placed on the trx system header page. */
+/** Create the doublewrite buffer if the doublewrite buffer header
+is not present in the TRX_SYS page.
+@return whether the operation succeeded
+@retval true if the doublewrite buffer exists or was created
+@retval false if the creation failed (too small first data file) */
UNIV_INTERN
-void
-buf_dblwr_create(void)
-/*==================*/
+bool
+buf_dblwr_create()
{
buf_block_t* block2;
buf_block_t* new_block;
@@ -194,8 +195,7 @@ buf_dblwr_create(void)
if (buf_dblwr) {
/* Already inited */
-
- return;
+ return(true);
}
start_again:
@@ -213,39 +213,59 @@ start_again:
mtr_commit(&mtr);
buf_dblwr_being_created = FALSE;
- return;
+ return(true);
}
- ib_logf(IB_LOG_LEVEL_INFO,
- "Doublewrite buffer not found: creating new");
-
if (buf_pool_get_curr_size()
< ((TRX_SYS_DOUBLEWRITE_BLOCKS * TRX_SYS_DOUBLEWRITE_BLOCK_SIZE
+ FSP_EXTENT_SIZE / 2 + 100)
* UNIV_PAGE_SIZE)) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Cannot create doublewrite buffer: you must "
- "increase your buffer pool size. Cannot continue "
- "operation.");
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Cannot create doublewrite buffer: "
+ "innodb_buffer_pool_size is too small.");
+ mtr_commit(&mtr);
+ return(false);
+ } else {
+ fil_space_t* space = fil_space_acquire(TRX_SYS_SPACE);
+ const bool fail = UT_LIST_GET_FIRST(space->chain)->size
+ < 3 * FSP_EXTENT_SIZE;
+ fil_space_release(space);
+
+ if (fail) {
+ goto too_small;
+ }
}
block2 = fseg_create(TRX_SYS_SPACE, TRX_SYS_PAGE_NO,
TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_FSEG, &mtr);
+ if (block2 == NULL) {
+too_small:
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Cannot create doublewrite buffer: "
+ "the first file in innodb_data_file_path"
+ " must be at least %luM.",
+ 3 * (FSP_EXTENT_SIZE * UNIV_PAGE_SIZE) >> 20);
+ mtr_commit(&mtr);
+ return(false);
+ }
+
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Doublewrite buffer not found: creating new");
+
+ /* FIXME: After this point, the doublewrite buffer creation
+ is not atomic. The doublewrite buffer should not exist in
+ the InnoDB system tablespace file in the first place.
+ It could be located in separate optional file(s) in a
+ user-specified location. */
+
/* fseg_create acquires a second latch on the page,
therefore we must declare it: */
buf_block_dbg_add_level(block2, SYNC_NO_ORDER_CHECK);
- if (block2 == NULL) {
- ib_logf(IB_LOG_LEVEL_FATAL,
- "Cannot create doublewrite buffer: you must "
- "increase your tablespace size. "
- "Cannot continue operation.");
- }
-
fseg_header = doublewrite + TRX_SYS_DOUBLEWRITE_FSEG;
prev_page_no = 0;
@@ -482,6 +502,14 @@ buf_dblwr_process()
byte* unaligned_read_buf;
recv_dblwr_t& recv_dblwr = recv_sys->dblwr;
+ if (!buf_dblwr) {
+ return;
+ }
+
+ ib_logf(IB_LOG_LEVEL_INFO,
+ "Restoring possible half-written data pages "
+ "from the doublewrite buffer...");
+
unaligned_read_buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
read_buf = static_cast<byte*>(
diff --git a/storage/xtradb/fil/fil0crypt.cc b/storage/xtradb/fil/fil0crypt.cc
index b40fd1dedaa..46ed7d37e42 100644
--- a/storage/xtradb/fil/fil0crypt.cc
+++ b/storage/xtradb/fil/fil0crypt.cc
@@ -887,7 +887,7 @@ fil_space_decrypt(
Calculate post encryption checksum
@param[in] zip_size zip_size or 0
@param[in] dst_frame Block where checksum is calculated
-@return page checksum or BUF_NO_CHECKSUM_MAGIC
+@return page checksum
not needed. */
UNIV_INTERN
ulint
@@ -896,30 +896,13 @@ fil_crypt_calculate_checksum(
const byte* dst_frame)
{
ib_uint32_t checksum = 0;
- srv_checksum_algorithm_t algorithm =
- static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
+ /* For encrypted tables we use only crc32 and strict_crc32 */
if (zip_size == 0) {
- switch (algorithm) {
- case SRV_CHECKSUM_ALGORITHM_CRC32:
- case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32:
- checksum = buf_calc_page_crc32(dst_frame);
- break;
- case SRV_CHECKSUM_ALGORITHM_INNODB:
- case SRV_CHECKSUM_ALGORITHM_STRICT_INNODB:
- checksum = (ib_uint32_t) buf_calc_page_new_checksum(
- dst_frame);
- break;
- case SRV_CHECKSUM_ALGORITHM_NONE:
- case SRV_CHECKSUM_ALGORITHM_STRICT_NONE:
- checksum = BUF_NO_CHECKSUM_MAGIC;
- break;
- /* no default so the compiler will emit a warning
- * if new enum is added and not handled here */
- }
+ checksum = buf_calc_page_crc32(dst_frame);
} else {
checksum = page_zip_calc_checksum(dst_frame, zip_size,
- algorithm);
+ SRV_CHECKSUM_ALGORITHM_CRC32);
}
return checksum;
@@ -953,14 +936,6 @@ fil_space_verify_crypt_checksum(
return(false);
}
- srv_checksum_algorithm_t algorithm =
- static_cast<srv_checksum_algorithm_t>(srv_checksum_algorithm);
-
- /* If no checksum is used, can't continue checking. */
- if (algorithm == SRV_CHECKSUM_ALGORITHM_NONE) {
- return(true);
- }
-
/* Read stored post encryption checksum. */
ib_uint32_t checksum = mach_read_from_4(
page + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION + 4);
@@ -1044,7 +1019,6 @@ fil_space_verify_crypt_checksum(
checksum1 = mach_read_from_4(
page + UNIV_PAGE_SIZE - FIL_PAGE_END_LSN_OLD_CHKSUM);
valid = (buf_page_is_checksum_valid_crc32(page,checksum1,checksum2)
- || buf_page_is_checksum_valid_none(page,checksum1,checksum2)
|| buf_page_is_checksum_valid_innodb(page,checksum1, checksum2));
}
diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc
index 09ba89459ad..d979c05c9a6 100644
--- a/storage/xtradb/fil/fil0fil.cc
+++ b/storage/xtradb/fil/fil0fil.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2014, 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2014, 2017, 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
@@ -2265,99 +2265,70 @@ fil_set_max_space_id_if_bigger(
mutex_exit(&fil_system->mutex);
}
-/****************************************************************//**
-Writes the flushed lsn and the latest archived log number to the page header
-of the first page of a data file of the system tablespace (space 0),
-which is uncompressed. */
-static MY_ATTRIBUTE((warn_unused_result))
+/** Write the flushed LSN to the page header of the first page in the
+system tablespace.
+@param[in] lsn flushed LSN
+@return DB_SUCCESS or error number */
dberr_t
-fil_write_lsn_and_arch_no_to_file(
-/*==============================*/
- ulint space, /*!< in: space to write to */
- ulint sum_of_sizes, /*!< in: combined size of previous files
- in space, in database pages */
- lsn_t lsn, /*!< in: lsn to write */
- ulint arch_log_no MY_ATTRIBUTE((unused)))
- /*!< in: archived log number to write */
+fil_write_flushed_lsn(
+ lsn_t lsn)
{
byte* buf1;
byte* buf;
dberr_t err;
- buf1 = static_cast<byte*>(mem_alloc(2 * UNIV_PAGE_SIZE));
+ buf1 = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE));
- err = fil_read(TRUE, space, 0, sum_of_sizes, 0,
- UNIV_PAGE_SIZE, buf, NULL, 0);
- if (err == DB_SUCCESS) {
- mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
- lsn);
-
- err = fil_write(TRUE, space, 0, sum_of_sizes, 0,
- UNIV_PAGE_SIZE, buf, NULL, 0);
- }
-
- mem_free(buf1);
-
- return(err);
-}
-
-/****************************************************************//**
-Writes the flushed lsn and the latest archived log number to the page
-header of the first page of each data file in the system tablespace.
-@return DB_SUCCESS or error number */
-UNIV_INTERN
-dberr_t
-fil_write_flushed_lsn_to_data_files(
-/*================================*/
- lsn_t lsn, /*!< in: lsn to write */
- ulint arch_log_no) /*!< in: latest archived log file number */
-{
- fil_space_t* space;
- fil_node_t* node;
- dberr_t err;
-
- mutex_enter(&fil_system->mutex);
-
- for (space = UT_LIST_GET_FIRST(fil_system->space_list);
- space != NULL;
- space = UT_LIST_GET_NEXT(space_list, space)) {
-
- /* We only write the lsn to all existing data files which have
- been open during the lifetime of the mysqld process; they are
- represented by the space objects in the tablespace memory
- cache. Note that all data files in the system tablespace 0
- and the UNDO log tablespaces (if separate) are always open. */
+ /* Acquire system tablespace */
+ fil_space_t* space = fil_space_acquire(0);
- if (space->purpose == FIL_TABLESPACE
- && !fil_is_user_tablespace_id(space->id)) {
- ulint sum_of_sizes = 0;
+ /* If tablespace is not encrypted, stamp flush_lsn to
+ first page of all system tablespace datafiles to avoid
+ unnecessary error messages on possible downgrade. */
+ if (space->crypt_data->min_key_version == 0) {
+ fil_node_t* node;
+ ulint sum_of_sizes = 0;
- for (node = UT_LIST_GET_FIRST(space->chain);
- node != NULL;
- node = UT_LIST_GET_NEXT(chain, node)) {
-
- mutex_exit(&fil_system->mutex);
-
- err = fil_write_lsn_and_arch_no_to_file(
- space->id, sum_of_sizes, lsn,
- arch_log_no);
+ for (node = UT_LIST_GET_FIRST(space->chain);
+ node != NULL;
+ node = UT_LIST_GET_NEXT(chain, node)) {
- if (err != DB_SUCCESS) {
+ err = fil_read(TRUE, 0, 0, sum_of_sizes, 0,
+ UNIV_PAGE_SIZE, buf, NULL, 0);
- return(err);
- }
+ if (err == DB_SUCCESS) {
+ mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ lsn);
- mutex_enter(&fil_system->mutex);
+ err = fil_write(TRUE, 0, 0, sum_of_sizes, 0,
+ UNIV_PAGE_SIZE, buf, NULL, 0);
sum_of_sizes += node->size;
}
}
+ } else {
+ /* When system tablespace is encrypted stamp flush_lsn to
+ only the first page of the first datafile (rest of pages
+ are encrypted). */
+ err = fil_read(TRUE, 0, 0, 0, 0,
+ UNIV_PAGE_SIZE, buf, NULL, 0);
+
+ if (err == DB_SUCCESS) {
+ mach_write_to_8(buf + FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION,
+ lsn);
+
+ err = fil_write(TRUE, 0, 0, 0, 0,
+ UNIV_PAGE_SIZE, buf, NULL, 0);
+ }
}
- mutex_exit(&fil_system->mutex);
+ fil_flush_file_spaces(FIL_TABLESPACE);
+ fil_space_release(space);
- return(DB_SUCCESS);
+ ut_free(buf1);
+
+ return(err);
}
/** Check the consistency of the first data page of a tablespace
@@ -2410,30 +2381,29 @@ fil_check_first_page(const page_t* page, ulint space_id, ulint flags)
return("inconsistent data in space header");
}
-/*******************************************************************//**
-Reads the flushed lsn, arch no, space_id and tablespace flag fields from
-the first page of a data file at database startup.
+/** Reads the flushed lsn, arch no, space_id and tablespace flag fields from
+the first page of a first data file at database startup.
+@param[in] data_file open data file
+@param[in] one_read_only true if first datafile is already
+ read
+@param[out] flags FSP_SPACE_FLAGS
+@param[out] space_id tablepspace ID
+@param[out] flushed_lsn flushed lsn value
+@param[out] crypt_data encryption crypt data
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
UNIV_INTERN
const char*
fil_read_first_page(
-/*================*/
- pfs_os_file_t data_file, /*!< in: open data file */
- ibool one_read_already, /*!< in: TRUE if min and max
- parameters below already
- contain sensible data */
- ulint* flags, /*!< out: FSP_SPACE_FLAGS */
- ulint* space_id, /*!< out: tablespace ID */
- lsn_t* min_flushed_lsn, /*!< out: min of flushed
- lsn values in data files */
- lsn_t* max_flushed_lsn, /*!< out: max of flushed
- lsn values in data files */
- fil_space_crypt_t** crypt_data) /*< out: crypt data */
+ pfs_os_file_t data_file,
+ ibool one_read_already,
+ ulint* flags,
+ ulint* space_id,
+ lsn_t* flushed_lsn,
+ fil_space_crypt_t** crypt_data)
{
byte* buf;
byte* page;
- lsn_t flushed_lsn;
const char* check_msg = NULL;
fil_space_crypt_t* cdata;
@@ -2450,6 +2420,7 @@ fil_read_first_page(
return "File size is less than minimum";
}
}
+
buf = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE));
/* Align the memory for a possible read from a raw device */
@@ -2468,6 +2439,11 @@ fil_read_first_page(
*space_id = fsp_header_get_space_id(page);
*flags = fsp_header_get_flags(page);
+ if (flushed_lsn) {
+ *flushed_lsn = mach_read_from_8(page +
+ FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+ }
+
if (!fsp_flags_is_valid(*flags)) {
ulint cflags = fsp_flags_convert_from_101(*flags);
if (cflags == ULINT_UNDEFINED) {
@@ -2480,37 +2456,36 @@ fil_read_first_page(
}
}
- if (!(IS_XTRABACKUP() && srv_backup_mode)) {
- check_msg = fil_check_first_page(page, *space_id, *flags);
+ if (!(IS_XTRABACKUP() && srv_backup_mode)) {
+ check_msg = fil_check_first_page(page, *space_id, *flags);
}
- }
- flushed_lsn = mach_read_from_8(page +
- FIL_PAGE_FILE_FLUSH_LSN_OR_KEY_VERSION);
+ /* Possible encryption crypt data is also stored only to first page
+ of the first datafile. */
+ ulint offset = fsp_header_get_crypt_offset(
+ fsp_flags_get_zip_size(*flags));
- ulint space = fsp_header_get_space_id(page);
- ulint offset = fsp_header_get_crypt_offset(
- fsp_flags_get_zip_size(*flags));
+ cdata = fil_space_read_crypt_data(*space_id, page, offset);
- cdata = fil_space_read_crypt_data(space, page, offset);
-
- if (crypt_data) {
- *crypt_data = cdata;
- }
-
- /* If file space is encrypted we need to have at least some
- encryption service available where to get keys */
- if (cdata && cdata->should_encrypt()) {
+ if (crypt_data) {
+ *crypt_data = cdata;
+ }
- if (!encryption_key_id_exists(cdata->key_id)) {
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Tablespace id %ld is encrypted but encryption service"
- " or used key_id %u is not available. Can't continue opening tablespace.",
- space, cdata->key_id);
+ /* If file space is encrypted we need to have at least some
+ encryption service available where to get keys */
+ if (cdata && cdata->should_encrypt()) {
- return ("table encrypted but encryption service not available.");
+ if (!encryption_key_id_exists(cdata->key_id)) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Tablespace id " ULINTPF
+ " is encrypted but encryption service"
+ " or used key_id %u is not available. "
+ "Can't continue opening tablespace.",
+ *space_id, cdata->key_id);
+ return ("table encrypted but encryption service not available.");
+ }
}
}
@@ -2520,20 +2495,6 @@ fil_read_first_page(
return(check_msg);
}
- if (!one_read_already) {
- *min_flushed_lsn = flushed_lsn;
- *max_flushed_lsn = flushed_lsn;
-
- return(NULL);
- }
-
- if (*min_flushed_lsn > flushed_lsn) {
- *min_flushed_lsn = flushed_lsn;
- }
- if (*max_flushed_lsn < flushed_lsn) {
- *max_flushed_lsn = flushed_lsn;
- }
-
return(NULL);
}
@@ -4377,6 +4338,7 @@ fil_open_single_table_tablespace(
def.file = os_file_create_simple_no_error_handling(
innodb_file_data_key, def.filepath, OS_FILE_OPEN,
OS_FILE_READ_ONLY, &def.success, atomic_writes);
+
if (def.success) {
tablespaces_found++;
}
@@ -4391,8 +4353,8 @@ fil_open_single_table_tablespace(
/* Read the first page of the datadir tablespace, if found. */
if (def.success) {
def.check_msg = fil_read_first_page(
- def.file, FALSE, &def.flags, &def.id,
- &def.lsn, &def.lsn, &def.crypt_data);
+ def.file, false, &def.flags, &def.id,
+ NULL, &def.crypt_data);
if (table) {
table->crypt_data = def.crypt_data;
@@ -4401,6 +4363,7 @@ fil_open_single_table_tablespace(
def.valid = !def.check_msg && def.id == id
&& fsp_flags_match(flags, def.flags);
+
if (def.valid) {
valid_tablespaces_found++;
} else {
@@ -4414,8 +4377,8 @@ fil_open_single_table_tablespace(
/* Read the first page of the remote tablespace */
if (remote.success) {
remote.check_msg = fil_read_first_page(
- remote.file, FALSE, &remote.flags, &remote.id,
- &remote.lsn, &remote.lsn, &remote.crypt_data);
+ remote.file, false, &remote.flags, &remote.id,
+ NULL, &remote.crypt_data);
if (table) {
table->crypt_data = remote.crypt_data;
@@ -4425,6 +4388,7 @@ fil_open_single_table_tablespace(
/* Validate this single-table-tablespace with SYS_TABLES. */
remote.valid = !remote.check_msg && remote.id == id
&& fsp_flags_match(flags, remote.flags);
+
if (remote.valid) {
valid_tablespaces_found++;
} else {
@@ -4439,8 +4403,8 @@ fil_open_single_table_tablespace(
/* Read the first page of the datadir tablespace, if found. */
if (dict.success) {
dict.check_msg = fil_read_first_page(
- dict.file, FALSE, &dict.flags, &dict.id,
- &dict.lsn, &dict.lsn, &dict.crypt_data);
+ dict.file, false, &dict.flags, &dict.id,
+ NULL, &dict.crypt_data);
if (table) {
table->crypt_data = dict.crypt_data;
@@ -4472,14 +4436,16 @@ fil_open_single_table_tablespace(
"See " REFMAN "innodb-troubleshooting-datadict.html "
"for how to resolve the issue.",
tablename);
+
if (IS_XTRABACKUP() && fix_dict) {
ib_logf(IB_LOG_LEVEL_WARN,
- "It will be removed from the data dictionary.");
+ "It will be removed from the data dictionary.");
if (purge_sys) {
fil_remove_invalid_table_from_data_dict(tablename);
}
}
+
err = DB_CORRUPTION;
goto cleanup_and_exit;
@@ -4491,26 +4457,32 @@ fil_open_single_table_tablespace(
ib_logf(IB_LOG_LEVEL_ERROR,
"A tablespace for %s has been found in "
"multiple places;", tablename);
+
if (def.success) {
ib_logf(IB_LOG_LEVEL_ERROR,
- "Default location; %s, LSN=" LSN_PF
- ", Space ID=%lu, Flags=%lu",
- def.filepath, def.lsn,
- (ulong) def.id, (ulong) def.flags);
+ "Default location; %s"
+ ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
+ def.filepath,
+ def.id,
+ def.flags);
}
+
if (remote.success) {
ib_logf(IB_LOG_LEVEL_ERROR,
- "Remote location; %s, LSN=" LSN_PF
- ", Space ID=%lu, Flags=%lu",
- remote.filepath, remote.lsn,
- (ulong) remote.id, (ulong) remote.flags);
+ "Remote location; %s"
+ ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
+ remote.filepath,
+ remote.id,
+ remote.flags);
}
+
if (dict.success) {
ib_logf(IB_LOG_LEVEL_ERROR,
- "Dictionary location; %s, LSN=" LSN_PF
- ", Space ID=%lu, Flags=%lu",
- dict.filepath, dict.lsn,
- (ulong) dict.id, (ulong) dict.flags);
+ "Dictionary location; %s"
+ ", Space ID=" ULINTPF " , Flags=" ULINTPF " .",
+ dict.filepath,
+ dict.id,
+ dict.flags);
}
/* Force-recovery will allow some tablespaces to be
@@ -4543,6 +4515,7 @@ fil_open_single_table_tablespace(
os_file_close(def.file);
tablespaces_found--;
}
+
if (dict.success && !dict.valid) {
dict.success = false;
os_file_close(dict.file);
@@ -4895,8 +4868,8 @@ fil_validate_single_table_tablespace(
check_first_page:
fsp->success = TRUE;
if (const char* check_msg = fil_read_first_page(
- fsp->file, FALSE, &fsp->flags, &fsp->id,
- &fsp->lsn, &fsp->lsn, &fsp->crypt_data)) {
+ fsp->file, false, &fsp->flags, &fsp->id,
+ NULL, &fsp->crypt_data)) {
ib_logf(IB_LOG_LEVEL_ERROR,
"%s in tablespace %s (table %s)",
check_msg, fsp->filepath, tablename);
@@ -4909,6 +4882,7 @@ check_first_page:
in Xtrabackup, this does not work.*/
return;
}
+
if (!restore_attempted) {
if (!fil_user_tablespace_find_space_id(fsp)) {
return;
@@ -5152,11 +5126,11 @@ will_not_choose:
if (def.success && remote.success) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Tablespaces for %s have been found in two places;\n"
- "Location 1: SpaceID: %lu LSN: %lu File: %s\n"
- "Location 2: SpaceID: %lu LSN: %lu File: %s\n"
+ "Location 1: SpaceID: " ULINTPF " File: %s\n"
+ "Location 2: SpaceID: " ULINTPF " File: %s\n"
"You must delete one of them.",
- tablename, (ulong) def.id, (ulong) def.lsn,
- def.filepath, (ulong) remote.id, (ulong) remote.lsn,
+ tablename, def.id,
+ def.filepath, remote.id,
remote.filepath);
def.success = FALSE;
@@ -6141,19 +6115,19 @@ fil_report_invalid_page_access(
ulint len, /*!< in: I/O length */
ulint type) /*!< in: I/O type */
{
- fprintf(stderr,
- "InnoDB: Error: trying to access page number %lu"
- " in space %lu,\n"
- "InnoDB: space name %s,\n"
- "InnoDB: which is outside the tablespace bounds.\n"
- "InnoDB: Byte offset %lu, len %lu, i/o type %lu.\n"
- "InnoDB: If you get this error at mysqld startup,"
- " please check that\n"
- "InnoDB: your my.cnf matches the ibdata files"
- " that you have in the\n"
- "InnoDB: MySQL server.\n",
- (ulong) block_offset, (ulong) space_id, space_name,
- (ulong) byte_offset, (ulong) len, (ulong) type);
+ ib_logf(IB_LOG_LEVEL_FATAL,
+ "Trying to access page number " ULINTPF
+ " in space " ULINTPF
+ " space name %s,"
+ " which is outside the tablespace bounds."
+ " Byte offset " ULINTPF ", len " ULINTPF
+ " i/o type " ULINTPF ".%s",
+ block_offset, space_id, space_name,
+ byte_offset, len, type,
+ space_id == 0 && !srv_was_started
+ ? "Please check that the configuration matches"
+ " the InnoDB system tablespace location (ibdata files)"
+ : "");
}
/********************************************************************//**
@@ -6373,11 +6347,10 @@ _fil_io(
mutex_exit(&fil_system->mutex);
return(DB_ERROR);
}
+
fil_report_invalid_page_access(
block_offset, space_id, space->name,
byte_offset, len, type);
-
- ut_error;
}
/* Open file if closed */
@@ -6389,10 +6362,11 @@ _fil_io(
ib_logf(IB_LOG_LEVEL_ERROR,
"Trying to do i/o to a tablespace which "
"exists without .ibd data file. "
- "i/o type %lu, space id %lu, page no %lu, "
- "i/o length %lu bytes",
- (ulong) type, (ulong) space_id,
- (ulong) block_offset, (ulong) len);
+ "i/o type " ULINTPF ", space id "
+ ULINTPF ", page no " ULINTPF ", "
+ "i/o length " ULINTPF " bytes",
+ type, space_id,
+ block_offset, len);
return(DB_TABLESPACE_DELETED);
}
@@ -6412,8 +6386,6 @@ _fil_io(
fil_report_invalid_page_access(
block_offset, space_id, space->name, byte_offset,
len, type);
-
- ut_error;
}
/* Now we have made the changes in the data structures of fil_system */
diff --git a/storage/xtradb/fsp/fsp0fsp.cc b/storage/xtradb/fsp/fsp0fsp.cc
index 934824c6462..bd87b88f58d 100644
--- a/storage/xtradb/fsp/fsp0fsp.cc
+++ b/storage/xtradb/fsp/fsp0fsp.cc
@@ -673,16 +673,13 @@ fsp_header_init_fields(
}
#ifndef UNIV_HOTBACKUP
-/**********************************************************************//**
-Initializes the space header of a new created space and creates also the
-insert buffer tree root if space == 0. */
+/** Initialize a tablespace header.
+@param[in] space_id space id
+@param[in] size current size in blocks
+@param[in,out] mtr mini-transaction */
UNIV_INTERN
void
-fsp_header_init(
-/*============*/
- ulint space_id, /*!< in: space id */
- ulint size, /*!< in: current size in blocks */
- mtr_t* mtr) /*!< in/out: mini-transaction */
+fsp_header_init(ulint space_id, ulint size, mtr_t* mtr)
{
fsp_header_t* header;
buf_block_t* block;
@@ -725,14 +722,8 @@ fsp_header_init(
flst_init(header + FSP_SEG_INODES_FREE, mtr);
mlog_write_ull(header + FSP_SEG_ID, 1, mtr);
- if (space_id == 0) {
- fsp_fill_free_list(FALSE, space_id, header, mtr);
- btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
- 0, 0, DICT_IBUF_ID_MIN + space_id,
- dict_ind_redundant, mtr);
- } else {
- fsp_fill_free_list(TRUE, space_id, header, mtr);
- }
+
+ fsp_fill_free_list(space_id != TRX_SYS_SPACE, space_id, header, mtr);
fil_space_t* space = fil_space_acquire(space_id);
ut_ad(space);
@@ -2075,7 +2066,6 @@ fseg_create_general(
inode = fsp_alloc_seg_inode(space_header, mtr);
if (inode == NULL) {
-
goto funct_exit;
}
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 7383647496a..6b404b68dc9 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -19243,8 +19243,15 @@ checkpoint_now_set(
log_make_checkpoint_at(LSN_MAX, TRUE);
fil_flush_file_spaces(FIL_LOG);
}
- fil_write_flushed_lsn_to_data_files(log_sys->lsn, 0);
- fil_flush_file_spaces(FIL_TABLESPACE);
+
+ dberr_t err = fil_write_flushed_lsn(log_sys->lsn);
+
+ if (err != DB_SUCCESS) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Failed to write flush lsn to the "
+ "system tablespace at checkpoint err=%s",
+ ut_strerr(err));
+ }
}
}
diff --git a/storage/xtradb/include/buf0dblwr.h b/storage/xtradb/include/buf0dblwr.h
index 8e1b00db83c..7b7464761cc 100644
--- a/storage/xtradb/include/buf0dblwr.h
+++ b/storage/xtradb/include/buf0dblwr.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, MariaDB Corporation. All Rights Reserved.
+Copyright (c) 2017, 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
@@ -39,13 +39,15 @@ extern buf_dblwr_t* buf_dblwr;
/** Set to TRUE when the doublewrite buffer is being created */
extern ibool buf_dblwr_being_created;
-/****************************************************************//**
-Creates the doublewrite buffer to a new InnoDB installation. The header of the
-doublewrite buffer is placed on the trx system header page. */
+/** Create the doublewrite buffer if the doublewrite buffer header
+is not present in the TRX_SYS page.
+@return whether the operation succeeded
+@retval true if the doublewrite buffer exists or was created
+@retval false if the creation failed (too small first data file) */
UNIV_INTERN
-void
-buf_dblwr_create(void);
-/*==================*/
+bool
+buf_dblwr_create()
+ MY_ATTRIBUTE((warn_unused_result));
/****************************************************************//**
At a database startup initializes the doublewrite buffer memory structure if
diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h
index a4e147b9797..b861225f562 100644
--- a/storage/xtradb/include/fil0fil.h
+++ b/storage/xtradb/include/fil0fil.h
@@ -212,7 +212,6 @@ struct fsp_open_info {
ibool valid; /*!< Is the tablespace valid? */
pfs_os_file_t file; /*!< File handle */
char* filepath; /*!< File path to open */
- lsn_t lsn; /*!< Flushed LSN from header page */
ulint id; /*!< Space ID */
ulint flags; /*!< Tablespace flags */
ulint encryption_error; /*!< if an encryption error occurs */
@@ -643,17 +642,17 @@ void
fil_set_max_space_id_if_bigger(
/*===========================*/
ulint max_id);/*!< in: maximum known id */
+
#ifndef UNIV_HOTBACKUP
-/****************************************************************//**
-Writes the flushed lsn and the latest archived log number to the page
-header of the first page of each data file in the system tablespace.
-@return DB_SUCCESS or error number */
-UNIV_INTERN
+
+/** Write the flushed LSN to the page header of the first page in the
+system tablespace.
+@param[in] lsn flushed LSN
+@return DB_SUCCESS or error number */
dberr_t
-fil_write_flushed_lsn_to_data_files(
-/*================================*/
- lsn_t lsn, /*!< in: lsn to write */
- ulint arch_log_no); /*!< in: latest archived log file number */
+fil_write_flushed_lsn(
+ lsn_t lsn)
+ MY_ATTRIBUTE((warn_unused_result));
/** Acquire a tablespace when it could be dropped concurrently.
Used by background threads that do not necessarily hold proper locks
@@ -799,28 +798,28 @@ private:
fil_space_t* m_space;
};
-/*******************************************************************//**
-Reads the flushed lsn, arch no, and tablespace flag fields from a data
-file at database startup.
+/** Reads the flushed lsn, arch no, space_id and tablespace flag fields from
+the first page of a first data file at database startup.
+@param[in] data_file open data file
+@param[in] one_read_only true if first datafile is already
+ read
+@param[out] flags FSP_SPACE_FLAGS
+@param[out] space_id tablepspace ID
+@param[out] flushed_lsn flushed lsn value
+@param[out] crypt_data encryption crypt data
@retval NULL on success, or if innodb_force_recovery is set
@return pointer to an error message string */
UNIV_INTERN
const char*
fil_read_first_page(
-/*================*/
- pfs_os_file_t data_file, /*!< in: open data file */
- ibool one_read_already, /*!< in: TRUE if min and max
- parameters below already
- contain sensible data */
- ulint* flags, /*!< out: FSP_SPACE_FLAGS */
- ulint* space_id, /*!< out: tablespace ID */
- lsn_t* min_flushed_lsn, /*!< out: min of flushed
- lsn values in data files */
- lsn_t* max_flushed_lsn, /*!< out: max of flushed
- lsn values in data files */
- fil_space_crypt_t** crypt_data) /*!< out: crypt data */
-
- __attribute__((warn_unused_result));
+ pfs_os_file_t data_file,
+ ibool one_read_already,
+ ulint* flags,
+ ulint* space_id,
+ lsn_t* flushed_lsn,
+ fil_space_crypt_t** crypt_data)
+ MY_ATTRIBUTE((warn_unused_result));
+
#endif /* !UNIV_HOTBACKUP */
/*******************************************************************//**
Parses the body of a log record written about an .ibd file operation. That is,
diff --git a/storage/xtradb/include/fsp0fsp.h b/storage/xtradb/include/fsp0fsp.h
index 6ed78eba6f9..715572199ab 100644
--- a/storage/xtradb/include/fsp0fsp.h
+++ b/storage/xtradb/include/fsp0fsp.h
@@ -519,16 +519,14 @@ fsp_header_init_fields(
ulint space_id, /*!< in: space id */
ulint flags); /*!< in: tablespace flags (FSP_SPACE_FLAGS):
0, or table->flags if newer than COMPACT */
-/**********************************************************************//**
-Initializes the space header of a new created space and creates also the
-insert buffer tree root if space == 0. */
+/** Initialize a tablespace header.
+@param[in] space_id space id
+@param[in] size current size in blocks
+@param[in,out] mtr mini-transaction */
UNIV_INTERN
void
-fsp_header_init(
-/*============*/
- ulint space, /*!< in: space id */
- ulint size, /*!< in: current size in blocks */
- mtr_t* mtr); /*!< in/out: mini-transaction */
+fsp_header_init(ulint space_id, ulint size, mtr_t* mtr);
+
/**********************************************************************//**
Increases the space size field of a space. */
UNIV_INTERN
diff --git a/storage/xtradb/include/log0recv.h b/storage/xtradb/include/log0recv.h
index e7b6a937f01..73d53d2ddab 100644
--- a/storage/xtradb/include/log0recv.h
+++ b/storage/xtradb/include/log0recv.h
@@ -137,26 +137,25 @@ a freshly read page)
*/
# define recv_recover_page(jri, block) recv_recover_page_func(block)
#endif /* !UNIV_HOTBACKUP */
-/********************************************************//**
-Recovers from a checkpoint. When this function returns, the database is able
+
+/** Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function
recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it.
+@param[in] type LOG_CHECKPOINT or LOG_ARCHIVE
+@param[in] limit_lsn recover up to this lsn if possible
+@param[in] flushed_lsn flushed lsn from first data file
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
recv_recovery_from_checkpoint_start_func(
-/*=====================================*/
#ifdef UNIV_LOG_ARCHIVE
- ulint type, /*!< in: LOG_CHECKPOINT or
- LOG_ARCHIVE */
- lsn_t limit_lsn, /*!< in: recover up to this lsn
- if possible */
+ ulint type,
+ lsn_t limit_lsn,
#endif /* UNIV_LOG_ARCHIVE */
- lsn_t min_flushed_lsn,/*!< in: min flushed lsn from
- data files */
- lsn_t max_flushed_lsn);/*!< in: max flushed lsn from
- data files */
+ lsn_t flushed_lsn)
+ MY_ATTRIBUTE((warn_unused_result));
+
#ifdef UNIV_LOG_ARCHIVE
/** Wrapper for recv_recovery_from_checkpoint_start_func().
Recovers from a checkpoint. When this function returns, the database is able
@@ -165,11 +164,10 @@ recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it.
@param type in: LOG_CHECKPOINT or LOG_ARCHIVE
@param lim in: recover up to this log sequence number if possible
-@param min in: minimum flushed log sequence number from data files
-@param max in: maximum flushed log sequence number from data files
+@param lsn in: flushed log sequence number from first data file
@return error code or DB_SUCCESS */
-# define recv_recovery_from_checkpoint_start(type,lim,min,max) \
- recv_recovery_from_checkpoint_start_func(type,lim,min,max)
+# define recv_recovery_from_checkpoint_start(type,lim,lsn) \
+ recv_recovery_from_checkpoint_start_func(type,lim,lsn)
#else /* UNIV_LOG_ARCHIVE */
/** Wrapper for recv_recovery_from_checkpoint_start_func().
Recovers from a checkpoint. When this function returns, the database is able
@@ -178,12 +176,12 @@ recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it.
@param type ignored: LOG_CHECKPOINT or LOG_ARCHIVE
@param lim ignored: recover up to this log sequence number if possible
-@param min in: minimum flushed log sequence number from data files
-@param max in: maximum flushed log sequence number from data files
+@param lsn in: flushed log sequence number from first data file
@return error code or DB_SUCCESS */
-# define recv_recovery_from_checkpoint_start(type,lim,min,max) \
- recv_recovery_from_checkpoint_start_func(min,max)
+# define recv_recovery_from_checkpoint_start(type,lim,lsn) \
+ recv_recovery_from_checkpoint_start_func(lsn)
#endif /* UNIV_LOG_ARCHIVE */
+
/********************************************************//**
Completes recovery from a checkpoint. */
UNIV_INTERN
diff --git a/storage/xtradb/include/trx0rseg.h b/storage/xtradb/include/trx0rseg.h
index b9c84ef2b06..e2853df7045 100644
--- a/storage/xtradb/include/trx0rseg.h
+++ b/storage/xtradb/include/trx0rseg.h
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2017, 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
@@ -124,13 +125,13 @@ trx_rseg_mem_free(
/*==============*/
trx_rseg_t* rseg); /*!< in, own: instance to free */
-/*********************************************************************
-Creates a rollback segment. */
+/** Create a rollback segment.
+@param[in] space undo tablespace ID
+@return pointer to new rollback segment
+@retval NULL on failure */
UNIV_INTERN
trx_rseg_t*
-trx_rseg_create(
-/*============*/
- ulint space); /*!< in: id of UNDO tablespace */
+trx_rseg_create(ulint space);
/********************************************************************
Get the number of unique rollback tablespaces in use except space id 0.
diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h
index 766d61039b4..1b490eca2af 100644
--- a/storage/xtradb/include/trx0trx.h
+++ b/storage/xtradb/include/trx0trx.h
@@ -1,8 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2016, MariaDB Corporation. All Rights Reserved.
-
+Copyright (c) 2015, 2017, 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
@@ -334,6 +333,24 @@ trx_print_low(
/*!< in: mem_heap_get_size(trx->lock.lock_heap) */
MY_ATTRIBUTE((nonnull));
+#ifdef WITH_WSREP
+/**********************************************************************//**
+Prints info about a transaction.
+Transaction information may be retrieved without having trx_sys->mutex acquired
+so it may not be completely accurate. The caller must own lock_sys->mutex
+and the trx must have some locks to make sure that it does not escape
+without locking lock_sys->mutex. */
+UNIV_INTERN
+void
+wsrep_trx_print_locking(
+/*==============*/
+ FILE* f, /*!< in: output stream */
+ const trx_t* trx, /*!< in: transaction */
+ ulint max_query_len) /*!< in: max query length to print,
+ or 0 to use the default max length */
+ MY_ATTRIBUTE((nonnull));
+#endif /* WITH_WSREP */
+
/**********************************************************************//**
Prints info about a transaction.
The caller must hold lock_sys->mutex and trx_sys->mutex.
diff --git a/storage/xtradb/log/log0log.cc b/storage/xtradb/log/log0log.cc
index eae7f2bb09b..3252cd793c9 100644
--- a/storage/xtradb/log/log0log.cc
+++ b/storage/xtradb/log/log0log.cc
@@ -3836,9 +3836,14 @@ wait_suspend_loop:
srv_shutdown_lsn = lsn;
if (!srv_read_only_mode) {
- fil_write_flushed_lsn_to_data_files(lsn, 0);
+ dberr_t err = fil_write_flushed_lsn(lsn);
- fil_flush_file_spaces(FIL_TABLESPACE);
+ if (err != DB_SUCCESS) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Failed to write flush lsn to the "
+ "system tablespace at shutdown err=%s",
+ ut_strerr(err));
+ }
}
fil_close_all_files();
diff --git a/storage/xtradb/log/log0recv.cc b/storage/xtradb/log/log0recv.cc
index 0b797fd6c23..fb64309cee4 100644
--- a/storage/xtradb/log/log0recv.cc
+++ b/storage/xtradb/log/log0recv.cc
@@ -3004,11 +3004,6 @@ recv_init_crash_recovery(void)
possible */
if (srv_force_recovery < SRV_FORCE_NO_LOG_REDO) {
-
- ib_logf(IB_LOG_LEVEL_INFO,
- "Restoring possible half-written data pages "
- "from the doublewrite buffer...");
-
buf_dblwr_process();
/* Spawn the background thread to flush dirty pages
@@ -3019,22 +3014,22 @@ recv_init_crash_recovery(void)
}
}
-/********************************************************//**
-Recovers from a checkpoint. When this function returns, the database is able
+/** Recovers from a checkpoint. When this function returns, the database is able
to start processing of new user transactions, but the function
recv_recovery_from_checkpoint_finish should be called later to complete
the recovery and free the resources used in it.
+@param[in] type LOG_CHECKPOINT or LOG_ARCHIVE
+@param[in] limit_lsn recover up to this lsn if possible
+@param[in] flushed_lsn flushed lsn from first data file
@return error code or DB_SUCCESS */
UNIV_INTERN
dberr_t
recv_recovery_from_checkpoint_start_func(
-/*=====================================*/
#ifdef UNIV_LOG_ARCHIVE
- ulint type, /*!< in: LOG_CHECKPOINT or LOG_ARCHIVE */
- lsn_t limit_lsn, /*!< in: recover up to this lsn if possible */
+ ulint type,
+ lsn_t limit_lsn,
#endif /* UNIV_LOG_ARCHIVE */
- lsn_t min_flushed_lsn,/*!< in: min flushed lsn from data files */
- lsn_t max_flushed_lsn)/*!< in: max flushed lsn from data files */
+ lsn_t flushed_lsn)
{
log_group_t* group;
log_group_t* max_cp_group;
@@ -3262,6 +3257,7 @@ recv_recovery_from_checkpoint_start_func(
group = UT_LIST_GET_NEXT(log_groups, group);
}
+
/* Done with startup scan. Clear the flag. */
recv_log_scan_is_startup_type = FALSE;
@@ -3274,38 +3270,16 @@ recv_recovery_from_checkpoint_start_func(
there is something wrong we will print a message to the
user about recovery: */
- if (checkpoint_lsn != max_flushed_lsn
- || checkpoint_lsn != min_flushed_lsn) {
-
- if (checkpoint_lsn < max_flushed_lsn) {
-
- ib_logf(IB_LOG_LEVEL_WARN,
- "The log sequence number "
- "in the ibdata files is higher "
- "than the log sequence number "
- "in the ib_logfiles! Are you sure "
- "you are using the right "
- "ib_logfiles to start up the database. "
- "Log sequence number in the "
- "ib_logfiles is " LSN_PF ", log"
- "sequence numbers stamped "
- "to ibdata file headers are between "
- "" LSN_PF " and " LSN_PF ".",
- checkpoint_lsn,
- min_flushed_lsn,
- max_flushed_lsn);
- }
-
+ if (checkpoint_lsn != flushed_lsn) {
if (!recv_needed_recovery) {
ib_logf(IB_LOG_LEVEL_INFO,
- "The log sequence numbers "
- LSN_PF " and " LSN_PF
- " in ibdata files do not match"
+ "The log sequence number "
+ LSN_PF
+ " in ibdata file do not match"
" the log sequence number "
LSN_PF
" in the ib_logfiles!",
- min_flushed_lsn,
- max_flushed_lsn,
+ flushed_lsn,
checkpoint_lsn);
if (!srv_read_only_mode) {
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index fca6e859aa8..88ca7fc263b 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -3188,7 +3188,7 @@ suspend_thread:
case SRV_SHUTDOWN_CLEANUP:
if (srv_shutdown_state == SRV_SHUTDOWN_CLEANUP
&& srv_fast_shutdown < 2) {
- srv_shutdown(srv_fast_shutdown == 1);
+ srv_shutdown(srv_fast_shutdown == 0);
}
srv_suspend_thread(slot);
my_thread_end();
diff --git a/storage/xtradb/srv/srv0start.cc b/storage/xtradb/srv/srv0start.cc
index fd225e9cf65..bca59c148ca 100644
--- a/storage/xtradb/srv/srv0start.cc
+++ b/storage/xtradb/srv/srv0start.cc
@@ -206,6 +206,39 @@ UNIV_INTERN mysql_pfs_key_t srv_purge_thread_key;
UNIV_INTERN mysql_pfs_key_t srv_log_tracking_thread_key;
#endif /* UNIV_PFS_THREAD */
+/** Innobase start-up aborted. Perform cleanup actions.
+@param[in] create_new_db TRUE if new db is being created
+@param[in] file File name
+@param[in] line Line number
+@param[in] err Reason for aborting InnoDB startup
+@return DB_SUCCESS or error code. */
+static
+dberr_t
+srv_init_abort(
+ bool create_new_db,
+ const char* file,
+ ulint line,
+ dberr_t err)
+{
+ if (create_new_db) {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Database creation was aborted"
+ " at %s [" ULINTPF "]"
+ " with error %s. You may need"
+ " to delete the ibdata1 file before trying to start"
+ " up again.",
+ file, line, ut_strerr(err));
+ } else {
+ ib_logf(IB_LOG_LEVEL_ERROR,
+ "Plugin initialization aborted"
+ " at %s [" ULINTPF "]"
+ " with error %s.",
+ file, line, ut_strerr(err));
+ }
+
+ return(err);
+}
+
/*********************************************************************//**
Convert a numeric string that optionally ends in G or M or K, to a number
containing megabytes.
@@ -826,32 +859,32 @@ open_log_file(
return(DB_SUCCESS);
}
-/*********************************************************************//**
-Creates or opens database data files and closes them.
+
+/** Creates or opens database data files and closes them.
+@param[out] create_new_db true = create new database
+@param[out] min_arch_log_no min of archived log numbers in
+ data files
+@param[out] max_arch_log_no max of archived log numbers in
+ data files
+@param[out] flushed_lsn flushed lsn in fist datafile
+@param[out] sum_of_new_sizes sum of sizes of the new files
+ added
@return DB_SUCCESS or error code */
MY_ATTRIBUTE((nonnull, warn_unused_result))
dberr_t
open_or_create_data_files(
-/*======================*/
- ibool* create_new_db, /*!< out: TRUE if new database should be
- created */
+ bool* create_new_db,
#ifdef UNIV_LOG_ARCHIVE
- lsn_t* min_arch_log_no,/*!< out: min of archived log
- numbers in data files */
- lsn_t* max_arch_log_no,/*!< out: max of archived log
- numbers in data files */
+ lsn_t* min_arch_log_no,
+ lsn_t* max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
- lsn_t* min_flushed_lsn,/*!< out: min of flushed lsn
- values in data files */
- lsn_t* max_flushed_lsn,/*!< out: max of flushed lsn
- values in data files */
- ulint* sum_of_new_sizes)/*!< out: sum of sizes of the
- new files added */
+ lsn_t* flushed_lsn,
+ ulint* sum_of_new_sizes)
{
ibool ret;
ulint i;
- ibool one_opened = FALSE;
- ibool one_created = FALSE;
+ bool one_opened = false;
+ bool one_created = false;
os_offset_t size;
ulint flags;
ulint space;
@@ -870,7 +903,7 @@ open_or_create_data_files(
*sum_of_new_sizes = 0;
- *create_new_db = FALSE;
+ *create_new_db = false;
srv_normalize_path_for_win(srv_data_home);
@@ -958,9 +991,10 @@ open_or_create_data_files(
}
const char* check_msg;
+
check_msg = fil_read_first_page(
files[i], FALSE, &flags, &space,
- min_flushed_lsn, max_flushed_lsn, NULL);
+ flushed_lsn, NULL);
/* If first page is valid, don't overwrite DB.
It prevents overwriting DB when mysql_install_db
@@ -991,6 +1025,7 @@ open_or_create_data_files(
name);
return(DB_ERROR);
}
+
if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
ut_a(!srv_read_only_mode);
files[i] = os_file_create(
@@ -1010,7 +1045,6 @@ open_or_create_data_files(
}
if (!ret) {
-
os_file_get_last_error(true);
ib_logf(IB_LOG_LEVEL_ERROR,
@@ -1020,7 +1054,6 @@ open_or_create_data_files(
}
if (srv_data_file_is_raw_partition[i] == SRV_OLD_RAW) {
-
goto skip_size_check;
}
@@ -1047,16 +1080,15 @@ size_check:
"auto-extending "
"data file %s is "
"of a different size "
- "%lu pages (rounded "
+ ULINTPF " pages (rounded "
"down to MB) than specified "
"in the .cnf file: "
- "initial %lu pages, "
- "max %lu (relevant if "
+ "initial " ULINTPF " pages, "
+ "max " ULINTPF " (relevant if "
"non-zero) pages!",
name,
- (ulong) rounded_size_pages,
- (ulong) srv_data_file_sizes[i],
- (ulong)
+ rounded_size_pages,
+ srv_data_file_sizes[i],
srv_last_file_size_max);
return(DB_ERROR);
@@ -1069,12 +1101,12 @@ size_check:
ib_logf(IB_LOG_LEVEL_ERROR,
"Data file %s is of a different "
- "size %lu pages (rounded down to MB) "
+ "size " ULINTPF " pages (rounded down to MB) "
"than specified in the .cnf file "
- "%lu pages!",
+ ULINTPF " pages!",
name,
- (ulong) rounded_size_pages,
- (ulong) srv_data_file_sizes[i]);
+ rounded_size_pages,
+ srv_data_file_sizes[i]);
return(DB_ERROR);
}
@@ -1093,7 +1125,7 @@ skip_size_check:
check_first_page:
check_msg = fil_read_first_page(
files[i], one_opened, &flags, &space,
- min_flushed_lsn, max_flushed_lsn, &crypt_data);
+ flushed_lsn, &crypt_data);
if (check_msg) {
@@ -1130,9 +1162,9 @@ check_first_page:
!= fsp_flags_get_page_size(flags)) {
ib_logf(IB_LOG_LEVEL_ERROR,
- "Data file \"%s\" uses page size %lu,"
+ "Data file \"%s\" uses page size " ULINTPF " ,"
"but the start-up parameter "
- "is --innodb-page-size=%lu",
+ "is --innodb-page-size=" ULINTPF " .",
name,
fsp_flags_get_page_size(flags),
UNIV_PAGE_SIZE);
@@ -1163,9 +1195,9 @@ check_first_page:
}
ib_logf(IB_LOG_LEVEL_INFO,
- "Setting file %s size to %lu MB",
+ "Setting file %s size to " ULINTPF " MB",
name,
- (ulong) (srv_data_file_sizes[i]
+ (srv_data_file_sizes[i]
>> (20 - UNIV_PAGE_SIZE_SHIFT)));
ret = os_file_set_size(
@@ -1655,9 +1687,8 @@ dberr_t
innobase_start_or_create_for_mysql(void)
/*====================================*/
{
- ibool create_new_db;
- lsn_t min_flushed_lsn;
- lsn_t max_flushed_lsn;
+ bool create_new_db;
+ lsn_t flushed_lsn;
#ifdef UNIV_LOG_ARCHIVE
lsn_t min_arch_log_no = LSN_MAX;
lsn_t max_arch_log_no = LSN_MAX;
@@ -2206,7 +2237,7 @@ innobase_start_or_create_for_mysql(void)
#ifdef UNIV_LOG_ARCHIVE
&min_arch_log_no, &max_arch_log_no,
#endif /* UNIV_LOG_ARCHIVE */
- &min_flushed_lsn, &max_flushed_lsn,
+ &flushed_lsn,
&sum_of_new_sizes);
if (err == DB_FAIL) {
@@ -2250,12 +2281,12 @@ innobase_start_or_create_for_mysql(void)
bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
ut_a(success);
- min_flushed_lsn = max_flushed_lsn = log_get_lsn();
+ flushed_lsn = log_get_lsn();
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
err = create_log_files(create_new_db, logfilename, dirnamelen,
- max_flushed_lsn, logfile0);
+ flushed_lsn, logfile0);
if (err != DB_SUCCESS) {
return(err);
@@ -2275,19 +2306,8 @@ innobase_start_or_create_for_mysql(void)
if (err == DB_NOT_FOUND) {
if (i == 0) {
- if (max_flushed_lsn
- != min_flushed_lsn) {
- ib_logf(IB_LOG_LEVEL_ERROR,
- "Cannot create"
- " log files because"
- " data files are"
- " corrupt or"
- " not in sync"
- " with each other");
- return(DB_ERROR);
- }
- if (max_flushed_lsn < (lsn_t) 1000) {
+ if (flushed_lsn < (lsn_t) 1000) {
ib_logf(IB_LOG_LEVEL_ERROR,
"Cannot create"
" log files because"
@@ -2302,14 +2322,14 @@ innobase_start_or_create_for_mysql(void)
err = create_log_files(
create_new_db, logfilename,
- dirnamelen, max_flushed_lsn,
+ dirnamelen, flushed_lsn,
logfile0);
if (err == DB_SUCCESS) {
err = create_log_files_rename(
logfilename,
dirnamelen,
- max_flushed_lsn,
+ flushed_lsn,
logfile0);
}
@@ -2319,8 +2339,7 @@ innobase_start_or_create_for_mysql(void)
/* Suppress the message about
crash recovery. */
- max_flushed_lsn = min_flushed_lsn
- = log_get_lsn();
+ flushed_lsn = log_get_lsn();
goto files_checked;
} else if (i < 2 && !IS_XTRABACKUP()) {
/* must have at least 2 log files */
@@ -2450,9 +2469,23 @@ files_checked:
mtr_start(&mtr);
fsp_header_init(0, sum_of_new_sizes, &mtr);
+ compile_time_assert(TRX_SYS_SPACE == 0);
+ compile_time_assert(IBUF_SPACE_ID == 0);
+
+ ulint ibuf_root = btr_create(
+ DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF,
+ 0, 0, DICT_IBUF_ID_MIN,
+ dict_ind_redundant, &mtr);
mtr_commit(&mtr);
+ if (ibuf_root == FIL_NULL) {
+ return(srv_init_abort(true, __FILE__, __LINE__,
+ DB_ERROR));
+ }
+
+ ut_ad(ibuf_root == IBUF_TREE_ROOT_PAGE_NO);
+
/* To maintain backward compatibility we create only
the first rollback segment before the double write buffer.
All the remaining rollback segments will be created later,
@@ -2478,17 +2511,19 @@ files_checked:
bool success = buf_flush_list(ULINT_MAX, LSN_MAX, NULL);
ut_a(success);
- min_flushed_lsn = max_flushed_lsn = log_get_lsn();
+ flushed_lsn = log_get_lsn();
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
/* Stamp the LSN to the data files. */
- fil_write_flushed_lsn_to_data_files(max_flushed_lsn, 0);
+ err = fil_write_flushed_lsn(flushed_lsn);
- fil_flush_file_spaces(FIL_TABLESPACE);
+ if (err != DB_SUCCESS) {
+ return(err);
+ }
err = create_log_files_rename(logfilename, dirnamelen,
- max_flushed_lsn, logfile0);
+ flushed_lsn, logfile0);
if (err != DB_SUCCESS) {
return(err);
@@ -2543,7 +2578,7 @@ files_checked:
err = recv_recovery_from_checkpoint_start(
LOG_CHECKPOINT, LSN_MAX,
- min_flushed_lsn, max_flushed_lsn);
+ flushed_lsn);
if (err != DB_SUCCESS) {
return(err);
@@ -2726,7 +2761,7 @@ files_checked:
DBUG_EXECUTE_IF("innodb_log_abort_1",
return(DB_ERROR););
- min_flushed_lsn = max_flushed_lsn = log_get_lsn();
+ flushed_lsn = log_get_lsn();
ib_logf(IB_LOG_LEVEL_WARN,
"Resizing redo log from %u*%u to %u*%u pages"
@@ -2735,7 +2770,7 @@ files_checked:
(unsigned) srv_log_file_size,
(unsigned) srv_n_log_files,
(unsigned) srv_log_file_size_requested,
- max_flushed_lsn);
+ flushed_lsn);
buf_flush_wait_batch_end(NULL, BUF_FLUSH_LIST);
@@ -2745,7 +2780,7 @@ files_checked:
we need to explicitly flush the log buffers. */
fil_flush(SRV_LOG_SPACE_FIRST_ID);
- ut_ad(max_flushed_lsn == log_get_lsn());
+ ut_ad(flushed_lsn == log_get_lsn());
/* Prohibit redo log writes from any other
threads until creating a log checkpoint at the
@@ -2757,8 +2792,7 @@ files_checked:
return(DB_ERROR););
/* Stamp the LSN to the data files. */
- fil_write_flushed_lsn_to_data_files(
- max_flushed_lsn, 0);
+ err = fil_write_flushed_lsn(flushed_lsn);
DBUG_EXECUTE_IF("innodb_log_abort_4", err = DB_ERROR;);
@@ -2766,8 +2800,6 @@ files_checked:
return(err);
}
- fil_flush_file_spaces(FIL_TABLESPACE);
-
/* Close and free the redo log files, so that
we can replace them. */
fil_close_log_files(true);
@@ -2784,21 +2816,16 @@ files_checked:
srv_log_file_size = srv_log_file_size_requested;
err = create_log_files(create_new_db, logfilename,
- dirnamelen, max_flushed_lsn,
+ dirnamelen, flushed_lsn,
logfile0);
if (err != DB_SUCCESS) {
return(err);
}
- /* create_log_files() can increase system lsn that is
- why FIL_PAGE_FILE_FLUSH_LSN have to be updated */
- min_flushed_lsn = max_flushed_lsn = log_get_lsn();
- fil_write_flushed_lsn_to_data_files(min_flushed_lsn, 0);
- fil_flush_file_spaces(FIL_TABLESPACE);
-
err = create_log_files_rename(logfilename, dirnamelen,
log_get_lsn(), logfile0);
+
if (err != DB_SUCCESS) {
return(err);
}
@@ -2845,10 +2872,9 @@ files_checked:
/* fprintf(stderr, "Max allowed record size %lu\n",
page_get_free_space_of_empty() / 2); */
- if (buf_dblwr == NULL) {
- /* Create the doublewrite buffer to a new tablespace */
-
- buf_dblwr_create();
+ if (!buf_dblwr_create()) {
+ return(srv_init_abort(create_new_db, __FILE__, __LINE__,
+ DB_ERROR));
}
/* Here the double write buffer has already been created and so
@@ -2878,6 +2904,9 @@ files_checked:
/* Can only happen if server is read only. */
ut_a(srv_read_only_mode);
srv_undo_logs = ULONG_UNDEFINED;
+ } else if (srv_available_undo_logs < srv_undo_logs) {
+ /* Should due to out of file space. */
+ return (srv_init_abort(create_new_db, __FILE__, __LINE__, DB_ERROR));
}
if (!srv_read_only_mode) {
diff --git a/storage/xtradb/trx/trx0rseg.cc b/storage/xtradb/trx/trx0rseg.cc
index 003d1036a8c..16fa334872b 100644
--- a/storage/xtradb/trx/trx0rseg.cc
+++ b/storage/xtradb/trx/trx0rseg.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2017, 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
@@ -293,14 +294,13 @@ trx_rseg_create_instance(
}
}
-/*********************************************************************
-Creates a rollback segment.
-@return pointer to new rollback segment if create successful */
+/** Create a rollback segment.
+@param[in] space undo tablespace ID
+@return pointer to new rollback segment
+@retval NULL on failure */
UNIV_INTERN
trx_rseg_t*
-trx_rseg_create(
-/*============*/
- ulint space) /*!< in: id of UNDO tablespace */
+trx_rseg_create(ulint space)
{
mtr_t mtr;
ulint slot_no;
@@ -323,22 +323,21 @@ trx_rseg_create(
page_no = trx_rseg_header_create(
space, 0, ULINT_MAX, slot_no, &mtr);
- ut_a(page_no != FIL_NULL);
-
- sys_header = trx_sysf_get(&mtr);
+ if (page_no != FIL_NULL) {
+ sys_header = trx_sysf_get(&mtr);
- id = trx_sysf_rseg_get_space(sys_header, slot_no, &mtr);
- ut_a(id == space);
+ id = trx_sysf_rseg_get_space(sys_header, slot_no, &mtr);
+ ut_a(id == space);
- zip_size = space ? fil_space_get_zip_size(space) : 0;
+ zip_size = space ? fil_space_get_zip_size(space) : 0;
- rseg = trx_rseg_mem_create(
- slot_no, space, zip_size, page_no,
- purge_sys->ib_bh, &mtr);
+ rseg = trx_rseg_mem_create(
+ slot_no, space, zip_size, page_no,
+ purge_sys->ib_bh, &mtr);
+ }
}
mtr_commit(&mtr);
-
return(rseg);
}
diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc
index d0cb4a883cc..1d2f7ada54e 100644
--- a/storage/xtradb/trx/trx0trx.cc
+++ b/storage/xtradb/trx/trx0trx.cc
@@ -1,6 +1,7 @@
/*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
+Copyright (c) 2015, 2017, 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
@@ -2283,6 +2284,7 @@ state_ok:
}
}
#endif /* WITH_WSREP */
+
/**********************************************************************//**
Prints info about a transaction.
Acquires and releases lock_sys->mutex and trx_sys->mutex. */
@@ -2744,4 +2746,3 @@ trx_start_for_ddl_low(
ut_error;
}
-