summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2019-04-07 11:49:50 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2019-04-07 11:49:50 +0300
commitcc492bfd4ff2d15cc5803a7d80f1559ceeb003c1 (patch)
treee5d3abbe5551d4f05a59cfcc0d629f8d4f50e98f
parentd5a2bc6a0f24f2a9ec73a0d18bb7e6fba3496bed (diff)
parent867617a97684cdf2c8df326d9a986c2cae779796 (diff)
downloadmariadb-git-cc492bfd4ff2d15cc5803a7d80f1559ceeb003c1.tar.gz
Merge 10.2 into 10.3
-rw-r--r--extra/mariabackup/xtrabackup.cc9
-rw-r--r--mysql-test/main/cte_nonrecursive.result14
-rw-r--r--mysql-test/main/cte_nonrecursive.test12
-rw-r--r--mysql-test/suite/innodb/t/drop_table_background.test6
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_install.result2
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_load.result2
-rw-r--r--mysql-test/suite/plugins/r/feedback_plugin_send.result2
-rw-r--r--sql/sql_base.cc25
-rw-r--r--sql/sql_cte.cc1
-rw-r--r--sql/sql_parse.cc15
-rw-r--r--storage/innobase/btr/btr0btr.cc60
-rw-r--r--storage/innobase/btr/btr0bulk.cc12
-rw-r--r--storage/innobase/buf/buf0buf.cc10
-rw-r--r--storage/innobase/buf/buf0rea.cc6
-rw-r--r--storage/innobase/dict/dict0load.cc9
-rw-r--r--storage/innobase/fil/fil0fil.cc31
-rw-r--r--storage/innobase/fsp/fsp0fsp.cc42
-rw-r--r--storage/innobase/include/dict0types.h5
-rw-r--r--storage/innobase/include/fil0fil.h19
-rw-r--r--storage/innobase/include/fsp0fsp.h15
-rw-r--r--storage/innobase/include/log0recv.h13
-rw-r--r--storage/innobase/include/page0zip.h20
-rw-r--r--storage/innobase/include/row0merge.h8
-rw-r--r--storage/innobase/log/log0log.cc9
-rw-r--r--storage/innobase/log/log0recv.cc402
-rw-r--r--storage/innobase/page/page0zip.cc35
-rw-r--r--storage/innobase/row/row0ftsort.cc4
-rw-r--r--storage/innobase/row/row0merge.cc18
-rw-r--r--storage/innobase/row/row0mysql.cc2
29 files changed, 374 insertions, 434 deletions
diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc
index 001cce29933..338cf22a7de 100644
--- a/extra/mariabackup/xtrabackup.cc
+++ b/extra/mariabackup/xtrabackup.cc
@@ -2748,8 +2748,13 @@ static bool xtrabackup_copy_logfile(bool last = false)
my_sleep(1000);
}
- start_lsn = (lsn == start_lsn)
- ? 0 : xtrabackup_copy_log(start_lsn, lsn, last);
+ if (lsn == start_lsn) {
+ start_lsn = 0;
+ } else {
+ mutex_enter(&recv_sys->mutex);
+ start_lsn = xtrabackup_copy_log(start_lsn, lsn, last);
+ mutex_exit(&recv_sys->mutex);
+ }
log_mutex_exit();
diff --git a/mysql-test/main/cte_nonrecursive.result b/mysql-test/main/cte_nonrecursive.result
index 9bce4f0a9bd..b846ec2d8ac 100644
--- a/mysql-test/main/cte_nonrecursive.result
+++ b/mysql-test/main/cte_nonrecursive.result
@@ -1659,3 +1659,17 @@ a
2
drop view v1;
drop table t1,t2;
+#
+# MDEV-19112: CTE usage when information_schema is set as default db
+#
+with t as (select 1 as t ) select * from t;
+t
+1
+use information_schema;
+with t as (select 1 as t) select * from t;
+t
+1
+with columns as (select 1 as t) select * from columns;
+t
+1
+use test;
diff --git a/mysql-test/main/cte_nonrecursive.test b/mysql-test/main/cte_nonrecursive.test
index 920c27a70f9..c0c5c22bed0 100644
--- a/mysql-test/main/cte_nonrecursive.test
+++ b/mysql-test/main/cte_nonrecursive.test
@@ -1168,3 +1168,15 @@ select * from v1;
drop view v1;
drop table t1,t2;
+
+--echo #
+--echo # MDEV-19112: CTE usage when information_schema is set as default db
+--echo #
+
+with t as (select 1 as t ) select * from t;
+
+use information_schema;
+with t as (select 1 as t) select * from t;
+with columns as (select 1 as t) select * from columns;
+
+use test;
diff --git a/mysql-test/suite/innodb/t/drop_table_background.test b/mysql-test/suite/innodb/t/drop_table_background.test
index 8d82bea9675..20101dada84 100644
--- a/mysql-test/suite/innodb/t/drop_table_background.test
+++ b/mysql-test/suite/innodb/t/drop_table_background.test
@@ -3,6 +3,8 @@
# Embedded server does not support restarting
--source include/not_embedded.inc
+let $MYSQLD_DATADIR=`select @@datadir`;
+
CREATE TABLE t(c0 SERIAL, c1 INT, c2 INT, c3 INT, c4 INT,
KEY(c1), KEY(c2), KEY(c2,c1),
KEY(c3), KEY(c3,c1), KEY(c3,c2), KEY(c3,c2,c1),
@@ -32,7 +34,9 @@ CREATE TABLE target (PRIMARY KEY(c1)) ENGINE=InnoDB SELECT * FROM t;
--error ER_NO_SUCH_TABLE
SELECT * from target;
DROP TABLE t;
---source include/restart_mysqld.inc
+--source include/shutdown_mysqld.inc
+--remove_files_wildcard $MYSQLD_DATADIR/test #sql-*.ibd
+--source include/start_mysqld.inc
CREATE TABLE t (a INT) ENGINE=InnoDB;
DROP TABLE t;
--error ER_BAD_TABLE_ERROR
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_install.result b/mysql-test/suite/plugins/r/feedback_plugin_install.result
index ee74435e05a..c7f7a5c79f3 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_install.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_install.result
@@ -6,7 +6,7 @@ select * from information_schema.feedback where variable_name like 'feed%'
and variable_name not like '%_uid'
and variable_name not like '%debug%';
VARIABLE_NAME VARIABLE_VALUE
-FEEDBACK used 1
+FEEDBACK used 2
FEEDBACK version 1.1
FEEDBACK_HTTP_PROXY
FEEDBACK_SEND_RETRY_WAIT 60
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_load.result b/mysql-test/suite/plugins/r/feedback_plugin_load.result
index 8770ce19f49..f96b4d9b71f 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_load.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_load.result
@@ -4,7 +4,7 @@ ACTIVE
SELECT variable_value INTO @feedback_used FROM information_schema.feedback where variable_name = 'FEEDBACK used';
SELECT variable_value = @feedback_used + 1 FROM information_schema.feedback where variable_name = 'FEEDBACK used';
variable_value = @feedback_used + 1
-1
+0
select * from information_schema.feedback where variable_name like 'feed%'
and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used'
and variable_name not like '%debug%';
diff --git a/mysql-test/suite/plugins/r/feedback_plugin_send.result b/mysql-test/suite/plugins/r/feedback_plugin_send.result
index 935ea11d67b..35db81fa6c1 100644
--- a/mysql-test/suite/plugins/r/feedback_plugin_send.result
+++ b/mysql-test/suite/plugins/r/feedback_plugin_send.result
@@ -4,7 +4,7 @@ ACTIVE
SELECT variable_value INTO @feedback_used FROM information_schema.feedback where variable_name = 'FEEDBACK used';
SELECT variable_value = @feedback_used + 1 FROM information_schema.feedback where variable_name = 'FEEDBACK used';
variable_value = @feedback_used + 1
-1
+0
select * from information_schema.feedback where variable_name like 'feed%'
and variable_name not like '%_uid' and variable_name not like 'FEEDBACK used'
and variable_name not like '%debug%';
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index cf9a15dec68..ddb8fee6f70 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates.
- Copyright (c) 2010, 2016, MariaDB
+ Copyright (c) 2010, 2019, MariaDB
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
@@ -3447,6 +3447,29 @@ open_and_process_table(THD *thd, LEX *lex, TABLE_LIST *tables,
goto end;
}
}
+
+ if (!tables->derived && is_infoschema_db(&tables->db))
+ {
+ /*
+ Check whether the information schema contains a table
+ whose name is tables->schema_table_name
+ */
+ ST_SCHEMA_TABLE *schema_table;
+ schema_table= find_schema_table(thd, &tables->schema_table_name);
+ if (!schema_table ||
+ (schema_table->hidden &&
+ ((sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0 ||
+ /*
+ this check is used for show columns|keys from I_S hidden table
+ */
+ lex->sql_command == SQLCOM_SHOW_FIELDS ||
+ lex->sql_command == SQLCOM_SHOW_KEYS)))
+ {
+ my_error(ER_UNKNOWN_TABLE, MYF(0),
+ tables->schema_table_name.str, INFORMATION_SCHEMA_NAME.str);
+ DBUG_RETURN(1);
+ }
+ }
/*
If this TABLE_LIST object is a placeholder for an information_schema
table, create a temporary table to represent the information_schema
diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc
index 01caeda1325..247d7e5a3d1 100644
--- a/sql/sql_cte.cc
+++ b/sql/sql_cte.cc
@@ -1109,6 +1109,7 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem)
table= 0;
}
with= with_elem;
+ schema_table= NULL;
if (!with_elem->is_referenced() || with_elem->is_recursive)
{
derived= with_elem->spec;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 7f4cc5adaf2..33a1fa8a291 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -8304,7 +8304,6 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->derived= table->sel;
if (!ptr->derived && is_infoschema_db(&ptr->db))
{
- ST_SCHEMA_TABLE *schema_table;
if (ptr->updating &&
/* Special cases which are processed by commands itself */
lex->sql_command != SQLCOM_CHECK &&
@@ -8316,20 +8315,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
INFORMATION_SCHEMA_NAME.str);
DBUG_RETURN(0);
}
+ ST_SCHEMA_TABLE *schema_table;
schema_table= find_schema_table(thd, &ptr->table_name);
- if (unlikely(!schema_table) ||
- (schema_table->hidden &&
- ((sql_command_flags[lex->sql_command] & CF_STATUS_COMMAND) == 0 ||
- /*
- this check is used for show columns|keys from I_S hidden table
- */
- lex->sql_command == SQLCOM_SHOW_FIELDS ||
- lex->sql_command == SQLCOM_SHOW_KEYS)))
- {
- my_error(ER_UNKNOWN_TABLE, MYF(0),
- ptr->table_name.str, INFORMATION_SCHEMA_NAME.str);
- DBUG_RETURN(0);
- }
ptr->schema_table_name= ptr->table_name;
ptr->schema_table= schema_table;
}
diff --git a/storage/innobase/btr/btr0btr.cc b/storage/innobase/btr/btr0btr.cc
index cf027053cf1..10e8dfc6904 100644
--- a/storage/innobase/btr/btr0btr.cc
+++ b/storage/innobase/btr/btr0btr.cc
@@ -273,11 +273,6 @@ btr_root_get(
And block the segment list access by others.*/
buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH,
mtr);
-
- if (root && root->page.encrypted == true) {
- root = NULL;
- }
-
return(root ? buf_block_get_frame(root) : NULL);
}
@@ -1081,17 +1076,17 @@ void btr_page_get_father(dict_index_t* index, buf_block_t* block, mtr_t* mtr,
mem_heap_free(heap);
}
+/** PAGE_INDEX_ID value for freed index B-trees */
+static const index_id_t BTR_FREED_INDEX_ID = 0;
+
/** Free a B-tree root page. btr_free_but_not_root() must already
have been called.
In a persistent tablespace, the caller must invoke fsp_init_file_page()
before mtr.commit().
-@param[in,out] block index root page
-@param[in,out] mtr mini-transaction */
-static
-void
-btr_free_root(
- buf_block_t* block,
- mtr_t* mtr)
+@param[in,out] block index root page
+@param[in,out] mtr mini-transaction
+@param[in] invalidate whether to invalidate PAGE_INDEX_ID */
+static void btr_free_root(buf_block_t* block, mtr_t* mtr, bool invalidate)
{
fseg_header_t* header;
@@ -1105,31 +1100,18 @@ btr_free_root(
#ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(header, block->page.id.space()));
#endif /* UNIV_BTR_DEBUG */
+ if (invalidate) {
+ btr_page_set_index_id(
+ buf_block_get_frame(block),
+ buf_block_get_page_zip(block),
+ BTR_FREED_INDEX_ID, mtr);
+ }
while (!fseg_free_step(header, true, mtr)) {
/* Free the entire segment in small steps. */
}
}
-/** PAGE_INDEX_ID value for freed index B-trees */
-static const index_id_t BTR_FREED_INDEX_ID = 0;
-
-/** Invalidate an index root page so that btr_free_root_check()
-will not find it.
-@param[in,out] block index root page
-@param[in,out] mtr mini-transaction */
-static
-void
-btr_free_root_invalidate(
- buf_block_t* block,
- mtr_t* mtr)
-{
- btr_page_set_index_id(
- buf_block_get_frame(block),
- buf_block_get_page_zip(block),
- BTR_FREED_INDEX_ID, mtr);
-}
-
/** Prepare to free a B-tree.
@param[in] page_id page id
@param[in] page_size page size
@@ -1247,11 +1229,8 @@ btr_create(
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root
segment before return. */
- btr_free_root(block, mtr);
- if (!index->table->is_temporary()) {
- btr_free_root_invalidate(block, mtr);
- }
-
+ btr_free_root(block, mtr,
+ !index->table->is_temporary());
return(FIL_NULL);
}
@@ -1424,8 +1403,7 @@ btr_free_if_exists(
btr_free_but_not_root(root, mtr->get_log_mode());
mtr->set_named_space_id(page_id.space());
- btr_free_root(root, mtr);
- btr_free_root_invalidate(root, mtr);
+ btr_free_root(root, mtr, true);
}
/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
@@ -1445,7 +1423,7 @@ btr_free(
if (block) {
btr_free_but_not_root(block, MTR_LOG_NO_REDO);
- btr_free_root(block, &mtr);
+ btr_free_root(block, &mtr, false);
}
mtr.commit();
}
@@ -5423,8 +5401,8 @@ btr_validate_index(
page_t* root = btr_root_get(index, &mtr);
- if (root == NULL && !index->is_readable()) {
- err = DB_DECRYPTION_FAILED;
+ if (!root) {
+ err = DB_CORRUPTION;
mtr_commit(&mtr);
return err;
}
diff --git a/storage/innobase/btr/btr0bulk.cc b/storage/innobase/btr/btr0bulk.cc
index bd79a805a7d..9702ae9b4ad 100644
--- a/storage/innobase/btr/btr0bulk.cc
+++ b/storage/innobase/btr/btr0bulk.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, 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
@@ -662,11 +662,11 @@ PageBulk::latch()
/* In case the block is S-latched by page_cleaner. */
if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock,
__FILE__, __LINE__, &m_mtr)) {
- m_block = buf_page_get_gen(
- page_id_t(m_index->table->space_id, m_page_no),
- page_size_t(m_index->table->space->flags),
- RW_X_LATCH, m_block, BUF_GET_IF_IN_POOL,
- __FILE__, __LINE__, &m_mtr, &m_err);
+ m_block = buf_page_get_gen(page_id_t(m_index->table->space_id,
+ m_page_no),
+ univ_page_size, RW_X_LATCH,
+ m_block, BUF_GET_IF_IN_POOL,
+ __FILE__, __LINE__, &m_mtr, &m_err);
if (m_err != DB_SUCCESS) {
return (m_err);
diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc
index e54dd7023e6..2d5c0ddc3ca 100644
--- a/storage/innobase/buf/buf0buf.cc
+++ b/storage/innobase/buf/buf0buf.cc
@@ -4263,7 +4263,8 @@ buf_page_get_gen(
Skip the assertion on space_page_size. */
break;
case BUF_PEEK_IF_IN_POOL:
- /* In this mode, the caller may pass a dummy page size,
+ case BUF_GET_IF_IN_POOL:
+ /* The caller may pass a dummy page size,
because it does not really matter. */
break;
default:
@@ -4272,7 +4273,6 @@ buf_page_get_gen(
ut_ad(rw_latch == RW_NO_LATCH);
/* fall through */
case BUF_GET:
- case BUF_GET_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_GET_POSSIBLY_FREED:
bool found;
@@ -6101,9 +6101,7 @@ database_corrupted:
page_not_corrupt: bpage = bpage; );
if (recv_recovery_is_on()) {
- /* Pages must be uncompressed for crash recovery. */
- ut_a(uncompressed);
- recv_recover_page(TRUE, (buf_block_t*) bpage);
+ recv_recover_page(bpage);
}
/* If space is being truncated then avoid ibuf operation.
@@ -6123,7 +6121,7 @@ database_corrupted:
<< " encrypted. However key "
"management plugin or used "
<< "key_version " << key_version
- << "is not found or"
+ << " is not found or"
" used encryption algorithm or method does not match."
" Can't continue opening the table.";
} else {
diff --git a/storage/innobase/buf/buf0rea.cc b/storage/innobase/buf/buf0rea.cc
index 3edb6c6ee98..18006563f0e 100644
--- a/storage/innobase/buf/buf0rea.cc
+++ b/storage/innobase/buf/buf0rea.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2018, MariaDB Corporation.
+Copyright (c) 2015, 2019, 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
@@ -186,13 +186,13 @@ buf_read_page_low(
thd_wait_end(NULL);
}
- if (*err != DB_SUCCESS) {
+ if (UNIV_UNLIKELY(*err != DB_SUCCESS)) {
if (*err == DB_TABLESPACE_TRUNCATED) {
/* Remove the page which is outside the
truncated tablespace bounds when recovering
from a crash happened during a truncation */
buf_read_page_handle_error(bpage);
- if (recv_recovery_on) {
+ if (recv_recovery_is_on()) {
mutex_enter(&recv_sys->mutex);
ut_ad(recv_sys->n_addrs > 0);
recv_sys->n_addrs--;
diff --git a/storage/innobase/dict/dict0load.cc b/storage/innobase/dict/dict0load.cc
index 283ad22ba55..6cb62f7e256 100644
--- a/storage/innobase/dict/dict0load.cc
+++ b/storage/innobase/dict/dict0load.cc
@@ -1422,7 +1422,7 @@ next:
look to see if it is already in the tablespace cache. */
if (const fil_space_t* space
= fil_space_for_table_exists_in_mem(
- space_id, table_name.m_name, false, flags)) {
+ space_id, table_name.m_name, flags)) {
/* Recovery can open a datafile that does not
match SYS_DATAFILES. If they don't match, update
SYS_DATAFILES. */
@@ -2797,11 +2797,16 @@ dict_load_tablespace(
/* The tablespace may already be open. */
table->space = fil_space_for_table_exists_in_mem(
- table->space_id, table->name.m_name, false, table->flags);
+ table->space_id, table->name.m_name, table->flags);
if (table->space) {
return;
}
+ if (ignore_err == DICT_ERR_IGNORE_DROP) {
+ table->file_unreadable = true;
+ return;
+ }
+
if (!(ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK)) {
ib::error() << "Failed to find tablespace for table "
<< table->name << " in the cache. Attempting"
diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc
index cb74ba8d687..4da8a4c4d60 100644
--- a/storage/innobase/fil/fil0fil.cc
+++ b/storage/innobase/fil/fil0fil.cc
@@ -1271,9 +1271,7 @@ fil_space_free(
rw_lock_x_unlock(&space->latch);
}
- bool need_mutex = !recv_recovery_on;
-
- if (need_mutex) {
+ if (!recv_recovery_is_on()) {
log_mutex_enter();
}
@@ -1284,7 +1282,7 @@ fil_space_free(
UT_LIST_REMOVE(fil_system.named_spaces, space);
}
- if (need_mutex) {
+ if (!recv_recovery_is_on()) {
log_mutex_exit();
}
@@ -1343,9 +1341,8 @@ fil_space_create(
UT_LIST_INIT(space->chain, &fil_node_t::chain);
if ((purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT)
- && !recv_recovery_on
+ && !recv_recovery_is_on()
&& id > fil_system.max_assigned_id) {
-
if (!fil_system.space_id_reuse_warned) {
fil_system.space_id_reuse_warned = true;
@@ -2905,7 +2902,7 @@ fil_rename_tablespace(
ut_ad(strchr(old_file_name, OS_PATH_SEPARATOR) != NULL);
ut_ad(strchr(new_file_name, OS_PATH_SEPARATOR) != NULL);
- if (!recv_recovery_on) {
+ if (!recv_recovery_is_on()) {
fil_name_write_rename(id, old_file_name, new_file_name);
log_mutex_enter();
}
@@ -2927,7 +2924,7 @@ fil_rename_tablespace(
node->name = new_file_name;
}
- if (!recv_recovery_on) {
+ if (!recv_recovery_is_on()) {
log_mutex_exit();
}
@@ -3949,9 +3946,6 @@ memory cache. Note that if we have not done a crash recovery at the database
startup, there may be many tablespaces which are not yet in the memory cache.
@param[in] id Tablespace ID
@param[in] name Tablespace name used in fil_space_create().
-@param[in] print_error_if_does_not_exist
- Print detailed error information to the
-error log if a matching tablespace is not found from memory.
@param[in] table_flags table flags
@return the tablespace
@retval NULL if no matching tablespace exists in the memory cache */
@@ -3959,7 +3953,6 @@ fil_space_t*
fil_space_for_table_exists_in_mem(
ulint id,
const char* name,
- bool print_error_if_does_not_exist,
ulint table_flags)
{
const ulint expected_flags = dict_tf_to_fsp_flags(table_flags);
@@ -3977,7 +3970,8 @@ fil_space_for_table_exists_in_mem(
<< ", but the tablespace"
" with that id has name " << space->name << "."
" Have you deleted or moved .ibd files?";
- goto error_exit;
+ ib::info() << TROUBLESHOOT_DATADICT_MSG;
+ goto func_exit;
}
/* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
@@ -3991,17 +3985,6 @@ fil_space_for_table_exists_in_mem(
return space;
}
- if (print_error_if_does_not_exist) {
- ib::error() << "Table " << name
- << " in the InnoDB data dictionary"
- " has tablespace id " << id
- << ", but tablespace with that id"
- " or name does not exist. Have"
- " you deleted or moved .ibd files?";
-error_exit:
- ib::info() << TROUBLESHOOT_DATADICT_MSG;
- }
-
func_exit:
mutex_exit(&fil_system.mutex);
return NULL;
diff --git a/storage/innobase/fsp/fsp0fsp.cc b/storage/innobase/fsp/fsp0fsp.cc
index f4a0c9e3461..d300212a56c 100644
--- a/storage/innobase/fsp/fsp0fsp.cc
+++ b/storage/innobase/fsp/fsp0fsp.cc
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, 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
@@ -574,13 +574,9 @@ xdes_get_offset(
* FSP_EXTENT_SIZE);
}
-/***********************************************************//**
-Inits a file page whose prior contents should be ignored. */
-static
-void
-fsp_init_file_page_low(
-/*===================*/
- buf_block_t* block) /*!< in: pointer to a page */
+/** Initialize a file page whose prior contents should be ignored.
+@param[in,out] block buffer pool block */
+void fsp_apply_init_file_page(buf_block_t* block)
{
page_t* page = buf_block_get_frame(block);
@@ -638,14 +634,10 @@ fsp_space_modify_check(
/** Initialize a file page.
@param[in,out] block file page
@param[in,out] mtr mini-transaction */
-static
-void
-fsp_init_file_page(buf_block_t* block, mtr_t* mtr)
+static void fsp_init_file_page(buf_block_t* block, mtr_t* mtr)
{
- fsp_init_file_page_low(block);
-
- mlog_write_initial_log_record(buf_block_get_frame(block),
- MLOG_INIT_FILE_PAGE2, mtr);
+ fsp_apply_init_file_page(block);
+ mlog_write_initial_log_record(block->frame, MLOG_INIT_FILE_PAGE2, mtr);
}
#ifdef UNIV_DEBUG
@@ -661,26 +653,6 @@ fsp_init_file_page(const fil_space_t* space, buf_block_t* block, mtr_t* mtr)
# define fsp_init_file_page(space, block, mtr) fsp_init_file_page(block, mtr)
#endif
-/***********************************************************//**
-Parses a redo log record of a file page init.
-@return end of log record or NULL */
-byte*
-fsp_parse_init_file_page(
-/*=====================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr MY_ATTRIBUTE((unused)), /*!< in: buffer end */
- buf_block_t* block) /*!< in: block or NULL */
-{
- ut_ad(ptr != NULL);
- ut_ad(end_ptr != NULL);
-
- if (block) {
- fsp_init_file_page_low(block);
- }
-
- return(ptr);
-}
-
/**********************************************************************//**
Writes the space id and flags to a tablespace header. The flags contain
row type, physical/compressed page size, and logical/uncompressed page
diff --git a/storage/innobase/include/dict0types.h b/storage/innobase/include/dict0types.h
index e3b536b83ee..80b918b2df0 100644
--- a/storage/innobase/include/dict0types.h
+++ b/storage/innobase/include/dict0types.h
@@ -78,7 +78,10 @@ enum dict_err_ignore_t {
Silently load a missing
tablespace, and do not load
incomplete index definitions. */
- DICT_ERR_IGNORE_ALL = 0xFFFF /*!< ignore all errors */
+ /** ignore all errors above */
+ DICT_ERR_IGNORE_ALL = 15,
+ /** prepare to drop the table; do not attempt to load tablespace */
+ DICT_ERR_IGNORE_DROP = 31
};
/** Quiescing states for flushing tables to disk. */
diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h
index 0a5c1a5cfc5..8fedd962290 100644
--- a/storage/innobase/include/fil0fil.h
+++ b/storage/innobase/include/fil0fil.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, 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
@@ -1034,9 +1034,6 @@ memory cache. Note that if we have not done a crash recovery at the database
startup, there may be many tablespaces which are not yet in the memory cache.
@param[in] id Tablespace ID
@param[in] name Tablespace name used in fil_space_create().
-@param[in] print_error_if_does_not_exist
- Print detailed error information to the
-error log if a matching tablespace is not found from memory.
@param[in] table_flags table flags
@return the tablespace
@retval NULL if no matching tablespace exists in the memory cache */
@@ -1044,7 +1041,6 @@ fil_space_t*
fil_space_for_table_exists_in_mem(
ulint id,
const char* name,
- bool print_error_if_does_not_exist,
ulint table_flags);
/** Try to extend a tablespace if it is smaller than the specified size.
@@ -1250,16 +1246,12 @@ fil_names_write_if_was_clean(
return(was_clean);
}
-extern volatile bool recv_recovery_on;
-
/** During crash recovery, open a tablespace if it had not been opened
yet, to get valid size and flags.
@param[in,out] space tablespace */
-inline
-void
-fil_space_open_if_needed(
- fil_space_t* space)
+inline void fil_space_open_if_needed(fil_space_t* space)
{
+ ut_d(extern volatile bool recv_recovery_on);
ut_ad(recv_recovery_on);
if (space->size == 0) {
@@ -1267,10 +1259,7 @@ fil_space_open_if_needed(
until the files are opened for the first time.
fil_space_get_size() will open the file
and adjust the size and flags. */
-#ifdef UNIV_DEBUG
- ulint size =
-#endif /* UNIV_DEBUG */
- fil_space_get_size(space->id);
+ ut_d(ulint size =) fil_space_get_size(space->id);
ut_ad(size == space->size);
}
}
diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h
index 76c7762fac3..cdbcbd2c82e 100644
--- a/storage/innobase/include/fsp0fsp.h
+++ b/storage/innobase/include/fsp0fsp.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2013, 2018, MariaDB Corporation.
+Copyright (c) 2013, 2019, 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
@@ -627,15 +627,10 @@ fsp_descr_page(
const page_id_t page_id,
const page_size_t& page_size);
-/***********************************************************//**
-Parses a redo log record of a file page init.
-@return end of log record or NULL */
-byte*
-fsp_parse_init_file_page(
-/*=====================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr, /*!< in: buffer end */
- buf_block_t* block); /*!< in: block or NULL */
+/** Initialize a file page whose prior contents should be ignored.
+@param[in,out] block buffer pool block */
+void fsp_apply_init_file_page(buf_block_t* block);
+
#ifdef UNIV_BTR_PRINT
/*******************************************************************//**
Writes info of a segment. */
diff --git a/storage/innobase/include/log0recv.h b/storage/innobase/include/log0recv.h
index 89485b7f31d..7107e35810b 100644
--- a/storage/innobase/include/log0recv.h
+++ b/storage/innobase/include/log0recv.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2017, 2018, MariaDB Corporation.
+Copyright (c) 2017, 2019, 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
@@ -40,7 +40,7 @@ Created 9/20/1997 Heikki Tuuri
extern bool recv_writer_thread_active;
/** @return whether recovery is currently running. */
-#define recv_recovery_is_on() recv_recovery_on
+#define recv_recovery_is_on() UNIV_UNLIKELY(recv_recovery_on)
/** Find the latest checkpoint in the log header.
@param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2
@@ -49,12 +49,9 @@ dberr_t
recv_find_max_checkpoint(ulint* max_field)
MY_ATTRIBUTE((nonnull, warn_unused_result));
-/** Apply the hashed log records to the page, if the page lsn is less than the
-lsn of a log record.
-@param just_read_in whether the page recently arrived to the I/O handler
-@param block the page in the buffer pool */
-void
-recv_recover_page(bool just_read_in, buf_block_t* block);
+/** Apply any buffered redo log to a page that was just read from a data file.
+@param[in,out] bpage buffer pool page */
+ATTRIBUTE_COLD void recv_recover_page(buf_page_t* bpage);
/** Start recovering from a redo log checkpoint.
@see recv_recovery_from_checkpoint_finish
diff --git a/storage/innobase/include/page0zip.h b/storage/innobase/include/page0zip.h
index bb9bb049c22..c9ce4efd3dc 100644
--- a/storage/innobase/include/page0zip.h
+++ b/storage/innobase/include/page0zip.h
@@ -2,7 +2,7 @@
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc.
-Copyright (c) 2017, MariaDB Corporation.
+Copyright (c) 2017, 2019, 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
@@ -496,16 +496,14 @@ page_zip_copy_recs(
dict_index_t* index, /*!< in: index of the B-tree */
mtr_t* mtr); /*!< in: mini-transaction */
-/**********************************************************************//**
-Parses a log record of compressing an index page.
-@return end of log record or NULL */
-byte*
-page_zip_parse_compress(
-/*====================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr, /*!< in: buffer end */
- page_t* page, /*!< out: uncompressed page */
- page_zip_des_t* page_zip); /*!< out: compressed page */
+/** Parse and optionally apply MLOG_ZIP_PAGE_COMPRESS.
+@param[in] ptr log record
+@param[in] end_ptr end of log
+@param[in,out] block ROW_FORMAT=COMPRESSED block, or NULL for parsing only
+@return end of log record
+@retval NULL if the log record is incomplete */
+byte* page_zip_parse_compress(const byte* ptr, const byte* end_ptr,
+ buf_block_t* block);
#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h
index 7d49f0ee346..1bc3bc060dc 100644
--- a/storage/innobase/include/row0merge.h
+++ b/storage/innobase/include/row0merge.h
@@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
-Copyright (c) 2015, 2017, MariaDB Corporation.
+Copyright (c) 2015, 2019, 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
@@ -292,6 +292,12 @@ row_merge_drop_table(
dict_table_t* table) /*!< in: table instance to drop */
MY_ATTRIBUTE((nonnull, warn_unused_result));
+/** Write an MLOG_INDEX_LOAD record to indicate in the redo-log
+that redo-logging of individual index pages was disabled, and
+the flushing of such pages to the data files was completed.
+@param[in] index an index tree on which redo logging was disabled */
+void row_merge_write_redo(const dict_index_t* index);
+
/** Build indexes on a table by reading a clustered index, creating a temporary
file containing index entries, merge sorting these index entries and inserting
sorted index entries to indexes.
diff --git a/storage/innobase/log/log0log.cc b/storage/innobase/log/log0log.cc
index 9d94f6e83b5..8c17f1383df 100644
--- a/storage/innobase/log/log0log.cc
+++ b/storage/innobase/log/log0log.cc
@@ -2,7 +2,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc.
-Copyright (c) 2014, 2018, MariaDB Corporation.
+Copyright (c) 2014, 2019, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@@ -1193,14 +1193,11 @@ synchronization objects!
this lsn
@return false if there was a flush batch of the same type running,
which means that we could not start this flush batch */
-static
-bool
-log_preflush_pool_modified_pages(
- lsn_t new_oldest)
+static bool log_preflush_pool_modified_pages(lsn_t new_oldest)
{
bool success;
- if (recv_recovery_on) {
+ if (recv_recovery_is_on()) {
/* If the recovery is running, we must first apply all
log records to their respective file pages to get the
right modify lsn values to these pages: otherwise, there
diff --git a/storage/innobase/log/log0recv.cc b/storage/innobase/log/log0recv.cc
index 39ebb6885d5..60732ed8fef 100644
--- a/storage/innobase/log/log0recv.cc
+++ b/storage/innobase/log/log0recv.cc
@@ -675,7 +675,7 @@ DECLARE_THREAD(recv_writer_thread)(
mutex_enter(&recv_sys->writer_mutex);
- if (!recv_recovery_on) {
+ if (!recv_recovery_is_on()) {
mutex_exit(&recv_sys->writer_mutex);
break;
}
@@ -770,7 +770,7 @@ recv_sys_debug_free(void)
/* wake page cleaner up to progress */
if (!srv_read_only_mode) {
- ut_ad(!recv_recovery_on);
+ ut_ad(!recv_recovery_is_on());
ut_ad(!recv_writer_thread_active);
os_event_reset(buf_flush_event);
os_event_set(recv_sys->flush_start);
@@ -1615,7 +1615,7 @@ parse_log:
break;
case MLOG_INIT_FILE_PAGE2:
/* Allow anything in page_type when creating a page. */
- ptr = fsp_parse_init_file_page(ptr, end_ptr, block);
+ if (block) fsp_apply_init_file_page(block);
break;
case MLOG_WRITE_STRING:
ptr = mlog_parse_string(ptr, end_ptr, page, page_zip);
@@ -1637,7 +1637,7 @@ parse_log:
break;
case MLOG_ZIP_PAGE_COMPRESS:
/* Allow anything in page_type when creating a page. */
- ptr = page_zip_parse_compress(ptr, end_ptr, page, page_zip);
+ ptr = page_zip_parse_compress(ptr, end_ptr, block);
break;
case MLOG_ZIP_PAGE_COMPRESS_NO_DATA:
if (NULL != (ptr = mlog_parse_index(
@@ -1719,6 +1719,8 @@ recv_get_fil_addr_struct(
ulint space, /*!< in: space id */
ulint page_no)/*!< in: page number */
{
+ ut_ad(mutex_own(&recv_sys->mutex));
+
recv_addr_t* recv_addr;
for (recv_addr = static_cast<recv_addr_t*>(
@@ -1792,10 +1794,6 @@ recv_add_to_hash_table(
HASH_INSERT(recv_addr_t, addr_hash, recv_sys->addr_hash,
recv_fold(space, page_no), recv_addr);
recv_sys->n_addrs++;
-#if 0
- fprintf(stderr, "Inserting log rec for space %lu, page %lu\n",
- space, page_no);
-#endif
}
UT_LIST_ADD_LAST(recv_addr->rec_list, recv);
@@ -1864,48 +1862,20 @@ recv_data_copy_to_buf(
/** Apply the hashed log records to the page, if the page lsn is less than the
lsn of a log record.
-@param just_read_in whether the page recently arrived to the I/O handler
-@param block the page in the buffer pool */
-void
-recv_recover_page(bool just_read_in, buf_block_t* block)
+@param[in,out] block buffer pool page
+@param[in,out] mtr mini-transaction
+@param[in,out] recv_addr recovery address */
+static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
+ recv_addr_t* recv_addr)
{
page_t* page;
page_zip_des_t* page_zip;
- recv_addr_t* recv_addr;
- recv_t* recv;
- byte* buf;
- lsn_t start_lsn;
- lsn_t end_lsn;
- lsn_t page_lsn;
- lsn_t page_newest_lsn;
- ibool modification_to_page;
- mtr_t mtr;
-
- mutex_enter(&(recv_sys->mutex));
-
- if (recv_sys->apply_log_recs == FALSE) {
-
- /* Log records should not be applied now */
-
- mutex_exit(&(recv_sys->mutex));
-
- return;
- }
-
- recv_addr = recv_get_fil_addr_struct(block->page.id.space(),
- block->page.id.page_no());
-
- if ((recv_addr == NULL)
- || (recv_addr->state == RECV_BEING_PROCESSED)
- || (recv_addr->state == RECV_PROCESSED)) {
- ut_ad(recv_addr == NULL || recv_needed_recovery);
-
- mutex_exit(&(recv_sys->mutex));
-
- return;
- }
+ ut_ad(mutex_own(&recv_sys->mutex));
+ ut_ad(recv_sys->apply_log_recs);
ut_ad(recv_needed_recovery);
+ ut_ad(recv_addr->state != RECV_BEING_PROCESSED);
+ ut_ad(recv_addr->state != RECV_PROCESSED);
if (UNIV_UNLIKELY(srv_print_verbose_log == 2)) {
fprintf(stderr, "Applying log to page %u:%u\n",
@@ -1915,95 +1885,53 @@ recv_recover_page(bool just_read_in, buf_block_t* block)
DBUG_LOG("ib_log", "Applying log to page " << block->page.id);
recv_addr->state = RECV_BEING_PROCESSED;
-
- mutex_exit(&(recv_sys->mutex));
-
- mtr_start(&mtr);
- mtr_set_log_mode(&mtr, MTR_LOG_NONE);
+ mutex_exit(&recv_sys->mutex);
page = block->frame;
page_zip = buf_block_get_page_zip(block);
- if (just_read_in) {
- /* Move the ownership of the x-latch on the page to
- this OS thread, so that we can acquire a second
- x-latch on it. This is needed for the operations to
- the page to pass the debug checks. */
-
- rw_lock_x_lock_move_ownership(&block->lock);
+ /* The page may have been modified in the buffer pool.
+ FIL_PAGE_LSN would only be updated right before flushing. */
+ lsn_t page_lsn = buf_page_get_newest_modification(&block->page);
+ if (!page_lsn) {
+ page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
}
- ibool success = buf_page_get_known_nowait(
- RW_X_LATCH, block, BUF_KEEP_OLD,
- __FILE__, __LINE__, &mtr);
- ut_a(success);
-
- buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
-
- /* Read the newest modification lsn from the page */
- page_lsn = mach_read_from_8(page + FIL_PAGE_LSN);
-
- /* It may be that the page has been modified in the buffer
- pool: read the newest modification lsn there */
+ lsn_t start_lsn = 0, end_lsn = 0;
+ fil_space_t* space;
- page_newest_lsn = buf_page_get_newest_modification(&block->page);
-
- if (page_newest_lsn) {
-
- page_lsn = page_newest_lsn;
+ if (srv_is_tablespace_truncated(recv_addr->space)) {
+ /* The table will be truncated after applying
+ normal redo log records. */
+ goto skip_log;
}
- modification_to_page = FALSE;
- start_lsn = end_lsn = 0;
-
- recv = UT_LIST_GET_FIRST(recv_addr->rec_list);
- fil_space_t* space = fil_space_acquire(block->page.id.space());
+ space = fil_space_acquire(recv_addr->space);
+ if (!space) {
+ goto skip_log;
+ }
- while (recv) {
+ for (recv_t* recv = UT_LIST_GET_FIRST(recv_addr->rec_list);
+ recv; recv = UT_LIST_GET_NEXT(rec_list, recv)) {
+ ut_ad(recv->start_lsn);
end_lsn = recv->end_lsn;
-
ut_ad(end_lsn <= log_sys.log.scanned_lsn);
- if (recv->len > RECV_DATA_BLOCK_SIZE) {
- /* We have to copy the record body to a separate
- buffer */
-
- buf = static_cast<byte*>(ut_malloc_nokey(recv->len));
-
- recv_data_copy_to_buf(buf, recv);
+ if (recv->start_lsn < page_lsn) {
+ /* Ignore this record, because there are later changes
+ for this page. */
+ } else if (srv_was_tablespace_truncated(space)
+ && recv->start_lsn
+ < truncate_t::get_truncated_tablespace_init_lsn(
+ recv_addr->space)) {
+ /* If per-table tablespace was truncated and
+ there exist REDO records before truncate that
+ are to be applied as part of recovery
+ (checkpoint didn't happen since truncate was
+ done) skip such records using lsn check as
+ they may not stand valid post truncate. */
} else {
- buf = ((byte*)(recv->data)) + sizeof(recv_data_t);
- }
-
- /* If per-table tablespace was truncated and there exist REDO
- records before truncate that are to be applied as part of
- recovery (checkpoint didn't happen since truncate was done)
- skip such records using lsn check as they may not stand valid
- post truncate.
- LSN at start of truncate is recorded and any redo record
- with LSN less than recorded LSN is skipped.
- Note: We can't skip complete recv_addr as same page may have
- valid REDO records post truncate those needs to be applied. */
-
- /* Ignore applying the redo logs for tablespace that is
- truncated. Post recovery there is fixup action that will
- restore the tablespace back to normal state.
- Applying redo at this stage can result in error given that
- redo will have action recorded on page before tablespace
- was re-inited and that would lead to an error while applying
- such action. */
- if (recv->start_lsn >= page_lsn
- && !srv_is_tablespace_truncated(space->id)
- && !(srv_was_tablespace_truncated(space)
- && recv->start_lsn
- < truncate_t::get_truncated_tablespace_init_lsn(
- space->id))) {
-
- lsn_t end_lsn;
-
- if (!modification_to_page) {
-
- modification_to_page = TRUE;
+ if (!start_lsn) {
start_lsn = recv->start_lsn;
}
@@ -2019,11 +1947,23 @@ recv_recover_page(bool just_read_in, buf_block_t* block)
<< " len " << recv->len
<< " page " << block->page.id);
+ byte* buf;
+
+ if (recv->len > RECV_DATA_BLOCK_SIZE) {
+ /* We have to copy the record body to
+ a separate buffer */
+ buf = static_cast<byte*>
+ (ut_malloc_nokey(recv->len));
+ recv_data_copy_to_buf(buf, recv);
+ } else {
+ buf = reinterpret_cast<byte*>(recv->data)
+ + sizeof *recv->data;
+ }
+
recv_parse_or_apply_log_rec_body(
recv->type, buf, buf + recv->len,
block->page.id.space(),
- block->page.id.page_no(),
- true, block, &mtr);
+ block->page.id.page_no(), true, block, &mtr);
end_lsn = recv->start_lsn + recv->len;
mach_write_to_8(FIL_PAGE_LSN + page, end_lsn);
@@ -2032,32 +1972,26 @@ recv_recover_page(bool just_read_in, buf_block_t* block)
+ page, end_lsn);
if (page_zip) {
- mach_write_to_8(FIL_PAGE_LSN
- + page_zip->data, end_lsn);
+ mach_write_to_8(FIL_PAGE_LSN + page_zip->data,
+ end_lsn);
}
- }
- if (recv->len > RECV_DATA_BLOCK_SIZE) {
- ut_free(buf);
+ if (recv->len > RECV_DATA_BLOCK_SIZE) {
+ ut_free(buf);
+ }
}
-
- recv = UT_LIST_GET_NEXT(rec_list, recv);
}
space->release();
+skip_log:
#ifdef UNIV_ZIP_DEBUG
- if (fil_page_index_page_check(page)) {
- page_zip_des_t* page_zip = buf_block_get_page_zip(block);
-
- ut_a(!page_zip
- || page_zip_validate_low(page_zip, page, NULL, FALSE));
- }
+ ut_ad(!fil_page_index_page_check(page)
+ || !page_zip
+ || page_zip_validate_low(page_zip, page, NULL, FALSE));
#endif /* UNIV_ZIP_DEBUG */
- if (modification_to_page) {
- ut_a(block);
-
+ if (start_lsn) {
log_flush_order_mutex_enter();
buf_flush_recv_note_modification(block, start_lsn, end_lsn);
log_flush_order_mutex_exit();
@@ -2067,8 +2001,7 @@ recv_recover_page(bool just_read_in, buf_block_t* block)
lsn values of page */
mtr.discard_modifications();
-
- mtr_commit(&mtr);
+ mtr.commit();
ib_time_t time = ut_time();
@@ -2078,6 +2011,7 @@ recv_recover_page(bool just_read_in, buf_block_t* block)
recv_max_page_lsn = page_lsn;
}
+ ut_ad(recv_addr->state == RECV_BEING_PROCESSED);
recv_addr->state = RECV_PROCESSED;
ut_a(recv_sys->n_addrs > 0);
@@ -2088,52 +2022,76 @@ recv_recover_page(bool just_read_in, buf_block_t* block)
INNODB_EXTEND_TIMEOUT_INTERVAL, "To recover: " ULINTPF " pages from log", n);
}
}
+}
+/** Apply any buffered redo log to a page that was just read from a data file.
+@param[in,out] bpage buffer pool page */
+void recv_recover_page(buf_page_t* bpage)
+{
+ mtr_t mtr;
+ mtr.start();
+ mtr.set_log_mode(MTR_LOG_NONE);
+
+ ut_ad(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE);
+ buf_block_t* block = reinterpret_cast<buf_block_t*>(bpage);
+
+ /* Move the ownership of the x-latch on the page to
+ this OS thread, so that we can acquire a second
+ x-latch on it. This is needed for the operations to
+ the page to pass the debug checks. */
+ rw_lock_x_lock_move_ownership(&block->lock);
+ buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
+ ibool success = buf_page_get_known_nowait(
+ RW_X_LATCH, block, BUF_KEEP_OLD,
+ __FILE__, __LINE__, &mtr);
+ ut_a(success);
+
+ mutex_enter(&recv_sys->mutex);
+ if (!recv_sys->apply_log_recs) {
+ } else if (recv_addr_t* recv_addr = recv_get_fil_addr_struct(
+ bpage->id.space(), bpage->id.page_no())) {
+ switch (recv_addr->state) {
+ case RECV_BEING_PROCESSED:
+ case RECV_PROCESSED:
+ break;
+ default:
+ recv_recover_page(block, mtr, recv_addr);
+ goto func_exit;
+ }
+ }
+
+ mtr.commit();
+func_exit:
mutex_exit(&recv_sys->mutex);
+ ut_ad(mtr.has_committed());
}
/** Reads in pages which have hashed log records, from an area around a given
page number.
-@param[in] page_id page id
-@return number of pages found */
-static ulint recv_read_in_area(const page_id_t page_id)
+@param[in] page_id page id */
+static void recv_read_in_area(const page_id_t page_id)
{
- recv_addr_t* recv_addr;
ulint page_nos[RECV_READ_AHEAD_AREA];
- ulint low_limit;
- ulint n;
-
- low_limit = page_id.page_no()
+ ulint page_no = page_id.page_no()
- (page_id.page_no() % RECV_READ_AHEAD_AREA);
+ ulint* p = page_nos;
- n = 0;
-
- for (ulint page_no = low_limit;
- page_no < low_limit + RECV_READ_AHEAD_AREA;
- page_no++) {
-
- recv_addr = recv_get_fil_addr_struct(page_id.space(), page_no);
-
- const page_id_t cur_page_id(page_id.space(), page_no);
-
- if (recv_addr && !buf_page_peek(cur_page_id)) {
-
- mutex_enter(&(recv_sys->mutex));
-
- if (recv_addr->state == RECV_NOT_PROCESSED) {
- recv_addr->state = RECV_BEING_READ;
-
- page_nos[n] = page_no;
-
- n++;
- }
-
- mutex_exit(&(recv_sys->mutex));
+ for (const ulint up_limit = page_no + RECV_READ_AHEAD_AREA;
+ page_no < up_limit; page_no++) {
+ recv_addr_t* recv_addr = recv_get_fil_addr_struct(
+ page_id.space(), page_no);
+ if (recv_addr
+ && recv_addr->state == RECV_NOT_PROCESSED
+ && !buf_page_peek(page_id_t(page_id.space(), page_no))) {
+ recv_addr->state = RECV_BEING_READ;
+ *p++ = page_no;
}
}
- buf_read_recv_pages(FALSE, page_id.space(), page_nos, n);
- return(n);
+ mutex_exit(&recv_sys->mutex);
+ buf_read_recv_pages(FALSE, page_id.space(), page_nos,
+ ulint(p - page_nos));
+ mutex_enter(&recv_sys->mutex);
}
/** Apply the hash table of stored log records to persistent data pages.
@@ -2186,59 +2144,55 @@ void recv_apply_hashed_log_recs(bool last_batch)
}
}
+ mtr_t mtr;
+
for (ulint i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) {
for (recv_addr_t* recv_addr = static_cast<recv_addr_t*>(
HASH_GET_FIRST(recv_sys->addr_hash, i));
recv_addr;
recv_addr = static_cast<recv_addr_t*>(
HASH_GET_NEXT(addr_hash, recv_addr))) {
-
- if (srv_is_tablespace_truncated(recv_addr->space)) {
- /* Avoid applying REDO log for the tablespace
- that is schedule for TRUNCATE. */
+ if (!UT_LIST_GET_LEN(recv_addr->rec_list)) {
+ignore:
ut_a(recv_sys->n_addrs);
- recv_addr->state = RECV_DISCARDED;
recv_sys->n_addrs--;
continue;
}
- if (recv_addr->state == RECV_DISCARDED
- || !UT_LIST_GET_LEN(recv_addr->rec_list)) {
- ut_a(recv_sys->n_addrs);
- recv_sys->n_addrs--;
+ switch (recv_addr->state) {
+ case RECV_BEING_READ:
+ case RECV_BEING_PROCESSED:
+ case RECV_PROCESSED:
continue;
+ case RECV_DISCARDED:
+ goto ignore;
+ case RECV_NOT_PROCESSED:
+ break;
}
- const page_id_t page_id(recv_addr->space,
- recv_addr->page_no);
- bool found;
- const page_size_t& page_size
- = fil_space_get_page_size(recv_addr->space,
- &found);
-
- ut_ad(found);
-
- if (recv_addr->state == RECV_NOT_PROCESSED) {
- mutex_exit(&recv_sys->mutex);
-
- if (buf_page_peek(page_id)) {
- mtr_t mtr;
- mtr.start();
-
- buf_block_t* block = buf_page_get(
- page_id, page_size,
- RW_X_LATCH, &mtr);
-
- buf_block_dbg_add_level(
- block, SYNC_NO_ORDER_CHECK);
-
- recv_recover_page(FALSE, block);
- mtr.commit();
- } else {
- recv_read_in_area(page_id);
- }
+ if (srv_is_tablespace_truncated(recv_addr->space)) {
+ /* Avoid applying REDO log for the tablespace
+ that is schedule for TRUNCATE. */
+ recv_addr->state = RECV_DISCARDED;
+ goto ignore;
+ }
- mutex_enter(&recv_sys->mutex);
+ const page_id_t page_id(recv_addr->space,
+ recv_addr->page_no);
+
+ mtr.start();
+ mtr.set_log_mode(MTR_LOG_NONE);
+ if (buf_block_t* block = buf_page_get_gen(
+ page_id, univ_page_size, RW_X_LATCH,
+ NULL, BUF_GET_IF_IN_POOL,
+ __FILE__, __LINE__, &mtr, NULL)) {
+ buf_block_dbg_add_level(
+ block, SYNC_NO_ORDER_CHECK);
+ recv_recover_page(block, mtr, recv_addr);
+ ut_ad(mtr.has_committed());
+ } else {
+ mtr.commit();
+ recv_read_in_area(page_id);
}
}
}
@@ -2485,6 +2439,15 @@ recv_report_corrupt_log(
return(true);
}
+/** Report a MLOG_INDEX_LOAD operation.
+@param[in] space_id tablespace identifier */
+ATTRIBUTE_COLD static void recv_mlog_index_load(ulint space_id)
+{
+ if (log_optimized_ddl_op) {
+ log_optimized_ddl_op(space_id);
+ }
+}
+
/** Parse log records from a buffer and optionally store them to a
hash table to wait merging to file pages.
@param[in] checkpoint_lsn the LSN of the latest checkpoint
@@ -2506,6 +2469,7 @@ bool recv_parse_log_recs(lsn_t checkpoint_lsn, store_t store, bool apply)
byte* body;
ut_ad(log_mutex_own());
+ ut_ad(mutex_own(&recv_sys->mutex));
ut_ad(recv_sys->parse_start_lsn != 0);
loop:
ptr = recv_sys->buf + recv_sys->recovered_offset;
@@ -2640,9 +2604,7 @@ loop:
/* fall through */
case MLOG_INDEX_LOAD:
if (type == MLOG_INDEX_LOAD) {
- if (log_optimized_ddl_op) {
- log_optimized_ddl_op(space);
- }
+ recv_mlog_index_load(space);
}
/* fall through */
case MLOG_FILE_NAME:
@@ -2796,10 +2758,7 @@ corrupted_log:
break;
#endif /* UNIV_LOG_LSN_DEBUG */
case MLOG_INDEX_LOAD:
- /* Mariabackup FIXME: Report an error
- when encountering MLOG_INDEX_LOAD on
- --prepare or already on --backup. */
- ut_a(srv_operation == SRV_OPERATION_NORMAL);
+ recv_mlog_index_load(space);
break;
case MLOG_FILE_NAME:
case MLOG_FILE_DELETE:
@@ -3077,6 +3036,8 @@ recv_scan_log_recs(
*group_scanned_lsn = scanned_lsn;
+ mutex_enter(&recv_sys->mutex);
+
if (more_data && !recv_sys->found_corrupt_log) {
/* Try to parse more log records */
@@ -3086,7 +3047,8 @@ recv_scan_log_recs(
|| recv_sys->found_corrupt_fs
|| recv_sys->mlog_checkpoint_lsn
== recv_sys->recovered_lsn);
- return(true);
+ finished = true;
+ goto func_exit;
}
if (*store_to_hash != STORE_NO
@@ -3107,6 +3069,8 @@ recv_scan_log_recs(
}
}
+func_exit:
+ mutex_exit(&recv_sys->mutex);
return(finished);
}
diff --git a/storage/innobase/page/page0zip.cc b/storage/innobase/page/page0zip.cc
index 8b07b2b953d..ac0ff39f4f9 100644
--- a/storage/innobase/page/page0zip.cc
+++ b/storage/innobase/page/page0zip.cc
@@ -4917,23 +4917,20 @@ page_zip_copy_recs(
page_zip_compress_write_log(page_zip, page, index, mtr);
}
-/**********************************************************************//**
-Parses a log record of compressing an index page.
-@return end of log record or NULL */
-byte*
-page_zip_parse_compress(
-/*====================*/
- byte* ptr, /*!< in: buffer */
- byte* end_ptr,/*!< in: buffer end */
- page_t* page, /*!< out: uncompressed page */
- page_zip_des_t* page_zip)/*!< out: compressed page */
+/** Parse and optionally apply MLOG_ZIP_PAGE_COMPRESS.
+@param[in] ptr log record
+@param[in] end_ptr end of log
+@param[in,out] block ROW_FORMAT=COMPRESSED block, or NULL for parsing only
+@return end of log record
+@retval NULL if the log record is incomplete */
+byte* page_zip_parse_compress(const byte* ptr, const byte* end_ptr,
+ buf_block_t* block)
{
ulint size;
ulint trailer_size;
ut_ad(ptr != NULL);
ut_ad(end_ptr!= NULL);
- ut_ad(!page == !page_zip);
if (UNIV_UNLIKELY(ptr + (2 + 2) > end_ptr)) {
@@ -4950,14 +4947,22 @@ page_zip_parse_compress(
return(NULL);
}
- if (page) {
- if (!page_zip || page_zip_get_size(page_zip) < size) {
+ if (block) {
+ ut_ad(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
+ page_zip_des_t* page_zip = buf_block_get_page_zip(block);
+ if (!page_zip || page_zip_get_size(page_zip) < size
+ || block->page.id.page_no() < 3) {
corrupt:
recv_sys->found_corrupt_log = TRUE;
return(NULL);
}
+ memset(page_zip->data, 0, page_zip_get_size(page_zip));
+ mach_write_to_4(FIL_PAGE_OFFSET
+ + page_zip->data, block->page.id.page_no());
+ mach_write_to_4(FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID
+ + page_zip->data, block->page.id.space());
memcpy(page_zip->data + FIL_PAGE_PREV, ptr, 4);
memcpy(page_zip->data + FIL_PAGE_NEXT, ptr + 4, 4);
memcpy(page_zip->data + FIL_PAGE_TYPE, ptr + 8, size);
@@ -4967,14 +4972,14 @@ corrupt:
memcpy(page_zip->data + page_zip_get_size(page_zip)
- trailer_size, ptr + 8 + size, trailer_size);
- if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, page,
+ if (UNIV_UNLIKELY(!page_zip_decompress(page_zip, block->frame,
TRUE))) {
goto corrupt;
}
}
- return(ptr + 8 + size + trailer_size);
+ return(const_cast<byte*>(ptr) + 8 + size + trailer_size);
}
#endif /* !UNIV_INNOCHECKSUM */
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index b9f01f4547e..8afee045493 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -1806,5 +1806,9 @@ exit:
ib::info() << "InnoDB_FTS: inserted " << count << " records";
}
+ if (psort_info[0].psort_common->trx->get_flush_observer()) {
+ row_merge_write_redo(aux_index);
+ }
+
return(error);
}
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index 101287c204e..1f4ffdf1e8c 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -4519,17 +4519,14 @@ row_merge_drop_table(
that redo-logging of individual index pages was disabled, and
the flushing of such pages to the data files was completed.
@param[in] index an index tree on which redo logging was disabled */
-static
-void
-row_merge_write_redo(
- const dict_index_t* index)
+void row_merge_write_redo(const dict_index_t* index)
{
- mtr_t mtr;
- byte* log_ptr;
-
ut_ad(!index->table->is_temporary());
+ ut_ad(!(index->type & (DICT_SPATIAL | DICT_FTS)));
+
+ mtr_t mtr;
mtr.start();
- log_ptr = mlog_open(&mtr, 11 + 8);
+ byte* log_ptr = mlog_open(&mtr, 11 + 8);
log_ptr = mlog_write_initial_log_record_low(
MLOG_INDEX_LOAD,
index->table->space_id, index->page, log_ptr, &mtr);
@@ -5070,7 +5067,10 @@ func_exit:
= dict_table_get_first_index(new_table);
index != NULL;
index = dict_table_get_next_index(index)) {
- row_merge_write_redo(index);
+ if (!(index->type
+ & (DICT_FTS | DICT_SPATIAL))) {
+ row_merge_write_redo(index);
+ }
}
}
}
diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc
index 0400cce24ef..237e3f7d749 100644
--- a/storage/innobase/row/row0mysql.cc
+++ b/storage/innobase/row/row0mysql.cc
@@ -2771,7 +2771,7 @@ row_mysql_drop_garbage_tables()
btr_pcur_commit_specify_mtr(&pcur, &mtr);
if (dict_load_table(table_name, true,
- DICT_ERR_IGNORE_ALL)) {
+ DICT_ERR_IGNORE_DROP)) {
row_drop_table_for_mysql(table_name, trx,
SQLCOM_DROP_TABLE);
trx_commit_for_mysql(trx);