Merge 10.2 into 10.3

This commit is contained in:
Marko Mäkelä 2019-04-07 11:49:50 +03:00
commit cc492bfd4f
29 changed files with 376 additions and 436 deletions

View File

@ -2748,8 +2748,13 @@ static bool xtrabackup_copy_logfile(bool last = false)
my_sleep(1000); my_sleep(1000);
} }
start_lsn = (lsn == start_lsn) if (lsn == start_lsn) {
? 0 : xtrabackup_copy_log(start_lsn, lsn, last); 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(); log_mutex_exit();

View File

@ -1659,3 +1659,17 @@ a
2 2
drop view v1; drop view v1;
drop table t1,t2; 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;

View File

@ -1168,3 +1168,15 @@ select * from v1;
drop view v1; drop view v1;
drop table t1,t2; 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;

View File

@ -3,6 +3,8 @@
# Embedded server does not support restarting # Embedded server does not support restarting
--source include/not_embedded.inc --source include/not_embedded.inc
let $MYSQLD_DATADIR=`select @@datadir`;
CREATE TABLE t(c0 SERIAL, c1 INT, c2 INT, c3 INT, c4 INT, CREATE TABLE t(c0 SERIAL, c1 INT, c2 INT, c3 INT, c4 INT,
KEY(c1), KEY(c2), KEY(c2,c1), KEY(c1), KEY(c2), KEY(c2,c1),
KEY(c3), KEY(c3,c1), KEY(c3,c2), KEY(c3,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 --error ER_NO_SUCH_TABLE
SELECT * from target; SELECT * from target;
DROP TABLE t; 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; CREATE TABLE t (a INT) ENGINE=InnoDB;
DROP TABLE t; DROP TABLE t;
--error ER_BAD_TABLE_ERROR --error ER_BAD_TABLE_ERROR

View File

@ -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 '%_uid'
and variable_name not like '%debug%'; and variable_name not like '%debug%';
VARIABLE_NAME VARIABLE_VALUE VARIABLE_NAME VARIABLE_VALUE
FEEDBACK used 1 FEEDBACK used 2
FEEDBACK version 1.1 FEEDBACK version 1.1
FEEDBACK_HTTP_PROXY FEEDBACK_HTTP_PROXY
FEEDBACK_SEND_RETRY_WAIT 60 FEEDBACK_SEND_RETRY_WAIT 60

View File

@ -4,7 +4,7 @@ ACTIVE
SELECT variable_value INTO @feedback_used FROM information_schema.feedback where variable_name = 'FEEDBACK used'; 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'; SELECT variable_value = @feedback_used + 1 FROM information_schema.feedback where variable_name = 'FEEDBACK used';
variable_value = @feedback_used + 1 variable_value = @feedback_used + 1
1 0
select * from information_schema.feedback where variable_name like 'feed%' 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 '%_uid' and variable_name not like 'FEEDBACK used'
and variable_name not like '%debug%'; and variable_name not like '%debug%';

View File

@ -4,7 +4,7 @@ ACTIVE
SELECT variable_value INTO @feedback_used FROM information_schema.feedback where variable_name = 'FEEDBACK used'; 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'; SELECT variable_value = @feedback_used + 1 FROM information_schema.feedback where variable_name = 'FEEDBACK used';
variable_value = @feedback_used + 1 variable_value = @feedback_used + 1
1 0
select * from information_schema.feedback where variable_name like 'feed%' 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 '%_uid' and variable_name not like 'FEEDBACK used'
and variable_name not like '%debug%'; and variable_name not like '%debug%';

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2016, Oracle and/or its affiliates. /* 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 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 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; 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 If this TABLE_LIST object is a placeholder for an information_schema
table, create a temporary table to represent the information_schema table, create a temporary table to represent the information_schema

View File

@ -1109,6 +1109,7 @@ bool TABLE_LIST::set_as_with_table(THD *thd, With_element *with_elem)
table= 0; table= 0;
} }
with= with_elem; with= with_elem;
schema_table= NULL;
if (!with_elem->is_referenced() || with_elem->is_recursive) if (!with_elem->is_referenced() || with_elem->is_recursive)
{ {
derived= with_elem->spec; derived= with_elem->spec;

View File

@ -8304,7 +8304,6 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->derived= table->sel; ptr->derived= table->sel;
if (!ptr->derived && is_infoschema_db(&ptr->db)) if (!ptr->derived && is_infoschema_db(&ptr->db))
{ {
ST_SCHEMA_TABLE *schema_table;
if (ptr->updating && if (ptr->updating &&
/* Special cases which are processed by commands itself */ /* Special cases which are processed by commands itself */
lex->sql_command != SQLCOM_CHECK && lex->sql_command != SQLCOM_CHECK &&
@ -8316,20 +8315,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
INFORMATION_SCHEMA_NAME.str); INFORMATION_SCHEMA_NAME.str);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
ST_SCHEMA_TABLE *schema_table;
schema_table= find_schema_table(thd, &ptr->table_name); 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_name= ptr->table_name;
ptr->schema_table= schema_table; ptr->schema_table= schema_table;
} }

View File

@ -273,11 +273,6 @@ btr_root_get(
And block the segment list access by others.*/ And block the segment list access by others.*/
buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH, buf_block_t* root = btr_root_block_get(index, RW_SX_LATCH,
mtr); mtr);
if (root && root->page.encrypted == true) {
root = NULL;
}
return(root ? buf_block_get_frame(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); 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 /** Free a B-tree root page. btr_free_but_not_root() must already
have been called. have been called.
In a persistent tablespace, the caller must invoke fsp_init_file_page() In a persistent tablespace, the caller must invoke fsp_init_file_page()
before mtr.commit(). before mtr.commit().
@param[in,out] block index root page @param[in,out] block index root page
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction
static @param[in] invalidate whether to invalidate PAGE_INDEX_ID */
void static void btr_free_root(buf_block_t* block, mtr_t* mtr, bool invalidate)
btr_free_root(
buf_block_t* block,
mtr_t* mtr)
{ {
fseg_header_t* header; fseg_header_t* header;
@ -1105,29 +1100,16 @@ btr_free_root(
#ifdef UNIV_BTR_DEBUG #ifdef UNIV_BTR_DEBUG
ut_a(btr_root_fseg_validate(header, block->page.id.space())); ut_a(btr_root_fseg_validate(header, block->page.id.space()));
#endif /* UNIV_BTR_DEBUG */ #endif /* UNIV_BTR_DEBUG */
if (invalidate) {
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( btr_page_set_index_id(
buf_block_get_frame(block), buf_block_get_frame(block),
buf_block_get_page_zip(block), buf_block_get_page_zip(block),
BTR_FREED_INDEX_ID, mtr); BTR_FREED_INDEX_ID, mtr);
}
while (!fseg_free_step(header, true, mtr)) {
/* Free the entire segment in small steps. */
}
} }
/** Prepare to free a B-tree. /** Prepare to free a B-tree.
@ -1247,11 +1229,8 @@ btr_create(
PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) { PAGE_HEADER + PAGE_BTR_SEG_LEAF, mtr)) {
/* Not enough space for new segment, free root /* Not enough space for new segment, free root
segment before return. */ segment before return. */
btr_free_root(block, mtr); btr_free_root(block, mtr,
if (!index->table->is_temporary()) { !index->table->is_temporary());
btr_free_root_invalidate(block, mtr);
}
return(FIL_NULL); return(FIL_NULL);
} }
@ -1424,8 +1403,7 @@ btr_free_if_exists(
btr_free_but_not_root(root, mtr->get_log_mode()); btr_free_but_not_root(root, mtr->get_log_mode());
mtr->set_named_space_id(page_id.space()); mtr->set_named_space_id(page_id.space());
btr_free_root(root, mtr); btr_free_root(root, mtr, true);
btr_free_root_invalidate(root, mtr);
} }
/** Free an index tree in a temporary tablespace or during TRUNCATE TABLE. /** Free an index tree in a temporary tablespace or during TRUNCATE TABLE.
@ -1445,7 +1423,7 @@ btr_free(
if (block) { if (block) {
btr_free_but_not_root(block, MTR_LOG_NO_REDO); btr_free_but_not_root(block, MTR_LOG_NO_REDO);
btr_free_root(block, &mtr); btr_free_root(block, &mtr, false);
} }
mtr.commit(); mtr.commit();
} }
@ -5423,8 +5401,8 @@ btr_validate_index(
page_t* root = btr_root_get(index, &mtr); page_t* root = btr_root_get(index, &mtr);
if (root == NULL && !index->is_readable()) { if (!root) {
err = DB_DECRYPTION_FAILED; err = DB_CORRUPTION;
mtr_commit(&mtr); mtr_commit(&mtr);
return err; return err;
} }

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -662,10 +662,10 @@ PageBulk::latch()
/* In case the block is S-latched by page_cleaner. */ /* In case the block is S-latched by page_cleaner. */
if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock, if (!buf_page_optimistic_get(RW_X_LATCH, m_block, m_modify_clock,
__FILE__, __LINE__, &m_mtr)) { __FILE__, __LINE__, &m_mtr)) {
m_block = buf_page_get_gen( m_block = buf_page_get_gen(page_id_t(m_index->table->space_id,
page_id_t(m_index->table->space_id, m_page_no), m_page_no),
page_size_t(m_index->table->space->flags), univ_page_size, RW_X_LATCH,
RW_X_LATCH, m_block, BUF_GET_IF_IN_POOL, m_block, BUF_GET_IF_IN_POOL,
__FILE__, __LINE__, &m_mtr, &m_err); __FILE__, __LINE__, &m_mtr, &m_err);
if (m_err != DB_SUCCESS) { if (m_err != DB_SUCCESS) {

View File

@ -4263,7 +4263,8 @@ buf_page_get_gen(
Skip the assertion on space_page_size. */ Skip the assertion on space_page_size. */
break; break;
case BUF_PEEK_IF_IN_POOL: 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. */ because it does not really matter. */
break; break;
default: default:
@ -4272,7 +4273,6 @@ buf_page_get_gen(
ut_ad(rw_latch == RW_NO_LATCH); ut_ad(rw_latch == RW_NO_LATCH);
/* fall through */ /* fall through */
case BUF_GET: case BUF_GET:
case BUF_GET_IF_IN_POOL:
case BUF_GET_IF_IN_POOL_OR_WATCH: case BUF_GET_IF_IN_POOL_OR_WATCH:
case BUF_GET_POSSIBLY_FREED: case BUF_GET_POSSIBLY_FREED:
bool found; bool found;
@ -6101,9 +6101,7 @@ database_corrupted:
page_not_corrupt: bpage = bpage; ); page_not_corrupt: bpage = bpage; );
if (recv_recovery_is_on()) { if (recv_recovery_is_on()) {
/* Pages must be uncompressed for crash recovery. */ recv_recover_page(bpage);
ut_a(uncompressed);
recv_recover_page(TRUE, (buf_block_t*) bpage);
} }
/* If space is being truncated then avoid ibuf operation. /* If space is being truncated then avoid ibuf operation.
@ -6123,7 +6121,7 @@ database_corrupted:
<< " encrypted. However key " << " encrypted. However key "
"management plugin or used " "management plugin or used "
<< "key_version " << key_version << "key_version " << key_version
<< "is not found or" << " is not found or"
" used encryption algorithm or method does not match." " used encryption algorithm or method does not match."
" Can't continue opening the table."; " Can't continue opening the table.";
} else { } else {

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -186,13 +186,13 @@ buf_read_page_low(
thd_wait_end(NULL); thd_wait_end(NULL);
} }
if (*err != DB_SUCCESS) { if (UNIV_UNLIKELY(*err != DB_SUCCESS)) {
if (*err == DB_TABLESPACE_TRUNCATED) { if (*err == DB_TABLESPACE_TRUNCATED) {
/* Remove the page which is outside the /* Remove the page which is outside the
truncated tablespace bounds when recovering truncated tablespace bounds when recovering
from a crash happened during a truncation */ from a crash happened during a truncation */
buf_read_page_handle_error(bpage); buf_read_page_handle_error(bpage);
if (recv_recovery_on) { if (recv_recovery_is_on()) {
mutex_enter(&recv_sys->mutex); mutex_enter(&recv_sys->mutex);
ut_ad(recv_sys->n_addrs > 0); ut_ad(recv_sys->n_addrs > 0);
recv_sys->n_addrs--; recv_sys->n_addrs--;

View File

@ -1422,7 +1422,7 @@ next:
look to see if it is already in the tablespace cache. */ look to see if it is already in the tablespace cache. */
if (const fil_space_t* space if (const fil_space_t* space
= fil_space_for_table_exists_in_mem( = 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 /* Recovery can open a datafile that does not
match SYS_DATAFILES. If they don't match, update match SYS_DATAFILES. If they don't match, update
SYS_DATAFILES. */ SYS_DATAFILES. */
@ -2797,11 +2797,16 @@ dict_load_tablespace(
/* The tablespace may already be open. */ /* The tablespace may already be open. */
table->space = fil_space_for_table_exists_in_mem( 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) { if (table->space) {
return; return;
} }
if (ignore_err == DICT_ERR_IGNORE_DROP) {
table->file_unreadable = true;
return;
}
if (!(ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK)) { if (!(ignore_err & DICT_ERR_IGNORE_RECOVER_LOCK)) {
ib::error() << "Failed to find tablespace for table " ib::error() << "Failed to find tablespace for table "
<< table->name << " in the cache. Attempting" << table->name << " in the cache. Attempting"

View File

@ -1271,9 +1271,7 @@ fil_space_free(
rw_lock_x_unlock(&space->latch); rw_lock_x_unlock(&space->latch);
} }
bool need_mutex = !recv_recovery_on; if (!recv_recovery_is_on()) {
if (need_mutex) {
log_mutex_enter(); log_mutex_enter();
} }
@ -1284,7 +1282,7 @@ fil_space_free(
UT_LIST_REMOVE(fil_system.named_spaces, space); UT_LIST_REMOVE(fil_system.named_spaces, space);
} }
if (need_mutex) { if (!recv_recovery_is_on()) {
log_mutex_exit(); log_mutex_exit();
} }
@ -1343,9 +1341,8 @@ fil_space_create(
UT_LIST_INIT(space->chain, &fil_node_t::chain); UT_LIST_INIT(space->chain, &fil_node_t::chain);
if ((purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT) if ((purpose == FIL_TYPE_TABLESPACE || purpose == FIL_TYPE_IMPORT)
&& !recv_recovery_on && !recv_recovery_is_on()
&& id > fil_system.max_assigned_id) { && id > fil_system.max_assigned_id) {
if (!fil_system.space_id_reuse_warned) { if (!fil_system.space_id_reuse_warned) {
fil_system.space_id_reuse_warned = true; 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(old_file_name, OS_PATH_SEPARATOR) != NULL);
ut_ad(strchr(new_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); fil_name_write_rename(id, old_file_name, new_file_name);
log_mutex_enter(); log_mutex_enter();
} }
@ -2927,7 +2924,7 @@ fil_rename_tablespace(
node->name = new_file_name; node->name = new_file_name;
} }
if (!recv_recovery_on) { if (!recv_recovery_is_on()) {
log_mutex_exit(); 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. startup, there may be many tablespaces which are not yet in the memory cache.
@param[in] id Tablespace ID @param[in] id Tablespace ID
@param[in] name Tablespace name used in fil_space_create(). @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 @param[in] table_flags table flags
@return the tablespace @return the tablespace
@retval NULL if no matching tablespace exists in the memory cache */ @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( fil_space_for_table_exists_in_mem(
ulint id, ulint id,
const char* name, const char* name,
bool print_error_if_does_not_exist,
ulint table_flags) ulint table_flags)
{ {
const ulint expected_flags = dict_tf_to_fsp_flags(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" << ", but the tablespace"
" with that id has name " << space->name << "." " with that id has name " << space->name << "."
" Have you deleted or moved .ibd files?"; " 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. /* Adjust the flags that are in FSP_FLAGS_MEM_MASK.
@ -3991,17 +3985,6 @@ fil_space_for_table_exists_in_mem(
return space; 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: func_exit:
mutex_exit(&fil_system.mutex); mutex_exit(&fil_system.mutex);
return NULL; return NULL;

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation. Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -574,13 +574,9 @@ xdes_get_offset(
* FSP_EXTENT_SIZE); * FSP_EXTENT_SIZE);
} }
/***********************************************************//** /** Initialize a file page whose prior contents should be ignored.
Inits a file page whose prior contents should be ignored. */ @param[in,out] block buffer pool block */
static void fsp_apply_init_file_page(buf_block_t* block)
void
fsp_init_file_page_low(
/*===================*/
buf_block_t* block) /*!< in: pointer to a page */
{ {
page_t* page = buf_block_get_frame(block); page_t* page = buf_block_get_frame(block);
@ -638,14 +634,10 @@ fsp_space_modify_check(
/** Initialize a file page. /** Initialize a file page.
@param[in,out] block file page @param[in,out] block file page
@param[in,out] mtr mini-transaction */ @param[in,out] mtr mini-transaction */
static static void fsp_init_file_page(buf_block_t* block, mtr_t* mtr)
void
fsp_init_file_page(buf_block_t* block, mtr_t* mtr)
{ {
fsp_init_file_page_low(block); fsp_apply_init_file_page(block);
mlog_write_initial_log_record(block->frame, MLOG_INIT_FILE_PAGE2, mtr);
mlog_write_initial_log_record(buf_block_get_frame(block),
MLOG_INIT_FILE_PAGE2, mtr);
} }
#ifdef UNIV_DEBUG #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) # define fsp_init_file_page(space, block, mtr) fsp_init_file_page(block, mtr)
#endif #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 Writes the space id and flags to a tablespace header. The flags contain
row type, physical/compressed page size, and logical/uncompressed page row type, physical/compressed page size, and logical/uncompressed page

View File

@ -78,7 +78,10 @@ enum dict_err_ignore_t {
Silently load a missing Silently load a missing
tablespace, and do not load tablespace, and do not load
incomplete index definitions. */ 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. */ /** Quiescing states for flushing tables to disk. */

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -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. startup, there may be many tablespaces which are not yet in the memory cache.
@param[in] id Tablespace ID @param[in] id Tablespace ID
@param[in] name Tablespace name used in fil_space_create(). @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 @param[in] table_flags table flags
@return the tablespace @return the tablespace
@retval NULL if no matching tablespace exists in the memory cache */ @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( fil_space_for_table_exists_in_mem(
ulint id, ulint id,
const char* name, const char* name,
bool print_error_if_does_not_exist,
ulint table_flags); ulint table_flags);
/** Try to extend a tablespace if it is smaller than the specified size. /** 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); return(was_clean);
} }
extern volatile bool recv_recovery_on;
/** During crash recovery, open a tablespace if it had not been opened /** During crash recovery, open a tablespace if it had not been opened
yet, to get valid size and flags. yet, to get valid size and flags.
@param[in,out] space tablespace */ @param[in,out] space tablespace */
inline inline void fil_space_open_if_needed(fil_space_t* space)
void
fil_space_open_if_needed(
fil_space_t* space)
{ {
ut_d(extern volatile bool recv_recovery_on);
ut_ad(recv_recovery_on); ut_ad(recv_recovery_on);
if (space->size == 0) { if (space->size == 0) {
@ -1267,10 +1259,7 @@ fil_space_open_if_needed(
until the files are opened for the first time. until the files are opened for the first time.
fil_space_get_size() will open the file fil_space_get_size() will open the file
and adjust the size and flags. */ and adjust the size and flags. */
#ifdef UNIV_DEBUG ut_d(ulint size =) fil_space_get_size(space->id);
ulint size =
#endif /* UNIV_DEBUG */
fil_space_get_size(space->id);
ut_ad(size == space->size); ut_ad(size == space->size);
} }
} }

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2018, MariaDB Corporation. Copyright (c) 2013, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -627,15 +627,10 @@ fsp_descr_page(
const page_id_t page_id, const page_id_t page_id,
const page_size_t& page_size); const page_size_t& page_size);
/***********************************************************//** /** Initialize a file page whose prior contents should be ignored.
Parses a redo log record of a file page init. @param[in,out] block buffer pool block */
@return end of log record or NULL */ void fsp_apply_init_file_page(buf_block_t* block);
byte*
fsp_parse_init_file_page(
/*=====================*/
byte* ptr, /*!< in: buffer */
byte* end_ptr, /*!< in: buffer end */
buf_block_t* block); /*!< in: block or NULL */
#ifdef UNIV_BTR_PRINT #ifdef UNIV_BTR_PRINT
/*******************************************************************//** /*******************************************************************//**
Writes info of a segment. */ Writes info of a segment. */

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -40,7 +40,7 @@ Created 9/20/1997 Heikki Tuuri
extern bool recv_writer_thread_active; extern bool recv_writer_thread_active;
/** @return whether recovery is currently running. */ /** @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. /** Find the latest checkpoint in the log header.
@param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2 @param[out] max_field LOG_CHECKPOINT_1 or LOG_CHECKPOINT_2
@ -49,12 +49,9 @@ dberr_t
recv_find_max_checkpoint(ulint* max_field) recv_find_max_checkpoint(ulint* max_field)
MY_ATTRIBUTE((nonnull, warn_unused_result)); MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Apply the hashed log records to the page, if the page lsn is less than the /** Apply any buffered redo log to a page that was just read from a data file.
lsn of a log record. @param[in,out] bpage buffer pool page */
@param just_read_in whether the page recently arrived to the I/O handler ATTRIBUTE_COLD void recv_recover_page(buf_page_t* bpage);
@param block the page in the buffer pool */
void
recv_recover_page(bool just_read_in, buf_block_t* block);
/** Start recovering from a redo log checkpoint. /** Start recovering from a redo log checkpoint.
@see recv_recovery_from_checkpoint_finish @see recv_recovery_from_checkpoint_finish

View File

@ -2,7 +2,7 @@
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2012, Facebook Inc. 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -496,16 +496,14 @@ page_zip_copy_recs(
dict_index_t* index, /*!< in: index of the B-tree */ dict_index_t* index, /*!< in: index of the B-tree */
mtr_t* mtr); /*!< in: mini-transaction */ mtr_t* mtr); /*!< in: mini-transaction */
/**********************************************************************//** /** Parse and optionally apply MLOG_ZIP_PAGE_COMPRESS.
Parses a log record of compressing an index page. @param[in] ptr log record
@return end of log record or NULL */ @param[in] end_ptr end of log
byte* @param[in,out] block ROW_FORMAT=COMPRESSED block, or NULL for parsing only
page_zip_parse_compress( @return end of log record
/*====================*/ @retval NULL if the log record is incomplete */
byte* ptr, /*!< in: buffer */ byte* page_zip_parse_compress(const byte* ptr, const byte* end_ptr,
byte* end_ptr, /*!< in: buffer end */ buf_block_t* block);
page_t* page, /*!< out: uncompressed page */
page_zip_des_t* page_zip); /*!< out: compressed page */
#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_INNOCHECKSUM */

View File

@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. 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 This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
@ -292,6 +292,12 @@ row_merge_drop_table(
dict_table_t* table) /*!< in: table instance to drop */ dict_table_t* table) /*!< in: table instance to drop */
MY_ATTRIBUTE((nonnull, warn_unused_result)); 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 /** Build indexes on a table by reading a clustered index, creating a temporary
file containing index entries, merge sorting these index entries and inserting file containing index entries, merge sorting these index entries and inserting
sorted index entries to indexes. sorted index entries to indexes.

View File

@ -2,7 +2,7 @@
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2009, Google Inc. 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 Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described Google, Inc. Those modifications are gratefully acknowledged and are described
@ -1193,14 +1193,11 @@ synchronization objects!
this lsn this lsn
@return false if there was a flush batch of the same type running, @return false if there was a flush batch of the same type running,
which means that we could not start this flush batch */ which means that we could not start this flush batch */
static static bool log_preflush_pool_modified_pages(lsn_t new_oldest)
bool
log_preflush_pool_modified_pages(
lsn_t new_oldest)
{ {
bool success; bool success;
if (recv_recovery_on) { if (recv_recovery_is_on()) {
/* If the recovery is running, we must first apply all /* If the recovery is running, we must first apply all
log records to their respective file pages to get the log records to their respective file pages to get the
right modify lsn values to these pages: otherwise, there right modify lsn values to these pages: otherwise, there

View File

@ -675,7 +675,7 @@ DECLARE_THREAD(recv_writer_thread)(
mutex_enter(&recv_sys->writer_mutex); mutex_enter(&recv_sys->writer_mutex);
if (!recv_recovery_on) { if (!recv_recovery_is_on()) {
mutex_exit(&recv_sys->writer_mutex); mutex_exit(&recv_sys->writer_mutex);
break; break;
} }
@ -770,7 +770,7 @@ recv_sys_debug_free(void)
/* wake page cleaner up to progress */ /* wake page cleaner up to progress */
if (!srv_read_only_mode) { if (!srv_read_only_mode) {
ut_ad(!recv_recovery_on); ut_ad(!recv_recovery_is_on());
ut_ad(!recv_writer_thread_active); ut_ad(!recv_writer_thread_active);
os_event_reset(buf_flush_event); os_event_reset(buf_flush_event);
os_event_set(recv_sys->flush_start); os_event_set(recv_sys->flush_start);
@ -1615,7 +1615,7 @@ parse_log:
break; break;
case MLOG_INIT_FILE_PAGE2: case MLOG_INIT_FILE_PAGE2:
/* Allow anything in page_type when creating a page. */ /* 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; break;
case MLOG_WRITE_STRING: case MLOG_WRITE_STRING:
ptr = mlog_parse_string(ptr, end_ptr, page, page_zip); ptr = mlog_parse_string(ptr, end_ptr, page, page_zip);
@ -1637,7 +1637,7 @@ parse_log:
break; break;
case MLOG_ZIP_PAGE_COMPRESS: case MLOG_ZIP_PAGE_COMPRESS:
/* Allow anything in page_type when creating a page. */ /* 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; break;
case MLOG_ZIP_PAGE_COMPRESS_NO_DATA: case MLOG_ZIP_PAGE_COMPRESS_NO_DATA:
if (NULL != (ptr = mlog_parse_index( if (NULL != (ptr = mlog_parse_index(
@ -1719,6 +1719,8 @@ recv_get_fil_addr_struct(
ulint space, /*!< in: space id */ ulint space, /*!< in: space id */
ulint page_no)/*!< in: page number */ ulint page_no)/*!< in: page number */
{ {
ut_ad(mutex_own(&recv_sys->mutex));
recv_addr_t* recv_addr; recv_addr_t* recv_addr;
for (recv_addr = static_cast<recv_addr_t*>( 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, HASH_INSERT(recv_addr_t, addr_hash, recv_sys->addr_hash,
recv_fold(space, page_no), recv_addr); recv_fold(space, page_no), recv_addr);
recv_sys->n_addrs++; 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); 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 /** Apply the hashed log records to the page, if the page lsn is less than the
lsn of a log record. lsn of a log record.
@param just_read_in whether the page recently arrived to the I/O handler @param[in,out] block buffer pool page
@param block the page in the buffer pool */ @param[in,out] mtr mini-transaction
void @param[in,out] recv_addr recovery address */
recv_recover_page(bool just_read_in, buf_block_t* block) static void recv_recover_page(buf_block_t* block, mtr_t& mtr,
recv_addr_t* recv_addr)
{ {
page_t* page; page_t* page;
page_zip_des_t* page_zip; 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_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)) { if (UNIV_UNLIKELY(srv_print_verbose_log == 2)) {
fprintf(stderr, "Applying log to page %u:%u\n", 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); DBUG_LOG("ib_log", "Applying log to page " << block->page.id);
recv_addr->state = RECV_BEING_PROCESSED; recv_addr->state = RECV_BEING_PROCESSED;
mutex_exit(&recv_sys->mutex);
mutex_exit(&(recv_sys->mutex));
mtr_start(&mtr);
mtr_set_log_mode(&mtr, MTR_LOG_NONE);
page = block->frame; page = block->frame;
page_zip = buf_block_get_page_zip(block); page_zip = buf_block_get_page_zip(block);
if (just_read_in) { /* The page may have been modified in the buffer pool.
/* Move the ownership of the x-latch on the page to FIL_PAGE_LSN would only be updated right before flushing. */
this OS thread, so that we can acquire a second lsn_t page_lsn = buf_page_get_newest_modification(&block->page);
x-latch on it. This is needed for the operations to if (!page_lsn) {
the page to pass the debug checks. */
rw_lock_x_lock_move_ownership(&block->lock);
}
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); 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 */
page_newest_lsn = buf_page_get_newest_modification(&block->page);
if (page_newest_lsn) {
page_lsn = page_newest_lsn;
} }
modification_to_page = FALSE; lsn_t start_lsn = 0, end_lsn = 0;
start_lsn = end_lsn = 0; fil_space_t* space;
recv = UT_LIST_GET_FIRST(recv_addr->rec_list); if (srv_is_tablespace_truncated(recv_addr->space)) {
fil_space_t* space = fil_space_acquire(block->page.id.space()); /* The table will be truncated after applying
normal redo log records. */
goto skip_log;
}
while (recv) { space = fil_space_acquire(recv_addr->space);
if (!space) {
goto skip_log;
}
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; end_lsn = recv->end_lsn;
ut_ad(end_lsn <= log_sys.log.scanned_lsn); ut_ad(end_lsn <= log_sys.log.scanned_lsn);
if (recv->len > RECV_DATA_BLOCK_SIZE) { if (recv->start_lsn < page_lsn) {
/* We have to copy the record body to a separate /* Ignore this record, because there are later changes
buffer */ for this page. */
} else if (srv_was_tablespace_truncated(space)
buf = static_cast<byte*>(ut_malloc_nokey(recv->len));
recv_data_copy_to_buf(buf, recv);
} 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 && recv->start_lsn
< truncate_t::get_truncated_tablespace_init_lsn( < truncate_t::get_truncated_tablespace_init_lsn(
space->id))) { recv_addr->space)) {
/* If per-table tablespace was truncated and
lsn_t end_lsn; there exist REDO records before truncate that
are to be applied as part of recovery
if (!modification_to_page) { (checkpoint didn't happen since truncate was
done) skip such records using lsn check as
modification_to_page = TRUE; they may not stand valid post truncate. */
} else {
if (!start_lsn) {
start_lsn = recv->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 << " len " << recv->len
<< " page " << block->page.id); << " 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_parse_or_apply_log_rec_body(
recv->type, buf, buf + recv->len, recv->type, buf, buf + recv->len,
block->page.id.space(), block->page.id.space(),
block->page.id.page_no(), block->page.id.page_no(), true, block, &mtr);
true, block, &mtr);
end_lsn = recv->start_lsn + recv->len; end_lsn = recv->start_lsn + recv->len;
mach_write_to_8(FIL_PAGE_LSN + page, end_lsn); 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); + page, end_lsn);
if (page_zip) { if (page_zip) {
mach_write_to_8(FIL_PAGE_LSN mach_write_to_8(FIL_PAGE_LSN + page_zip->data,
+ page_zip->data, end_lsn); end_lsn);
}
} }
if (recv->len > RECV_DATA_BLOCK_SIZE) { if (recv->len > RECV_DATA_BLOCK_SIZE) {
ut_free(buf); ut_free(buf);
} }
}
recv = UT_LIST_GET_NEXT(rec_list, recv);
} }
space->release(); space->release();
skip_log:
#ifdef UNIV_ZIP_DEBUG #ifdef UNIV_ZIP_DEBUG
if (fil_page_index_page_check(page)) { ut_ad(!fil_page_index_page_check(page)
page_zip_des_t* page_zip = buf_block_get_page_zip(block); || !page_zip
ut_a(!page_zip
|| page_zip_validate_low(page_zip, page, NULL, FALSE)); || page_zip_validate_low(page_zip, page, NULL, FALSE));
}
#endif /* UNIV_ZIP_DEBUG */ #endif /* UNIV_ZIP_DEBUG */
if (modification_to_page) { if (start_lsn) {
ut_a(block);
log_flush_order_mutex_enter(); log_flush_order_mutex_enter();
buf_flush_recv_note_modification(block, start_lsn, end_lsn); buf_flush_recv_note_modification(block, start_lsn, end_lsn);
log_flush_order_mutex_exit(); log_flush_order_mutex_exit();
@ -2067,8 +2001,7 @@ recv_recover_page(bool just_read_in, buf_block_t* block)
lsn values of page */ lsn values of page */
mtr.discard_modifications(); mtr.discard_modifications();
mtr.commit();
mtr_commit(&mtr);
ib_time_t time = ut_time(); 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; recv_max_page_lsn = page_lsn;
} }
ut_ad(recv_addr->state == RECV_BEING_PROCESSED);
recv_addr->state = RECV_PROCESSED; recv_addr->state = RECV_PROCESSED;
ut_a(recv_sys->n_addrs > 0); 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); 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); mutex_exit(&recv_sys->mutex);
ut_ad(mtr.has_committed());
} }
/** Reads in pages which have hashed log records, from an area around a given /** Reads in pages which have hashed log records, from an area around a given
page number. page number.
@param[in] page_id page id @param[in] page_id page id */
@return number of pages found */ static void recv_read_in_area(const page_id_t page_id)
static ulint recv_read_in_area(const page_id_t page_id)
{ {
recv_addr_t* recv_addr;
ulint page_nos[RECV_READ_AHEAD_AREA]; ulint page_nos[RECV_READ_AHEAD_AREA];
ulint low_limit; ulint page_no = page_id.page_no()
ulint n;
low_limit = page_id.page_no()
- (page_id.page_no() % RECV_READ_AHEAD_AREA); - (page_id.page_no() % RECV_READ_AHEAD_AREA);
ulint* p = page_nos;
n = 0; for (const ulint up_limit = page_no + RECV_READ_AHEAD_AREA;
page_no < up_limit; page_no++) {
for (ulint page_no = low_limit; recv_addr_t* recv_addr = recv_get_fil_addr_struct(
page_no < low_limit + RECV_READ_AHEAD_AREA; page_id.space(), page_no);
page_no++) { if (recv_addr
&& recv_addr->state == RECV_NOT_PROCESSED
recv_addr = recv_get_fil_addr_struct(page_id.space(), page_no); && !buf_page_peek(page_id_t(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; recv_addr->state = RECV_BEING_READ;
*p++ = page_no;
page_nos[n] = page_no;
n++;
}
mutex_exit(&(recv_sys->mutex));
} }
} }
buf_read_recv_pages(FALSE, page_id.space(), page_nos, n); mutex_exit(&recv_sys->mutex);
return(n); 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. /** Apply the hash table of stored log records to persistent data pages.
@ -2186,60 +2144,56 @@ 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 (ulint i = 0; i < hash_get_n_cells(recv_sys->addr_hash); i++) {
for (recv_addr_t* recv_addr = static_cast<recv_addr_t*>( for (recv_addr_t* recv_addr = static_cast<recv_addr_t*>(
HASH_GET_FIRST(recv_sys->addr_hash, i)); HASH_GET_FIRST(recv_sys->addr_hash, i));
recv_addr; recv_addr;
recv_addr = static_cast<recv_addr_t*>( recv_addr = static_cast<recv_addr_t*>(
HASH_GET_NEXT(addr_hash, recv_addr))) { HASH_GET_NEXT(addr_hash, recv_addr))) {
if (!UT_LIST_GET_LEN(recv_addr->rec_list)) {
ignore:
ut_a(recv_sys->n_addrs);
recv_sys->n_addrs--;
continue;
}
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;
}
if (srv_is_tablespace_truncated(recv_addr->space)) { if (srv_is_tablespace_truncated(recv_addr->space)) {
/* Avoid applying REDO log for the tablespace /* Avoid applying REDO log for the tablespace
that is schedule for TRUNCATE. */ that is schedule for TRUNCATE. */
ut_a(recv_sys->n_addrs);
recv_addr->state = RECV_DISCARDED; recv_addr->state = RECV_DISCARDED;
recv_sys->n_addrs--; goto ignore;
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--;
continue;
} }
const page_id_t page_id(recv_addr->space, const page_id_t page_id(recv_addr->space,
recv_addr->page_no); 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(); mtr.start();
mtr.set_log_mode(MTR_LOG_NONE);
buf_block_t* block = buf_page_get( if (buf_block_t* block = buf_page_get_gen(
page_id, page_size, page_id, univ_page_size, RW_X_LATCH,
RW_X_LATCH, &mtr); NULL, BUF_GET_IF_IN_POOL,
__FILE__, __LINE__, &mtr, NULL)) {
buf_block_dbg_add_level( buf_block_dbg_add_level(
block, SYNC_NO_ORDER_CHECK); block, SYNC_NO_ORDER_CHECK);
recv_recover_page(block, mtr, recv_addr);
recv_recover_page(FALSE, block); ut_ad(mtr.has_committed());
mtr.commit();
} else { } else {
mtr.commit();
recv_read_in_area(page_id); recv_read_in_area(page_id);
} }
mutex_enter(&recv_sys->mutex);
}
} }
} }
@ -2485,6 +2439,15 @@ recv_report_corrupt_log(
return(true); 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 /** Parse log records from a buffer and optionally store them to a
hash table to wait merging to file pages. hash table to wait merging to file pages.
@param[in] checkpoint_lsn the LSN of the latest checkpoint @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; byte* body;
ut_ad(log_mutex_own()); ut_ad(log_mutex_own());
ut_ad(mutex_own(&recv_sys->mutex));
ut_ad(recv_sys->parse_start_lsn != 0); ut_ad(recv_sys->parse_start_lsn != 0);
loop: loop:
ptr = recv_sys->buf + recv_sys->recovered_offset; ptr = recv_sys->buf + recv_sys->recovered_offset;
@ -2640,9 +2604,7 @@ loop:
/* fall through */ /* fall through */
case MLOG_INDEX_LOAD: case MLOG_INDEX_LOAD:
if (type == MLOG_INDEX_LOAD) { if (type == MLOG_INDEX_LOAD) {
if (log_optimized_ddl_op) { recv_mlog_index_load(space);
log_optimized_ddl_op(space);
}
} }
/* fall through */ /* fall through */
case MLOG_FILE_NAME: case MLOG_FILE_NAME:
@ -2796,10 +2758,7 @@ corrupted_log:
break; break;
#endif /* UNIV_LOG_LSN_DEBUG */ #endif /* UNIV_LOG_LSN_DEBUG */
case MLOG_INDEX_LOAD: case MLOG_INDEX_LOAD:
/* Mariabackup FIXME: Report an error recv_mlog_index_load(space);
when encountering MLOG_INDEX_LOAD on
--prepare or already on --backup. */
ut_a(srv_operation == SRV_OPERATION_NORMAL);
break; break;
case MLOG_FILE_NAME: case MLOG_FILE_NAME:
case MLOG_FILE_DELETE: case MLOG_FILE_DELETE:
@ -3077,6 +3036,8 @@ recv_scan_log_recs(
*group_scanned_lsn = scanned_lsn; *group_scanned_lsn = scanned_lsn;
mutex_enter(&recv_sys->mutex);
if (more_data && !recv_sys->found_corrupt_log) { if (more_data && !recv_sys->found_corrupt_log) {
/* Try to parse more log records */ /* Try to parse more log records */
@ -3086,7 +3047,8 @@ recv_scan_log_recs(
|| recv_sys->found_corrupt_fs || recv_sys->found_corrupt_fs
|| recv_sys->mlog_checkpoint_lsn || recv_sys->mlog_checkpoint_lsn
== recv_sys->recovered_lsn); == recv_sys->recovered_lsn);
return(true); finished = true;
goto func_exit;
} }
if (*store_to_hash != STORE_NO if (*store_to_hash != STORE_NO
@ -3107,6 +3069,8 @@ recv_scan_log_recs(
} }
} }
func_exit:
mutex_exit(&recv_sys->mutex);
return(finished); return(finished);
} }

View File

@ -4917,23 +4917,20 @@ page_zip_copy_recs(
page_zip_compress_write_log(page_zip, page, index, mtr); page_zip_compress_write_log(page_zip, page, index, mtr);
} }
/**********************************************************************//** /** Parse and optionally apply MLOG_ZIP_PAGE_COMPRESS.
Parses a log record of compressing an index page. @param[in] ptr log record
@return end of log record or NULL */ @param[in] end_ptr end of log
byte* @param[in,out] block ROW_FORMAT=COMPRESSED block, or NULL for parsing only
page_zip_parse_compress( @return end of log record
/*====================*/ @retval NULL if the log record is incomplete */
byte* ptr, /*!< in: buffer */ byte* page_zip_parse_compress(const byte* ptr, const byte* end_ptr,
byte* end_ptr,/*!< in: buffer end */ buf_block_t* block)
page_t* page, /*!< out: uncompressed page */
page_zip_des_t* page_zip)/*!< out: compressed page */
{ {
ulint size; ulint size;
ulint trailer_size; ulint trailer_size;
ut_ad(ptr != NULL); ut_ad(ptr != NULL);
ut_ad(end_ptr!= NULL); ut_ad(end_ptr!= NULL);
ut_ad(!page == !page_zip);
if (UNIV_UNLIKELY(ptr + (2 + 2) > end_ptr)) { if (UNIV_UNLIKELY(ptr + (2 + 2) > end_ptr)) {
@ -4950,14 +4947,22 @@ page_zip_parse_compress(
return(NULL); return(NULL);
} }
if (page) { if (block) {
if (!page_zip || page_zip_get_size(page_zip) < size) { 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: corrupt:
recv_sys->found_corrupt_log = TRUE; recv_sys->found_corrupt_log = TRUE;
return(NULL); 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_PREV, ptr, 4);
memcpy(page_zip->data + FIL_PAGE_NEXT, ptr + 4, 4); memcpy(page_zip->data + FIL_PAGE_NEXT, ptr + 4, 4);
memcpy(page_zip->data + FIL_PAGE_TYPE, ptr + 8, size); 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) memcpy(page_zip->data + page_zip_get_size(page_zip)
- trailer_size, ptr + 8 + size, trailer_size); - 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))) { TRUE))) {
goto corrupt; goto corrupt;
} }
} }
return(ptr + 8 + size + trailer_size); return(const_cast<byte*>(ptr) + 8 + size + trailer_size);
} }
#endif /* !UNIV_INNOCHECKSUM */ #endif /* !UNIV_INNOCHECKSUM */

View File

@ -1806,5 +1806,9 @@ exit:
ib::info() << "InnoDB_FTS: inserted " << count << " records"; 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); return(error);
} }

View File

@ -4519,17 +4519,14 @@ row_merge_drop_table(
that redo-logging of individual index pages was disabled, and that redo-logging of individual index pages was disabled, and
the flushing of such pages to the data files was completed. the flushing of such pages to the data files was completed.
@param[in] index an index tree on which redo logging was disabled */ @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->table->is_temporary());
ut_ad(!(index->type & (DICT_SPATIAL | DICT_FTS)));
mtr_t mtr;
mtr.start(); 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( log_ptr = mlog_write_initial_log_record_low(
MLOG_INDEX_LOAD, MLOG_INDEX_LOAD,
index->table->space_id, index->page, log_ptr, &mtr); index->table->space_id, index->page, log_ptr, &mtr);
@ -5070,10 +5067,13 @@ func_exit:
= dict_table_get_first_index(new_table); = dict_table_get_first_index(new_table);
index != NULL; index != NULL;
index = dict_table_get_next_index(index)) { index = dict_table_get_next_index(index)) {
if (!(index->type
& (DICT_FTS | DICT_SPATIAL))) {
row_merge_write_redo(index); row_merge_write_redo(index);
} }
} }
} }
}
DBUG_RETURN(error); DBUG_RETURN(error);
} }

View File

@ -2771,7 +2771,7 @@ row_mysql_drop_garbage_tables()
btr_pcur_commit_specify_mtr(&pcur, &mtr); btr_pcur_commit_specify_mtr(&pcur, &mtr);
if (dict_load_table(table_name, true, if (dict_load_table(table_name, true,
DICT_ERR_IGNORE_ALL)) { DICT_ERR_IGNORE_DROP)) {
row_drop_table_for_mysql(table_name, trx, row_drop_table_for_mysql(table_name, trx,
SQLCOM_DROP_TABLE); SQLCOM_DROP_TABLE);
trx_commit_for_mysql(trx); trx_commit_for_mysql(trx);