mariadb/storage/innobase/include/row0log.h

266 lines
9.5 KiB
C
Raw Normal View History

/*****************************************************************************
2016-06-21 14:21:03 +02:00
Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
*****************************************************************************/
/**************************************************//**
@file include/row0log.h
Modification log for online index creation and online table rebuild
Created 2011-05-26 Marko Makela
*******************************************************/
#ifndef row0log_h
#define row0log_h
#include "univ.i"
#include "mtr0types.h"
#include "row0types.h"
#include "rem0types.h"
#include "data0types.h"
#include "dict0types.h"
#include "trx0types.h"
#include "que0types.h"
class ut_stage_alter_t;
extern ulint onlineddl_rowlog_rows;
extern ulint onlineddl_rowlog_pct_used;
extern ulint onlineddl_pct_progress;
/******************************************************//**
Allocate the row log for an index and flag the index
for online creation.
@retval true if success, false if not */
bool
row_log_allocate(
/*=============*/
MDEV-13654 Various crashes due to DB_TRX_ID mismatch in table-rebuilding ALTER TABLE…LOCK=NONE After MDEV-12288 and MDEV-13536, the DB_TRX_ID of old clustered index records for which no history is available should be reset to 0. This caused crashes in online table-rebuilding ALTER, because the row_log_table_apply() is built on the assumption that the PRIMARY KEY together with DB_TRX_ID,DB_ROLL_PTR identifies the record. Both when copying the old table and when writing log about changes to the old table, we must map "old" DB_TRX_ID to 0. "old" here is simply "older than the trx_id of the ALTER TABLE transaction", because the MDL_EXCLUSIVE (and exclusive InnoDB table lock) in ha_innobase::prepare_inplace_alter_table() forces any transactions accessing the table to commit or rollback. So, we know that we can safely reset any DB_TRX_ID in the table that is older than the transaction ID of the ALTER TABLE, because the undo log history would be lost in a table-rebuilding ALTER. Note: After a table-rebuilding online ALTER TABLE, the rebuilt table may end up containing some nonzero DB_TRX_ID columns. The apply logic identifies the rows by the combination of PRIMARY KEY and DB_TRX_ID. These nonzero DB_TRX_ID would necessarily refer to concurrent DML operations that were started during ha_innobase::inplace_alter_table(). row_log_allocate(): Add a parameter for the ALTER TABLE transaction. row_log_t::min_trx: The ALTER TABLE transaction ID. trx_id_check(): A debug function to check that DB_TRX_ID makes sense (is either 0 or bigger than the ALTER TABLE transaction ID). reset_trx_id[]: The reset DB_TRX_ID,DB_ROLL_PTR columns. row_log_table_delete(), row_log_table_get_pk(): Reset the DB_TRX_ID,DB_ROLL_PTR when they precede the ALTER TABLE transaction. row_log_table_apply_delete(), row_log_table_apply_update(): Assert trx_id_check(). row_merge_insert_index_tuples(): Remove the unused parameter trx_id. row_merge_read_clustered_index(): In a table-rebuilding ALTER, reset the DB_TRX_ID,DB_ROLL_PTR when they precede the ALTER TABLE transaction. Assert trx_id_check() on clustered index records that are being buffered.
2017-08-31 17:03:50 +02:00
const trx_t* trx, /*!< in: the ALTER TABLE transaction */
dict_index_t* index, /*!< in/out: index */
dict_table_t* table, /*!< in/out: new table being rebuilt,
or NULL when creating a secondary index */
bool same_pk,/*!< in: whether the definition of the
PRIMARY KEY has remained the same */
const dtuple_t* defaults,
/*!< in: default values of
added, changed columns, or NULL */
const ulint* col_map,/*!< in: mapping of old column
numbers to new ones, or NULL if !table */
const char* path, /*!< in: where to create temporary file */
const TABLE* old_table, /*!< in:table definition before alter */
bool allow_not_null) /*!< in: allow null to non-null
conversion */
2016-06-21 14:21:03 +02:00
MY_ATTRIBUTE((nonnull(1), warn_unused_result));
/******************************************************//**
Free the row log for an index that was being created online. */
void
row_log_free(
/*=========*/
row_log_t*& log) /*!< in,own: row log */
2016-06-21 14:21:03 +02:00
MY_ATTRIBUTE((nonnull));
/******************************************************//**
Free the row log for an index on which online creation was aborted. */
UNIV_INLINE
void
row_log_abort_sec(
/*==============*/
dict_index_t* index) /*!< in/out: index (x-latched) */
2016-06-21 14:21:03 +02:00
MY_ATTRIBUTE((nonnull));
/******************************************************//**
Try to log an operation to a secondary index that is
(or was) being created.
@retval true if the operation was logged or can be ignored
@retval false if online index creation is not taking place */
UNIV_INLINE
bool
row_log_online_op_try(
/*==================*/
dict_index_t* index, /*!< in/out: index, S or X latched */
const dtuple_t* tuple, /*!< in: index tuple */
trx_id_t trx_id) /*!< in: transaction ID for insert,
or 0 for delete */
2016-06-21 14:21:03 +02:00
MY_ATTRIBUTE((nonnull, warn_unused_result));
/******************************************************//**
Logs an operation to a secondary index that is (or was) being created. */
void
row_log_online_op(
/*==============*/
dict_index_t* index, /*!< in/out: index, S or X latched */
const dtuple_t* tuple, /*!< in: index tuple */
trx_id_t trx_id) /*!< in: transaction ID for insert,
or 0 for delete */
ATTRIBUTE_COLD __attribute__((nonnull));
/******************************************************//**
Gets the error status of the online index rebuild log.
@return DB_SUCCESS or error code */
dberr_t
row_log_table_get_error(
/*====================*/
const dict_index_t* index) /*!< in: clustered index of a table
that is being rebuilt online */
2016-06-21 14:21:03 +02:00
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Check whether a virtual column is indexed in the new table being
created during alter table
@param[in] index cluster index
@param[in] v_no virtual column number
@return true if it is indexed, else false */
bool
row_log_col_is_indexed(
const dict_index_t* index,
ulint v_no);
/******************************************************//**
Logs a delete operation to a table that is being rebuilt.
This will be merged in row_log_table_apply_delete(). */
void
row_log_table_delete(
/*=================*/
const rec_t* rec, /*!< in: clustered index leaf page record,
page X-latched */
dict_index_t* index, /*!< in/out: clustered index, S-latched
or X-latched */
const ulint* offsets,/*!< in: rec_get_offsets(rec,index) */
2014-05-06 21:13:16 +02:00
const byte* sys) /*!< in: DB_TRX_ID,DB_ROLL_PTR that should
be logged, or NULL to use those in rec */
ATTRIBUTE_COLD __attribute__((nonnull(1,2,3)));
/******************************************************//**
Logs an update operation to a table that is being rebuilt.
This will be merged in row_log_table_apply_update(). */
void
row_log_table_update(
/*=================*/
const rec_t* rec, /*!< in: clustered index leaf page record,
page X-latched */
dict_index_t* index, /*!< in/out: clustered index, S-latched
or X-latched */
const ulint* offsets,/*!< in: rec_get_offsets(rec,index) */
const dtuple_t* old_pk);/*!< in: row_log_table_get_pk()
before the update */
/******************************************************//**
Constructs the old PRIMARY KEY and DB_TRX_ID,DB_ROLL_PTR
of a table that is being rebuilt.
@return tuple of PRIMARY KEY,DB_TRX_ID,DB_ROLL_PTR in the rebuilt table,
or NULL if the PRIMARY KEY definition does not change */
const dtuple_t*
row_log_table_get_pk(
/*=================*/
const rec_t* rec, /*!< in: clustered index leaf page record,
page X-latched */
dict_index_t* index, /*!< in/out: clustered index, S-latched
or X-latched */
const ulint* offsets,/*!< in: rec_get_offsets(rec,index),
or NULL */
2014-05-06 21:13:16 +02:00
byte* sys, /*!< out: DB_TRX_ID,DB_ROLL_PTR for
row_log_table_delete(), or NULL */
mem_heap_t** heap) /*!< in/out: memory heap where allocated */
ATTRIBUTE_COLD __attribute__((nonnull(1,2,5), warn_unused_result));
/******************************************************//**
Logs an insert to a table that is being rebuilt.
This will be merged in row_log_table_apply_insert(). */
void
row_log_table_insert(
/*=================*/
const rec_t* rec, /*!< in: clustered index leaf page record,
page X-latched */
dict_index_t* index, /*!< in/out: clustered index, S-latched
or X-latched */
const ulint* offsets);/*!< in: rec_get_offsets(rec,index) */
/******************************************************//**
Notes that a BLOB is being freed during online ALTER TABLE. */
void
row_log_table_blob_free(
/*====================*/
dict_index_t* index, /*!< in/out: clustered index, X-latched */
ulint page_no)/*!< in: starting page number of the BLOB */
ATTRIBUTE_COLD __attribute__((nonnull));
/******************************************************//**
Notes that a BLOB is being allocated during online ALTER TABLE. */
void
row_log_table_blob_alloc(
/*=====================*/
dict_index_t* index, /*!< in/out: clustered index, X-latched */
ulint page_no)/*!< in: starting page number of the BLOB */
ATTRIBUTE_COLD __attribute__((nonnull));
/** Apply the row_log_table log to a table upon completing rebuild.
@param[in] thr query graph
@param[in] old_table old table
@param[in,out] table MySQL table (for reporting duplicates)
@param[in,out] stage performance schema accounting object, used by
ALTER TABLE. stage->begin_phase_log_table() will be called initially and then
stage->inc() will be called for each block of log that is applied.
@param[in] new_table Altered table
@return DB_SUCCESS, or error code on failure */
dberr_t
row_log_table_apply(
que_thr_t* thr,
dict_table_t* old_table,
struct TABLE* table,
ut_stage_alter_t* stage,
dict_table_t* new_table)
MY_ATTRIBUTE((warn_unused_result));
/******************************************************//**
Get the latest transaction ID that has invoked row_log_online_op()
during online creation.
@return latest transaction ID, or 0 if nothing was logged */
trx_id_t
row_log_get_max_trx(
/*================*/
dict_index_t* index) /*!< in: index, must be locked */
2016-06-21 14:21:03 +02:00
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Apply the row log to the index upon completing index creation.
@param[in] trx transaction (for checking if the operation was
interrupted)
@param[in,out] index secondary index
@param[in,out] table MySQL table (for reporting duplicates)
@param[in,out] stage performance schema accounting object, used by
ALTER TABLE. stage->begin_phase_log_index() will be called initially and then
stage->inc() will be called for each block of log that is applied.
@return DB_SUCCESS, or error code on failure */
dberr_t
row_log_apply(
const trx_t* trx,
dict_index_t* index,
struct TABLE* table,
ut_stage_alter_t* stage)
MY_ATTRIBUTE((warn_unused_result));
#ifdef HAVE_PSI_STAGE_INTERFACE
/** Estimate how much work is to be done by the log apply phase
of an ALTER TABLE for this index.
@param[in] index index whose log to assess
@return work to be done by log-apply in abstract units
*/
ulint
row_log_estimate_work(
const dict_index_t* index);
#endif /* HAVE_PSI_STAGE_INTERFACE */
#include "row0log.ic"
#endif /* row0log.h */