mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
XtraDB from Percona-Server-5.5.28-rel29.1
This commit is contained in:
@@ -4,6 +4,9 @@ plugin-load=$HA_INNODB_SO
|
||||
innodb
|
||||
innodb-cmpmem
|
||||
innodb-trx
|
||||
innodb-buffer-pool-stats
|
||||
innodb-buffer-page
|
||||
innodb-buffer-page-lru
|
||||
|
||||
[xtradb_plugin]
|
||||
ignore-builtin-innodb
|
||||
@@ -11,8 +14,14 @@ plugin-load=$HA_XTRADB_SO
|
||||
innodb
|
||||
innodb-cmpmem
|
||||
innodb-trx
|
||||
innodb-buffer-pool-stats
|
||||
innodb-buffer-page
|
||||
innodb-buffer-page-lru
|
||||
|
||||
[xtradb]
|
||||
innodb
|
||||
innodb-cmpmem
|
||||
innodb-trx
|
||||
innodb-buffer-pool-stats
|
||||
innodb-buffer-page
|
||||
innodb-buffer-page-lru
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-29.0" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-29.0 or earlier
|
||||
}
|
||||
|
||||
-- disable_result_log
|
||||
SELECT * FROM INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ select "---- -v -v -t ------" as "";
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
|
||||
if (`select count(*) from information_schema.plugins where plugin_name='innodb' and plugin_auth_version > "1.1.8-29.0"`)
|
||||
if (`select count(*) from information_schema.plugins where plugin_name='innodb' and plugin_auth_version > "1.1.8-29.1"`)
|
||||
{
|
||||
# because of lp:1066512 this test shows xtradb I_S plugins, even when
|
||||
# xtradb is supposed to be disabled
|
||||
|
||||
@@ -1891,6 +1891,7 @@ btr_root_raise_and_insert(
|
||||
root = btr_cur_get_page(cursor);
|
||||
root_block = btr_cur_get_block(cursor);
|
||||
root_page_zip = buf_block_get_page_zip(root_block);
|
||||
ut_ad(page_get_n_recs(root) > 0);
|
||||
#ifdef UNIV_ZIP_DEBUG
|
||||
ut_a(!root_page_zip || page_zip_validate(root_page_zip, root));
|
||||
#endif /* UNIV_ZIP_DEBUG */
|
||||
@@ -2371,12 +2372,20 @@ btr_insert_on_non_leaf_level_func(
|
||||
BTR_CONT_MODIFY_TREE,
|
||||
&cursor, 0, file, line, mtr);
|
||||
|
||||
err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
|
||||
| BTR_KEEP_SYS_FLAG
|
||||
| BTR_NO_UNDO_LOG_FLAG,
|
||||
&cursor, tuple, &rec,
|
||||
&dummy_big_rec, 0, NULL, mtr);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
ut_ad(cursor.flag == BTR_CUR_BINARY);
|
||||
|
||||
err = btr_cur_optimistic_insert(
|
||||
BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
|
||||
| BTR_NO_UNDO_LOG_FLAG, &cursor, tuple, &rec,
|
||||
&dummy_big_rec, 0, NULL, mtr);
|
||||
|
||||
if (err == DB_FAIL) {
|
||||
err = btr_cur_pessimistic_insert(
|
||||
BTR_NO_LOCKING_FLAG | BTR_KEEP_SYS_FLAG
|
||||
| BTR_NO_UNDO_LOG_FLAG,
|
||||
&cursor, tuple, &rec, &dummy_big_rec, 0, NULL, mtr);
|
||||
ut_a(err == DB_SUCCESS);
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************//**
|
||||
|
||||
@@ -1412,7 +1412,12 @@ fail_err:
|
||||
|
||||
if (UNIV_UNLIKELY(reorg)) {
|
||||
ut_a(zip_size);
|
||||
ut_a(*rec);
|
||||
/* It's possible for rec to be NULL if the
|
||||
page is compressed. This is because a
|
||||
reorganized page may become incompressible. */
|
||||
if (!*rec) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1548,20 +1553,9 @@ btr_cur_pessimistic_insert(
|
||||
ut_ad((thr && thr_get_trx(thr)->fake_changes) || mtr_memo_contains(mtr, btr_cur_get_block(cursor),
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
|
||||
/* Try first an optimistic insert; reset the cursor flag: we do not
|
||||
assume anything of how it was positioned */
|
||||
|
||||
cursor->flag = BTR_CUR_BINARY;
|
||||
|
||||
err = btr_cur_optimistic_insert(flags, cursor, entry, rec,
|
||||
big_rec, n_ext, thr, mtr);
|
||||
if (err != DB_FAIL) {
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
/* Retry with a pessimistic insert. Check locks and write to undo log,
|
||||
if specified */
|
||||
/* Check locks and write to undo log, if specified */
|
||||
|
||||
err = btr_cur_ins_lock_and_undo(flags, cursor, entry,
|
||||
thr, mtr, &dummy_inh);
|
||||
@@ -2188,8 +2182,12 @@ any_extern:
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
max_size = old_rec_size
|
||||
+ page_get_max_insert_size_after_reorganize(page, 1);
|
||||
/* We do not attempt to reorganize if the page is compressed.
|
||||
This is because the page may fail to compress after reorganization. */
|
||||
max_size = page_zip
|
||||
? page_get_max_insert_size(page, 1)
|
||||
: (old_rec_size
|
||||
+ page_get_max_insert_size_after_reorganize(page, 1));
|
||||
|
||||
if (!(((max_size >= BTR_CUR_PAGE_REORGANIZE_LIMIT)
|
||||
&& (max_size >= new_rec_size))
|
||||
@@ -2559,7 +2557,12 @@ make_external:
|
||||
err = DB_SUCCESS;
|
||||
goto return_after_reservations;
|
||||
} else {
|
||||
ut_a(optim_err != DB_UNDERFLOW);
|
||||
/* If the page is compressed and it initially
|
||||
compresses very well, and there is a subsequent insert
|
||||
of a badly-compressing record, it is possible for
|
||||
btr_cur_optimistic_update() to return DB_UNDERFLOW and
|
||||
btr_cur_insert_if_possible() to return FALSE. */
|
||||
ut_a(page_zip || optim_err != DB_UNDERFLOW);
|
||||
|
||||
/* Out of space: reset the free bits. */
|
||||
if (!dict_index_is_clust(index)
|
||||
@@ -2588,7 +2591,9 @@ make_external:
|
||||
was_first = page_cur_is_before_first(page_cursor);
|
||||
|
||||
/* Lock checks and undo logging were already performed by
|
||||
btr_cur_upd_lock_and_undo(). */
|
||||
btr_cur_upd_lock_and_undo(). We do not try
|
||||
btr_cur_optimistic_insert() because
|
||||
btr_cur_insert_if_possible() already failed above. */
|
||||
|
||||
err = btr_cur_pessimistic_insert(BTR_NO_UNDO_LOG_FLAG
|
||||
| BTR_NO_LOCKING_FLAG
|
||||
|
||||
@@ -354,44 +354,39 @@ btr_pcur_restore_position_func(
|
||||
/* Restore the old search mode */
|
||||
cursor->search_mode = old_mode;
|
||||
|
||||
if (btr_pcur_is_on_user_rec(cursor)) {
|
||||
switch (cursor->rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
if (!cmp_dtuple_rec(
|
||||
tuple, btr_pcur_get_rec(cursor),
|
||||
rec_get_offsets(btr_pcur_get_rec(cursor),
|
||||
index, NULL,
|
||||
ULINT_UNDEFINED, &heap))) {
|
||||
switch (cursor->rel_pos) {
|
||||
case BTR_PCUR_ON:
|
||||
if (btr_pcur_is_on_user_rec(cursor)
|
||||
&& !cmp_dtuple_rec(
|
||||
tuple, btr_pcur_get_rec(cursor),
|
||||
rec_get_offsets(btr_pcur_get_rec(cursor),
|
||||
index, NULL,
|
||||
ULINT_UNDEFINED, &heap))) {
|
||||
|
||||
/* We have to store the NEW value for
|
||||
the modify clock, since the cursor can
|
||||
now be on a different page! But we can
|
||||
retain the value of old_rec */
|
||||
/* We have to store the NEW value for
|
||||
the modify clock, since the cursor can
|
||||
now be on a different page! But we can
|
||||
retain the value of old_rec */
|
||||
|
||||
cursor->block_when_stored =
|
||||
btr_pcur_get_block(cursor);
|
||||
cursor->modify_clock =
|
||||
buf_block_get_modify_clock(
|
||||
cursor->block_when_stored);
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
cursor->block_when_stored =
|
||||
btr_pcur_get_block(cursor);
|
||||
cursor->modify_clock =
|
||||
buf_block_get_modify_clock(
|
||||
cursor->block_when_stored);
|
||||
cursor->old_stored = BTR_PCUR_OLD_STORED;
|
||||
|
||||
mem_heap_free(heap);
|
||||
mem_heap_free(heap);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
break;
|
||||
case BTR_PCUR_BEFORE:
|
||||
page_cur_move_to_next(btr_pcur_get_page_cur(cursor));
|
||||
break;
|
||||
case BTR_PCUR_AFTER:
|
||||
page_cur_move_to_prev(btr_pcur_get_page_cur(cursor));
|
||||
break;
|
||||
#ifdef UNIV_DEBUG
|
||||
default:
|
||||
ut_error;
|
||||
#endif /* UNIV_DEBUG */
|
||||
return(TRUE);
|
||||
}
|
||||
#ifdef UNIV_DEBUG
|
||||
/* fall through */
|
||||
case BTR_PCUR_BEFORE:
|
||||
case BTR_PCUR_AFTER:
|
||||
break;
|
||||
default:
|
||||
ut_error;
|
||||
#endif /* UNIV_DEBUG */
|
||||
}
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
@@ -336,15 +336,6 @@ be effective only if PFS_GROUP_BUFFER_SYNC is defined. */
|
||||
# endif /* !PFS_SKIP_BUFFER_MUTEX_RWLOCK */
|
||||
#endif /* UNIV_PFS_MUTEX || UNIV_PFS_RWLOCK */
|
||||
|
||||
/** A chunk of buffers. The buffer pool is allocated in chunks. (moved to buf0buf.h)*/
|
||||
//struct buf_chunk_struct{
|
||||
// ulint mem_size; /*!< allocated size of the chunk */
|
||||
// ulint size; /*!< size of frames[] and blocks[] */
|
||||
// void* mem; /*!< pointer to the memory area which
|
||||
// was allocated for the frames */
|
||||
// buf_block_t* blocks; /*!< array of buffer control blocks */
|
||||
//};
|
||||
|
||||
/********************************************************************//**
|
||||
Gets the smallest oldest_modification lsn for any page in the pool. Returns
|
||||
zero if all modified pages have been flushed to disk.
|
||||
@@ -1028,7 +1019,8 @@ buf_chunk_init(
|
||||
/*===========*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
buf_chunk_t* chunk, /*!< out: chunk of buffers */
|
||||
ulint mem_size) /*!< in: requested size in bytes */
|
||||
ulint mem_size, /*!< in: requested size in bytes */
|
||||
ibool populate) /*!< in: virtual page preallocation */
|
||||
{
|
||||
buf_block_t* block;
|
||||
byte* frame;
|
||||
@@ -1044,7 +1036,7 @@ buf_chunk_init(
|
||||
+ (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE);
|
||||
|
||||
chunk->mem_size = mem_size;
|
||||
chunk->mem = os_mem_alloc_large(&chunk->mem_size);
|
||||
chunk->mem = os_mem_alloc_large(&chunk->mem_size, populate);
|
||||
|
||||
if (UNIV_UNLIKELY(chunk->mem == NULL)) {
|
||||
|
||||
@@ -1254,6 +1246,7 @@ buf_pool_init_instance(
|
||||
/*===================*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint buf_pool_size, /*!< in: size in bytes */
|
||||
ibool populate, /*!< in: virtual page preallocation */
|
||||
ulint instance_no) /*!< in: id of the instance */
|
||||
{
|
||||
ulint i;
|
||||
@@ -1286,7 +1279,7 @@ buf_pool_init_instance(
|
||||
|
||||
UT_LIST_INIT(buf_pool->free);
|
||||
|
||||
if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) {
|
||||
if (!buf_chunk_init(buf_pool, chunk, buf_pool_size, populate)) {
|
||||
mem_free(chunk);
|
||||
mem_free(buf_pool);
|
||||
|
||||
@@ -1381,6 +1374,7 @@ ulint
|
||||
buf_pool_init(
|
||||
/*==========*/
|
||||
ulint total_size, /*!< in: size of the total pool in bytes */
|
||||
ibool populate, /*!< in: virtual page preallocation */
|
||||
ulint n_instances) /*!< in: number of instances */
|
||||
{
|
||||
ulint i;
|
||||
@@ -1398,7 +1392,7 @@ buf_pool_init(
|
||||
for (i = 0; i < n_instances; i++) {
|
||||
buf_pool_t* ptr = &buf_pool_ptr[i];
|
||||
|
||||
if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) {
|
||||
if (buf_pool_init_instance(ptr, size, populate, i) != DB_SUCCESS) {
|
||||
|
||||
/* Free all the instances created so far. */
|
||||
buf_pool_free(i);
|
||||
@@ -4973,7 +4967,7 @@ buf_stats_aggregate_pool_info(
|
||||
Collect buffer pool stats information for a buffer pool. Also
|
||||
record aggregated stats if there are more than one buffer pool
|
||||
in the server */
|
||||
static
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_stats_get_pool_info(
|
||||
/*====================*/
|
||||
|
||||
@@ -2384,7 +2384,7 @@ buf_LRU_free_one_page(
|
||||
#endif
|
||||
mutex_t* block_mutex = buf_page_get_mutex(bpage);
|
||||
|
||||
ut_ad(buf_pool_mutex_own(buf_pool));
|
||||
ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
|
||||
ut_ad(mutex_own(block_mutex));
|
||||
|
||||
if (buf_LRU_block_remove_hashed_page(bpage, TRUE)
|
||||
|
||||
@@ -64,7 +64,7 @@ buf_read_page_handle_error(
|
||||
== BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
/* First unfix and release lock on the bpage */
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
mutex_enter(&buf_pool->LRU_list_mutex);
|
||||
mutex_enter(buf_page_get_mutex(bpage));
|
||||
ut_ad(buf_page_get_io_fix(bpage) == BUF_IO_READ);
|
||||
ut_ad(bpage->buf_fix_count == 0);
|
||||
@@ -85,7 +85,7 @@ buf_read_page_handle_error(
|
||||
buf_pool->n_pend_reads--;
|
||||
|
||||
mutex_exit(buf_page_get_mutex(bpage));
|
||||
buf_pool_mutex_exit(buf_pool);
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
|
||||
@@ -874,7 +874,7 @@ extern "C" UNIV_INTERN
|
||||
ibool
|
||||
thd_is_replication_slave_thread(
|
||||
/*============================*/
|
||||
void* thd) /*!< in: thread handle (THD*) */
|
||||
const void* thd) /*!< in: thread handle (THD*) */
|
||||
{
|
||||
return((ibool) thd_slave_thread((THD*) thd));
|
||||
}
|
||||
@@ -2465,6 +2465,122 @@ ha_innobase::init_table_handle_for_HANDLER(void)
|
||||
reset_template();
|
||||
}
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
/* The last read master log coordinates in the slave info file */
|
||||
static char master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
|
||||
static int master_log_pos;
|
||||
/* The slave relay log coordinates in the slave info file after startup */
|
||||
static char original_relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
|
||||
static int original_relay_log_pos;
|
||||
/* The master log coordinates in the slave info file after startup */
|
||||
static char original_master_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN] = "";
|
||||
static int original_master_log_pos;
|
||||
#endif
|
||||
|
||||
/*****************************************************************//**
|
||||
Overwrites the MySQL relay log info file with the current master and relay log
|
||||
coordinates from InnoDB. Skips overwrite if the master log position did not
|
||||
change from the last overwrite. If the InnoDB master log position is equal
|
||||
to position that was read from the info file on startup before any overwrites,
|
||||
restores the original positions. */
|
||||
static
|
||||
void
|
||||
innobase_do_overwrite_relay_log_info(void)
|
||||
/*======================================*/
|
||||
{
|
||||
#ifdef HAVE_REPLICATION
|
||||
char info_fname[FN_REFLEN];
|
||||
File info_fd = -1;
|
||||
int error = 0;
|
||||
char buff[FN_REFLEN*2+22*2+4];
|
||||
char *relay_info_log_pos;
|
||||
size_t buf_len;
|
||||
|
||||
if (master_log_fname[0] == '\0') {
|
||||
fprintf(stderr,
|
||||
"InnoDB: something wrong with relay-log.info. "
|
||||
"InnoDB will not overwrite it.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(master_log_fname, trx_sys_mysql_master_log_name) == 0
|
||||
&& master_log_pos == trx_sys_mysql_master_log_pos) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: InnoDB and relay-log.info are synchronized. "
|
||||
"InnoDB will not overwrite it.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If we overwrite the file back to the original master log position,
|
||||
restore the original relay log position too. This is required because
|
||||
we might have rolled back a prepared transaction and restored the
|
||||
original master log position from the InnoDB trx sys header, but the
|
||||
corresponding relay log position points to an already-purged file. */
|
||||
if (strcmp(original_master_log_fname, trx_sys_mysql_master_log_name)
|
||||
== 0
|
||||
&& (original_master_log_pos == trx_sys_mysql_master_log_pos)) {
|
||||
|
||||
strncpy(trx_sys_mysql_relay_log_name, original_relay_log_fname,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
trx_sys_mysql_relay_log_pos = original_relay_log_pos;
|
||||
}
|
||||
|
||||
fn_format(info_fname, relay_log_info_file, mysql_data_home, "",
|
||||
MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH);
|
||||
|
||||
if (access(info_fname, F_OK)) {
|
||||
/* File does not exist */
|
||||
error = 1;
|
||||
goto skip_overwrite;
|
||||
}
|
||||
|
||||
/* File exists */
|
||||
info_fd = my_open(info_fname, O_RDWR|O_BINARY, MYF(MY_WME));
|
||||
if (info_fd < 0) {
|
||||
error = 1;
|
||||
goto skip_overwrite;
|
||||
}
|
||||
|
||||
relay_info_log_pos = strmov(buff, trx_sys_mysql_relay_log_name);
|
||||
*relay_info_log_pos ++= '\n';
|
||||
relay_info_log_pos = longlong2str(trx_sys_mysql_relay_log_pos,
|
||||
relay_info_log_pos, 10);
|
||||
*relay_info_log_pos ++= '\n';
|
||||
relay_info_log_pos = strmov(relay_info_log_pos,
|
||||
trx_sys_mysql_master_log_name);
|
||||
*relay_info_log_pos ++= '\n';
|
||||
relay_info_log_pos = longlong2str(trx_sys_mysql_master_log_pos,
|
||||
relay_info_log_pos, 10);
|
||||
*relay_info_log_pos = '\n';
|
||||
|
||||
buf_len = (relay_info_log_pos - buff) + 1;
|
||||
if (my_write(info_fd, (uchar *)buff, buf_len, MY_WME) != buf_len) {
|
||||
error = 1;
|
||||
} else if (my_sync(info_fd, MY_WME)) {
|
||||
error = 1;
|
||||
}
|
||||
|
||||
if (info_fd >= 0) {
|
||||
my_close(info_fd, MYF(0));
|
||||
}
|
||||
|
||||
strncpy(master_log_fname, trx_sys_mysql_relay_log_name,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
master_log_pos = trx_sys_mysql_master_log_pos;
|
||||
|
||||
skip_overwrite:
|
||||
if (error) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: ERROR: error occured during overwriting "
|
||||
"relay-log.info.\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"InnoDB: relay-log.info was overwritten.\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************//**
|
||||
Opens an InnoDB database.
|
||||
@return 0 on success, error code on failure */
|
||||
@@ -2598,12 +2714,13 @@ innobase_init(
|
||||
#ifdef HAVE_REPLICATION
|
||||
#ifdef MYSQL_SERVER
|
||||
/* read master log position from relay-log.info if exists */
|
||||
char fname[FN_REFLEN+128];
|
||||
int pos;
|
||||
char info_fname[FN_REFLEN];
|
||||
char relay_log_fname[TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN];
|
||||
int relay_log_pos;
|
||||
int info_fd;
|
||||
IO_CACHE info_file;
|
||||
|
||||
fname[0] = '\0';
|
||||
info_fname[0] = '\0';
|
||||
|
||||
if(innobase_overwrite_relay_log_info) {
|
||||
|
||||
@@ -2612,13 +2729,14 @@ innobase_init(
|
||||
" Updates by other storage engines may not be synchronized.\n");
|
||||
|
||||
bzero((char*) &info_file, sizeof(info_file));
|
||||
fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
|
||||
fn_format(info_fname, relay_log_info_file, mysql_data_home, "", 4+32);
|
||||
|
||||
int error=0;
|
||||
|
||||
if (!access(fname,F_OK)) {
|
||||
if (!access(info_fname,F_OK)) {
|
||||
/* exist */
|
||||
if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
|
||||
if ((info_fd = my_open(info_fname, O_RDWR | O_BINARY,
|
||||
MYF(MY_WME))) < 0) {
|
||||
error=1;
|
||||
} else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
|
||||
READ_CACHE, 0L, 0, MYF(MY_WME))) {
|
||||
@@ -2629,16 +2747,18 @@ innobase_init(
|
||||
relay_info_error:
|
||||
if (info_fd >= 0)
|
||||
my_close(info_fd, MYF(0));
|
||||
fname[0] = '\0';
|
||||
master_log_fname[0] = '\0';
|
||||
goto skip_relay;
|
||||
}
|
||||
} else {
|
||||
fname[0] = '\0';
|
||||
master_log_fname[0] = '\0';
|
||||
goto skip_relay;
|
||||
}
|
||||
|
||||
if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") || /* dummy (it is relay-log) */
|
||||
init_intvar_from_file(&pos, &info_file, BIN_LOG_HEADER_SIZE)) {
|
||||
if (init_strvar_from_file(relay_log_fname, sizeof(relay_log_fname),
|
||||
&info_file, "")
|
||||
|| /* dummy (it is relay-log) */ init_intvar_from_file(
|
||||
&relay_log_pos, &info_file, BIN_LOG_HEADER_SIZE)) {
|
||||
end_io_cache(&info_file);
|
||||
error=1;
|
||||
goto relay_info_error;
|
||||
@@ -2647,13 +2767,19 @@ relay_info_error:
|
||||
fprintf(stderr,
|
||||
"InnoDB: relay-log.info is detected.\n"
|
||||
"InnoDB: relay log: position %u, file name %s\n",
|
||||
pos, fname);
|
||||
relay_log_pos, relay_log_fname);
|
||||
|
||||
strncpy(trx_sys_mysql_relay_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
trx_sys_mysql_relay_log_pos = (ib_int64_t) pos;
|
||||
strncpy(trx_sys_mysql_relay_log_name, relay_log_fname,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
trx_sys_mysql_relay_log_pos = (ib_int64_t) relay_log_pos;
|
||||
|
||||
if (init_strvar_from_file(fname, sizeof(fname), &info_file, "") ||
|
||||
init_intvar_from_file(&pos, &info_file, 0)) {
|
||||
strncpy(original_relay_log_fname, relay_log_fname,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
original_relay_log_pos = relay_log_pos;
|
||||
|
||||
if (init_strvar_from_file(master_log_fname, sizeof(master_log_fname),
|
||||
&info_file, "")
|
||||
|| init_intvar_from_file(&master_log_pos, &info_file, 0)) {
|
||||
end_io_cache(&info_file);
|
||||
error=1;
|
||||
goto relay_info_error;
|
||||
@@ -2661,10 +2787,15 @@ relay_info_error:
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: master log: position %u, file name %s\n",
|
||||
pos, fname);
|
||||
master_log_pos, master_log_fname);
|
||||
|
||||
strncpy(trx_sys_mysql_master_log_name, fname, TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
trx_sys_mysql_master_log_pos = (ib_int64_t) pos;
|
||||
strncpy(trx_sys_mysql_master_log_name, master_log_fname,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
trx_sys_mysql_master_log_pos = (ib_int64_t) master_log_pos;
|
||||
|
||||
strncpy(original_master_log_fname, master_log_fname,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
original_master_log_pos = master_log_pos;
|
||||
|
||||
end_io_cache(&info_file);
|
||||
if (info_fd >= 0)
|
||||
@@ -2999,75 +3130,9 @@ innobase_change_buffering_inited_ok:
|
||||
goto mem_free_and_error;
|
||||
}
|
||||
|
||||
#ifdef HAVE_REPLICATION
|
||||
#ifdef MYSQL_SERVER
|
||||
if(innobase_overwrite_relay_log_info) {
|
||||
/* If InnoDB progressed from relay-log.info, overwrite it */
|
||||
if (fname[0] == '\0') {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Something is wrong with the file relay-info.log. InnoDB will not overwrite it.\n");
|
||||
} else if (0 != strcmp(fname, trx_sys_mysql_master_log_name)
|
||||
|| pos != trx_sys_mysql_master_log_pos) {
|
||||
/* Overwrite relay-log.info */
|
||||
bzero((char*) &info_file, sizeof(info_file));
|
||||
fn_format(fname, relay_log_info_file, mysql_data_home, "", 4+32);
|
||||
|
||||
int error = 0;
|
||||
|
||||
if (!access(fname,F_OK)) {
|
||||
/* exist */
|
||||
if ((info_fd = my_open(fname, O_RDWR|O_BINARY, MYF(MY_WME))) < 0) {
|
||||
error = 1;
|
||||
} else if (init_io_cache(&info_file, info_fd, IO_SIZE*2,
|
||||
WRITE_CACHE, 0L, 0, MYF(MY_WME))) {
|
||||
error = 1;
|
||||
}
|
||||
|
||||
if (error) {
|
||||
if (info_fd >= 0)
|
||||
my_close(info_fd, MYF(0));
|
||||
goto skip_overwrite;
|
||||
}
|
||||
} else {
|
||||
error = 1;
|
||||
goto skip_overwrite;
|
||||
}
|
||||
|
||||
char buff[FN_REFLEN*2+22*2+4], *pos;
|
||||
|
||||
my_b_seek(&info_file, 0L);
|
||||
pos=strmov(buff, trx_sys_mysql_relay_log_name);
|
||||
*pos++='\n';
|
||||
pos=longlong10_to_str(trx_sys_mysql_relay_log_pos, pos, 10);
|
||||
*pos++='\n';
|
||||
pos=strmov(pos, trx_sys_mysql_master_log_name);
|
||||
*pos++='\n';
|
||||
pos=longlong10_to_str(trx_sys_mysql_master_log_pos, pos, 10);
|
||||
*pos='\n';
|
||||
|
||||
if (my_b_write(&info_file, (uchar*) buff, (size_t) (pos-buff)+1))
|
||||
error = 1;
|
||||
if (flush_io_cache(&info_file))
|
||||
error = 1;
|
||||
|
||||
end_io_cache(&info_file);
|
||||
if (info_fd >= 0)
|
||||
my_close(info_fd, MYF(0));
|
||||
skip_overwrite:
|
||||
if (error) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: ERROR: An error occurred while overwriting relay-log.info.\n");
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"InnoDB: The file relay-log.info was successfully overwritten.\n");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
"InnoDB: InnoDB and relay-log.info are synchronized. InnoDB will not overwrite it.\n");
|
||||
innobase_do_overwrite_relay_log_info();
|
||||
}
|
||||
}
|
||||
#endif /* MYSQL_SERVER */
|
||||
#endif /* HAVE_REPLICATION */
|
||||
|
||||
innobase_old_blocks_pct = buf_LRU_old_ratio_update(
|
||||
innobase_old_blocks_pct, TRUE);
|
||||
@@ -3170,6 +3235,32 @@ innobase_alter_table_flags(
|
||||
| HA_INPLACE_ADD_PK_INDEX_NO_READ_WRITE);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Copy the current replication position from MySQL to a transaction. */
|
||||
static
|
||||
void
|
||||
innobase_copy_repl_coords_to_trx(
|
||||
/*=============================*/
|
||||
const THD* thd, /*!< in: thread handle */
|
||||
trx_t* trx) /*!< in/out: transaction */
|
||||
{
|
||||
if (thd && thd_is_replication_slave_thread(thd)) {
|
||||
/* Update the replication position info inside InnoDB.
|
||||
In embedded server, does nothing. */
|
||||
const char *log_file_name, *group_relay_log_name;
|
||||
ulonglong log_pos, relay_log_pos;
|
||||
bool res = rpl_get_position_info(&log_file_name, &log_pos,
|
||||
&group_relay_log_name,
|
||||
&relay_log_pos);
|
||||
if (res) {
|
||||
trx->mysql_master_log_file_name = log_file_name;
|
||||
trx->mysql_master_log_pos = (ib_int64_t)log_pos;
|
||||
trx->mysql_relay_log_file_name = group_relay_log_name;
|
||||
trx->mysql_relay_log_pos = (ib_int64_t)relay_log_pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Commits a transaction in an InnoDB database. */
|
||||
static
|
||||
@@ -3179,27 +3270,12 @@ innobase_commit_low(
|
||||
trx_t* trx) /*!< in: transaction handle */
|
||||
{
|
||||
if (trx_is_started(trx)) {
|
||||
#ifdef HAVE_REPLICATION
|
||||
#ifdef MYSQL_SERVER
|
||||
THD *thd=current_thd;
|
||||
|
||||
if (thd && thd_is_replication_slave_thread(thd)) {
|
||||
/* Update the replication position info inside InnoDB.
|
||||
In embedded server, does nothing. */
|
||||
const char *log_file_name, *group_relay_log_name;
|
||||
ulonglong log_pos, relay_log_pos;
|
||||
bool res = rpl_get_position_info(&log_file_name, &log_pos,
|
||||
&group_relay_log_name,
|
||||
&relay_log_pos);
|
||||
if (res) {
|
||||
trx->mysql_master_log_file_name = log_file_name;
|
||||
trx->mysql_master_log_pos = (ib_int64_t)log_pos;
|
||||
trx->mysql_relay_log_file_name = group_relay_log_name;
|
||||
trx->mysql_relay_log_pos = (ib_int64_t)relay_log_pos;
|
||||
}
|
||||
}
|
||||
#endif /* MYSQL_SERVER */
|
||||
#endif /* HAVE_REPLICATION */
|
||||
/* Save the current replication position for write to trx sys
|
||||
header for undo purposes, see the comment at corresponding call
|
||||
at innobase_xa_prepare(). */
|
||||
|
||||
innobase_copy_repl_coords_to_trx(current_thd, trx);
|
||||
|
||||
trx_commit_for_mysql(trx);
|
||||
}
|
||||
@@ -3399,6 +3475,9 @@ innobase_commit(
|
||||
if (all
|
||||
|| (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
|
||||
|
||||
DBUG_EXECUTE_IF("crash_innodb_before_commit",
|
||||
DBUG_SUICIDE(););
|
||||
|
||||
/* Run the fast part of commit if we did not already. */
|
||||
if (!trx_is_active_commit_ordered(trx)) {
|
||||
innobase_commit_ordered_2(trx, thd);
|
||||
@@ -11559,7 +11638,27 @@ innobase_xa_prepare(
|
||||
|
||||
ut_ad(trx_is_registered_for_2pc(trx));
|
||||
|
||||
/* Update the replication position info in current trx. This
|
||||
is different from the binlog position update that happens
|
||||
during XA COMMIT. In contrast to that, the slave position is
|
||||
an actual part of the changes made by this transaction and thus
|
||||
must be updated in the XA PREPARE stage. Since the trx sys
|
||||
header page changes are not undo-logged, again store this
|
||||
position in a different field in the XA COMMIT stage, so that
|
||||
it might be used in case of rollbacks. */
|
||||
|
||||
/* Since currently there might be only one slave SQL thread, we
|
||||
don't need to take any precautions (e.g. prepare_commit_mutex)
|
||||
to ensure position ordering. Revisit this in 5.6 which has
|
||||
both the multi-threaded replication to cause us problems and
|
||||
the group commit to solve them. */
|
||||
|
||||
innobase_copy_repl_coords_to_trx(thd, trx);
|
||||
|
||||
error = (int) trx_prepare_for_mysql(trx);
|
||||
|
||||
DBUG_EXECUTE_IF("crash_innodb_after_prepare",
|
||||
DBUG_SUICIDE(););
|
||||
} else {
|
||||
/* We just mark the SQL statement ended and do not do a
|
||||
transaction prepare */
|
||||
@@ -11652,6 +11751,22 @@ innobase_rollback_by_xid(
|
||||
if (trx) {
|
||||
int ret = innobase_rollback_trx(trx);
|
||||
trx_free_for_background(trx);
|
||||
|
||||
if (innobase_overwrite_relay_log_info) {
|
||||
|
||||
/* On rollback of a prepared transaction revert the
|
||||
current slave positions to the ones recorded by the
|
||||
last COMMITTed transaction. This has an effect of
|
||||
undoing the position change caused by the transaction
|
||||
being rolled back. Assumes single-threaded slave SQL
|
||||
thread. If the server has non-master write traffic
|
||||
with XA rollbacks, this will cause additional spurious
|
||||
slave info log overwrites, which should be harmless. */
|
||||
|
||||
trx_sys_print_committed_mysql_master_log_pos();
|
||||
innobase_do_overwrite_relay_log_info();
|
||||
}
|
||||
|
||||
return(ret);
|
||||
} else {
|
||||
return(XAER_NOTA);
|
||||
@@ -12670,6 +12785,12 @@ static MYSQL_SYSVAR_LONGLONG(buffer_pool_size, innobase_buffer_pool_size,
|
||||
"The size of the memory buffer InnoDB uses to cache data and indexes of its tables.",
|
||||
NULL, NULL, 128*1024*1024L, 5*1024*1024L, LONGLONG_MAX, 1024*1024L);
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(buffer_pool_populate, srv_buf_pool_populate,
|
||||
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
|
||||
"Preallocate (pre-fault) the page frames required for the mapping "
|
||||
"established by the buffer pool memory region. Disabled by default.",
|
||||
NULL, NULL, FALSE);
|
||||
|
||||
static MYSQL_SYSVAR_LONG(buffer_pool_instances, innobase_buffer_pool_instances,
|
||||
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
|
||||
"Number of buffer pool instances, set to higher value on high-end machines to increase scalability",
|
||||
@@ -13049,6 +13170,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||
MYSQL_SYSVAR(additional_mem_pool_size),
|
||||
MYSQL_SYSVAR(autoextend_increment),
|
||||
MYSQL_SYSVAR(buffer_pool_size),
|
||||
MYSQL_SYSVAR(buffer_pool_populate),
|
||||
MYSQL_SYSVAR(buffer_pool_instances),
|
||||
MYSQL_SYSVAR(buffer_pool_shm_key),
|
||||
MYSQL_SYSVAR(buffer_pool_shm_checksum),
|
||||
@@ -13194,7 +13316,10 @@ i_s_innodb_buffer_pool_pages,
|
||||
i_s_innodb_buffer_pool_pages_index,
|
||||
i_s_innodb_buffer_pool_pages_blob,
|
||||
i_s_innodb_admin_command,
|
||||
i_s_innodb_changed_pages
|
||||
i_s_innodb_changed_pages,
|
||||
i_s_innodb_buffer_page,
|
||||
i_s_innodb_buffer_page_lru,
|
||||
i_s_innodb_buffer_stats
|
||||
maria_declare_plugin_end;
|
||||
|
||||
/** @brief Initialize the default value of innodb_commit_concurrency.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,5 +52,8 @@ extern struct st_maria_plugin i_s_innodb_buffer_pool_pages;
|
||||
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_index;
|
||||
extern struct st_maria_plugin i_s_innodb_buffer_pool_pages_blob;
|
||||
extern struct st_maria_plugin i_s_innodb_changed_pages;
|
||||
extern struct st_maria_plugin i_s_innodb_buffer_page;
|
||||
extern struct st_maria_plugin i_s_innodb_buffer_page_lru;
|
||||
extern struct st_maria_plugin i_s_innodb_buffer_stats;
|
||||
|
||||
#endif /* i_s_h */
|
||||
|
||||
@@ -3650,11 +3650,18 @@ bitmap_fail:
|
||||
|
||||
root = ibuf_tree_root_get(&mtr);
|
||||
|
||||
err = btr_cur_pessimistic_insert(BTR_NO_LOCKING_FLAG
|
||||
| BTR_NO_UNDO_LOG_FLAG,
|
||||
cursor,
|
||||
ibuf_entry, &ins_rec,
|
||||
&dummy_big_rec, 0, thr, &mtr);
|
||||
err = btr_cur_optimistic_insert(
|
||||
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
|
||||
cursor, ibuf_entry, &ins_rec,
|
||||
&dummy_big_rec, 0, thr, &mtr);
|
||||
|
||||
if (err == DB_FAIL) {
|
||||
err = btr_cur_pessimistic_insert(
|
||||
BTR_NO_LOCKING_FLAG | BTR_NO_UNDO_LOG_FLAG,
|
||||
cursor, ibuf_entry, &ins_rec,
|
||||
&dummy_big_rec, 0, thr, &mtr);
|
||||
}
|
||||
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
ibuf_size_update(root, &mtr);
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
@@ -68,7 +68,10 @@ Created 11/5/1995 Heikki Tuuri
|
||||
position of the block. */
|
||||
/* @} */
|
||||
|
||||
#define MAX_BUFFER_POOLS 64 /*!< The maximum number of buffer
|
||||
#define MAX_BUFFER_POOLS_BITS 6 /*!< Number of bits to representing
|
||||
a buffer pool ID */
|
||||
#define MAX_BUFFER_POOLS (1 << MAX_BUFFER_POOLS_BITS)
|
||||
/*!< The maximum number of buffer
|
||||
pools that can be defined */
|
||||
|
||||
#define BUF_POOL_WATCH_SIZE 1 /*!< Maximum number of concurrent
|
||||
@@ -233,6 +236,7 @@ ulint
|
||||
buf_pool_init(
|
||||
/*=========*/
|
||||
ulint size, /*!< in: Size of the total pool in bytes */
|
||||
ibool populate, /*!< in: Force virtual page preallocation */
|
||||
ulint n_instances); /*!< in: Number of instances */
|
||||
/********************************************************************//**
|
||||
Frees the buffer pool at shutdown. This must not be invoked before
|
||||
@@ -778,6 +782,18 @@ void
|
||||
buf_print_io(
|
||||
/*=========*/
|
||||
FILE* file); /*!< in: file where to print */
|
||||
/*******************************************************************//**
|
||||
Collect buffer pool stats information for a buffer pool. Also
|
||||
record aggregated stats if there are more than one buffer pool
|
||||
in the server */
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_stats_get_pool_info(
|
||||
/*====================*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool */
|
||||
ulint pool_id, /*!< in: buffer pool ID */
|
||||
buf_pool_info_t* all_pool_info); /*!< in/out: buffer pool info
|
||||
to fill */
|
||||
/*********************************************************************//**
|
||||
Returns the ratio in percents of modified pages in the buffer pool /
|
||||
database pages in the buffer pool.
|
||||
@@ -1364,12 +1380,25 @@ void
|
||||
buf_get_total_stat(
|
||||
/*===============*/
|
||||
buf_pool_stat_t*tot_stat); /*!< out: buffer pool stats */
|
||||
/*********************************************************************//**
|
||||
Get the nth chunk's buffer block in the specified buffer pool.
|
||||
@return the nth chunk's buffer block. */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_get_nth_chunk_block(
|
||||
/*====================*/
|
||||
const buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint n, /*!< in: nth chunk in the buffer pool */
|
||||
ulint* chunk_size); /*!< in: chunk size */
|
||||
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/** The common buffer control block structure
|
||||
for compressed and uncompressed frames */
|
||||
|
||||
/** Number of bits used for buffer page states. */
|
||||
#define BUF_PAGE_STATE_BITS 3
|
||||
|
||||
struct buf_page_struct{
|
||||
/** @name General fields
|
||||
None of these bit-fields must be modified without holding
|
||||
@@ -1384,7 +1413,8 @@ struct buf_page_struct{
|
||||
unsigned offset:32; /*!< page number; also protected
|
||||
by buf_pool->mutex. */
|
||||
|
||||
unsigned state:3; /*!< state of the control block; also
|
||||
unsigned state:BUF_PAGE_STATE_BITS;
|
||||
/*!< state of the control block; also
|
||||
protected by buf_pool->mutex.
|
||||
State transitions from
|
||||
BUF_BLOCK_READY_FOR_USE to
|
||||
|
||||
@@ -36,6 +36,8 @@ Created 11/5/1995 Heikki Tuuri
|
||||
#include "buf0lru.h"
|
||||
#include "buf0rea.h"
|
||||
#include "srv0srv.h"
|
||||
#include "buf0types.h"
|
||||
|
||||
/*********************************************************************//**
|
||||
Gets the current size of buffer buf_pool in bytes.
|
||||
@return size in bytes */
|
||||
@@ -1354,4 +1356,21 @@ buf_pool_page_hash_x_unlock_all(void)
|
||||
rw_lock_x_unlock(&buf_pool->page_hash_latch);
|
||||
}
|
||||
}
|
||||
/*********************************************************************//**
|
||||
Get the nth chunk's buffer block in the specified buffer pool.
|
||||
@return the nth chunk's buffer block. */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_get_nth_chunk_block(
|
||||
/*====================*/
|
||||
const buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
ulint n, /*!< in: nth chunk in the buffer pool */
|
||||
ulint* chunk_size) /*!< in: chunk size */
|
||||
{
|
||||
const buf_chunk_t* chunk;
|
||||
|
||||
chunk = buf_pool->chunks + n;
|
||||
*chunk_size = chunk->size;
|
||||
return(chunk->blocks);
|
||||
}
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
@@ -144,6 +144,8 @@ extern fil_addr_t fil_addr_null;
|
||||
#define FIL_PAGE_TYPE_BLOB 10 /*!< Uncompressed BLOB page */
|
||||
#define FIL_PAGE_TYPE_ZBLOB 11 /*!< First compressed BLOB page */
|
||||
#define FIL_PAGE_TYPE_ZBLOB2 12 /*!< Subsequent compressed BLOB page */
|
||||
#define FIL_PAGE_TYPE_LAST FIL_PAGE_TYPE_ZBLOB2
|
||||
/*!< Last page type */
|
||||
/* @} */
|
||||
|
||||
/** Space types @{ */
|
||||
|
||||
@@ -111,7 +111,7 @@ UNIV_INTERN
|
||||
ibool
|
||||
thd_is_replication_slave_thread(
|
||||
/*============================*/
|
||||
void* thd); /*!< in: thread handle (THD*) */
|
||||
const void* thd); /*!< in: thread handle (THD*) */
|
||||
|
||||
/******************************************************************//**
|
||||
Returns true if the transaction this thread is processing has edited
|
||||
|
||||
@@ -41,6 +41,9 @@ Created 12/9/1995 Heikki Tuuri
|
||||
#include "sync0rw.h"
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
/* Type used for all log sequence number storage and arithmetics */
|
||||
typedef ib_uint64_t lsn_t;
|
||||
|
||||
/** Redo log buffer */
|
||||
typedef struct log_struct log_t;
|
||||
/** Redo log group */
|
||||
|
||||
@@ -58,7 +58,8 @@ UNIV_INTERN
|
||||
void*
|
||||
os_mem_alloc_large(
|
||||
/*===============*/
|
||||
ulint* n); /*!< in/out: number of bytes */
|
||||
ulint* n, /*!< in/out: number of bytes */
|
||||
ibool populate); /*!< in: virtual page preallocation */
|
||||
/****************************************************************//**
|
||||
Frees large pages memory. */
|
||||
UNIV_INTERN
|
||||
|
||||
@@ -182,6 +182,7 @@ extern my_bool srv_use_sys_malloc;
|
||||
extern ibool srv_use_sys_malloc;
|
||||
#endif /* UNIV_HOTBACKUP */
|
||||
extern ulint srv_buf_pool_size; /*!< requested size in bytes */
|
||||
extern my_bool srv_buf_pool_populate; /*!< virtual page preallocation */
|
||||
extern ulint srv_buf_pool_instances; /*!< requested number of buffer pool instances */
|
||||
extern ulint srv_buf_pool_old_size; /*!< previously requested size */
|
||||
extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
|
||||
|
||||
@@ -342,6 +342,14 @@ void
|
||||
trx_sys_print_mysql_binlog_offset(void);
|
||||
/*===================================*/
|
||||
/*****************************************************************//**
|
||||
Prints to stderr the MySQL master log offset info in the trx system header
|
||||
COMMIT set of fields if the magic number shows it valid and stores it
|
||||
in global variables. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_print_committed_mysql_master_log_pos(void);
|
||||
/*==============================================*/
|
||||
/*****************************************************************//**
|
||||
Prints to stderr the MySQL master log offset info in the trx system header if
|
||||
the magic number shows it valid. */
|
||||
UNIV_INTERN
|
||||
@@ -534,10 +542,16 @@ We must remember this limit in order to keep file compatibility. */
|
||||
//# error "UNIV_PAGE_SIZE < 4096"
|
||||
//#endif
|
||||
/** The offset of the MySQL replication info in the trx system header;
|
||||
this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */
|
||||
this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below. These are
|
||||
written at prepare time and are the main copy. */
|
||||
#define TRX_SYS_MYSQL_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 2000)
|
||||
#define TRX_SYS_MYSQL_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 1500)
|
||||
|
||||
/** The copy of the above which is made at transaction COMMIT time. If binlog
|
||||
crash recovery rollbacks a PREPAREd transaction, they are copied back. */
|
||||
#define TRX_SYS_COMMIT_MASTER_LOG_INFO (UNIV_PAGE_SIZE - 3000)
|
||||
#define TRX_SYS_COMMIT_RELAY_LOG_INFO (UNIV_PAGE_SIZE - 2500)
|
||||
|
||||
/** The offset of the MySQL binlog offset info in the trx system header */
|
||||
#define TRX_SYS_MYSQL_LOG_INFO (UNIV_PAGE_SIZE - 1000)
|
||||
#define TRX_SYS_MYSQL_LOG_MAGIC_N_FLD 0 /*!< magic number which is
|
||||
|
||||
@@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri
|
||||
#define INNODB_VERSION_BUGFIX 8
|
||||
|
||||
#ifndef PERCONA_INNODB_VERSION
|
||||
#define PERCONA_INNODB_VERSION 29.0
|
||||
#define PERCONA_INNODB_VERSION 29.1
|
||||
#endif
|
||||
|
||||
/* The following is the InnoDB version as shown in
|
||||
|
||||
@@ -32,6 +32,12 @@ Created 9/30/1995 Heikki Tuuri
|
||||
#include "ut0mem.h"
|
||||
#include "ut0byte.h"
|
||||
|
||||
/* Linux release version */
|
||||
#if defined(UNIV_LINUX) && defined(_GNU_SOURCE)
|
||||
#include <string.h> /* strverscmp() */
|
||||
#include <sys/utsname.h> /* uname() */
|
||||
#endif
|
||||
|
||||
/* FreeBSD for example has only MAP_ANON, Linux has MAP_ANONYMOUS and
|
||||
MAP_ANON but MAP_ANON is marked as deprecated */
|
||||
#if defined(MAP_ANONYMOUS)
|
||||
@@ -40,6 +46,13 @@ MAP_ANON but MAP_ANON is marked as deprecated */
|
||||
#define OS_MAP_ANON MAP_ANON
|
||||
#endif
|
||||
|
||||
/* Linux's MAP_POPULATE */
|
||||
#if defined(MAP_POPULATE)
|
||||
#define OS_MAP_POPULATE MAP_POPULATE
|
||||
#else
|
||||
#define OS_MAP_POPULATE 0
|
||||
#endif
|
||||
|
||||
UNIV_INTERN ibool os_use_large_pages;
|
||||
/* Large page size. This may be a boot-time option on some platforms */
|
||||
UNIV_INTERN ulint os_large_page_size;
|
||||
@@ -62,6 +75,24 @@ os_proc_get_number(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Retrieve and compare operating system release.
|
||||
@return TRUE if the OS release is equal to, or later than release. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
os_compare_release(
|
||||
/*===============*/
|
||||
const char* release /*!< in: OS release */
|
||||
__attribute__((unused)))
|
||||
{
|
||||
#if defined(UNIV_LINUX) && defined(_GNU_SOURCE)
|
||||
struct utsname name;
|
||||
return uname(&name) == 0 && strverscmp(name.release, release) >= 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Allocates large pages memory.
|
||||
@return allocated memory */
|
||||
@@ -69,7 +100,8 @@ UNIV_INTERN
|
||||
void*
|
||||
os_mem_alloc_large(
|
||||
/*===============*/
|
||||
ulint* n) /*!< in/out: number of bytes */
|
||||
ulint* n, /*!< in/out: number of bytes */
|
||||
ibool populate) /*!< in: virtual page preallocation */
|
||||
{
|
||||
void* ptr;
|
||||
ulint size;
|
||||
@@ -155,12 +187,13 @@ skip:
|
||||
ut_ad(ut_is_2pow(size));
|
||||
size = *n = ut_2pow_round(*n + (size - 1), size);
|
||||
ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | OS_MAP_ANON, -1, 0);
|
||||
MAP_PRIVATE | OS_MAP_ANON |
|
||||
(populate ? OS_MAP_POPULATE : 0), -1, 0);
|
||||
if (UNIV_UNLIKELY(ptr == (void*) -1)) {
|
||||
fprintf(stderr, "InnoDB: mmap(%lu bytes) failed;"
|
||||
" errno %lu\n",
|
||||
(ulong) size, (ulong) errno);
|
||||
ptr = NULL;
|
||||
return(NULL);
|
||||
} else {
|
||||
os_fast_mutex_lock(&ut_list_mutex);
|
||||
ut_total_allocated_memory += size;
|
||||
@@ -168,6 +201,25 @@ skip:
|
||||
UNIV_MEM_ALLOC(ptr, size);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if OS_MAP_ANON && OS_MAP_POPULATE
|
||||
/* MAP_POPULATE is only supported for private mappings
|
||||
since Linux 2.6.23. */
|
||||
populate = populate && !os_compare_release("2.6.23");
|
||||
|
||||
if (populate) {
|
||||
fprintf(stderr, "InnoDB: Warning: mmap(MAP_POPULATE) "
|
||||
"is not supported for private mappings. "
|
||||
"Forcing preallocation by faulting in pages.\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize the entire buffer to force the allocation
|
||||
of physical memory page frames. */
|
||||
if (populate) {
|
||||
memset(ptr, '\0', size);
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -781,12 +781,18 @@ page_copy_rec_list_start(
|
||||
if (UNIV_LIKELY_NULL(new_page_zip)) {
|
||||
mtr_set_log_mode(mtr, log_mode);
|
||||
|
||||
DBUG_EXECUTE_IF("page_copy_rec_list_start_compress_fail",
|
||||
goto zip_reorganize;);
|
||||
|
||||
if (UNIV_UNLIKELY
|
||||
(!page_zip_compress(new_page_zip, new_page, index, mtr))) {
|
||||
ulint ret_pos;
|
||||
#ifndef DBUG_OFF
|
||||
zip_reorganize:
|
||||
#endif /* DBUG_OFF */
|
||||
/* Before trying to reorganize the page,
|
||||
store the number of preceding records on the page. */
|
||||
ulint ret_pos
|
||||
= page_rec_get_n_recs_before(ret);
|
||||
ret_pos = page_rec_get_n_recs_before(ret);
|
||||
/* Before copying, "ret" was the predecessor
|
||||
of the predefined supremum record. If it was
|
||||
the predefined infimum record, then it would
|
||||
@@ -807,15 +813,10 @@ page_copy_rec_list_start(
|
||||
btr_blob_dbg_add(new_page, index,
|
||||
"copy_start_reorg_fail");
|
||||
return(NULL);
|
||||
} else {
|
||||
/* The page was reorganized:
|
||||
Seek to ret_pos. */
|
||||
ret = new_page + PAGE_NEW_INFIMUM;
|
||||
|
||||
do {
|
||||
ret = rec_get_next_ptr(ret, TRUE);
|
||||
} while (--ret_pos);
|
||||
}
|
||||
|
||||
/* The page was reorganized: Seek to ret_pos. */
|
||||
ret = page_rec_get_nth(new_page, ret_pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2181,9 +2181,16 @@ row_ins_index_entry_low(
|
||||
|
||||
goto function_exit;
|
||||
}
|
||||
err = btr_cur_pessimistic_insert(
|
||||
|
||||
err = btr_cur_optimistic_insert(
|
||||
0, &cursor, entry, &insert_rec, &big_rec,
|
||||
n_ext, thr, &mtr);
|
||||
|
||||
if (err == DB_FAIL) {
|
||||
err = btr_cur_pessimistic_insert(
|
||||
0, &cursor, entry, &insert_rec,
|
||||
&big_rec, n_ext, thr, &mtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1254,11 +1254,25 @@ row_merge_read_clustered_index(
|
||||
goto err_exit;
|
||||
}
|
||||
|
||||
/* Store the cursor position on the last user
|
||||
record on the page. */
|
||||
btr_pcur_move_to_prev_on_page(&pcur);
|
||||
/* Leaf pages must never be empty, unless
|
||||
this is the only page in the index tree. */
|
||||
ut_ad(btr_pcur_is_on_user_rec(&pcur)
|
||||
|| buf_block_get_page_no(
|
||||
btr_pcur_get_block(&pcur))
|
||||
== clust_index->page);
|
||||
|
||||
btr_pcur_store_position(&pcur, &mtr);
|
||||
mtr_commit(&mtr);
|
||||
mtr_start(&mtr);
|
||||
/* Restore position on the record, or its
|
||||
predecessor if the record was purged
|
||||
meanwhile. */
|
||||
btr_pcur_restore_position(BTR_SEARCH_LEAF,
|
||||
&pcur, &mtr);
|
||||
/* Move to the successor of the original record. */
|
||||
has_next = btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
||||
}
|
||||
|
||||
@@ -2720,7 +2734,7 @@ row_merge_build_indexes(
|
||||
|
||||
merge_files = mem_alloc(n_indexes * sizeof *merge_files);
|
||||
block_size = 3 * merge_sort_block_size;
|
||||
block_mem = os_mem_alloc_large(&block_size);
|
||||
block_mem = os_mem_alloc_large(&block_size, FALSE);
|
||||
|
||||
for (i = 0; i < UT_ARR_SIZE(block); i++) {
|
||||
block[i] = (row_merge_block_t ) ((byte *) block_mem +
|
||||
|
||||
@@ -232,6 +232,8 @@ UNIV_INTERN const byte* srv_latin1_ordering;
|
||||
UNIV_INTERN my_bool srv_use_sys_malloc = TRUE;
|
||||
/* requested size in kilobytes */
|
||||
UNIV_INTERN ulint srv_buf_pool_size = ULINT_MAX;
|
||||
/* force virtual page preallocation (prefault) */
|
||||
UNIV_INTERN my_bool srv_buf_pool_populate = FALSE;
|
||||
/* requested number of buffer pool instances */
|
||||
UNIV_INTERN ulint srv_buf_pool_instances = 1;
|
||||
/* previously requested size */
|
||||
|
||||
@@ -1543,7 +1543,8 @@ innobase_start_or_create_for_mysql(void)
|
||||
((double) srv_buf_pool_size) / (1024 * 1024));
|
||||
}
|
||||
|
||||
err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances);
|
||||
err = buf_pool_init(srv_buf_pool_size, (ibool) srv_buf_pool_populate,
|
||||
srv_buf_pool_instances);
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
||||
@@ -959,8 +959,31 @@ trx_sys_print_mysql_binlog_offset(void)
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Prints to stderr the MySQL master log offset info in the trx system header if
|
||||
the magic number shows it valid. */
|
||||
Reads the log coordinates at the given offset in the trx sys header. */
|
||||
static
|
||||
void
|
||||
trx_sys_read_log_pos(
|
||||
/*=================*/
|
||||
const trx_sysf_t* sys_header, /*!< in: the trx sys header */
|
||||
uint header_offset, /*!< in: coord offset in the
|
||||
header */
|
||||
char* log_fn, /*!< out: the log file name */
|
||||
ib_int64_t* log_pos) /*!< out: the log poistion */
|
||||
{
|
||||
ut_memcpy(log_fn, sys_header + header_offset + TRX_SYS_MYSQL_LOG_NAME,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
|
||||
*log_pos =
|
||||
(((ib_int64_t)mach_read_from_4(sys_header + header_offset
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
|
||||
+ mach_read_from_4(sys_header + header_offset
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Prints to stderr the MySQL master log offset info in the trx system header
|
||||
PREPARE set of fields if the magic number shows it valid and stores it
|
||||
in global variables. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_print_mysql_master_log_pos(void)
|
||||
@@ -982,60 +1005,79 @@ trx_sys_print_mysql_master_log_pos(void)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy the master log position info to global variables we can
|
||||
use in ha_innobase.cc to initialize glob_mi to right values */
|
||||
trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_MASTER_LOG_INFO,
|
||||
trx_sys_mysql_master_log_name,
|
||||
&trx_sys_mysql_master_log_pos);
|
||||
|
||||
trx_sys_read_log_pos(sys_header, TRX_SYS_MYSQL_RELAY_LOG_INFO,
|
||||
trx_sys_mysql_relay_log_name,
|
||||
&trx_sys_mysql_relay_log_pos);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: In a MySQL replication slave the last"
|
||||
" master binlog file\n"
|
||||
"InnoDB: position %lu %lu, file name %s\n",
|
||||
(ulong) mach_read_from_4(sys_header
|
||||
+ TRX_SYS_MYSQL_MASTER_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
|
||||
(ulong) mach_read_from_4(sys_header
|
||||
+ TRX_SYS_MYSQL_MASTER_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
|
||||
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_NAME);
|
||||
"InnoDB: position %llu, file name %s\n",
|
||||
trx_sys_mysql_master_log_pos,
|
||||
trx_sys_mysql_master_log_name);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: and relay log file\n"
|
||||
"InnoDB: position %lu %lu, file name %s\n",
|
||||
(ulong) mach_read_from_4(sys_header
|
||||
+ TRX_SYS_MYSQL_RELAY_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH),
|
||||
(ulong) mach_read_from_4(sys_header
|
||||
+ TRX_SYS_MYSQL_RELAY_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW),
|
||||
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_NAME);
|
||||
"InnoDB: position %llu, file name %s\n",
|
||||
trx_sys_mysql_relay_log_pos,
|
||||
trx_sys_mysql_relay_log_name);
|
||||
}
|
||||
|
||||
/*****************************************************************//**
|
||||
Prints to stderr the MySQL master log offset info in the trx system header
|
||||
COMMIT set of fields if the magic number shows it valid and stores it
|
||||
in global variables. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
trx_sys_print_committed_mysql_master_log_pos(void)
|
||||
/*==============================================*/
|
||||
{
|
||||
trx_sysf_t* sys_header;
|
||||
mtr_t mtr;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
sys_header = trx_sysf_get(&mtr);
|
||||
|
||||
if (mach_read_from_4(sys_header + TRX_SYS_COMMIT_MASTER_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_MAGIC_N_FLD)
|
||||
!= TRX_SYS_MYSQL_LOG_MAGIC_N) {
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy the master log position info to global variables we can
|
||||
use in ha_innobase.cc to initialize glob_mi to right values */
|
||||
use in ha_innobase.cc to initialize glob_mi to right values */
|
||||
trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_MASTER_LOG_INFO,
|
||||
trx_sys_mysql_master_log_name,
|
||||
&trx_sys_mysql_master_log_pos);
|
||||
|
||||
ut_memcpy(trx_sys_mysql_master_log_name,
|
||||
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_NAME,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
trx_sys_read_log_pos(sys_header, TRX_SYS_COMMIT_RELAY_LOG_INFO,
|
||||
trx_sys_mysql_relay_log_name,
|
||||
&trx_sys_mysql_relay_log_pos);
|
||||
|
||||
trx_sys_mysql_master_log_pos
|
||||
= (((ib_int64_t) mach_read_from_4(
|
||||
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
|
||||
+ ((ib_int64_t) mach_read_from_4(
|
||||
sys_header + TRX_SYS_MYSQL_MASTER_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW));
|
||||
|
||||
ut_memcpy(trx_sys_mysql_relay_log_name,
|
||||
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_NAME,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_NAME_LEN);
|
||||
|
||||
trx_sys_mysql_relay_log_pos
|
||||
= (((ib_int64_t) mach_read_from_4(
|
||||
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_HIGH)) << 32)
|
||||
+ ((ib_int64_t) mach_read_from_4(
|
||||
sys_header + TRX_SYS_MYSQL_RELAY_LOG_INFO
|
||||
+ TRX_SYS_MYSQL_LOG_OFFSET_LOW));
|
||||
mtr_commit(&mtr);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: In a MySQL replication slave the last"
|
||||
" master binlog file\n"
|
||||
"InnoDB: position %llu, file name %s\n",
|
||||
trx_sys_mysql_master_log_pos, trx_sys_mysql_master_log_name);
|
||||
|
||||
fprintf(stderr,
|
||||
"InnoDB: and relay log file\n"
|
||||
"InnoDB: position %llu, file name %s\n",
|
||||
trx_sys_mysql_relay_log_pos, trx_sys_mysql_relay_log_name);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
|
||||
@@ -938,13 +938,13 @@ trx_write_serialisation_history(
|
||||
sys_header,
|
||||
trx->mysql_relay_log_file_name,
|
||||
trx->mysql_relay_log_pos,
|
||||
TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
|
||||
TRX_SYS_COMMIT_RELAY_LOG_INFO, &mtr);
|
||||
|
||||
trx_sys_update_mysql_binlog_offset(
|
||||
sys_header,
|
||||
trx->mysql_master_log_file_name,
|
||||
trx->mysql_master_log_pos,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
|
||||
TRX_SYS_COMMIT_MASTER_LOG_INFO, &mtr);
|
||||
|
||||
trx->mysql_master_log_file_name = "";
|
||||
}
|
||||
@@ -2050,6 +2050,23 @@ trx_prepare_off_kernel(
|
||||
|
||||
mutex_exit(&(rseg->mutex));
|
||||
|
||||
if (trx->mysql_master_log_file_name[0] != '\0') {
|
||||
/* This database server is a MySQL replication slave */
|
||||
trx_sysf_t* sys_header = trx_sysf_get(&mtr);
|
||||
|
||||
trx_sys_update_mysql_binlog_offset(
|
||||
sys_header,
|
||||
trx->mysql_relay_log_file_name,
|
||||
trx->mysql_relay_log_pos,
|
||||
TRX_SYS_MYSQL_RELAY_LOG_INFO, &mtr);
|
||||
trx_sys_update_mysql_binlog_offset(
|
||||
sys_header,
|
||||
trx->mysql_master_log_file_name,
|
||||
trx->mysql_master_log_pos,
|
||||
TRX_SYS_MYSQL_MASTER_LOG_INFO, &mtr);
|
||||
trx->mysql_master_log_file_name = "";
|
||||
}
|
||||
|
||||
/*--------------*/
|
||||
mtr_commit(&mtr); /* This mtr commit makes the
|
||||
transaction prepared in the file-based
|
||||
|
||||
Reference in New Issue
Block a user