mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 03:21:53 +01:00
branches/innodb+: Create additional rollback segments on startup. Reduce
the upper limit of total rollback segments from 256 to 128. This is because we can't use the sign bit. It has not caused problems in the past because we only created one segment. InnoDB has always had the capability to use the additional rollback segments therefore this patch is backwards compatible. The only requirement to maintain backward compatibility has been to ensure that the additional segments are created after the double write buffer. This is to avoid breaking assumptions in the existing code. Fix Bug#26590 MySQL does not allow more than 1023 open transactions
This commit is contained in:
parent
2635191059
commit
f50ad079a1
6 changed files with 196 additions and 64 deletions
|
@ -103,7 +103,7 @@ trx_rseg_header_create(
|
|||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint max_size, /*!< in: max size in pages */
|
||||
ulint* slot_no, /*!< out: rseg id == slot number in trx sys */
|
||||
ulint rseg_slot_no, /*!< in: rseg id == slot number in trx sys */
|
||||
mtr_t* mtr); /*!< in: mtr */
|
||||
/*********************************************************************//**
|
||||
Creates the memory copies for rollback segments and initializes the
|
||||
|
@ -122,6 +122,12 @@ trx_rseg_mem_free(
|
|||
/*==============*/
|
||||
trx_rseg_t* rseg); /* in, own: instance to free */
|
||||
|
||||
/*********************************************************************
|
||||
Creates a rollback segment. */
|
||||
UNIV_INTERN
|
||||
trx_rseg_t*
|
||||
trx_rseg_create(void);
|
||||
/*==================*/
|
||||
|
||||
/* Number of undo log slots in a rollback segment file copy */
|
||||
#define TRX_RSEG_N_SLOTS (UNIV_PAGE_SIZE / 16)
|
||||
|
|
|
@ -431,6 +431,14 @@ trx_sys_file_format_id_to_name(
|
|||
const ulint id); /*!< in: id of the file format */
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/*********************************************************************
|
||||
Creates the rollback segments */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_create_rsegs(
|
||||
/*=================*/
|
||||
ulint n_rsegs); /*!< number of rollback segments to create */
|
||||
|
||||
/* The automatically created system rollback segment has this id */
|
||||
#define TRX_SYS_SYSTEM_RSEG_ID 0
|
||||
|
||||
|
@ -465,11 +473,16 @@ trx_sys_file_format_id_to_name(
|
|||
slots */
|
||||
/*------------------------------------------------------------- @} */
|
||||
|
||||
/** Maximum number of rollback segments: the number of segment
|
||||
specification slots in the transaction system array; rollback segment
|
||||
id must fit in one byte, therefore 256; each slot is currently 8 bytes
|
||||
in size */
|
||||
#define TRX_SYS_N_RSEGS 256
|
||||
/* Max number of rollback segments: the number of segment specification slots
|
||||
in the transaction system array; rollback segment id must fit in one (signed)
|
||||
byte, therefore 128; each slot is currently 8 bytes in size. If you want
|
||||
to raise the level to 256 then you will need to fix some assertions that
|
||||
impose the 7 bit restriction. e.g., mach_write_to_3() */
|
||||
#define TRX_SYS_N_RSEGS 128
|
||||
/* Originally, InnoDB defined TRX_SYS_N_RSEGS as 256 but created only one
|
||||
rollback segment. It initialized some arrays with this number of entries.
|
||||
We must remember this limit in order to keep file compatibility. */
|
||||
#define TRX_SYS_OLD_N_RSEGS 256
|
||||
|
||||
/** Maximum length of MySQL binlog file name, in bytes.
|
||||
@see trx_sys_mysql_master_log_name
|
||||
|
|
|
@ -42,7 +42,7 @@ trx_undo_build_roll_ptr(
|
|||
#if DATA_ROLL_PTR_LEN != 7
|
||||
# error "DATA_ROLL_PTR_LEN != 7"
|
||||
#endif
|
||||
ut_ad(rseg_id < 128);
|
||||
ut_ad(rseg_id < TRX_SYS_N_RSEGS);
|
||||
|
||||
return(ut_dulint_create(is_insert * 128 * 256 * 256
|
||||
+ rseg_id * 256 * 256
|
||||
|
|
|
@ -1533,12 +1533,19 @@ innobase_start_or_create_for_mysql(void)
|
|||
|
||||
if (create_new_db) {
|
||||
mtr_start(&mtr);
|
||||
|
||||
fsp_header_init(0, sum_of_new_sizes, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
/* To maintain backward compatibility we create only
|
||||
the first rollback segment before the double write buffer.
|
||||
All the remaining rollback segments will be created later,
|
||||
after the double write buffer has been created. */
|
||||
trx_sys_create();
|
||||
|
||||
dict_create();
|
||||
|
||||
srv_startup_is_before_trx_rollback_phase = FALSE;
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
|
@ -1557,7 +1564,9 @@ innobase_start_or_create_for_mysql(void)
|
|||
in any disk i/o, first call dict_boot */
|
||||
|
||||
dict_boot();
|
||||
|
||||
trx_sys_init_at_db_start();
|
||||
|
||||
srv_startup_is_before_trx_rollback_phase = FALSE;
|
||||
|
||||
/* Initialize the fsp free limit global variable in the log
|
||||
|
@ -1714,6 +1723,14 @@ innobase_start_or_create_for_mysql(void)
|
|||
trx_sys_create_doublewrite_buf();
|
||||
}
|
||||
|
||||
/* Here the double write buffer has already been created and so
|
||||
any new rollback segments will be allocated after the double
|
||||
write buffer. The default segment should already exist.
|
||||
We create the new segments only if it's a new database or
|
||||
the database was shutdown cleanly. */
|
||||
|
||||
trx_sys_create_rsegs(TRX_SYS_N_RSEGS - 1);
|
||||
|
||||
err = dict_create_or_check_foreign_constraint_tables();
|
||||
|
||||
if (err != DB_SUCCESS) {
|
||||
|
|
135
trx/trx0rseg.c
135
trx/trx0rseg.c
|
@ -51,11 +51,9 @@ trx_rseg_get_on_id(
|
|||
trx_rseg_t* rseg;
|
||||
|
||||
rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
|
||||
ut_ad(rseg);
|
||||
|
||||
while (rseg->id != id) {
|
||||
while (rseg && rseg->id != id) {
|
||||
rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
|
||||
ut_ad(rseg);
|
||||
}
|
||||
|
||||
return(rseg);
|
||||
|
@ -73,7 +71,7 @@ trx_rseg_header_create(
|
|||
ulint zip_size, /*!< in: compressed page size in bytes
|
||||
or 0 for uncompressed pages */
|
||||
ulint max_size, /*!< in: max size in pages */
|
||||
ulint* slot_no, /*!< out: rseg id == slot number in trx sys */
|
||||
ulint rseg_slot_no, /*!< in: rseg id == slot number in trx sys */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ulint page_no;
|
||||
|
@ -86,14 +84,6 @@ trx_rseg_header_create(
|
|||
ut_ad(mutex_own(&kernel_mutex));
|
||||
ut_ad(mtr_memo_contains(mtr, fil_space_get_latch(space, NULL),
|
||||
MTR_MEMO_X_LOCK));
|
||||
sys_header = trx_sysf_get(mtr);
|
||||
|
||||
*slot_no = trx_sysf_rseg_find_free(mtr);
|
||||
|
||||
if (*slot_no == ULINT_UNDEFINED) {
|
||||
|
||||
return(FIL_NULL);
|
||||
}
|
||||
|
||||
/* Allocate a new file segment for the rollback segment */
|
||||
block = fseg_create(space, 0,
|
||||
|
@ -127,11 +117,13 @@ trx_rseg_header_create(
|
|||
trx_rsegf_set_nth_undo(rsegf, i, FIL_NULL, mtr);
|
||||
}
|
||||
|
||||
/* Add the rollback segment info to the free slot in the trx system
|
||||
header */
|
||||
/* Add the rollback segment info to the free slot in
|
||||
the trx system header */
|
||||
|
||||
trx_sysf_rseg_set_space(sys_header, *slot_no, space, mtr);
|
||||
trx_sysf_rseg_set_page_no(sys_header, *slot_no, page_no, mtr);
|
||||
sys_header = trx_sysf_get(mtr);
|
||||
|
||||
trx_sysf_rseg_set_space(sys_header, rseg_slot_no, space, mtr);
|
||||
trx_sysf_rseg_set_page_no(sys_header, rseg_slot_no, page_no, mtr);
|
||||
|
||||
return(page_no);
|
||||
}
|
||||
|
@ -196,16 +188,16 @@ trx_rseg_mem_create(
|
|||
ulint page_no, /*!< in: page number of the segment header */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
trx_rsegf_t* rseg_header;
|
||||
trx_rseg_t* rseg;
|
||||
trx_ulogf_t* undo_log_hdr;
|
||||
fil_addr_t node_addr;
|
||||
ulint sum_of_undo_sizes;
|
||||
ulint len;
|
||||
trx_rseg_t* rseg;
|
||||
fil_addr_t node_addr;
|
||||
trx_rsegf_t* rseg_header;
|
||||
trx_ulogf_t* undo_log_hdr;
|
||||
ulint sum_of_undo_sizes;
|
||||
|
||||
ut_ad(mutex_own(&kernel_mutex));
|
||||
|
||||
rseg = mem_alloc(sizeof(trx_rseg_t));
|
||||
rseg = mem_zalloc(sizeof(trx_rseg_t));
|
||||
|
||||
rseg->id = id;
|
||||
rseg->space = space;
|
||||
|
@ -255,39 +247,108 @@ trx_rseg_mem_create(
|
|||
return(rseg);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Creates the memory copies for rollback segments and initializes the
|
||||
/********************************************************************
|
||||
Creates the memory copies for the rollback segments and initializes the
|
||||
rseg list and array in trx_sys at a database startup. */
|
||||
UNIV_INTERN
|
||||
static
|
||||
void
|
||||
trx_rseg_list_and_array_init(
|
||||
/*=========================*/
|
||||
trx_rseg_create_instance(
|
||||
/*=====================*/
|
||||
trx_sysf_t* sys_header, /*!< in: trx system header */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ulint i;
|
||||
ulint page_no;
|
||||
ulint space;
|
||||
|
||||
UT_LIST_INIT(trx_sys->rseg_list);
|
||||
|
||||
trx_sys->rseg_history_len = 0;
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
||||
ulint page_no;
|
||||
|
||||
page_no = trx_sysf_rseg_get_page_no(sys_header, i, mtr);
|
||||
|
||||
if (page_no == FIL_NULL) {
|
||||
|
||||
trx_sys_set_nth_rseg(trx_sys, i, NULL);
|
||||
} else {
|
||||
ulint zip_size;
|
||||
ulint space;
|
||||
ulint zip_size;
|
||||
trx_rseg_t* rseg = NULL;
|
||||
|
||||
ut_a(!trx_rseg_get_on_id(i));
|
||||
|
||||
space = trx_sysf_rseg_get_space(sys_header, i, mtr);
|
||||
|
||||
zip_size = space ? fil_space_get_zip_size(space) : 0;
|
||||
|
||||
trx_rseg_mem_create(i, space, zip_size, page_no, mtr);
|
||||
rseg = trx_rseg_mem_create(
|
||||
i, space, zip_size, page_no, mtr);
|
||||
|
||||
ut_a(rseg->id == i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Creates a rollback segment.
|
||||
@return pointer to new rollback segment if create successful */
|
||||
UNIV_INTERN
|
||||
trx_rseg_t*
|
||||
trx_rseg_create(void)
|
||||
/*=================*/
|
||||
{
|
||||
mtr_t mtr;
|
||||
ulint slot_no;
|
||||
trx_rseg_t* rseg = NULL;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* To obey the latching order, acquire the file space
|
||||
x-latch before the kernel mutex. */
|
||||
mtr_x_lock(fil_space_get_latch(TRX_SYS_SPACE, NULL), &mtr);
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
||||
slot_no = trx_sysf_rseg_find_free(&mtr);
|
||||
|
||||
if (slot_no != ULINT_UNDEFINED) {
|
||||
ulint space;
|
||||
ulint page_no;
|
||||
ulint zip_size;
|
||||
trx_sysf_t* sys_header;
|
||||
|
||||
page_no = trx_rseg_header_create(
|
||||
TRX_SYS_SPACE, 0, ULINT_MAX, slot_no, &mtr);
|
||||
|
||||
ut_a(page_no != FIL_NULL);
|
||||
|
||||
ut_ad(!trx_rseg_get_on_id(slot_no));
|
||||
|
||||
sys_header = trx_sysf_get(&mtr);
|
||||
|
||||
space = trx_sysf_rseg_get_space(sys_header, slot_no, &mtr);
|
||||
|
||||
zip_size = space ? fil_space_get_zip_size(space) : 0;
|
||||
|
||||
rseg = trx_rseg_mem_create(
|
||||
slot_no, space, zip_size, page_no, &mtr);
|
||||
}
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(rseg);
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Initialize the rollback instance list. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_rseg_list_and_array_init(
|
||||
/*=========================*/
|
||||
trx_sysf_t* sys_header, /* in: trx system header */
|
||||
mtr_t* mtr) /* in: mtr */
|
||||
{
|
||||
UT_LIST_INIT(trx_sys->rseg_list);
|
||||
|
||||
trx_sys->rseg_history_len = 0;
|
||||
|
||||
trx_rseg_create_instance(sys_header, mtr);
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ Created 3/26/1996 Heikki Tuuri
|
|||
#include "srv0srv.h"
|
||||
#include "trx0purge.h"
|
||||
#include "log0log.h"
|
||||
#include "log0recv.h"
|
||||
#include "os0file.h"
|
||||
#include "read0read.h"
|
||||
|
||||
|
@ -877,7 +878,8 @@ trx_sysf_create(
|
|||
buf_block_t* block;
|
||||
page_t* page;
|
||||
ulint page_no;
|
||||
ulint i;
|
||||
byte* ptr;
|
||||
ulint len;
|
||||
|
||||
ut_ad(mtr);
|
||||
|
||||
|
@ -910,32 +912,31 @@ trx_sysf_create(
|
|||
sys_header = trx_sysf_get(mtr);
|
||||
|
||||
/* Start counting transaction ids from number 1 up */
|
||||
mlog_write_dulint(sys_header + TRX_SYS_TRX_ID_STORE,
|
||||
ut_dulint_create(0, 1), mtr);
|
||||
mach_write_to_8(sys_header + TRX_SYS_TRX_ID_STORE,
|
||||
ut_dulint_create(0, 1));
|
||||
|
||||
/* Reset the rollback segment slots */
|
||||
for (i = 0; i < TRX_SYS_N_RSEGS; i++) {
|
||||
/* Reset the rollback segment slots. Old versions of InnoDB
|
||||
define TRX_SYS_N_RSEGS as 256 (TRX_SYS_OLD_N_RSEGS) and expect
|
||||
that the whole array is initialized. */
|
||||
ptr = TRX_SYS_RSEGS + sys_header;
|
||||
len = ut_max(TRX_SYS_OLD_N_RSEGS, TRX_SYS_N_RSEGS)
|
||||
* TRX_SYS_RSEG_SLOT_SIZE;
|
||||
memset(ptr, 0xff, len);
|
||||
ptr += len;
|
||||
ut_a(ptr <= page + (UNIV_PAGE_SIZE - FIL_PAGE_DATA_END));
|
||||
|
||||
trx_sysf_rseg_set_space(sys_header, i, ULINT_UNDEFINED, mtr);
|
||||
trx_sysf_rseg_set_page_no(sys_header, i, FIL_NULL, mtr);
|
||||
}
|
||||
/* Initialize all of the page. This part used to be uninitialized. */
|
||||
memset(ptr, 0, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END + page - ptr);
|
||||
|
||||
/* The remaining area (up to the page trailer) is uninitialized.
|
||||
Silence Valgrind warnings about it. */
|
||||
UNIV_MEM_VALID(sys_header + (TRX_SYS_RSEGS
|
||||
+ TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
|
||||
+ TRX_SYS_RSEG_SPACE),
|
||||
(UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
|
||||
- (TRX_SYS_RSEGS
|
||||
+ TRX_SYS_N_RSEGS * TRX_SYS_RSEG_SLOT_SIZE
|
||||
+ TRX_SYS_RSEG_SPACE))
|
||||
+ page - sys_header);
|
||||
mlog_log_string(sys_header, UNIV_PAGE_SIZE - FIL_PAGE_DATA_END
|
||||
+ page - sys_header, mtr);
|
||||
|
||||
/* Create the first rollback segment in the SYSTEM tablespace */
|
||||
page_no = trx_rseg_header_create(TRX_SYS_SPACE, 0, ULINT_MAX, &slot_no,
|
||||
slot_no = trx_sysf_rseg_find_free(mtr);
|
||||
page_no = trx_rseg_header_create(TRX_SYS_SPACE, 0, ULINT_MAX, slot_no,
|
||||
mtr);
|
||||
ut_a(slot_no == TRX_SYS_SYSTEM_RSEG_ID);
|
||||
ut_a(page_no != FIL_NULL);
|
||||
ut_a(page_no == FSP_FIRST_RSEG_PAGE_NO);
|
||||
|
||||
mutex_exit(&kernel_mutex);
|
||||
}
|
||||
|
@ -1310,6 +1311,40 @@ trx_sys_file_format_close(void)
|
|||
{
|
||||
/* Does nothing at the moment */
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Creates the rollback segments */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_create_rsegs(
|
||||
/*=================*/
|
||||
ulint n_rsegs) /*!< number of rollback segments to create */
|
||||
{
|
||||
ulint new_rsegs = 0;
|
||||
|
||||
/* Do not create additional rollback segments if
|
||||
innodb_force_recovery has been set and the database
|
||||
was not shutdown cleanly. */
|
||||
if (!srv_force_recovery && !recv_needed_recovery) {
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < n_rsegs; ++i) {
|
||||
|
||||
if (trx_rseg_create() != NULL) {
|
||||
++new_rsegs;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_rsegs > 0) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: %lu rollback segment(s) active.\n",
|
||||
new_rsegs);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
/*****************************************************************//**
|
||||
Prints to stderr the MySQL binlog info in the system header if the
|
||||
|
|
Loading…
Add table
Reference in a new issue