summaryrefslogtreecommitdiff
path: root/storage/innobase/trx/trx0sys.cc
diff options
context:
space:
mode:
Diffstat (limited to 'storage/innobase/trx/trx0sys.cc')
-rw-r--r--storage/innobase/trx/trx0sys.cc818
1 files changed, 72 insertions, 746 deletions
diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc
index 6529de31fb5..3a09d6929fa 100644
--- a/storage/innobase/trx/trx0sys.cc
+++ b/storage/innobase/trx/trx0sys.cc
@@ -24,8 +24,8 @@ Transaction system
Created 3/26/1996 Heikki Tuuri
*******************************************************/
-#include "mysqld.h"
#include "trx0sys.h"
+#include "mysqld.h"
#include "sql_error.h"
#include "fsp0fsp.h"
@@ -40,55 +40,9 @@ Created 3/26/1996 Heikki Tuuri
#include "log0log.h"
#include "log0recv.h"
#include "os0file.h"
-#include "read0read.h"
-
-#include <mysql/service_wsrep.h>
-
-/** The file format tag structure with id and name. */
-struct file_format_t {
- ulint id; /*!< id of the file format */
- const char* name; /*!< text representation of the
- file format */
- ib_mutex_t mutex; /*!< covers changes to the above
- fields */
-};
/** The transaction system */
-trx_sys_t* trx_sys;
-
-/** List of animal names representing file format. */
-static const char* file_format_name_map[] = {
- "Antelope",
- "Barracuda",
- "Cheetah",
- "Dragon",
- "Elk",
- "Fox",
- "Gazelle",
- "Hornet",
- "Impala",
- "Jaguar",
- "Kangaroo",
- "Leopard",
- "Moose",
- "Nautilus",
- "Ocelot",
- "Porpoise",
- "Quail",
- "Rabbit",
- "Shark",
- "Tiger",
- "Urchin",
- "Viper",
- "Whale",
- "Xenops",
- "Yak",
- "Zebra"
-};
-
-/** The number of elements in the file format name array. */
-static const ulint FILE_FORMAT_NAME_N
- = sizeof(file_format_name_map) / sizeof(file_format_name_map[0]);
+trx_sys_t trx_sys;
/** Check whether transaction id is valid.
@param[in] id transaction id to check
@@ -98,7 +52,7 @@ ReadView::check_trx_id_sanity(
trx_id_t id,
const table_name_t& name)
{
- if (id >= trx_sys->max_trx_id) {
+ if (id >= trx_sys.get_max_trx_id()) {
ib::warn() << "A transaction id"
<< " in a record of table "
@@ -129,249 +83,32 @@ ReadView::check_trx_id_sanity(
uint trx_rseg_n_slots_debug = 0;
#endif
-/** This is used to track the maximum file format id known to InnoDB. It's
-updated via SET GLOBAL innodb_file_format_max = 'x' or when we open
-or create a table. */
-static file_format_t file_format_max;
-
-/*****************************************************************//**
-Writes the value of max_trx_id to the file based trx system header. */
-void
-trx_sys_flush_max_trx_id(void)
-/*==========================*/
-{
- mtr_t mtr;
- trx_sysf_t* sys_header;
-
- /* wsrep_fake_trx_id violates this assert
- Copied from trx_sys_get_new_trx_id
- */
- ut_ad(trx_sys_mutex_own());
-
- if (!srv_read_only_mode) {
- mtr_start(&mtr);
-
- sys_header = trx_sysf_get(&mtr);
-
- mlog_write_ull(
- sys_header + TRX_SYS_TRX_ID_STORE,
- trx_sys->max_trx_id, &mtr);
-
- mtr_commit(&mtr);
- }
-}
-
-/*****************************************************************//**
-Updates the offset information about the end of the MySQL binlog entry
-which corresponds to the transaction just being committed. In a MySQL
-replication slave updates the latest master binlog position up to which
-replication has proceeded. */
-void
-trx_sys_update_mysql_binlog_offset(
-/*===============================*/
- const char* file_name,/*!< in: MySQL log file name */
- int64_t offset, /*!< in: position in that log file */
- trx_sysf_t* sys_header, /*!< in: trx sys header */
- mtr_t* mtr) /*!< in: mtr */
-{
- DBUG_PRINT("InnoDB",("trx_mysql_binlog_offset: %lld", (longlong) offset));
-
- const size_t len = strlen(file_name) + 1;
-
- if (len > TRX_SYS_MYSQL_LOG_NAME_LEN) {
-
- /* We cannot fit the name to the 512 bytes we have reserved */
-
- return;
- }
-
- if (mach_read_from_4(TRX_SYS_MYSQL_LOG_MAGIC_N_FLD
- + TRX_SYS_MYSQL_LOG_INFO + sys_header)
- != TRX_SYS_MYSQL_LOG_MAGIC_N) {
-
- mlog_write_ulint(TRX_SYS_MYSQL_LOG_MAGIC_N_FLD
- + TRX_SYS_MYSQL_LOG_INFO + sys_header,
- TRX_SYS_MYSQL_LOG_MAGIC_N,
- MLOG_4BYTES, mtr);
- }
-
- if (memcmp(file_name, TRX_SYS_MYSQL_LOG_NAME + TRX_SYS_MYSQL_LOG_INFO
- + sys_header, len)) {
- mlog_write_string(TRX_SYS_MYSQL_LOG_NAME
- + TRX_SYS_MYSQL_LOG_INFO
- + sys_header,
- reinterpret_cast<const byte*>(file_name),
- len, mtr);
- }
-
- mlog_write_ull(TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_OFFSET
- + sys_header, offset, mtr);
-}
-
/** Display the MySQL binlog offset info if it is present in the trx
system header. */
void
trx_sys_print_mysql_binlog_offset()
{
- mtr_t mtr;
-
- mtr.start();
-
- const trx_sysf_t* sys_header = trx_sysf_get(&mtr);
-
- if (mach_read_from_4(TRX_SYS_MYSQL_LOG_INFO
- + TRX_SYS_MYSQL_LOG_MAGIC_N_FLD + sys_header)
- == TRX_SYS_MYSQL_LOG_MAGIC_N) {
- ib::info() << "Last binlog file '"
- << TRX_SYS_MYSQL_LOG_INFO + TRX_SYS_MYSQL_LOG_NAME
- + sys_header
- << "', position "
- << mach_read_from_8(TRX_SYS_MYSQL_LOG_INFO
- + TRX_SYS_MYSQL_LOG_OFFSET
- + sys_header);
- }
-
- mtr.commit();
-}
-
-#ifdef WITH_WSREP
-
-#ifdef UNIV_DEBUG
-static long long trx_sys_cur_xid_seqno = -1;
-static unsigned char trx_sys_cur_xid_uuid[16];
-
-/** Read WSREP XID seqno */
-static inline long long read_wsrep_xid_seqno(const XID* xid)
-{
- long long seqno;
- memcpy(&seqno, xid->data + 24, sizeof(long long));
- return seqno;
-}
-
-/** Read WSREP XID UUID */
-static inline void read_wsrep_xid_uuid(const XID* xid, unsigned char* buf)
-{
- memcpy(buf, xid->data + 8, 16);
-}
-
-#endif /* UNIV_DEBUG */
-
-/** Update WSREP XID info in sys_header of TRX_SYS_PAGE_NO = 5.
-@param[in] xid Transaction XID
-@param[in,out] sys_header sys_header
-@param[in] mtr minitransaction */
-UNIV_INTERN
-void
-trx_sys_update_wsrep_checkpoint(
- const XID* xid,
- trx_sysf_t* sys_header,
- mtr_t* mtr)
-{
- ut_ad(xid->formatID == 1);
- ut_ad(wsrep_is_wsrep_xid(xid));
-
- if (mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO
- + TRX_SYS_WSREP_XID_MAGIC_N_FLD)
- != TRX_SYS_WSREP_XID_MAGIC_N) {
- mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO
- + TRX_SYS_WSREP_XID_MAGIC_N_FLD,
- TRX_SYS_WSREP_XID_MAGIC_N,
- MLOG_4BYTES, mtr);
-#ifdef UNIV_DEBUG
- } else {
- /* Check that seqno is monotonically increasing */
- unsigned char xid_uuid[16];
- long long xid_seqno = read_wsrep_xid_seqno(xid);
- read_wsrep_xid_uuid(xid, xid_uuid);
-
- if (!memcmp(xid_uuid, trx_sys_cur_xid_uuid, 8)) {
- ut_ad(xid_seqno > trx_sys_cur_xid_seqno);
- trx_sys_cur_xid_seqno = xid_seqno;
- } else {
- memcpy(trx_sys_cur_xid_uuid, xid_uuid, 16);
- }
-
- trx_sys_cur_xid_seqno = xid_seqno;
-#endif /* UNIV_DEBUG */
- }
-
- mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO
- + TRX_SYS_WSREP_XID_FORMAT,
- (int)xid->formatID,
- MLOG_4BYTES, mtr);
- mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO
- + TRX_SYS_WSREP_XID_GTRID_LEN,
- (int)xid->gtrid_length,
- MLOG_4BYTES, mtr);
- mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO
- + TRX_SYS_WSREP_XID_BQUAL_LEN,
- (int)xid->bqual_length,
- MLOG_4BYTES, mtr);
- mlog_write_string(sys_header + TRX_SYS_WSREP_XID_INFO
- + TRX_SYS_WSREP_XID_DATA,
- (const unsigned char*) xid->data,
- XIDDATASIZE, mtr);
-}
-
-/** Read WSREP checkpoint XID from sys header.
-@param[out] xid WSREP XID
-@return whether the checkpoint was present */
-UNIV_INTERN
-bool
-trx_sys_read_wsrep_checkpoint(XID* xid)
-{
- trx_sysf_t* sys_header;
- mtr_t mtr;
- ulint magic;
-
- ut_ad(xid);
-
- mtr_start(&mtr);
-
- sys_header = trx_sysf_get(&mtr);
-
- if ((magic = mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO
- + TRX_SYS_WSREP_XID_MAGIC_N_FLD))
- != TRX_SYS_WSREP_XID_MAGIC_N) {
- mtr.commit();
- xid->null();
- xid->gtrid_length = 0;
- xid->bqual_length = 0;
- memset(xid->data, 0, sizeof xid->data);
- memset(xid->data + 24, 0xff, 8);
- return false;
+ if (!*trx_sys.recovered_binlog_filename) {
+ return;
}
- xid->formatID = (int)mach_read_from_4(
- sys_header
- + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_FORMAT);
- xid->gtrid_length = (int)mach_read_from_4(
- sys_header
- + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_GTRID_LEN);
- xid->bqual_length = (int)mach_read_from_4(
- sys_header
- + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_BQUAL_LEN);
- ut_memcpy(xid->data,
- sys_header + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_DATA,
- XIDDATASIZE);
-
- mtr_commit(&mtr);
- return true;
+ ib::info() << "Last binlog file '"
+ << trx_sys.recovered_binlog_filename
+ << "', position "
+ << trx_sys.recovered_binlog_offset;
}
-#endif /* WITH_WSREP */
-
-/** @return an unallocated rollback segment slot in the TRX_SYS header
+/** Find an available rollback segment.
+@param[in] sys_header
+@return an unallocated rollback segment slot in the TRX_SYS header
@retval ULINT_UNDEFINED if not found */
ulint
-trx_sysf_rseg_find_free(mtr_t* mtr)
+trx_sys_rseg_find_free(const buf_block_t* sys_header)
{
- trx_sysf_t* sys_header = trx_sysf_get(mtr);
-
- for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
- if (trx_sysf_rseg_get_page_no(sys_header, i, mtr)
+ for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
+ if (trx_sysf_rseg_get_page_no(sys_header, rseg_id)
== FIL_NULL) {
- return(i);
+ return rseg_id;
}
}
@@ -386,13 +123,14 @@ trx_sysf_get_n_rseg_slots()
mtr_t mtr;
mtr.start();
- trx_sysf_t* sys_header = trx_sysf_get(&mtr);
srv_available_undo_logs = 0;
-
- for (ulint i = 0; i < TRX_SYS_N_RSEGS; i++) {
- srv_available_undo_logs
- += trx_sysf_rseg_get_page_no(sys_header, i, &mtr)
- != FIL_NULL;
+ if (const buf_block_t* sys_header = trx_sysf_get(&mtr, false)) {
+ for (ulint rseg_id = 0; rseg_id < TRX_SYS_N_RSEGS; rseg_id++) {
+ srv_available_undo_logs
+ += trx_sysf_rseg_get_page_no(sys_header,
+ rseg_id)
+ != FIL_NULL;
+ }
}
mtr.commit();
@@ -407,7 +145,6 @@ trx_sysf_create(
/*============*/
mtr_t* mtr) /*!< in: mtr */
{
- trx_sysf_t* sys_header;
ulint slot_no;
buf_block_t* block;
page_t* page;
@@ -419,10 +156,12 @@ trx_sysf_create(
then enter the kernel: we must do it in this order to conform
to the latching order rules. */
- mtr_x_lock_space(TRX_SYS_SPACE, mtr);
+ mtr_x_lock(&fil_system.sys_space->latch, mtr);
+ compile_time_assert(TRX_SYS_SPACE == 0);
/* Create the trx sys file block in a new allocated file segment */
- block = fseg_create(TRX_SYS_SPACE, 0, TRX_SYS + TRX_SYS_FSEG_HEADER,
+ block = fseg_create(fil_system.sys_space, 0,
+ TRX_SYS + TRX_SYS_FSEG_HEADER,
mtr);
buf_block_dbg_add_level(block, SYNC_TRX_SYS_HEADER);
@@ -440,126 +179,42 @@ trx_sysf_create(
mlog_write_ulint(page + TRX_SYS_DOUBLEWRITE
+ TRX_SYS_DOUBLEWRITE_MAGIC, 0, MLOG_4BYTES, mtr);
- sys_header = trx_sysf_get(mtr);
-
- /* Start counting transaction ids from number 1 up */
- mach_write_to_8(sys_header + TRX_SYS_TRX_ID_STORE, 1);
-
/* Reset the rollback segment slots. Old versions of InnoDB
(before MySQL 5.5) define TRX_SYS_N_RSEGS as 256 and expect
that the whole array is initialized. */
- ptr = TRX_SYS_RSEGS + sys_header;
+ ptr = TRX_SYS + TRX_SYS_RSEGS + page;
compile_time_assert(256 >= TRX_SYS_N_RSEGS);
memset(ptr, 0xff, 256 * TRX_SYS_RSEG_SLOT_SIZE);
ptr += 256 * TRX_SYS_RSEG_SLOT_SIZE;
- ut_a(ptr <= page + (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END));
+ ut_a(ptr <= page + (srv_page_size - FIL_PAGE_DATA_END));
/* Initialize all of the page. This part used to be uninitialized. */
- memset(ptr, 0, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page - ptr);
+ memset(ptr, 0, srv_page_size - FIL_PAGE_DATA_END + size_t(page - ptr));
- mlog_log_string(sys_header, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
- + page - sys_header, mtr);
+ mlog_log_string(TRX_SYS + page, srv_page_size - FIL_PAGE_DATA_END
+ - TRX_SYS, mtr);
/* Create the first rollback segment in the SYSTEM tablespace */
- slot_no = trx_sysf_rseg_find_free(mtr);
- buf_block_t* rblock = trx_rseg_header_create(TRX_SYS_SPACE, ULINT_MAX,
- slot_no, mtr);
+ slot_no = trx_sys_rseg_find_free(block);
+ buf_block_t* rblock = trx_rseg_header_create(fil_system.sys_space,
+ slot_no, block, mtr);
ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
ut_a(rblock->page.id.page_no() == FSP_FIRST_RSEG_PAGE_NO);
}
-/** Initialize the transaction system main-memory data structures. */
-void
-trx_sys_init_at_db_start()
-{
- trx_sysf_t* sys_header;
- ib_uint64_t rows_to_undo = 0;
- const char* unit = "";
-
- /* VERY important: after the database is started, max_trx_id value is
- divisible by TRX_SYS_TRX_ID_WRITE_MARGIN, and the 'if' in
- trx_sys_get_new_trx_id will evaluate to TRUE when the function
- is first time called, and the value for trx id will be written
- to the disk-based header! Thus trx id values will not overlap when
- the database is repeatedly started! */
-
- mtr_t mtr;
- mtr.start();
-
- sys_header = trx_sysf_get(&mtr);
-
- trx_sys->max_trx_id = 2 * TRX_SYS_TRX_ID_WRITE_MARGIN
- + ut_uint64_align_up(mach_read_from_8(sys_header
- + TRX_SYS_TRX_ID_STORE),
- TRX_SYS_TRX_ID_WRITE_MARGIN);
-
- mtr.commit();
- ut_d(trx_sys->rw_max_trx_id = trx_sys->max_trx_id);
-
- trx_lists_init_at_db_start();
-
- /* This mutex is not strictly required, it is here only to satisfy
- the debug code (assertions). We are still running in single threaded
- bootstrap mode. */
-
- trx_sys_mutex_enter();
-
- if (UT_LIST_GET_LEN(trx_sys->rw_trx_list) > 0) {
- const trx_t* trx;
-
- for (trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
- trx != NULL;
- trx = UT_LIST_GET_NEXT(trx_list, trx)) {
-
- ut_ad(trx->is_recovered);
- assert_trx_in_rw_list(trx);
-
- if (trx_state_eq(trx, TRX_STATE_ACTIVE)) {
- rows_to_undo += trx->undo_no;
- }
- }
-
- if (rows_to_undo > 1000000000) {
- unit = "M";
- rows_to_undo = rows_to_undo / 1000000;
- }
-
- ib::info() << UT_LIST_GET_LEN(trx_sys->rw_trx_list)
- << " transaction(s) which must be rolled back or"
- " cleaned up in total " << rows_to_undo << unit
- << " row operations to undo";
-
- ib::info() << "Trx id counter is " << trx_sys->max_trx_id;
- }
-
- trx_sys_mutex_exit();
-
- trx_sys->mvcc->clone_oldest_view(&purge_sys->view);
-}
-
-/*****************************************************************//**
-Creates the trx_sys instance and initializes purge_queue and mutex. */
+/** Create the instance */
void
-trx_sys_create(void)
-/*================*/
+trx_sys_t::create()
{
- ut_ad(trx_sys == NULL);
-
- trx_sys = static_cast<trx_sys_t*>(ut_zalloc_nokey(sizeof(*trx_sys)));
-
- mutex_create(LATCH_ID_TRX_SYS, &trx_sys->mutex);
-
- UT_LIST_INIT(trx_sys->serialisation_list, &trx_t::no_list);
- UT_LIST_INIT(trx_sys->rw_trx_list, &trx_t::trx_list);
- UT_LIST_INIT(trx_sys->mysql_trx_list, &trx_t::mysql_trx_list);
-
- trx_sys->mvcc = UT_NEW_NOKEY(MVCC(1024));
-
- new(&trx_sys->rw_trx_ids) trx_ids_t(ut_allocator<trx_id_t>(
- mem_key_trx_sys_t_rw_trx_ids));
-
- new(&trx_sys->rw_trx_set) TrxIdSet();
+ ut_ad(this == &trx_sys);
+ ut_ad(!is_initialised());
+ m_initialised = true;
+ mutex_create(LATCH_ID_TRX_SYS, &mutex);
+ UT_LIST_INIT(trx_list, &trx_t::trx_list);
+ my_atomic_store32(&rseg_history_len, 0);
+
+ rw_trx_hash.init();
}
/*****************************************************************//**
@@ -577,260 +232,6 @@ trx_sys_create_sys_pages(void)
mtr_commit(&mtr);
}
-/*****************************************************************//**
-Update the file format tag.
-@return always TRUE */
-static
-ibool
-trx_sys_file_format_max_write(
-/*==========================*/
- ulint format_id, /*!< in: file format id */
- const char** name) /*!< out: max file format name, can
- be NULL */
-{
- mtr_t mtr;
- byte* ptr;
- buf_block_t* block;
- ib_uint64_t tag_value;
-
- mtr_start(&mtr);
-
- block = buf_page_get(
- page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), univ_page_size,
- RW_X_LATCH, &mtr);
-
- file_format_max.id = format_id;
- file_format_max.name = trx_sys_file_format_id_to_name(format_id);
-
- ptr = buf_block_get_frame(block) + TRX_SYS_FILE_FORMAT_TAG;
- tag_value = format_id + TRX_SYS_FILE_FORMAT_TAG_MAGIC_N;
-
- if (name) {
- *name = file_format_max.name;
- }
-
- mlog_write_ull(ptr, tag_value, &mtr);
-
- mtr_commit(&mtr);
-
- return(TRUE);
-}
-
-/*****************************************************************//**
-Read the file format tag.
-@return the file format or ULINT_UNDEFINED if not set. */
-static
-ulint
-trx_sys_file_format_max_read(void)
-/*==============================*/
-{
- mtr_t mtr;
- const byte* ptr;
- const buf_block_t* block;
- ib_id_t file_format_id;
-
- /* Since this is called during the startup phase it's safe to
- read the value without a covering mutex. */
- mtr_start(&mtr);
-
- block = buf_page_get(
- page_id_t(TRX_SYS_SPACE, TRX_SYS_PAGE_NO), univ_page_size,
- RW_X_LATCH, &mtr);
-
- ptr = buf_block_get_frame(block) + TRX_SYS_FILE_FORMAT_TAG;
- file_format_id = mach_read_from_8(ptr);
-
- mtr_commit(&mtr);
-
- file_format_id -= TRX_SYS_FILE_FORMAT_TAG_MAGIC_N;
-
- if (file_format_id >= FILE_FORMAT_NAME_N) {
-
- /* Either it has never been tagged, or garbage in it. */
- return(ULINT_UNDEFINED);
- }
-
- return((ulint) file_format_id);
-}
-
-/*****************************************************************//**
-Get the name representation of the file format from its id.
-@return pointer to the name */
-const char*
-trx_sys_file_format_id_to_name(
-/*===========================*/
- const ulint id) /*!< in: id of the file format */
-{
- ut_a(id < FILE_FORMAT_NAME_N);
-
- return(file_format_name_map[id]);
-}
-
-/*****************************************************************//**
-Check for the max file format tag stored on disk. Note: If max_format_id
-is == UNIV_FORMAT_MAX + 1 then we only print a warning.
-@return DB_SUCCESS or error code */
-dberr_t
-trx_sys_file_format_max_check(
-/*==========================*/
- ulint max_format_id) /*!< in: max format id to check */
-{
- ulint format_id;
-
- /* Check the file format in the tablespace. Do not try to
- recover if the file format is not supported by the engine
- unless forced by the user. */
- format_id = trx_sys_file_format_max_read();
- if (format_id == ULINT_UNDEFINED) {
- /* Format ID was not set. Set it to minimum possible
- value. */
- format_id = UNIV_FORMAT_MIN;
- }
-
- ib::info() << "Highest supported file format is "
- << trx_sys_file_format_id_to_name(UNIV_FORMAT_MAX) << ".";
-
- if (format_id > UNIV_FORMAT_MAX) {
-
- ut_a(format_id < FILE_FORMAT_NAME_N);
-
- const std::string msg = std::string("The system"
- " tablespace is in a file format that this version"
- " doesn't support - ")
- + trx_sys_file_format_id_to_name(format_id)
- + ".";
-
- if (max_format_id <= UNIV_FORMAT_MAX) {
- ib::error() << msg;
- } else {
- ib::warn() << msg;
- }
-
- if (max_format_id <= UNIV_FORMAT_MAX) {
- return(DB_ERROR);
- }
- }
-
- format_id = (format_id > max_format_id) ? format_id : max_format_id;
-
- /* We don't need a mutex here, as this function should only
- be called once at start up. */
- file_format_max.id = format_id;
- file_format_max.name = trx_sys_file_format_id_to_name(format_id);
-
- return(DB_SUCCESS);
-}
-
-/*****************************************************************//**
-Set the file format id unconditionally except if it's already the
-same value.
-@return TRUE if value updated */
-ibool
-trx_sys_file_format_max_set(
-/*========================*/
- ulint format_id, /*!< in: file format id */
- const char** name) /*!< out: max file format name or
- NULL if not needed. */
-{
- ibool ret = FALSE;
-
- ut_a(format_id <= UNIV_FORMAT_MAX);
-
- mutex_enter(&file_format_max.mutex);
-
- /* Only update if not already same value. */
- if (format_id != file_format_max.id) {
-
- ret = trx_sys_file_format_max_write(format_id, name);
- }
-
- mutex_exit(&file_format_max.mutex);
-
- return(ret);
-}
-
-/********************************************************************//**
-Tags the system table space with minimum format id if it has not been
-tagged yet.
-WARNING: This function is only called during the startup and AFTER the
-redo log application during recovery has finished. */
-void
-trx_sys_file_format_tag_init(void)
-/*==============================*/
-{
- ulint format_id;
-
- format_id = trx_sys_file_format_max_read();
-
- /* If format_id is not set then set it to the minimum. */
- if (format_id == ULINT_UNDEFINED) {
- trx_sys_file_format_max_set(UNIV_FORMAT_MIN, NULL);
- }
-}
-
-/********************************************************************//**
-Update the file format tag in the system tablespace only if the given
-format id is greater than the known max id.
-@return TRUE if format_id was bigger than the known max id */
-ibool
-trx_sys_file_format_max_upgrade(
-/*============================*/
- const char** name, /*!< out: max file format name */
- ulint format_id) /*!< in: file format identifier */
-{
- ibool ret = FALSE;
-
- ut_a(name);
- ut_a(file_format_max.name != NULL);
- ut_a(format_id <= UNIV_FORMAT_MAX);
-
- mutex_enter(&file_format_max.mutex);
-
- if (format_id > file_format_max.id) {
-
- ret = trx_sys_file_format_max_write(format_id, name);
- }
-
- mutex_exit(&file_format_max.mutex);
-
- return(ret);
-}
-
-/*****************************************************************//**
-Get the name representation of the file format from its id.
-@return pointer to the max format name */
-const char*
-trx_sys_file_format_max_get(void)
-/*=============================*/
-{
- return(file_format_max.name);
-}
-
-/*****************************************************************//**
-Initializes the tablespace tag system. */
-void
-trx_sys_file_format_init(void)
-/*==========================*/
-{
- mutex_create(LATCH_ID_FILE_FORMAT_MAX, &file_format_max.mutex);
-
- /* We don't need a mutex here, as this function should only
- be called once at start up. */
- file_format_max.id = UNIV_FORMAT_MIN;
-
- file_format_max.name = trx_sys_file_format_id_to_name(
- file_format_max.id);
-}
-
-/*****************************************************************//**
-Closes the tablespace tag system. */
-void
-trx_sys_file_format_close(void)
-/*===========================*/
-{
- mutex_free(&file_format_max.mutex);
-}
-
/** Create the rollback segments.
@return whether the creation succeeded */
bool
@@ -909,128 +310,53 @@ trx_sys_create_rsegs()
return(true);
}
-/*********************************************************************
-Shutdown/Close the transaction system. */
+/** Close the transaction system on shutdown */
void
-trx_sys_close(void)
-/*===============*/
+trx_sys_t::close()
{
- ut_ad(trx_sys != NULL);
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_EXIT_THREADS);
+ if (!is_initialised()) {
+ return;
+ }
- if (ulint size = trx_sys->mvcc->size()) {
+ if (size_t size = view_count()) {
ib::error() << "All read views were not closed before"
" shutdown: " << size << " read views open";
}
- /* Only prepared transactions may be left in the system. Free them. */
- ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == trx_sys->n_prepared_trx
- || !srv_was_started
- || srv_read_only_mode
- || srv_force_recovery >= SRV_FORCE_NO_TRX_UNDO);
-
- while (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->rw_trx_list)) {
- UT_LIST_REMOVE(trx_sys->rw_trx_list, trx);
- trx_free_prepared(trx);
- }
+ rw_trx_hash.destroy();
/* There can't be any active transactions. */
for (ulint i = 0; i < TRX_SYS_N_RSEGS; ++i) {
- if (trx_rseg_t* rseg = trx_sys->rseg_array[i]) {
+ if (trx_rseg_t* rseg = rseg_array[i]) {
trx_rseg_mem_free(rseg);
}
- if (trx_rseg_t* rseg = trx_sys->temp_rsegs[i]) {
+ if (trx_rseg_t* rseg = temp_rsegs[i]) {
trx_rseg_mem_free(rseg);
}
}
- UT_DELETE(trx_sys->mvcc);
-
- ut_a(UT_LIST_GET_LEN(trx_sys->rw_trx_list) == 0);
- ut_a(UT_LIST_GET_LEN(trx_sys->mysql_trx_list) == 0);
- ut_a(UT_LIST_GET_LEN(trx_sys->serialisation_list) == 0);
-
- /* We used placement new to create this mutex. Call the destructor. */
- mutex_free(&trx_sys->mutex);
-
- trx_sys->rw_trx_ids.~trx_ids_t();
-
- trx_sys->rw_trx_set.~TrxIdSet();
-
- ut_free(trx_sys);
-
- trx_sys = NULL;
-}
-
-/*********************************************************************
-Check if there are any active (non-prepared) transactions.
-This is only used to check if it's safe to shutdown.
-@return total number of active transactions or 0 if none */
-ulint
-trx_sys_any_active_transactions(void)
-/*=================================*/
-{
- ulint total_trx = 0;
-
- trx_sys_mutex_enter();
-
- total_trx = UT_LIST_GET_LEN(trx_sys->rw_trx_list);
-
- for (trx_t* trx = UT_LIST_GET_FIRST(trx_sys->mysql_trx_list);
- trx != NULL;
- trx = UT_LIST_GET_NEXT(mysql_trx_list, trx)) {
- total_trx += trx->state != TRX_STATE_NOT_STARTED;
- }
-
- ut_a(total_trx >= trx_sys->n_prepared_trx);
- total_trx -= trx_sys->n_prepared_trx;
-
- trx_sys_mutex_exit();
-
- return(total_trx);
-}
-
-#ifdef UNIV_DEBUG
-/*************************************************************//**
-Validate the trx_ut_list_t.
-@return true if valid. */
-static
-bool
-trx_sys_validate_trx_list_low(
-/*===========================*/
- trx_ut_list_t* trx_list) /*!< in: &trx_sys->rw_trx_list */
-{
- const trx_t* trx;
- const trx_t* prev_trx = NULL;
-
- ut_ad(trx_sys_mutex_own());
-
- ut_ad(trx_list == &trx_sys->rw_trx_list);
-
- for (trx = UT_LIST_GET_FIRST(*trx_list);
- trx != NULL;
- prev_trx = trx, trx = UT_LIST_GET_NEXT(trx_list, prev_trx)) {
-
- check_trx_state(trx);
- ut_a(prev_trx == NULL || prev_trx->id > trx->id);
- }
-
- return(true);
+ ut_a(UT_LIST_GET_LEN(trx_list) == 0);
+ mutex_free(&mutex);
+ m_initialised = false;
}
-/*************************************************************//**
-Validate the trx_sys_t::rw_trx_list.
-@return true if the list is valid. */
-bool
-trx_sys_validate_trx_list()
-/*=======================*/
+/** @return total number of active (non-prepared) transactions */
+ulint trx_sys_t::any_active_transactions()
{
- ut_ad(trx_sys_mutex_own());
-
- ut_a(trx_sys_validate_trx_list_low(&trx_sys->rw_trx_list));
-
- return(true);
+ uint32_t total_trx= 0;
+
+ mutex_enter(&mutex);
+ for (trx_t* trx= UT_LIST_GET_FIRST(trx_sys.trx_list);
+ trx != NULL;
+ trx= UT_LIST_GET_NEXT(trx_list, trx))
+ {
+ if (trx->state == TRX_STATE_COMMITTED_IN_MEMORY ||
+ (trx->state == TRX_STATE_ACTIVE && trx->id))
+ total_trx++;
+ }
+ mutex_exit(&mutex);
+ return total_trx;
}
-#endif /* UNIV_DEBUG */