271 lines
12 KiB
C++
271 lines
12 KiB
C++
/*****************************************************************************
|
|
|
|
Copyright (c) 2007, 2018, Oracle and/or its affiliates. All Rights Reserved.
|
|
|
|
This program is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License, version 2.0, as published by the
|
|
Free Software Foundation.
|
|
|
|
This program is also distributed with certain software (including but not
|
|
limited to OpenSSL) that is licensed under separate terms, as designated in a
|
|
particular file or component or in included license documentation. The authors
|
|
of MySQL hereby grant you an additional permission to link the program and
|
|
your derivative works with the separately licensed software that they have
|
|
included with MySQL.
|
|
|
|
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, version 2.0,
|
|
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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*****************************************************************************/
|
|
|
|
/** @file include/trx0i_s.h
|
|
INFORMATION SCHEMA innodb_trx, innodb_locks and
|
|
innodb_lock_waits tables cache structures and public
|
|
functions.
|
|
|
|
Created July 17, 2007 Vasil Dimov
|
|
*******************************************************/
|
|
|
|
#ifndef trx0i_s_h
|
|
#define trx0i_s_h
|
|
|
|
#include "dict0types.h"
|
|
#include "trx0types.h"
|
|
#include "univ.i"
|
|
|
|
class PSI_server_data_lock_container;
|
|
|
|
/** The maximum amount of memory that can be consumed by innodb_trx,
|
|
innodb_locks and innodb_lock_waits information schema tables. */
|
|
#define TRX_I_S_MEM_LIMIT 16777216 /* 16 MiB */
|
|
|
|
/** The maximum length of a string that can be stored in
|
|
i_s_locks_row_t::lock_data */
|
|
#define TRX_I_S_LOCK_DATA_MAX_LEN 8192
|
|
|
|
/** The maximum length of a string that can be stored in
|
|
i_s_trx_row_t::trx_query */
|
|
#define TRX_I_S_TRX_QUERY_MAX_LEN 1024
|
|
|
|
/** The maximum length of a string that can be stored in
|
|
i_s_trx_row_t::trx_operation_state */
|
|
#define TRX_I_S_TRX_OP_STATE_MAX_LEN 64
|
|
|
|
/** The maximum length of a string that can be stored in
|
|
i_s_trx_row_t::trx_foreign_key_error */
|
|
#define TRX_I_S_TRX_FK_ERROR_MAX_LEN 256
|
|
|
|
/** The maximum length of a string that can be stored in
|
|
i_s_trx_row_t::trx_isolation_level */
|
|
#define TRX_I_S_TRX_ISOLATION_LEVEL_MAX_LEN 16
|
|
|
|
/** Safely copy strings in to the INNODB_TRX table's
|
|
string based columns */
|
|
#define TRX_I_S_STRING_COPY(data, field, constraint, tcache) \
|
|
do { \
|
|
if (strlen(data) > constraint) { \
|
|
char buff[constraint + 1]; \
|
|
strncpy(buff, data, constraint); \
|
|
buff[constraint] = '\0'; \
|
|
\
|
|
field = static_cast<const char *>( \
|
|
ha_storage_put_memlim((tcache)->storage, buff, constraint + 1, \
|
|
MAX_ALLOWED_FOR_STORAGE(tcache))); \
|
|
} else { \
|
|
field = static_cast<const char *>(ha_storage_put_str_memlim( \
|
|
(tcache)->storage, data, MAX_ALLOWED_FOR_STORAGE(tcache))); \
|
|
} \
|
|
} while (0)
|
|
|
|
/** This structure represents INFORMATION_SCHEMA.innodb_locks row */
|
|
struct i_s_locks_row_t {
|
|
uint64_t lock_trx_immutable_id; /*!< transaction address as integer. We need
|
|
an id which is unique and does not change over time.
|
|
Unfortunately trx->id is initially equal to 0 for
|
|
all trxs which still appear to be read only, and it
|
|
changes to non-zero, once trx needs to perform write.
|
|
For this reason trx->id is not good enough for our
|
|
purpose. */
|
|
uint64_t lock_immutable_id; /*!< lock address as integer. We need to identify
|
|
the lock in unique way. Specifying space, page and heap_no
|
|
and trx is not enough, because there could be locks with
|
|
different modes. Using mode as part of id is not good,
|
|
because we sometimes change the mode of the lock (for
|
|
example when granting the lock we drop LOCK_WAITING flag
|
|
and in lock_trx_release_read_locks we add LOCK_REC_NOT_GAP
|
|
flag). The only permanent thing is then the address.
|
|
We use both lock_immutable_id and lock_trx_immutable_id
|
|
even though lock_immutable_id is unique, because we need
|
|
to be able to locate the row in PERFORMANCE_SCHEMA based
|
|
on the id, and we need a way to verify that the
|
|
lock_immutable_id is safe to dereference. Simplest way to
|
|
do that is to check that trx still has the lock on its
|
|
list of locks. */
|
|
|
|
/** Information for record locks. All these are
|
|
ULINT_UNDEFINED for table locks. */
|
|
/* @{ */
|
|
space_id_t lock_space; /*!< tablespace identifier */
|
|
page_no_t lock_page; /*!< page number within the_space */
|
|
ulint lock_rec; /*!< heap number of the record
|
|
on the page */
|
|
/* @} */
|
|
|
|
/** The following are auxiliary and not included in the table */
|
|
/* @{ */
|
|
table_id_t lock_table_id;
|
|
/*!< table identifier from
|
|
lock_get_table_id */
|
|
/* @} */
|
|
};
|
|
|
|
/** This structure represents INFORMATION_SCHEMA.innodb_trx row */
|
|
struct i_s_trx_row_t {
|
|
trx_id_t trx_id; /*!< transaction identifier */
|
|
const char *trx_state; /*!< transaction state from
|
|
trx_get_que_state_str() */
|
|
ib_time_t trx_started; /*!< trx_t::start_time */
|
|
const i_s_locks_row_t *requested_lock_row;
|
|
/*!< pointer to a row
|
|
in innodb_locks if trx
|
|
is waiting, or NULL */
|
|
ib_time_t trx_wait_started; /*!< trx_t::wait_started */
|
|
uintmax_t trx_weight; /*!< TRX_WEIGHT() */
|
|
ulint trx_mysql_thread_id; /*!< thd_get_thread_id() */
|
|
const char *trx_query; /*!< MySQL statement being
|
|
executed in the transaction */
|
|
const CHARSET_INFO *trx_query_cs; /*!< the charset of trx_query */
|
|
const char *trx_operation_state; /*!< trx_t::op_info */
|
|
ulint trx_tables_in_use; /*!< n_mysql_tables_in_use in
|
|
trx_t */
|
|
ulint trx_tables_locked;
|
|
/*!< mysql_n_tables_locked in
|
|
trx_t */
|
|
ulint trx_lock_structs; /*!< list len of trx_locks in
|
|
trx_t */
|
|
ulint trx_lock_memory_bytes;
|
|
/*!< mem_heap_get_size(
|
|
trx->lock_heap) */
|
|
ulint trx_rows_locked; /*!< lock_number_of_rows_locked() */
|
|
uintmax_t trx_rows_modified; /*!< trx_t::undo_no */
|
|
ulint trx_concurrency_tickets;
|
|
/*!< n_tickets_to_enter_innodb in
|
|
trx_t */
|
|
const char *trx_isolation_level;
|
|
/*!< isolation_level in trx_t */
|
|
ibool trx_unique_checks;
|
|
/*!< check_unique_secondary in trx_t*/
|
|
ibool trx_foreign_key_checks;
|
|
/*!< check_foreigns in trx_t */
|
|
const char *trx_foreign_key_error;
|
|
/*!< detailed_error in trx_t */
|
|
ibool trx_has_search_latch;
|
|
/*!< has_search_latch in trx_t */
|
|
ulint trx_is_read_only;
|
|
/*!< trx_t::read_only */
|
|
ulint trx_is_autocommit_non_locking;
|
|
/*!< trx_is_autocommit_non_locking(trx)
|
|
*/
|
|
};
|
|
|
|
/** Cache of INFORMATION_SCHEMA table data */
|
|
struct trx_i_s_cache_t;
|
|
|
|
/** Auxiliary enum used by functions that need to select one of the
|
|
INFORMATION_SCHEMA tables */
|
|
enum i_s_table {
|
|
I_S_INNODB_TRX, /*!< INFORMATION_SCHEMA.innodb_trx */
|
|
};
|
|
|
|
/** This is the intermediate buffer where data needed to fill the
|
|
INFORMATION SCHEMA tables is fetched and later retrieved by the C++
|
|
code in handler/i_s.cc. */
|
|
extern trx_i_s_cache_t *trx_i_s_cache;
|
|
|
|
/** Initialize INFORMATION SCHEMA trx related cache. */
|
|
void trx_i_s_cache_init(trx_i_s_cache_t *cache); /*!< out: cache to init */
|
|
/** Free the INFORMATION SCHEMA trx related cache. */
|
|
void trx_i_s_cache_free(trx_i_s_cache_t *cache); /*!< in/out: cache to free */
|
|
|
|
/** Issue a shared/read lock on the tables cache. */
|
|
void trx_i_s_cache_start_read(trx_i_s_cache_t *cache); /*!< in: cache */
|
|
|
|
/** Release a shared/read lock on the tables cache. */
|
|
void trx_i_s_cache_end_read(trx_i_s_cache_t *cache); /*!< in: cache */
|
|
|
|
/** Issue an exclusive/write lock on the tables cache. */
|
|
void trx_i_s_cache_start_write(trx_i_s_cache_t *cache); /*!< in: cache */
|
|
|
|
/** Release an exclusive/write lock on the tables cache. */
|
|
void trx_i_s_cache_end_write(trx_i_s_cache_t *cache); /*!< in: cache */
|
|
|
|
/** Retrieves the number of used rows in the cache for a given
|
|
INFORMATION SCHEMA table.
|
|
@return number of rows */
|
|
ulint trx_i_s_cache_get_rows_used(trx_i_s_cache_t *cache, /*!< in: cache */
|
|
enum i_s_table table); /*!< in: which table */
|
|
|
|
/** Retrieves the nth row in the cache for a given INFORMATION SCHEMA
|
|
table.
|
|
@return row */
|
|
void *trx_i_s_cache_get_nth_row(trx_i_s_cache_t *cache, /*!< in: cache */
|
|
enum i_s_table table, /*!< in: which table */
|
|
ulint n); /*!< in: row number */
|
|
|
|
/** Update the transactions cache if it has not been read for some time.
|
|
@return 0 - fetched, 1 - not */
|
|
int trx_i_s_possibly_fetch_data_into_cache(
|
|
trx_i_s_cache_t *cache); /*!< in/out: cache */
|
|
|
|
/** Returns TRUE if the data in the cache is truncated due to the memory
|
|
limit posed by TRX_I_S_MEM_LIMIT.
|
|
@return true if truncated */
|
|
ibool trx_i_s_cache_is_truncated(trx_i_s_cache_t *cache); /*!< in: cache */
|
|
/** The maximum length of a resulting lock_id_size in
|
|
trx_i_s_create_lock_id(), not including the terminating NUL.
|
|
"%lu:%lu:%lu:%lu:%lu" -> 20*5+4 chars */
|
|
#define TRX_I_S_LOCK_ID_MAX_LEN (20 * 5 + 4)
|
|
|
|
/** Crafts a lock id string from a i_s_locks_row_t object. Returns its
|
|
second argument. This function aborts if there is not enough space in
|
|
lock_id. Be sure to provide at least TRX_I_S_LOCK_ID_MAX_LEN + 1 if you
|
|
want to be 100% sure that it will not abort.
|
|
@return resulting lock id */
|
|
char *trx_i_s_create_lock_id(
|
|
const i_s_locks_row_t *row, /*!< in: innodb_locks row */
|
|
char *lock_id, /*!< out: resulting lock_id */
|
|
ulint lock_id_size); /*!< in: size of the lock id
|
|
buffer */
|
|
|
|
/** Fill performance schema lock data.
|
|
Create a string that represents the LOCK_DATA
|
|
column, for a given lock record.
|
|
@param[out] lock_data Lock data string
|
|
@param[in] lock Lock to inspect
|
|
@param[in] heap_no Lock heap number
|
|
@param[in] container Data container to fill
|
|
*/
|
|
void p_s_fill_lock_data(const char **lock_data, const lock_t *lock,
|
|
ulint heap_no,
|
|
PSI_server_data_lock_container *container);
|
|
|
|
/** Fills i_s_locks_row_t object with data about the lock.
|
|
@param[out] row Result object that's filled
|
|
@param[in] lock Lock to get data from
|
|
@param[in] heap_no Lock's record number or ULINT_UNDEFINED if the lock is a
|
|
table lock */
|
|
void fill_locks_row(i_s_locks_row_t *row, const lock_t *lock, ulint heap_no);
|
|
|
|
/** Parses lock id into row
|
|
@param[in] lock_id Lock id generated with trx_i_s_create_lock_id
|
|
@param[out] row Row to be filled in with data
|
|
@return LOCK_REC, LOCK_TABLE or 0 if failed to parse */
|
|
int trx_i_s_parse_lock_id(const char *lock_id, i_s_locks_row_t *row);
|
|
#endif /* trx0i_s_h */
|