mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
xtradb merge. Percona-Server-5.5.28-rel29.3
This commit is contained in:
@ -1,8 +1,8 @@
|
||||
-- source include/have_innodb.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-29.1" from information_schema.plugins where plugin_name='innodb'`)
|
||||
if (`select plugin_auth_version <= "1.1.8-29.3" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-29.1 or earlier
|
||||
--skip Not fixed in XtraDB 1.1.8-29.3 or earlier
|
||||
}
|
||||
|
||||
let $per_table=`select @@innodb_file_per_table`;
|
||||
|
@ -4,9 +4,9 @@
|
||||
# .\sync\sync0sync.c line 324
|
||||
# is fixed
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-29.1" from information_schema.plugins where plugin_name='innodb'`)
|
||||
if (`select plugin_auth_version <= "1.1.8-29.3" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-29.1 or earlier
|
||||
--skip Not fixed in XtraDB 1.1.8-29.3 or earlier
|
||||
}
|
||||
|
||||
#######################################################################
|
||||
|
@ -1,8 +1,8 @@
|
||||
--source include/have_innodb.inc
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-29.1" from information_schema.plugins where plugin_name='innodb'`)
|
||||
if (`select plugin_auth_version <= "1.1.8-29.3" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-29.1 or earlier
|
||||
--skip Not fixed in XtraDB 1.1.8-29.3 or earlier
|
||||
}
|
||||
let $file_format=`select @@innodb_file_format`;
|
||||
let $file_per_table=`select @@innodb_file_per_table`;
|
||||
|
@ -14,9 +14,9 @@
|
||||
# #
|
||||
######################################################################
|
||||
|
||||
if (`select plugin_auth_version <= "1.1.8-29.1" from information_schema.plugins where plugin_name='innodb'`)
|
||||
if (`select plugin_auth_version <= "1.1.8-29.3" from information_schema.plugins where plugin_name='innodb'`)
|
||||
{
|
||||
--skip Not fixed in XtraDB 1.1.8-29.1 or earlier
|
||||
--skip Not fixed in XtraDB 1.1.8-29.3 or earlier
|
||||
}
|
||||
|
||||
# Save innodb variables
|
||||
|
@ -0,0 +1 @@
|
||||
XtraDB extension
|
||||
|
@ -0,0 +1 @@
|
||||
XtraDB extension
|
@ -0,0 +1 @@
|
||||
XtraDB extension
|
@ -0,0 +1 @@
|
||||
--echo XtraDB extension
|
||||
|
@ -0,0 +1 @@
|
||||
--echo XtraDB extension
|
@ -0,0 +1 @@
|
||||
--echo XtraDB extension
|
@ -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.1"`)
|
||||
if (`select count(*) from information_schema.plugins where plugin_name='innodb' and plugin_auth_version > "1.1.8-29.3"`)
|
||||
{
|
||||
# because of lp:1066512 this test shows xtradb I_S plugins, even when
|
||||
# xtradb is supposed to be disabled
|
||||
|
@ -239,6 +239,7 @@ btr_cur_latch_leaves(
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
ulint mode;
|
||||
ulint sibling_mode;
|
||||
ulint left_page_no;
|
||||
ulint right_page_no;
|
||||
buf_block_t* get_block;
|
||||
@ -261,14 +262,21 @@ btr_cur_latch_leaves(
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
get_block->check_index_page_at_flush = TRUE;
|
||||
return;
|
||||
case BTR_SEARCH_TREE:
|
||||
case BTR_MODIFY_TREE:
|
||||
/* x-latch also brothers from left to right */
|
||||
if (UNIV_UNLIKELY(latch_mode == BTR_SEARCH_TREE)) {
|
||||
mode = RW_S_LATCH;
|
||||
sibling_mode = RW_NO_LATCH;
|
||||
} else {
|
||||
mode = sibling_mode = RW_X_LATCH;
|
||||
}
|
||||
/* Fetch and possibly latch also brothers from left to right */
|
||||
left_page_no = btr_page_get_prev(page, mtr);
|
||||
|
||||
if (left_page_no != FIL_NULL) {
|
||||
get_block = btr_block_get(
|
||||
space, zip_size, left_page_no,
|
||||
RW_X_LATCH, cursor->index, mtr);
|
||||
sibling_mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
@ -280,12 +288,21 @@ btr_cur_latch_leaves(
|
||||
ut_a(btr_page_get_next(get_block->frame, mtr)
|
||||
== page_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
if (sibling_mode == RW_NO_LATCH) {
|
||||
/* btr_block_get() called with RW_NO_LATCH will
|
||||
fix the read block in the buffer. This serves
|
||||
no purpose for the fake changes prefetching,
|
||||
thus we unfix the sibling blocks immediately.*/
|
||||
mtr_memo_release(mtr, get_block,
|
||||
MTR_MEMO_BUF_FIX);
|
||||
} else {
|
||||
get_block->check_index_page_at_flush = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
get_block = btr_block_get(
|
||||
space, zip_size, page_no,
|
||||
RW_X_LATCH, cursor->index, mtr);
|
||||
mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
@ -301,7 +318,7 @@ btr_cur_latch_leaves(
|
||||
if (right_page_no != FIL_NULL) {
|
||||
get_block = btr_block_get(
|
||||
space, zip_size, right_page_no,
|
||||
RW_X_LATCH, cursor->index, mtr);
|
||||
sibling_mode, cursor->index, mtr);
|
||||
|
||||
if (srv_pass_corrupt_table && !get_block) {
|
||||
return;
|
||||
@ -313,8 +330,13 @@ btr_cur_latch_leaves(
|
||||
ut_a(btr_page_get_prev(get_block->frame, mtr)
|
||||
== page_get_page_no(page));
|
||||
#endif /* UNIV_BTR_DEBUG */
|
||||
if (sibling_mode == RW_NO_LATCH) {
|
||||
mtr_memo_release(mtr, get_block,
|
||||
MTR_MEMO_BUF_FIX);
|
||||
} else {
|
||||
get_block->check_index_page_at_flush = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@ -1566,6 +1588,9 @@ btr_cur_pessimistic_insert(
|
||||
}
|
||||
|
||||
if (!(flags & BTR_NO_UNDO_LOG_FLAG)) {
|
||||
|
||||
ut_a(cursor->tree_height != ULINT_UNDEFINED);
|
||||
|
||||
/* First reserve enough free space for the file segments
|
||||
of the index tree, so that the insert will not fail because
|
||||
of lack of space */
|
||||
@ -1860,7 +1885,8 @@ btr_cur_update_alloc_zip(
|
||||
ulint length, /*!< in: size needed */
|
||||
ibool create, /*!< in: TRUE=delete-and-insert,
|
||||
FALSE=update-in-place */
|
||||
mtr_t* mtr) /*!< in: mini-transaction */
|
||||
mtr_t* mtr, /*!< in: mini-transaction */
|
||||
trx_t* trx) /*!< in: NULL or transaction */
|
||||
{
|
||||
ut_a(page_zip == buf_block_get_page_zip(block));
|
||||
ut_ad(page_zip);
|
||||
@ -1877,6 +1903,14 @@ btr_cur_update_alloc_zip(
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (trx && trx->fake_changes) {
|
||||
/* Don't call page_zip_compress_write_log_no_data as that has
|
||||
assert which would fail. Assume there won't be a compression
|
||||
failure. */
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (!page_zip_compress(page_zip, buf_block_get_frame(block),
|
||||
index, mtr)) {
|
||||
/* Unable to compress the page */
|
||||
@ -1960,7 +1994,8 @@ btr_cur_update_in_place(
|
||||
/* Check that enough space is available on the compressed page. */
|
||||
if (page_zip
|
||||
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
||||
rec_offs_size(offsets), FALSE, mtr)) {
|
||||
rec_offs_size(offsets), FALSE, mtr,
|
||||
trx)) {
|
||||
return(DB_ZIP_OVERFLOW);
|
||||
}
|
||||
|
||||
@ -2159,7 +2194,8 @@ any_extern:
|
||||
|
||||
if (page_zip
|
||||
&& !btr_cur_update_alloc_zip(page_zip, block, index,
|
||||
new_rec_size, TRUE, mtr)) {
|
||||
new_rec_size, TRUE, mtr,
|
||||
thr_get_trx(thr))) {
|
||||
err = DB_ZIP_OVERFLOW;
|
||||
goto err_exit;
|
||||
}
|
||||
@ -2402,7 +2438,15 @@ btr_cur_pessimistic_update(
|
||||
of the index tree, so that the update will not fail because
|
||||
of lack of space */
|
||||
|
||||
if (UNIV_UNLIKELY(cursor->tree_height == ULINT_UNDEFINED)) {
|
||||
/* When the tree height is uninitialized due to fake
|
||||
changes, reserve some hardcoded number of extents. */
|
||||
ut_a(thr && thr_get_trx(thr)->fake_changes);
|
||||
n_extents = 3;
|
||||
}
|
||||
else {
|
||||
n_extents = cursor->tree_height / 16 + 3;
|
||||
}
|
||||
|
||||
if (flags & BTR_NO_UNDO_LOG_FLAG) {
|
||||
reserve_flag = FSP_CLEANING;
|
||||
@ -2439,7 +2483,7 @@ btr_cur_pessimistic_update(
|
||||
itself. Thus the following call is safe. */
|
||||
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
|
||||
FALSE, *heap);
|
||||
if (!(flags & BTR_KEEP_SYS_FLAG)) {
|
||||
if (!(flags & BTR_KEEP_SYS_FLAG) && !trx->fake_changes) {
|
||||
row_upd_index_entry_sys_field(new_entry, index, DATA_ROLL_PTR,
|
||||
roll_ptr);
|
||||
row_upd_index_entry_sys_field(new_entry, index, DATA_TRX_ID,
|
||||
@ -3210,6 +3254,8 @@ btr_cur_pessimistic_delete(
|
||||
of the index tree, so that the node pointer updates will
|
||||
not fail because of lack of space */
|
||||
|
||||
ut_a(cursor->tree_height != ULINT_UNDEFINED);
|
||||
|
||||
n_extents = cursor->tree_height / 32 + 1;
|
||||
|
||||
success = fsp_reserve_free_extents(&n_reserved,
|
||||
|
@ -47,6 +47,7 @@ btr_pcur_create_for_mysql(void)
|
||||
|
||||
pcur->btr_cur.index = NULL;
|
||||
btr_pcur_init(pcur);
|
||||
pcur->btr_cur.tree_height = ULINT_UNDEFINED;
|
||||
|
||||
return(pcur);
|
||||
}
|
||||
|
@ -239,9 +239,11 @@ buf_LRU_drop_page_hash_batch(
|
||||
When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page
|
||||
hash index entries belonging to that table. This function tries to
|
||||
do that in batch. Note that this is a 'best effort' attempt and does
|
||||
not guarantee that ALL hash entries will be removed. */
|
||||
not guarantee that ALL hash entries will be removed.
|
||||
|
||||
@return number of hashed pages found*/
|
||||
static
|
||||
void
|
||||
ulint
|
||||
buf_LRU_drop_page_hash_for_tablespace(
|
||||
/*==================================*/
|
||||
buf_pool_t* buf_pool, /*!< in: buffer pool instance */
|
||||
@ -251,13 +253,14 @@ buf_LRU_drop_page_hash_for_tablespace(
|
||||
ulint* page_arr;
|
||||
ulint num_entries;
|
||||
ulint zip_size;
|
||||
ulint num_found = 0;
|
||||
|
||||
zip_size = fil_space_get_zip_size(id);
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
|
||||
/* Somehow, the tablespace does not exist. Nothing to drop. */
|
||||
ut_ad(0);
|
||||
return;
|
||||
return num_found;
|
||||
}
|
||||
|
||||
page_arr = ut_malloc(
|
||||
@ -315,6 +318,7 @@ next_page:
|
||||
ut_a(num_entries < BUF_LRU_DROP_SEARCH_SIZE);
|
||||
|
||||
++num_entries;
|
||||
++num_found;
|
||||
|
||||
if (num_entries < BUF_LRU_DROP_SEARCH_SIZE) {
|
||||
goto next_page;
|
||||
@ -370,6 +374,8 @@ next_page:
|
||||
/* Drop any remaining batch of search hashed pages. */
|
||||
buf_LRU_drop_page_hash_batch(id, zip_size, page_arr, num_entries);
|
||||
ut_free(page_arr);
|
||||
|
||||
return num_found;
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
@ -814,8 +820,6 @@ buf_LRU_mark_space_was_deleted(
|
||||
for (i = 0; i < srv_buf_pool_instances; i++) {
|
||||
buf_pool_t* buf_pool;
|
||||
buf_page_t* bpage;
|
||||
buf_chunk_t* chunk;
|
||||
ulint j, k;
|
||||
|
||||
buf_pool = buf_pool_from_array(i);
|
||||
|
||||
@ -832,28 +836,10 @@ buf_LRU_mark_space_was_deleted(
|
||||
|
||||
mutex_exit(&buf_pool->LRU_list_mutex);
|
||||
|
||||
btr_search_s_lock_all();
|
||||
chunk = buf_pool->chunks;
|
||||
for (j = buf_pool->n_chunks; j--; chunk++) {
|
||||
buf_block_t* block = chunk->blocks;
|
||||
for (k = chunk->size; k--; block++) {
|
||||
if (buf_block_get_state(block)
|
||||
!= BUF_BLOCK_FILE_PAGE
|
||||
|| !block->index
|
||||
|| buf_page_get_space(&block->page) != id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
btr_search_s_unlock_all();
|
||||
|
||||
rw_lock_x_lock(&block->lock);
|
||||
btr_search_drop_page_hash_index(block);
|
||||
rw_lock_x_unlock(&block->lock);
|
||||
|
||||
btr_search_s_lock_all();
|
||||
}
|
||||
}
|
||||
btr_search_s_unlock_all();
|
||||
/* The AHI entries for the tablespace being deleted should be
|
||||
removed by now. */
|
||||
ut_ad(buf_LRU_drop_page_hash_for_tablespace(buf_pool, id)
|
||||
== 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3031,7 +3031,11 @@ try_again:
|
||||
some of them will contain extent descriptor pages, and therefore
|
||||
will not be free extents */
|
||||
|
||||
if (size <= free_limit) {
|
||||
n_free_up = 0;
|
||||
} else {
|
||||
n_free_up = (size - free_limit) / FSP_EXTENT_SIZE;
|
||||
}
|
||||
|
||||
if (n_free_up > 0) {
|
||||
n_free_up--;
|
||||
|
@ -1043,6 +1043,13 @@ thd_to_trx(
|
||||
return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr));
|
||||
}
|
||||
|
||||
my_bool
|
||||
ha_innobase::is_fake_change_enabled(THD* thd)
|
||||
{
|
||||
trx_t* trx = thd_to_trx(thd);
|
||||
return(trx && trx->fake_changes);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Call this function when mysqld passes control to the client. That is to
|
||||
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
|
||||
@ -3041,6 +3048,14 @@ innobase_change_buffering_inited_ok:
|
||||
srv_use_checksums = (ibool) innobase_use_checksums;
|
||||
srv_fast_checksum = (ibool) innobase_fast_checksum;
|
||||
|
||||
if (innobase_fast_checksum) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: innodb_fast_checksum is DEPRECATED "
|
||||
"and *WILL* be removed in Percona Server 5.6. Please "
|
||||
"consult the Percona Server 5.6 documentation for "
|
||||
"help in upgrading.\n");
|
||||
}
|
||||
|
||||
srv_blocking_lru_restore = (ibool) innobase_blocking_lru_restore;
|
||||
|
||||
#ifdef HAVE_LARGE_PAGES
|
||||
@ -6143,7 +6158,9 @@ no_commit:
|
||||
error = row_insert_for_mysql((byte*) record, prebuilt);
|
||||
|
||||
#ifdef EXTENDED_FOR_USERSTAT
|
||||
if (error == DB_SUCCESS) rows_changed++;
|
||||
if (UNIV_LIKELY(error == DB_SUCCESS && !trx->fake_changes)) {
|
||||
rows_changed++;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Handle duplicate key errors */
|
||||
@ -6511,7 +6528,9 @@ ha_innobase::update_row(
|
||||
}
|
||||
|
||||
#ifdef EXTENDED_FOR_USERSTAT
|
||||
if (error == DB_SUCCESS) rows_changed++;
|
||||
if (UNIV_LIKELY(error == DB_SUCCESS && !trx->fake_changes)) {
|
||||
rows_changed++;
|
||||
}
|
||||
#endif
|
||||
|
||||
innodb_srv_conc_exit_innodb(trx);
|
||||
@ -6576,7 +6595,9 @@ ha_innobase::delete_row(
|
||||
error = row_update_for_mysql((byte*) record, prebuilt);
|
||||
|
||||
#ifdef EXTENDED_FOR_USERSTAT
|
||||
if (error == DB_SUCCESS) rows_changed++;
|
||||
if (UNIV_LIKELY(error == DB_SUCCESS && !trx->fake_changes)) {
|
||||
rows_changed++;
|
||||
}
|
||||
#endif
|
||||
|
||||
innodb_srv_conc_exit_innodb(trx);
|
||||
@ -12558,6 +12579,8 @@ static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums,
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(fast_checksum, innobase_fast_checksum,
|
||||
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
|
||||
"DEPRECATED. #### WARNING #### : This feature is DEPRECATED and WILL "
|
||||
"be removed in Percona Server 5.6. "
|
||||
"Change the algorithm of checksum for the whole of datapage to 4-bytes word based. "
|
||||
"The original checksum is checked after the new one. It may be slow for reading page"
|
||||
" which has orginal checksum. Overwrite the page or recreate the InnoDB database, "
|
||||
@ -12991,6 +13014,11 @@ static MYSQL_SYSVAR_BOOL(track_changed_pages, srv_track_changed_pages,
|
||||
"Track the redo log for changed pages and output a changed page bitmap",
|
||||
NULL, NULL, FALSE);
|
||||
|
||||
static MYSQL_SYSVAR_ULONGLONG(max_bitmap_file_size, srv_max_bitmap_file_size,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"The maximum size of changed page bitmap files",
|
||||
NULL, NULL, 100*1024*1024ULL, 4096ULL, ULONGLONG_MAX, 0);
|
||||
|
||||
static MYSQL_SYSVAR_ULONGLONG(changed_pages_limit, srv_changed_pages_limit,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"The maximum number of rows for "
|
||||
@ -13193,6 +13221,13 @@ static MYSQL_SYSVAR_ULINT(lazy_drop_table, srv_lazy_drop_table,
|
||||
"e.g. for http://bugs.mysql.com/51325",
|
||||
NULL, NULL, 0, 0, 1, 0);
|
||||
|
||||
static MYSQL_SYSVAR_BOOL(locking_fake_changes, srv_fake_changes_locks,
|
||||
PLUGIN_VAR_NOCMDARG,
|
||||
"###EXPERIMENTAL### if enabled, transactions will get S row locks instead "
|
||||
"of X locks for fake changes. If disabled, fake change transactions will "
|
||||
"not take any locks at all.",
|
||||
NULL, NULL, TRUE);
|
||||
|
||||
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||
MYSQL_SYSVAR(page_size),
|
||||
MYSQL_SYSVAR(log_block_size),
|
||||
@ -13284,6 +13319,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||
MYSQL_SYSVAR(use_native_aio),
|
||||
MYSQL_SYSVAR(change_buffering),
|
||||
MYSQL_SYSVAR(track_changed_pages),
|
||||
MYSQL_SYSVAR(max_bitmap_file_size),
|
||||
MYSQL_SYSVAR(changed_pages_limit),
|
||||
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||
MYSQL_SYSVAR(change_buffering_debug),
|
||||
@ -13302,6 +13338,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||
MYSQL_SYSVAR(corrupt_table_action),
|
||||
MYSQL_SYSVAR(lazy_drop_table),
|
||||
MYSQL_SYSVAR(fake_changes),
|
||||
MYSQL_SYSVAR(locking_fake_changes),
|
||||
MYSQL_SYSVAR(merge_sort_block_size),
|
||||
NULL
|
||||
};
|
||||
|
@ -138,6 +138,7 @@ class ha_innobase: public handler
|
||||
int close(void);
|
||||
double scan_time();
|
||||
double read_time(uint index, uint ranges, ha_rows rows);
|
||||
my_bool is_fake_change_enabled(THD *thd);
|
||||
bool is_corrupt() const;
|
||||
|
||||
int write_row(uchar * buf);
|
||||
|
@ -7147,29 +7147,38 @@ static ST_FIELD_INFO i_s_innodb_changed_pages_info[] =
|
||||
};
|
||||
|
||||
/***********************************************************************
|
||||
This function parses condition and gets upper bounds for start and end LSN's
|
||||
if condition corresponds to certain pattern.
|
||||
This function implements ICP for I_S.INNODB_CHANGED_PAGES by parsing a
|
||||
condition and getting lower and upper bounds for start and end LSNs if the
|
||||
condition corresponds to a certain pattern.
|
||||
|
||||
We can't know right position to avoid scanning bitmap files from the beginning
|
||||
to the lower bound. But we can stop scanning bitmap files if we reach upper bound.
|
||||
In the most general form, we understand queries like
|
||||
|
||||
It's expected the most used queries will be like the following:
|
||||
SELECT * FROM INNODB_CHANGED_PAGES
|
||||
WHERE START_LSN > num1 AND START_LSN < num2
|
||||
AND END_LSN > num3 AND END_LSN < num4;
|
||||
|
||||
SELECT * FROM INNODB_CHANGED_PAGES WHERE START_LSN > num1 AND start_lsn < num2;
|
||||
|
||||
That's why the pattern is:
|
||||
That's why the pattern syntax is:
|
||||
|
||||
pattern: comp | and_comp;
|
||||
comp: lsn < int_num | lsn <= int_num | int_num > lsn | int_num >= lsn;
|
||||
lsn: start_lsn | end_lsn;
|
||||
and_comp: some_expression AND some_expression | some_expression AND and_comp;
|
||||
some_expression: comp | any_other_expression;
|
||||
and_comp: expression AND expression | expression AND and_comp;
|
||||
expression: comp | any_other_expression;
|
||||
|
||||
Suppose the condition is start_lsn < 100, this means we have to read all
|
||||
blocks with start_lsn < 100. Which is equivalent to reading all the blocks
|
||||
with end_lsn <= 99, or just end_lsn < 100. That's why it's enough to find
|
||||
maximum lsn value, doesn't matter if this is start or end lsn and compare
|
||||
it with "start_lsn" field.
|
||||
The two bounds are handled differently: the lower bound is used to find the
|
||||
correct starting _file_, the upper bound the last _block_ that needs reading.
|
||||
|
||||
Lower bound conditions are handled in the following way: start_lsn >= X
|
||||
specifies that the reading must start from the file that has the highest
|
||||
starting LSN less than or equal to X. start_lsn > X is equivalent to
|
||||
start_lsn >= X + 1. For end_lsn, end_lsn >= X is treated as
|
||||
start_lsn >= X - 1 and end_lsn > X as start_lsn >= X.
|
||||
|
||||
For the upper bound, suppose the condition is start_lsn < 100, this means we
|
||||
have to read all blocks with start_lsn < 100. Which is equivalent to reading
|
||||
all the blocks with end_lsn <= 99, or just end_lsn < 100. That's why it's
|
||||
enough to find maximum lsn value, doesn't matter if this is start or end lsn
|
||||
and compare it with "start_lsn" field. LSN <= 100 is treated as LSN < 101.
|
||||
|
||||
Example:
|
||||
|
||||
@ -7180,7 +7189,11 @@ static ST_FIELD_INFO i_s_innodb_changed_pages_info[] =
|
||||
555 > end_lsn AND
|
||||
page_id = 100;
|
||||
|
||||
max_lsn will be set to 555.
|
||||
end_lsn will be set to 555, start_lsn will be set 11.
|
||||
|
||||
Support for other functions (equal, NULL-safe equal, BETWEEN, IN, etc.) will
|
||||
be added on demand.
|
||||
|
||||
*/
|
||||
static
|
||||
void
|
||||
@ -7188,25 +7201,29 @@ limit_lsn_range_from_condition(
|
||||
/*===========================*/
|
||||
TABLE* table, /*!<in: table */
|
||||
COND* cond, /*!<in: condition */
|
||||
ib_uint64_t* max_lsn) /*!<in/out: maximum LSN
|
||||
(must be initialized with maximum
|
||||
available value) */
|
||||
ib_uint64_t* start_lsn, /*!<in/out: minumum LSN */
|
||||
ib_uint64_t* end_lsn) /*!<in/out: maximum LSN */
|
||||
{
|
||||
enum Item_func::Functype func_type;
|
||||
|
||||
if (cond->type() != Item::COND_ITEM &&
|
||||
cond->type() != Item::FUNC_ITEM)
|
||||
return;
|
||||
|
||||
switch (((Item_func*) cond)->functype())
|
||||
func_type = ((Item_func*) cond)->functype();
|
||||
|
||||
switch (func_type)
|
||||
{
|
||||
case Item_func::COND_AND_FUNC:
|
||||
{
|
||||
List_iterator<Item> li(*((Item_cond*) cond)->
|
||||
argument_list());
|
||||
List_iterator<Item> li(*((Item_cond*) cond)
|
||||
->argument_list());
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
limit_lsn_range_from_condition(table,
|
||||
item,
|
||||
max_lsn);
|
||||
|
||||
while ((item= li++)) {
|
||||
limit_lsn_range_from_condition(table, item, start_lsn,
|
||||
end_lsn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case Item_func::LT_FUNC:
|
||||
@ -7218,17 +7235,13 @@ limit_lsn_range_from_condition(
|
||||
Item *right;
|
||||
Item_field *item_field;
|
||||
ib_uint64_t tmp_result;
|
||||
ibool is_end_lsn;
|
||||
|
||||
/*
|
||||
a <= b equals to b >= a that's why we just exchange
|
||||
"left" and "right" in the case of ">" or ">="
|
||||
function
|
||||
*/
|
||||
if (((Item_func*) cond)->functype() ==
|
||||
Item_func::LT_FUNC ||
|
||||
((Item_func*) cond)->functype() ==
|
||||
Item_func::LE_FUNC)
|
||||
{
|
||||
/* a <= b equals to b >= a that's why we just exchange "left"
|
||||
and "right" in the case of ">" or ">=" function. We don't
|
||||
touch the operation itself. */
|
||||
if (((Item_func*) cond)->functype() == Item_func::LT_FUNC
|
||||
|| ((Item_func*) cond)->functype() == Item_func::LE_FUNC) {
|
||||
left = ((Item_func*) cond)->arguments()[0];
|
||||
right = ((Item_func*) cond)->arguments()[1];
|
||||
} else {
|
||||
@ -7236,36 +7249,70 @@ limit_lsn_range_from_condition(
|
||||
right = ((Item_func*) cond)->arguments()[0];
|
||||
}
|
||||
|
||||
if (!left || !right)
|
||||
return;
|
||||
if (left->type() != Item::FIELD_ITEM)
|
||||
return;
|
||||
if (right->type() != Item::INT_ITEM)
|
||||
return;
|
||||
|
||||
if (left->type() == Item::FIELD_ITEM) {
|
||||
item_field = (Item_field *)left;
|
||||
|
||||
if (/* START_LSN */
|
||||
table->field[2] != item_field->field &&
|
||||
/* END_LSN */
|
||||
table->field[3] != item_field->field)
|
||||
{
|
||||
} else if (right->type() == Item::FIELD_ITEM) {
|
||||
item_field = (Item_field *)right;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if the current field belongs to our table */
|
||||
if (table != item_field->field->table)
|
||||
if (table != item_field->field->table) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check if the field is START_LSN or END_LSN */
|
||||
/* END_LSN */
|
||||
is_end_lsn = table->field[3]->eq(item_field->field);
|
||||
|
||||
if (/* START_LSN */ !table->field[2]->eq(item_field->field)
|
||||
&& !is_end_lsn) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (left->type() == Item::FIELD_ITEM
|
||||
&& right->type() == Item::INT_ITEM) {
|
||||
|
||||
/* The case of start_lsn|end_lsn <|<= const, i.e. the
|
||||
upper bound. */
|
||||
|
||||
tmp_result = right->val_int();
|
||||
if (tmp_result < *max_lsn)
|
||||
*max_lsn = tmp_result;
|
||||
if (((func_type == Item_func::LE_FUNC)
|
||||
|| (func_type == Item_func::GE_FUNC))
|
||||
&& (tmp_result != IB_ULONGLONG_MAX)) {
|
||||
|
||||
tmp_result++;
|
||||
}
|
||||
if (tmp_result < *end_lsn) {
|
||||
*end_lsn = tmp_result;
|
||||
}
|
||||
|
||||
} else if (left->type() == Item::INT_ITEM
|
||||
&& right->type() == Item::FIELD_ITEM) {
|
||||
|
||||
/* The case of const <|<= start_lsn|end_lsn, i.e. the
|
||||
lower bound */
|
||||
|
||||
tmp_result = left->val_int();
|
||||
if (is_end_lsn && tmp_result != 0) {
|
||||
tmp_result--;
|
||||
}
|
||||
if (((func_type == Item_func::LT_FUNC)
|
||||
|| (func_type == Item_func::GT_FUNC))
|
||||
&& (tmp_result != IB_ULONGLONG_MAX)) {
|
||||
|
||||
tmp_result++;
|
||||
}
|
||||
if (tmp_result > *start_lsn) {
|
||||
*start_lsn = tmp_result;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
@ -7282,16 +7329,31 @@ i_s_innodb_changed_pages_fill(
|
||||
TABLE* table = (TABLE *) tables->table;
|
||||
log_bitmap_iterator_t i;
|
||||
ib_uint64_t output_rows_num = 0UL;
|
||||
ib_uint64_t max_lsn = ~0ULL;
|
||||
ib_uint64_t max_lsn = IB_ULONGLONG_MAX;
|
||||
ib_uint64_t min_lsn = 0ULL;
|
||||
|
||||
if (!srv_track_changed_pages)
|
||||
return 0;
|
||||
DBUG_ENTER("i_s_innodb_changed_pages_fill");
|
||||
|
||||
if (!log_online_bitmap_iterator_init(&i))
|
||||
return 1;
|
||||
/* deny access to non-superusers */
|
||||
if (check_global_access(thd, PROCESS_ACL)) {
|
||||
|
||||
if (cond)
|
||||
limit_lsn_range_from_condition(table, cond, &max_lsn);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
RETURN_IF_INNODB_NOT_STARTED(tables->schema_table_name);
|
||||
|
||||
if (!srv_track_changed_pages) {
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
if (cond) {
|
||||
limit_lsn_range_from_condition(table, cond, &min_lsn,
|
||||
&max_lsn);
|
||||
}
|
||||
|
||||
if (!log_online_bitmap_iterator_init(&i, min_lsn, max_lsn)) {
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
while(log_online_bitmap_iterator_next(&i) &&
|
||||
(!srv_changed_pages_limit ||
|
||||
@ -7330,10 +7392,10 @@ i_s_innodb_changed_pages_fill(
|
||||
LOG_BITMAP_ITERATOR_PAGE_NUM(i));
|
||||
/* START_LSN */
|
||||
table->field[2]->store(
|
||||
LOG_BITMAP_ITERATOR_START_LSN(i));
|
||||
LOG_BITMAP_ITERATOR_START_LSN(i), true);
|
||||
/* END_LSN */
|
||||
table->field[3]->store(
|
||||
LOG_BITMAP_ITERATOR_END_LSN(i));
|
||||
LOG_BITMAP_ITERATOR_END_LSN(i), true);
|
||||
|
||||
/*
|
||||
I_S tables are in-memory tables. If bitmap file is big enough
|
||||
@ -7353,14 +7415,14 @@ i_s_innodb_changed_pages_fill(
|
||||
if (schema_table_store_record(thd, table))
|
||||
{
|
||||
log_online_bitmap_iterator_release(&i);
|
||||
return 1;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
++output_rows_num;
|
||||
}
|
||||
|
||||
log_online_bitmap_iterator_release(&i);
|
||||
return 0;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
static
|
||||
|
@ -4044,7 +4044,7 @@ updated_in_place:
|
||||
update)
|
||||
&& (!page_zip || btr_cur_update_alloc_zip(
|
||||
page_zip, block, index,
|
||||
rec_offs_size(offsets), FALSE, mtr))) {
|
||||
rec_offs_size(offsets), FALSE, mtr, NULL))) {
|
||||
/* This is the easy case. Do something similar
|
||||
to btr_cur_update_in_place(). */
|
||||
row_upd_rec_in_place(rec, index, offsets,
|
||||
|
@ -65,7 +65,10 @@ enum btr_latch_mode {
|
||||
/** Search the previous record. */
|
||||
BTR_SEARCH_PREV = 35,
|
||||
/** Modify the previous record. */
|
||||
BTR_MODIFY_PREV = 36
|
||||
BTR_MODIFY_PREV = 36,
|
||||
/** Weaker BTR_MODIFY_TREE that does not lock the leaf page siblings,
|
||||
used for fake changes. */
|
||||
BTR_SEARCH_TREE = 37 /* BTR_MODIFY_TREE | 4 */
|
||||
};
|
||||
|
||||
/* BTR_INSERT, BTR_DELETE and BTR_DELETE_MARK are mutually exclusive. */
|
||||
|
@ -259,8 +259,9 @@ btr_cur_update_alloc_zip(
|
||||
ulint length, /*!< in: size needed */
|
||||
ibool create, /*!< in: TRUE=delete-and-insert,
|
||||
FALSE=update-in-place */
|
||||
mtr_t* mtr) /*!< in: mini-transaction */
|
||||
__attribute__((nonnull, warn_unused_result));
|
||||
mtr_t* mtr, /*!< in: mini-transaction */
|
||||
trx_t* trx) /*!< in: NULL or transaction */
|
||||
__attribute__((nonnull (1, 2, 3, 6), warn_unused_result));
|
||||
/*************************************************************//**
|
||||
Updates a record when the update causes no size changes in its fields.
|
||||
@return DB_SUCCESS or error number */
|
||||
|
@ -27,6 +27,16 @@ Online database log parsing for changed page tracking
|
||||
#include "univ.i"
|
||||
#include "os0file.h"
|
||||
|
||||
/** Single bitmap file information */
|
||||
typedef struct log_online_bitmap_file_struct log_online_bitmap_file_t;
|
||||
|
||||
/** A set of bitmap files containing some LSN range */
|
||||
typedef struct log_online_bitmap_file_range_struct
|
||||
log_online_bitmap_file_range_t;
|
||||
|
||||
/** An iterator over changed page info */
|
||||
typedef struct log_bitmap_iterator_struct log_bitmap_iterator_t;
|
||||
|
||||
/*********************************************************************//**
|
||||
Initializes the online log following subsytem. */
|
||||
UNIV_INTERN
|
||||
@ -49,26 +59,6 @@ void
|
||||
log_online_follow_redo_log();
|
||||
/*=========================*/
|
||||
|
||||
/** The iterator through all bits of changed pages bitmap blocks */
|
||||
struct log_bitmap_iterator_struct
|
||||
{
|
||||
char in_name[FN_REFLEN]; /*!< the file name for bitmap
|
||||
input */
|
||||
os_file_t in; /*!< the bitmap input file */
|
||||
ib_uint64_t in_offset; /*!< the next write position in the
|
||||
bitmap output file */
|
||||
ib_uint32_t bit_offset; /*!< bit offset inside of bitmap
|
||||
block*/
|
||||
ib_uint64_t start_lsn; /*!< Start lsn of the block */
|
||||
ib_uint64_t end_lsn; /*!< End lsn of the block */
|
||||
ib_uint32_t space_id; /*!< Block space id */
|
||||
ib_uint32_t first_page_id; /*!< First block page id */
|
||||
ibool changed; /*!< true if current page was changed */
|
||||
byte* page; /*!< Bitmap block */
|
||||
};
|
||||
|
||||
typedef struct log_bitmap_iterator_struct log_bitmap_iterator_t;
|
||||
|
||||
#define LOG_BITMAP_ITERATOR_START_LSN(i) \
|
||||
((i).start_lsn)
|
||||
#define LOG_BITMAP_ITERATOR_END_LSN(i) \
|
||||
@ -81,13 +71,20 @@ typedef struct log_bitmap_iterator_struct log_bitmap_iterator_t;
|
||||
((i).changed)
|
||||
|
||||
/*********************************************************************//**
|
||||
Initializes log bitmap iterator.
|
||||
Initializes log bitmap iterator. The minimum LSN is used for finding the
|
||||
correct starting file with records and it there may be records returned by
|
||||
the iterator that have LSN less than start_lsn.
|
||||
|
||||
@return TRUE if the iterator is initialized OK, FALSE otherwise. */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
log_online_bitmap_iterator_init(
|
||||
/*============================*/
|
||||
log_bitmap_iterator_t *i); /*!<in/out: iterator */
|
||||
log_bitmap_iterator_t *i, /*!<in/out: iterator */
|
||||
ib_uint64_t min_lsn, /*!<in: start LSN for the
|
||||
iterator */
|
||||
ib_uint64_t max_lsn); /*!<in: end LSN for the
|
||||
iterator */
|
||||
|
||||
/*********************************************************************//**
|
||||
Releases log bitmap iterator. */
|
||||
@ -108,4 +105,57 @@ log_online_bitmap_iterator_next(
|
||||
/*============================*/
|
||||
log_bitmap_iterator_t *i); /*!<in/out: iterator */
|
||||
|
||||
/** Struct for single bitmap file information */
|
||||
struct log_online_bitmap_file_struct {
|
||||
char name[FN_REFLEN]; /*!< Name with full path */
|
||||
os_file_t file; /*!< Handle to opened file */
|
||||
ib_uint64_t size; /*!< Size of the file */
|
||||
ib_uint64_t offset; /*!< Offset of the next read,
|
||||
or count of already-read bytes
|
||||
*/
|
||||
};
|
||||
|
||||
/** Struct for a set of bitmap files containing some LSN range */
|
||||
struct log_online_bitmap_file_range_struct {
|
||||
size_t count; /*!< Number of files */
|
||||
/*!< Dynamically-allocated array of info about individual files */
|
||||
struct {
|
||||
char name[FN_REFLEN]; /*!< Name of a file */
|
||||
ib_uint64_t start_lsn; /*!< Starting LSN of
|
||||
data in this file */
|
||||
ulong seq_num; /*!< Sequence number of
|
||||
this file */
|
||||
} *files;
|
||||
};
|
||||
|
||||
/** Struct for an iterator through all bits of changed pages bitmap blocks */
|
||||
struct log_bitmap_iterator_struct
|
||||
{
|
||||
log_online_bitmap_file_range_t in_files; /*!< The bitmap files
|
||||
for this iterator */
|
||||
size_t in_i; /*!< Currently read
|
||||
file index in in_files
|
||||
*/
|
||||
log_online_bitmap_file_t in; /*!< Currently read
|
||||
file */
|
||||
ib_uint32_t bit_offset; /*!< bit offset inside
|
||||
the current bitmap
|
||||
block */
|
||||
ib_uint64_t start_lsn; /*!< Start LSN of the
|
||||
current bitmap block */
|
||||
ib_uint64_t end_lsn; /*!< End LSN of the
|
||||
current bitmap block */
|
||||
ib_uint32_t space_id; /*!< Current block
|
||||
space id */
|
||||
ib_uint32_t first_page_id; /*!< Id of the first
|
||||
page in the current
|
||||
block */
|
||||
ibool last_page_in_run;/*!< "Last page in
|
||||
run" flag value for the
|
||||
current block */
|
||||
ibool changed; /*!< true if current
|
||||
page was changed */
|
||||
byte* page; /*!< Bitmap block */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -145,6 +145,7 @@ extern char* srv_doublewrite_file;
|
||||
extern ibool srv_recovery_stats;
|
||||
|
||||
extern my_bool srv_track_changed_pages;
|
||||
extern ib_uint64_t srv_max_bitmap_file_size;
|
||||
|
||||
extern
|
||||
ulonglong srv_changed_pages_limit;
|
||||
@ -395,6 +396,10 @@ extern uint srv_auto_lru_dump;
|
||||
/** Whether startup should be blocked until buffer pool is fully restored */
|
||||
extern ibool srv_blocking_lru_restore;
|
||||
|
||||
/** When TRUE, fake change transcations take S rather than X row locks.
|
||||
When FALSE, row locks are not taken at all. */
|
||||
extern my_bool srv_fake_changes_locks;
|
||||
|
||||
/** Status variables to be passed to MySQL */
|
||||
typedef struct export_var_struct export_struc;
|
||||
|
||||
|
@ -54,7 +54,7 @@ Created 1/20/1994 Heikki Tuuri
|
||||
#define INNODB_VERSION_BUGFIX 8
|
||||
|
||||
#ifndef PERCONA_INNODB_VERSION
|
||||
#define PERCONA_INNODB_VERSION 29.1
|
||||
#define PERCONA_INNODB_VERSION 29.3
|
||||
#endif
|
||||
|
||||
/* The following is the InnoDB version as shown in
|
||||
|
@ -122,6 +122,15 @@ ut_max(
|
||||
/*===*/
|
||||
ulint n1, /*!< in: first number */
|
||||
ulint n2); /*!< in: second number */
|
||||
/******************************************************//**
|
||||
Calculates the maximum of two ib_uint64_t values.
|
||||
@return the maximum */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
ut_max_uint64(
|
||||
/*==========*/
|
||||
ib_uint64_t n1, /*!< in: first number */
|
||||
ib_uint64_t n2); /*!< in: second number */
|
||||
/****************************************************************//**
|
||||
Calculates minimum of two ulint-pairs. */
|
||||
UNIV_INLINE
|
||||
|
@ -49,6 +49,19 @@ ut_max(
|
||||
return((n1 <= n2) ? n2 : n1);
|
||||
}
|
||||
|
||||
/******************************************************//**
|
||||
Calculates the maximum of two ib_uint64_t values.
|
||||
@return the maximum */
|
||||
UNIV_INLINE
|
||||
ib_uint64_t
|
||||
ut_max_uint64(
|
||||
/*==========*/
|
||||
ib_uint64_t n1, /*!< in: first number */
|
||||
ib_uint64_t n2) /*!< in: second number */
|
||||
{
|
||||
return((n1 <= n2) ? n2 : n1);
|
||||
}
|
||||
|
||||
/****************************************************************//**
|
||||
Calculates minimum of two ulint-pairs. */
|
||||
UNIV_INLINE
|
||||
|
@ -5481,9 +5481,14 @@ lock_sec_rec_read_check_and_lock(
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
|
||||
if (UNIV_UNLIKELY((thr && thr_get_trx(thr)->fake_changes))) {
|
||||
if (!srv_fake_changes_locks) {
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
if (mode == LOCK_X) {
|
||||
mode = LOCK_S;
|
||||
}
|
||||
}
|
||||
|
||||
heap_no = page_rec_get_heap_no(rec);
|
||||
|
||||
@ -5561,9 +5566,14 @@ lock_clust_rec_read_check_and_lock(
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
if (thr && thr_get_trx(thr)->fake_changes && mode == LOCK_X) {
|
||||
if (UNIV_UNLIKELY((thr && thr_get_trx(thr)->fake_changes))) {
|
||||
if (!srv_fake_changes_locks) {
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
if (mode == LOCK_X) {
|
||||
mode = LOCK_S;
|
||||
}
|
||||
}
|
||||
|
||||
heap_no = page_rec_get_heap_no(rec);
|
||||
|
||||
|
@ -248,7 +248,7 @@ log_check_tracking_margin(
|
||||
checked for the already-written log. */
|
||||
{
|
||||
ib_uint64_t tracked_lsn;
|
||||
ulint tracked_lsn_age;
|
||||
ib_uint64_t tracked_lsn_age;
|
||||
|
||||
if (!srv_track_changed_pages) {
|
||||
return FALSE;
|
||||
@ -460,7 +460,7 @@ log_close(void)
|
||||
ib_uint64_t oldest_lsn;
|
||||
ib_uint64_t lsn;
|
||||
ib_uint64_t tracked_lsn;
|
||||
ulint tracked_lsn_age;
|
||||
ib_uint64_t tracked_lsn_age;
|
||||
log_t* log = log_sys;
|
||||
ib_uint64_t checkpoint_age;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2158,8 +2158,10 @@ os_file_set_eof_at(
|
||||
ib_uint64_t new_len)/*!< in: new file length */
|
||||
{
|
||||
#ifdef __WIN__
|
||||
/* TODO: untested! */
|
||||
return(!_chsize_s(file, new_len));
|
||||
LARGE_INTEGER li, li2;
|
||||
li.QuadPart = new_len;
|
||||
return(SetFilePointerEx(file, li, &li2,FILE_BEGIN)
|
||||
&& SetEndOfFile(file));
|
||||
#else
|
||||
/* TODO: works only with -D_FILE_OFFSET_BITS=64 ? */
|
||||
return(!ftruncate(file, new_len));
|
||||
|
@ -2012,7 +2012,10 @@ row_ins_index_entry_low(
|
||||
the function will return in both low_match and up_match of the
|
||||
cursor sensible values */
|
||||
|
||||
if (dict_index_is_clust(index)) {
|
||||
if (UNIV_UNLIKELY(thr_get_trx(thr)->fake_changes)) {
|
||||
search_mode = (mode & BTR_MODIFY_TREE)
|
||||
? BTR_SEARCH_TREE : BTR_SEARCH_LEAF;
|
||||
} else if (dict_index_is_clust(index)) {
|
||||
search_mode = mode;
|
||||
} else if (!(thr_get_trx(thr)->check_unique_secondary)) {
|
||||
search_mode = mode | BTR_INSERT | BTR_IGNORE_SEC_UNIQUE;
|
||||
@ -2021,7 +2024,7 @@ row_ins_index_entry_low(
|
||||
}
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
|
||||
thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : search_mode,
|
||||
search_mode,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
|
||||
if (cursor.flag == BTR_CUR_INSERT_TO_IBUF) {
|
||||
|
@ -1277,17 +1277,19 @@ run_again:
|
||||
|
||||
que_thr_stop_for_mysql_no_error(thr, trx);
|
||||
|
||||
prebuilt->table->stat_n_rows++;
|
||||
if (UNIV_LIKELY(!(trx->fake_changes))) {
|
||||
|
||||
srv_n_rows_inserted++;
|
||||
prebuilt->table->stat_n_rows++;
|
||||
|
||||
if (prebuilt->table->stat_n_rows == 0) {
|
||||
/* Avoid wrap-over */
|
||||
prebuilt->table->stat_n_rows--;
|
||||
}
|
||||
|
||||
if (!(trx->fake_changes))
|
||||
srv_n_rows_inserted++;
|
||||
row_update_statistics_if_needed(prebuilt->table);
|
||||
}
|
||||
|
||||
trx->op_info = "";
|
||||
|
||||
return((int) err);
|
||||
@ -1534,6 +1536,11 @@ run_again:
|
||||
|
||||
que_thr_stop_for_mysql_no_error(thr, trx);
|
||||
|
||||
if (UNIV_UNLIKELY(trx->fake_changes)) {
|
||||
trx->op_info = "";
|
||||
return((int) err);
|
||||
}
|
||||
|
||||
if (node->is_delete) {
|
||||
if (prebuilt->table->stat_n_rows > 0) {
|
||||
prebuilt->table->stat_n_rows--;
|
||||
@ -1548,7 +1555,6 @@ run_again:
|
||||
that changes indexed columns, UPDATEs that change only non-indexed
|
||||
columns would not affect statistics. */
|
||||
if (node->is_delete || !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {
|
||||
if (!(trx->fake_changes))
|
||||
row_update_statistics_if_needed(prebuilt->table);
|
||||
}
|
||||
|
||||
@ -1756,6 +1762,11 @@ run_again:
|
||||
return(err);
|
||||
}
|
||||
|
||||
if (UNIV_UNLIKELY((trx->fake_changes))) {
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
if (node->is_delete) {
|
||||
if (table->stat_n_rows > 0) {
|
||||
table->stat_n_rows--;
|
||||
@ -1766,7 +1777,6 @@ run_again:
|
||||
srv_n_rows_updated++;
|
||||
}
|
||||
|
||||
if (!(trx->fake_changes))
|
||||
row_update_statistics_if_needed(table);
|
||||
|
||||
return(err);
|
||||
|
@ -2018,7 +2018,8 @@ row_upd_clust_rec(
|
||||
the same transaction do not modify the record in the meantime.
|
||||
Therefore we can assert that the restoration of the cursor succeeds. */
|
||||
|
||||
ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes ? BTR_SEARCH_LEAF : BTR_MODIFY_TREE,
|
||||
ut_a(btr_pcur_restore_position(thr_get_trx(thr)->fake_changes
|
||||
? BTR_SEARCH_TREE : BTR_MODIFY_TREE,
|
||||
pcur, mtr));
|
||||
|
||||
ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
|
||||
|
@ -179,8 +179,14 @@ UNIV_INTERN ibool srv_recovery_stats = FALSE;
|
||||
|
||||
UNIV_INTERN my_bool srv_track_changed_pages = TRUE;
|
||||
|
||||
UNIV_INTERN ib_uint64_t srv_max_bitmap_file_size = 100 * 1024 * 1024;
|
||||
|
||||
UNIV_INTERN ulonglong srv_changed_pages_limit = 0;
|
||||
|
||||
/** When TRUE, fake change transcations take S rather than X row locks.
|
||||
When FALSE, row locks are not taken at all. */
|
||||
UNIV_INTERN my_bool srv_fake_changes_locks = TRUE;
|
||||
|
||||
/* if TRUE, then we auto-extend the last data file */
|
||||
UNIV_INTERN ibool srv_auto_extend_last_data_file = FALSE;
|
||||
/* if != 0, this tells the max size auto-extending may increase the
|
||||
|
@ -1148,6 +1148,24 @@ skip_size_check:
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Initializes the log tracking subsystem and starts its thread. */
|
||||
static
|
||||
void
|
||||
init_log_online(void)
|
||||
/*=================*/
|
||||
{
|
||||
if (srv_track_changed_pages) {
|
||||
|
||||
log_online_read_init();
|
||||
|
||||
/* Create the thread that follows the redo log to output the
|
||||
changed page bitmap */
|
||||
os_thread_create(&srv_redo_log_follow_thread, NULL,
|
||||
thread_ids + 5 + SRV_MAX_N_IO_THREADS);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************
|
||||
Starts InnoDB and creates a new database if database files
|
||||
are not found and the user wants.
|
||||
@ -1794,6 +1812,8 @@ innobase_start_or_create_for_mysql(void)
|
||||
trx_sys_file_format_init();
|
||||
|
||||
if (create_new_db) {
|
||||
init_log_online();
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
fsp_header_init(0, sum_of_new_sizes, &mtr);
|
||||
@ -1893,6 +1913,8 @@ innobase_start_or_create_for_mysql(void)
|
||||
return(DB_ERROR);
|
||||
}
|
||||
|
||||
init_log_online();
|
||||
|
||||
/* Since the insert buffer init is in dict_boot, and the
|
||||
insert buffer is needed in any disk i/o, first we call
|
||||
dict_boot(). Note that trx_sys_init_at_db_start() only needs
|
||||
@ -2040,19 +2062,6 @@ innobase_start_or_create_for_mysql(void)
|
||||
if (srv_auto_lru_dump && srv_blocking_lru_restore)
|
||||
buf_LRU_file_restore();
|
||||
|
||||
if (srv_track_changed_pages) {
|
||||
|
||||
/* Initialize the log tracking subsystem here to block
|
||||
server startup until it's completed due to the potential
|
||||
need to re-read previous server run's log. */
|
||||
log_online_read_init();
|
||||
|
||||
/* Create the thread that follows the redo log to output the
|
||||
changed page bitmap */
|
||||
os_thread_create(&srv_redo_log_follow_thread, NULL,
|
||||
thread_ids + 6 + SRV_MAX_N_IO_THREADS);
|
||||
}
|
||||
|
||||
srv_is_being_started = FALSE;
|
||||
|
||||
err = dict_create_or_check_foreign_constraint_tables();
|
||||
|
Reference in New Issue
Block a user