mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 20:42:30 +01:00
Merge XtraDB from Percona Server 5.1.56-12.7 into MariaDB-5.1.
This commit is contained in:
commit
8b046db411
70 changed files with 1337 additions and 910 deletions
|
@ -20,3 +20,4 @@ percona_server_variables: Feature not merged into MariaDB
|
|||
percona_slow_query_log-log_slow_verbosity: InnoDB filtering information not fully merged into MariaDB
|
||||
|
||||
percona_innodb_buffer_pool_shm: Requires big shmmax not default on many systems
|
||||
userstat_bug602047: Feature not merged into MariaDB
|
||||
|
|
13
mysql-test/suite/percona/innodb_fix_misc_bug51325.result
Normal file
13
mysql-test/suite/percona/innodb_fix_misc_bug51325.result
Normal file
|
@ -0,0 +1,13 @@
|
|||
DROP TABLE IF EXISTS t1;
|
||||
SET GLOBAL innodb_file_per_table=ON;
|
||||
SHOW VARIABLES LIKE 'innodb_lazy_drop_table';
|
||||
Variable_name Value
|
||||
innodb_lazy_drop_table 0
|
||||
SET GLOBAL innodb_lazy_drop_table=1;
|
||||
SHOW VARIABLES LIKE 'innodb_lazy_drop_table';
|
||||
Variable_name Value
|
||||
innodb_lazy_drop_table 1
|
||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||
DROP TABLE t1;
|
||||
SET GLOBAL innodb_lazy_drop_table=default;
|
||||
SET GLOBAL innodb_file_per_table=default;
|
13
mysql-test/suite/percona/innodb_fix_misc_bug51325.test
Normal file
13
mysql-test/suite/percona/innodb_fix_misc_bug51325.test
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Test for 'innodb_lazy_drop_table' variable
|
||||
--source include/have_innodb.inc
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
SET GLOBAL innodb_file_per_table=ON;
|
||||
SHOW VARIABLES LIKE 'innodb_lazy_drop_table';
|
||||
SET GLOBAL innodb_lazy_drop_table=1;
|
||||
SHOW VARIABLES LIKE 'innodb_lazy_drop_table';
|
||||
CREATE TABLE t1 (a INT) ENGINE=InnoDB;
|
||||
DROP TABLE t1;
|
||||
SET GLOBAL innodb_lazy_drop_table=default;
|
||||
SET GLOBAL innodb_file_per_table=default;
|
|
@ -1,9 +1,5 @@
|
|||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
DROP TABLE IF EXISTS t;
|
||||
CREATE TABLE t(id INT);
|
||||
INSERT INTO t SELECT SLEEP(10);
|
||||
|
@ -15,7 +11,11 @@ master 1
|
|||
slave count(*)
|
||||
slave 0
|
||||
SHOW SLAVE STATUS NOLOCK;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
slave count(*)
|
||||
slave 1
|
||||
DROP TABLE t;
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
|
|
|
@ -45,3 +45,6 @@ connection slave;
|
|||
connection master;
|
||||
DROP TABLE t;
|
||||
sync_slave_with_master;
|
||||
|
||||
STOP SLAVE;
|
||||
--source include/wait_for_slave_to_stop.inc
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
DROP TABLE IF EXISTS t;
|
||||
CREATE TABLE t(id INT,data CHAR(30)) ENGINE=InnoDB;
|
||||
INSERT INTO t VALUES
|
||||
|
@ -15,7 +11,9 @@ INSERT INTO t VALUES
|
|||
INSERT INTO t SELECT t2.id,t2.data from t as t1, t as t2;
|
||||
INSERT INTO t SELECT t2.id,t2.data from t as t1, t as t2;
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
INSERT INTO t SELECT t.id,t.data from t;
|
||||
DROP TABLE IF EXISTS t;
|
||||
FLUSH LOGS;
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
# Activate master-slave replication
|
||||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
# Make table t for test
|
||||
DROP TABLE IF EXISTS t;
|
||||
CREATE TABLE t(id INT);
|
||||
# Start slave replication
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
INSERT INTO t VALUES (1);
|
||||
# Read and change log_slow_slave_statements to ON on slave
|
||||
show variables like 'log_slow_slave_statements';
|
||||
|
@ -22,7 +19,9 @@ log_slow_slave_statements ON
|
|||
INSERT INTO t VALUES (2);
|
||||
# Restart slave
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
INSERT INTO t VALUES (3);
|
||||
show variables like 'long_query_time';
|
||||
Variable_name Value
|
||||
|
@ -91,3 +90,5 @@ FLUSH LOGS;
|
|||
1
|
||||
set global log_slow_slave_statements=OFF;
|
||||
DROP TABLE t;
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
|
|
|
@ -111,3 +111,6 @@ DROP TABLE t;
|
|||
|
||||
sync_slave_with_master;
|
||||
connection slave;
|
||||
|
||||
STOP SLAVE;
|
||||
-- source include/wait_for_slave_to_stop.inc
|
||||
|
|
|
@ -1,15 +1,12 @@
|
|||
# Activate master-slave replication
|
||||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
include/master-slave.inc
|
||||
[connection master]
|
||||
# Make table t for test
|
||||
DROP TABLE IF EXISTS t;
|
||||
CREATE TABLE t(id INT);
|
||||
# Start slave replication
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
INSERT INTO t VALUES (1);
|
||||
# Read information about master binlog
|
||||
# Sync(1) slave thread
|
||||
|
@ -26,7 +23,9 @@ INSERT INTO t VALUES (2);
|
|||
# Sync slave(2) thread
|
||||
# Restart slave
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
INSERT INTO t VALUES (3);
|
||||
# Read information about master binlog
|
||||
# Sync(3) slave thread
|
||||
|
@ -43,7 +42,9 @@ INSERT INTO t VALUES (4);
|
|||
# Sync slave(4) thread
|
||||
# Restart slave
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
INSERT INTO t VALUES (5);
|
||||
# Read information about master binlog
|
||||
# Sync slave(5) thread
|
||||
|
@ -60,7 +61,9 @@ INSERT INTO t VALUES (6);
|
|||
# Sync slave(6) thread
|
||||
# Restart slave
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
START SLAVE;
|
||||
include/wait_for_slave_to_start.inc
|
||||
INSERT INTO t VALUES (7);
|
||||
# Read information about master binlog
|
||||
# Sync slave(7) thread
|
||||
|
@ -86,3 +89,5 @@ set global log_slow_slave_statements=OFF;
|
|||
DROP TABLE t;
|
||||
# Read information about master binlog
|
||||
# Sync slave(8) thread
|
||||
STOP SLAVE;
|
||||
include/wait_for_slave_to_stop.inc
|
||||
|
|
|
@ -163,3 +163,6 @@ let $binlog_position = query_get_value(SHOW MASTER STATUS,Position,1);
|
|||
-- echo # Sync slave(8) thread
|
||||
connection slave;
|
||||
let $sync_result = `SELECT MASTER_POS_WAIT('$binlog_file',$binlog_position)`;
|
||||
|
||||
STOP SLAVE;
|
||||
-- source include/wait_for_slave_to_stop.inc
|
||||
|
|
16
mysql-test/suite/percona/userstat_bug602047.result
Normal file
16
mysql-test/suite/percona/userstat_bug602047.result
Normal file
|
@ -0,0 +1,16 @@
|
|||
DROP TABLE IF EXISTS t1;
|
||||
SET @userstat_running_old= @@userstat_running;
|
||||
SET GLOBAL userstat_running=ON;
|
||||
CREATE TABLE t1 ( id int(10), PRIMARY KEY (id)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
|
||||
SELECT COUNT(*) FROM t1;
|
||||
COUNT(*)
|
||||
10
|
||||
SELECT ROWS_READ FROM information_schema.table_statistics WHERE TABLE_NAME='t1';
|
||||
ROWS_READ
|
||||
10
|
||||
SELECT ROWS_READ FROM information_schema.index_statistics WHERE TABLE_NAME='t1';
|
||||
ROWS_READ
|
||||
10
|
||||
SET GLOBAL userstat_running= @userstat_running_old;
|
||||
DROP TABLE t1;
|
13
mysql-test/suite/percona/userstat_bug602047.test
Normal file
13
mysql-test/suite/percona/userstat_bug602047.test
Normal file
|
@ -0,0 +1,13 @@
|
|||
--source include/have_innodb.inc
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
SET @userstat_running_old= @@userstat_running;
|
||||
SET GLOBAL userstat_running=ON;
|
||||
CREATE TABLE t1 ( id int(10), PRIMARY KEY (id)) ENGINE=InnoDB;
|
||||
INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
|
||||
SELECT COUNT(*) FROM t1;
|
||||
SELECT ROWS_READ FROM information_schema.table_statistics WHERE TABLE_NAME='t1';
|
||||
SELECT ROWS_READ FROM information_schema.index_statistics WHERE TABLE_NAME='t1';
|
||||
SET GLOBAL userstat_running= @userstat_running_old;
|
||||
DROP TABLE t1;
|
|
@ -1,3 +1,61 @@
|
|||
2011-01-31 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c, include/row0upd.h,
|
||||
row/row0purge.c, row/row0umod.c, row/row0upd.c:
|
||||
Bug#59230 assert 0 row_upd_changes_ord_field_binary()
|
||||
in post-crash rollback or purge
|
||||
|
||||
2011-01-27 The InnoDB Team
|
||||
|
||||
* btr/btr0cur.c:
|
||||
Bug#59465 btr_estimate_number_of_different_key_vals use
|
||||
incorrect offset for external_size
|
||||
|
||||
2011-01-27 The InnoDB Team
|
||||
|
||||
* include/trx0trx.h, trx/trx0trx.c:
|
||||
Bug#59440 Race condition in XA ROLLBACK and XA COMMIT
|
||||
after server restart
|
||||
|
||||
2011-01-25 The InnoDB Team
|
||||
|
||||
* row/row0upd.c:
|
||||
Bug#59585 Fix 58912 introduces compiler warning
|
||||
due to potentially uninitialized variable
|
||||
|
||||
2011-01-25 The InnoDB Team
|
||||
|
||||
* mtr/mtr0log.c:
|
||||
Bug#59486 Incorrect usage of UNIV_UNLIKELY() in mlog_parse_string()
|
||||
|
||||
2011-01-25 The InnoDB Team
|
||||
|
||||
* row/row0vers.c:
|
||||
Fix Bug#59464 Race condition in row_vers_build_for_semi_consistent_read
|
||||
|
||||
2011-01-25 The InnoDB Team
|
||||
|
||||
* btr/btr0btr.c, btr/btr0cur.c, btr/btr0sea.c,
|
||||
buf/buf0buddy.c, buf/buf0buf.c, buf/buf0lru.c,
|
||||
include/buf0buf.h, include/buf0buf.ic, include/buf0lru.h,
|
||||
mem/mem0mem.c, page/page0zip.c:
|
||||
Fix Bug#59707 Unused compression-related parameters
|
||||
in buffer pool functions
|
||||
|
||||
2011-01-18 The InnoDB Team
|
||||
|
||||
* include/sync0rw.h, sync/sync0arr.c, sync/sync0rw.c:
|
||||
Fix Bug#59579 rw_lock_debug_print outputs to stderr, not to
|
||||
SHOW ENGINE INNODB STATUS
|
||||
|
||||
2011-01-14 The InnoDB Team
|
||||
* btr/btr0cur.c, dict/dict0dict.c, handler/ha_innodb.cc,
|
||||
include/btr0cur.h, include/dict0mem.h, include/rem0cmp.h,
|
||||
include/rem0cmp.ic, include/srv0srv.h, rem/rem0cmp.c,
|
||||
srv/srv0srv.c, innodb_bug30423.test:
|
||||
Fix Bug#30423 InnoDBs treatment of NULL in index stats causes
|
||||
bad "rows examined" estimates
|
||||
|
||||
2011-01-06 The InnoDB Team
|
||||
* row/row0merge.c:
|
||||
Fix Bug#59312 Examine MAX_FULL_NAME_LEN in InnoDB to address
|
||||
|
|
|
@ -1009,7 +1009,7 @@ btr_page_reorganize_low(
|
|||
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
temp_block = buf_block_alloc(0);
|
||||
temp_block = buf_block_alloc();
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
ut_ad(block == back_block1);
|
||||
temp_block = back_block2;
|
||||
|
|
|
@ -100,6 +100,18 @@ can be released by page reorganize, then it is reorganized */
|
|||
/*--------------------------------------*/
|
||||
#define BTR_BLOB_HDR_SIZE 8 /*!< Size of a BLOB
|
||||
part header, in bytes */
|
||||
|
||||
/** Estimated table level stats from sampled value.
|
||||
@param value sampled stats
|
||||
@param index index being sampled
|
||||
@param sample number of sampled rows
|
||||
@param ext_size external stored data size
|
||||
@param not_empty table not empty
|
||||
@return estimated table wide stats from sampled value */
|
||||
#define BTR_TABLE_STATS_FROM_SAMPLE(value, index, sample, ext_size, not_empty)\
|
||||
(((value) * (ib_int64_t) index->stat_n_leaf_pages \
|
||||
+ (sample) - 1 + (ext_size) + (not_empty)) / ((sample) + (ext_size)))
|
||||
|
||||
/* @} */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
@ -174,7 +186,7 @@ static
|
|||
ulint
|
||||
btr_rec_get_externally_stored_len(
|
||||
/*==============================*/
|
||||
rec_t* rec, /*!< in: record */
|
||||
const rec_t* rec, /*!< in: record */
|
||||
const ulint* offsets);/*!< in: array returned by rec_get_offsets() */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
|
||||
|
@ -961,108 +973,6 @@ btr_cur_open_at_rnd_pos_func(
|
|||
}
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Positions a cursor at a randomly chosen position within a B-tree
|
||||
after the given path
|
||||
@return TRUE if the position is at the first page, and cursor must point
|
||||
the first record for used by the caller.*/
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
btr_cur_open_at_rnd_pos_after_path(
|
||||
/*====================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint latch_mode, /*!< in: BTR_SEARCH_LEAF, ... */
|
||||
btr_path_t* first_rec_path,
|
||||
btr_cur_t* cursor, /*!< in/out: B-tree cursor */
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
page_cur_t* page_cursor;
|
||||
btr_path_t* slot;
|
||||
ibool is_first_rec = TRUE;
|
||||
ulint page_no;
|
||||
ulint space;
|
||||
ulint zip_size;
|
||||
ulint height;
|
||||
rec_t* node_ptr;
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets = offsets_;
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
if (latch_mode == BTR_MODIFY_TREE) {
|
||||
mtr_x_lock(dict_index_get_lock(index), mtr);
|
||||
} else {
|
||||
mtr_s_lock(dict_index_get_lock(index), mtr);
|
||||
}
|
||||
|
||||
page_cursor = btr_cur_get_page_cur(cursor);
|
||||
cursor->index = index;
|
||||
|
||||
space = dict_index_get_space(index);
|
||||
zip_size = dict_table_zip_size(index->table);
|
||||
page_no = dict_index_get_page(index);
|
||||
|
||||
height = ULINT_UNDEFINED;
|
||||
slot = first_rec_path;
|
||||
|
||||
for (;;) {
|
||||
buf_block_t* block;
|
||||
page_t* page;
|
||||
|
||||
block = buf_page_get_gen(space, zip_size, page_no,
|
||||
RW_NO_LATCH, NULL, BUF_GET,
|
||||
__FILE__, __LINE__, mtr);
|
||||
page = buf_block_get_frame(block);
|
||||
ut_ad(0 == ut_dulint_cmp(index->id,
|
||||
btr_page_get_index_id(page)));
|
||||
|
||||
if (height == ULINT_UNDEFINED) {
|
||||
/* We are in the root node */
|
||||
|
||||
height = btr_page_get_level(page, mtr);
|
||||
}
|
||||
|
||||
if (height == 0) {
|
||||
btr_cur_latch_leaves(page, space, zip_size, page_no,
|
||||
latch_mode, cursor, mtr);
|
||||
}
|
||||
|
||||
if (is_first_rec && slot->nth_rec != ULINT_UNDEFINED) {
|
||||
if (height == 0) {
|
||||
/* must open the first rec */
|
||||
page_cur_open_on_nth_user_rec(block, page_cursor, slot->nth_rec);
|
||||
} else {
|
||||
is_first_rec = page_cur_open_on_rnd_user_rec_after_nth(block,
|
||||
page_cursor, slot->nth_rec);
|
||||
}
|
||||
} else {
|
||||
is_first_rec = FALSE;
|
||||
page_cur_open_on_rnd_user_rec(block, page_cursor);
|
||||
}
|
||||
|
||||
if (height == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
ut_ad(height > 0);
|
||||
|
||||
height--;
|
||||
slot++;
|
||||
|
||||
node_ptr = page_cur_get_rec(page_cursor);
|
||||
offsets = rec_get_offsets(node_ptr, cursor->index, offsets,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
/* Go to the child node */
|
||||
page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
return (is_first_rec);
|
||||
}
|
||||
|
||||
/*==================== B-TREE INSERT =========================*/
|
||||
|
||||
/*************************************************************//**
|
||||
|
@ -1933,8 +1843,8 @@ btr_cur_update_in_place(
|
|||
NOT call it if index is secondary */
|
||||
|
||||
if (!dict_index_is_clust(index)
|
||||
|| row_upd_changes_ord_field_binary(NULL, NULL,
|
||||
index, update)) {
|
||||
|| row_upd_changes_ord_field_binary(index, update, thr,
|
||||
NULL, NULL)) {
|
||||
|
||||
/* Remove possible hash index pointer to this record */
|
||||
btr_search_update_hash_on_delete(cursor);
|
||||
|
@ -3383,149 +3293,43 @@ btr_estimate_n_rows_in_range(
|
|||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Estimates the number of pages which have not null value of the key of n_cols.
|
||||
@return estimated number of pages */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_estimate_n_pages_not_null(
|
||||
/*=========================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
ulint n_cols, /*!< in: The cols should be not null */
|
||||
btr_path_t* path1) /*!< in: path1[BTR_PATH_ARRAY_N_SLOTS] */
|
||||
Record the number of non_null key values in a given index for
|
||||
each n-column prefix of the index where n < dict_index_get_n_unique(index).
|
||||
The estimates are eventually stored in the array:
|
||||
index->stat_n_non_null_key_vals. */
|
||||
static
|
||||
void
|
||||
btr_record_not_null_field_in_rec(
|
||||
/*=============================*/
|
||||
rec_t* rec, /*!< in: physical record */
|
||||
ulint n_unique, /*!< in: dict_index_get_n_unique(index),
|
||||
number of columns uniquely determine
|
||||
an index entry */
|
||||
const ulint* offsets, /*!< in: rec_get_offsets(rec, index),
|
||||
its size could be for all fields or
|
||||
that of "n_unique" */
|
||||
ib_int64_t* n_not_null) /*!< in/out: array to record number of
|
||||
not null rows for n-column prefix */
|
||||
{
|
||||
dtuple_t* tuple1;
|
||||
btr_path_t path2[BTR_PATH_ARRAY_N_SLOTS];
|
||||
btr_cur_t cursor;
|
||||
btr_path_t* slot1;
|
||||
btr_path_t* slot2;
|
||||
ibool diverged;
|
||||
ibool diverged_lot;
|
||||
ulint divergence_level;
|
||||
ulint n_pages;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
mem_heap_t* heap;
|
||||
ulint i;
|
||||
|
||||
heap = mem_heap_create(n_cols * sizeof(dfield_t)
|
||||
+ sizeof(dtuple_t));
|
||||
ut_ad(rec_offs_n_fields(offsets) >= n_unique);
|
||||
|
||||
/* make tuple1 (NULL,NULL,,,) from n_cols */
|
||||
tuple1 = dtuple_create(heap, n_cols);
|
||||
dict_index_copy_types(tuple1, index, n_cols);
|
||||
|
||||
for (i = 0; i < n_cols; i++) {
|
||||
dfield_set_null(dtuple_get_nth_field(tuple1, i));
|
||||
if (n_not_null == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
mtr_start(&mtr);
|
||||
for (i = 0; i < n_unique; i++) {
|
||||
ulint rec_len;
|
||||
byte* field;
|
||||
|
||||
cursor.path_arr = path1;
|
||||
field = rec_get_nth_field(rec, offsets, i, &rec_len);
|
||||
|
||||
btr_cur_search_to_nth_level(index, 0, tuple1, PAGE_CUR_G,
|
||||
BTR_SEARCH_LEAF | BTR_ESTIMATE,
|
||||
&cursor, 0, __FILE__, __LINE__, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
cursor.path_arr = path2;
|
||||
|
||||
btr_cur_open_at_index_side(FALSE, index,
|
||||
BTR_SEARCH_LEAF | BTR_ESTIMATE,
|
||||
&cursor, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
/* We have the path information for the range in path1 and path2 */
|
||||
|
||||
n_pages = 1;
|
||||
diverged = FALSE; /* This becomes true when the path is not
|
||||
the same any more */
|
||||
diverged_lot = FALSE; /* This becomes true when the paths are
|
||||
not the same or adjacent any more */
|
||||
divergence_level = 1000000; /* This is the level where paths diverged
|
||||
a lot */
|
||||
for (i = 0; ; i++) {
|
||||
ut_ad(i < BTR_PATH_ARRAY_N_SLOTS);
|
||||
|
||||
slot1 = path1 + i;
|
||||
slot2 = path2 + i;
|
||||
|
||||
if ((slot1 + 1)->nth_rec == ULINT_UNDEFINED
|
||||
|| (slot2 + 1)->nth_rec == ULINT_UNDEFINED) {
|
||||
|
||||
if (i > divergence_level + 1) {
|
||||
/* In trees whose height is > 1 our algorithm
|
||||
tends to underestimate: multiply the estimate
|
||||
by 2: */
|
||||
|
||||
n_pages = n_pages * 2;
|
||||
}
|
||||
|
||||
/* Do not estimate the number of rows in the range
|
||||
to over 1 / 2 of the estimated rows in the whole
|
||||
table */
|
||||
|
||||
if (n_pages > index->stat_n_leaf_pages / 2) {
|
||||
n_pages = index->stat_n_leaf_pages / 2;
|
||||
|
||||
/* If there are just 0 or 1 rows in the table,
|
||||
then we estimate all rows are in the range */
|
||||
|
||||
if (n_pages == 0) {
|
||||
n_pages = index->stat_n_leaf_pages;
|
||||
}
|
||||
}
|
||||
|
||||
return(n_pages);
|
||||
}
|
||||
|
||||
if (!diverged && slot1->nth_rec != slot2->nth_rec) {
|
||||
|
||||
diverged = TRUE;
|
||||
|
||||
if (slot1->nth_rec < slot2->nth_rec) {
|
||||
n_pages = slot2->nth_rec - slot1->nth_rec;
|
||||
|
||||
if (n_pages > 1) {
|
||||
diverged_lot = TRUE;
|
||||
divergence_level = i;
|
||||
}
|
||||
} else {
|
||||
/* Maybe the tree has changed between
|
||||
searches */
|
||||
|
||||
return(10);
|
||||
}
|
||||
|
||||
} else if (diverged && !diverged_lot) {
|
||||
|
||||
if (slot1->nth_rec < slot1->n_recs
|
||||
|| slot2->nth_rec > 1) {
|
||||
|
||||
diverged_lot = TRUE;
|
||||
divergence_level = i;
|
||||
|
||||
n_pages = 0;
|
||||
|
||||
if (slot1->nth_rec < slot1->n_recs) {
|
||||
n_pages += slot1->n_recs
|
||||
- slot1->nth_rec;
|
||||
}
|
||||
|
||||
if (slot2->nth_rec > 1) {
|
||||
n_pages += slot2->nth_rec - 1;
|
||||
}
|
||||
}
|
||||
} else if (diverged_lot) {
|
||||
|
||||
n_pages = (n_pages * (slot1->n_recs + slot2->n_recs))
|
||||
/ 2;
|
||||
if (rec_len != UNIV_SQL_NULL) {
|
||||
n_not_null[i]++;
|
||||
} else {
|
||||
/* Break if we hit the first NULL value */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3533,7 +3337,10 @@ btr_estimate_n_pages_not_null(
|
|||
/*******************************************************************//**
|
||||
Estimates the number of different key values in a given index, for
|
||||
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
|
||||
The estimates are stored in the array index->stat_n_diff_key_vals. */
|
||||
The estimates are stored in the array index->stat_n_diff_key_vals.
|
||||
If innodb_stats_method is "nulls_ignored", we also record the number of
|
||||
non-null values for each prefix and store the estimates in
|
||||
array index->stat_n_non_null_key_vals. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_estimate_number_of_different_key_vals(
|
||||
|
@ -3547,6 +3354,8 @@ btr_estimate_number_of_different_key_vals(
|
|||
ulint matched_fields;
|
||||
ulint matched_bytes;
|
||||
ib_int64_t* n_diff;
|
||||
ib_int64_t* n_not_null;
|
||||
ibool stats_null_not_equal;
|
||||
ullint n_sample_pages; /* number of pages to sample */
|
||||
ulint not_empty_flag = 0;
|
||||
ulint total_external_size = 0;
|
||||
|
@ -3555,42 +3364,49 @@ btr_estimate_number_of_different_key_vals(
|
|||
ullint add_on;
|
||||
mtr_t mtr;
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint offsets_rec_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint offsets_next_rec_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint* offsets_rec = offsets_rec_;
|
||||
ulint* offsets_next_rec= offsets_next_rec_;
|
||||
ulint stats_method = srv_stats_method;
|
||||
btr_path_t first_rec_path[BTR_PATH_ARRAY_N_SLOTS];
|
||||
ulint effective_pages; /* effective leaf pages */
|
||||
rec_offs_init(offsets_rec_);
|
||||
rec_offs_init(offsets_next_rec_);
|
||||
ulint* offsets_rec = NULL;
|
||||
ulint* offsets_next_rec = NULL;
|
||||
|
||||
n_cols = dict_index_get_n_unique(index);
|
||||
|
||||
if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) {
|
||||
/* estimate effective pages and path for the first effective record */
|
||||
/* TODO: make it work also for n_cols > 1. */
|
||||
effective_pages = btr_estimate_n_pages_not_null(index, 1 /*k*/, first_rec_path);
|
||||
heap = mem_heap_create((sizeof *n_diff + sizeof *n_not_null)
|
||||
* (n_cols + 1)
|
||||
+ dict_index_get_n_fields(index)
|
||||
* (sizeof *offsets_rec
|
||||
+ sizeof *offsets_next_rec));
|
||||
|
||||
if (!effective_pages) {
|
||||
for (j = 0; j <= n_cols; j++) {
|
||||
index->stat_n_diff_key_vals[j] = (ib_int64_t)index->stat_n_leaf_pages;
|
||||
}
|
||||
return;
|
||||
} else if (effective_pages > index->stat_n_leaf_pages) {
|
||||
effective_pages = index->stat_n_leaf_pages;
|
||||
}
|
||||
} else {
|
||||
effective_pages = index->stat_n_leaf_pages;
|
||||
}
|
||||
n_diff = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
|
||||
|
||||
n_diff = mem_zalloc((n_cols + 1) * sizeof(ib_int64_t));
|
||||
n_not_null = NULL;
|
||||
|
||||
/* Check srv_innodb_stats_method setting, and decide whether we
|
||||
need to record non-null value and also decide if NULL is
|
||||
considered equal (by setting stats_null_not_equal value) */
|
||||
switch (srv_innodb_stats_method) {
|
||||
case SRV_STATS_NULLS_IGNORED:
|
||||
n_not_null = mem_heap_zalloc(heap, (n_cols + 1)
|
||||
* sizeof *n_not_null);
|
||||
/* fall through */
|
||||
|
||||
case SRV_STATS_NULLS_UNEQUAL:
|
||||
/* for both SRV_STATS_NULLS_IGNORED and SRV_STATS_NULLS_UNEQUAL
|
||||
case, we will treat NULLs as unequal value */
|
||||
stats_null_not_equal = TRUE;
|
||||
break;
|
||||
|
||||
case SRV_STATS_NULLS_EQUAL:
|
||||
stats_null_not_equal = FALSE;
|
||||
break;
|
||||
|
||||
default:
|
||||
ut_error;
|
||||
}
|
||||
|
||||
/* It makes no sense to test more pages than are contained
|
||||
in the index, thus we lower the number if it is too high */
|
||||
if (srv_stats_sample_pages > effective_pages) {
|
||||
if (effective_pages > 0) {
|
||||
n_sample_pages = effective_pages;
|
||||
if (srv_stats_sample_pages > index->stat_index_size) {
|
||||
if (index->stat_index_size > 0) {
|
||||
n_sample_pages = index->stat_index_size;
|
||||
} else {
|
||||
n_sample_pages = 1;
|
||||
}
|
||||
|
@ -3601,16 +3417,9 @@ btr_estimate_number_of_different_key_vals(
|
|||
/* We sample some pages in the index to get an estimate */
|
||||
|
||||
for (i = 0; i < n_sample_pages; i++) {
|
||||
rec_t* supremum;
|
||||
ibool is_first_page = TRUE;
|
||||
mtr_start(&mtr);
|
||||
|
||||
if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) {
|
||||
is_first_page = btr_cur_open_at_rnd_pos_after_path(index, BTR_SEARCH_LEAF,
|
||||
first_rec_path, &cursor, &mtr);
|
||||
} else {
|
||||
btr_cur_open_at_rnd_pos(index, BTR_SEARCH_LEAF, &cursor, &mtr);
|
||||
}
|
||||
|
||||
/* Count the number of different key values for each prefix of
|
||||
the key on this index page. If the prefix does not determine
|
||||
|
@ -3625,25 +3434,25 @@ btr_estimate_number_of_different_key_vals(
|
|||
}
|
||||
ut_a(page);
|
||||
|
||||
supremum = page_get_supremum_rec(page);
|
||||
if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS && is_first_page) {
|
||||
/* the cursor should be the first record of the page. */
|
||||
/* Counting should be started from here. */
|
||||
rec = btr_cur_get_rec(&cursor);
|
||||
} else {
|
||||
rec = page_rec_get_next(page_get_infimum_rec(page));
|
||||
}
|
||||
|
||||
if (rec != supremum) {
|
||||
if (!page_rec_is_supremum(rec)) {
|
||||
not_empty_flag = 1;
|
||||
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
|
||||
if (n_not_null) {
|
||||
btr_record_not_null_field_in_rec(
|
||||
rec, n_cols, offsets_rec, n_not_null);
|
||||
}
|
||||
}
|
||||
|
||||
while (rec != supremum) {
|
||||
rec_t* next_rec;
|
||||
next_rec = page_rec_get_next(rec);
|
||||
if (next_rec == supremum) {
|
||||
while (!page_rec_is_supremum(rec)) {
|
||||
rec_t* next_rec = page_rec_get_next(rec);
|
||||
if (page_rec_is_supremum(next_rec)) {
|
||||
total_external_size +=
|
||||
btr_rec_get_externally_stored_len(
|
||||
rec, offsets_rec);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3651,15 +3460,14 @@ btr_estimate_number_of_different_key_vals(
|
|||
matched_bytes = 0;
|
||||
offsets_next_rec = rec_get_offsets(next_rec, index,
|
||||
offsets_next_rec,
|
||||
n_cols, &heap);
|
||||
ULINT_UNDEFINED,
|
||||
&heap);
|
||||
|
||||
cmp_rec_rec_with_match(rec, next_rec,
|
||||
offsets_rec, offsets_next_rec,
|
||||
index, &matched_fields,
|
||||
&matched_bytes,
|
||||
(stats_method==SRV_STATS_METHOD_NULLS_NOT_EQUAL) ?
|
||||
SRV_STATS_METHOD_NULLS_NOT_EQUAL :
|
||||
SRV_STATS_METHOD_NULLS_EQUAL);
|
||||
index, stats_null_not_equal,
|
||||
&matched_fields,
|
||||
&matched_bytes);
|
||||
|
||||
for (j = matched_fields + 1; j <= n_cols; j++) {
|
||||
/* We add one if this index record has
|
||||
|
@ -3668,6 +3476,12 @@ btr_estimate_number_of_different_key_vals(
|
|||
n_diff[j]++;
|
||||
}
|
||||
|
||||
if (n_not_null) {
|
||||
btr_record_not_null_field_in_rec(
|
||||
next_rec, n_cols, offsets_next_rec,
|
||||
n_not_null);
|
||||
}
|
||||
|
||||
total_external_size
|
||||
+= btr_rec_get_externally_stored_len(
|
||||
rec, offsets_rec);
|
||||
|
@ -3702,10 +3516,6 @@ btr_estimate_number_of_different_key_vals(
|
|||
}
|
||||
}
|
||||
|
||||
offsets_rec = rec_get_offsets(rec, index, offsets_rec,
|
||||
ULINT_UNDEFINED, &heap);
|
||||
total_external_size += btr_rec_get_externally_stored_len(
|
||||
rec, offsets_rec);
|
||||
mtr_commit(&mtr);
|
||||
}
|
||||
|
||||
|
@ -3719,13 +3529,9 @@ btr_estimate_number_of_different_key_vals(
|
|||
|
||||
for (j = 0; j <= n_cols; j++) {
|
||||
index->stat_n_diff_key_vals[j]
|
||||
= ((n_diff[j]
|
||||
* (ib_int64_t)effective_pages
|
||||
+ n_sample_pages - 1
|
||||
+ total_external_size
|
||||
+ not_empty_flag)
|
||||
/ (n_sample_pages
|
||||
+ total_external_size));
|
||||
= BTR_TABLE_STATS_FROM_SAMPLE(
|
||||
n_diff[j], index, n_sample_pages,
|
||||
total_external_size, not_empty_flag);
|
||||
|
||||
/* If the tree is small, smaller than
|
||||
10 * n_sample_pages + total_external_size, then
|
||||
|
@ -3735,7 +3541,7 @@ btr_estimate_number_of_different_key_vals(
|
|||
different key values, or even more. Let us try to approximate
|
||||
that: */
|
||||
|
||||
add_on = effective_pages
|
||||
add_on = index->stat_n_leaf_pages
|
||||
/ (10 * (n_sample_pages
|
||||
+ total_external_size));
|
||||
|
||||
|
@ -3745,24 +3551,52 @@ btr_estimate_number_of_different_key_vals(
|
|||
|
||||
index->stat_n_diff_key_vals[j] += add_on;
|
||||
|
||||
if (stats_method == SRV_STATS_METHOD_IGNORE_NULLS) {
|
||||
/* index->stat_n_diff_key_vals[k] is used for calc rec_per_key,
|
||||
as "stats.records / index->stat_n_diff_key_vals[x]".
|
||||
So it should be adjusted to the value which is based on whole of the index. */
|
||||
index->stat_n_diff_key_vals[j] =
|
||||
index->stat_n_diff_key_vals[j] * (ib_int64_t)index->stat_n_leaf_pages
|
||||
/ (ib_int64_t)effective_pages;
|
||||
/* Update the stat_n_non_null_key_vals[] with our
|
||||
sampled result. stat_n_non_null_key_vals[] is created
|
||||
and initialized to zero in dict_index_add_to_cache(),
|
||||
along with stat_n_diff_key_vals[] array */
|
||||
if (n_not_null != NULL && (j < n_cols)) {
|
||||
index->stat_n_non_null_key_vals[j] =
|
||||
BTR_TABLE_STATS_FROM_SAMPLE(
|
||||
n_not_null[j], index, n_sample_pages,
|
||||
total_external_size, not_empty_flag);
|
||||
}
|
||||
}
|
||||
|
||||
mem_free(n_diff);
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
|
||||
|
||||
/***********************************************************//**
|
||||
Gets the offset of the pointer to the externally stored part of a field.
|
||||
@return offset of the pointer to the externally stored part */
|
||||
static
|
||||
ulint
|
||||
btr_rec_get_field_ref_offs(
|
||||
/*=======================*/
|
||||
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
|
||||
ulint n) /*!< in: index of the external field */
|
||||
{
|
||||
ulint field_ref_offs;
|
||||
ulint local_len;
|
||||
|
||||
ut_a(rec_offs_nth_extern(offsets, n));
|
||||
field_ref_offs = rec_get_nth_field_offs(offsets, n, &local_len);
|
||||
ut_a(local_len != UNIV_SQL_NULL);
|
||||
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||
|
||||
return(field_ref_offs + local_len - BTR_EXTERN_FIELD_REF_SIZE);
|
||||
}
|
||||
|
||||
/** Gets a pointer to the externally stored part of a field.
|
||||
@param rec record
|
||||
@param offsets rec_get_offsets(rec)
|
||||
@param n index of the externally stored field
|
||||
@return pointer to the externally stored part */
|
||||
#define btr_rec_get_field_ref(rec, offsets, n) \
|
||||
((rec) + btr_rec_get_field_ref_offs(offsets, n))
|
||||
|
||||
/***********************************************************//**
|
||||
Gets the externally stored size of a record, in units of a database page.
|
||||
@return externally stored part, in units of a database page */
|
||||
|
@ -3770,28 +3604,27 @@ static
|
|||
ulint
|
||||
btr_rec_get_externally_stored_len(
|
||||
/*==============================*/
|
||||
rec_t* rec, /*!< in: record */
|
||||
const rec_t* rec, /*!< in: record */
|
||||
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
|
||||
{
|
||||
ulint n_fields;
|
||||
byte* data;
|
||||
ulint local_len;
|
||||
ulint extern_len;
|
||||
ulint total_extern_len = 0;
|
||||
ulint i;
|
||||
|
||||
ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
|
||||
|
||||
if (!rec_offs_any_extern(offsets)) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
n_fields = rec_offs_n_fields(offsets);
|
||||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
if (rec_offs_nth_extern(offsets, i)) {
|
||||
|
||||
data = rec_get_nth_field(rec, offsets, i, &local_len);
|
||||
|
||||
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
|
||||
extern_len = mach_read_from_4(data + local_len
|
||||
+ BTR_EXTERN_LEN + 4);
|
||||
ulint extern_len = mach_read_from_4(
|
||||
btr_rec_get_field_ref(rec, offsets, i)
|
||||
+ BTR_EXTERN_LEN + 4);
|
||||
|
||||
total_extern_len += ut_calc_align(extern_len,
|
||||
UNIV_PAGE_SIZE);
|
||||
|
@ -3821,7 +3654,7 @@ btr_cur_set_ownership_of_extern_field(
|
|||
ulint byte_val;
|
||||
|
||||
data = rec_get_nth_field(rec, offsets, i, &local_len);
|
||||
|
||||
ut_ad(rec_offs_nth_extern(offsets, i));
|
||||
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||
|
||||
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
|
@ -3831,6 +3664,9 @@ btr_cur_set_ownership_of_extern_field(
|
|||
if (val) {
|
||||
byte_val = byte_val & (~BTR_EXTERN_OWNER_FLAG);
|
||||
} else {
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
ut_a(!(byte_val & BTR_EXTERN_OWNER_FLAG));
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
byte_val = byte_val | BTR_EXTERN_OWNER_FLAG;
|
||||
}
|
||||
|
||||
|
@ -4048,8 +3884,7 @@ btr_blob_free(
|
|||
&& buf_block_get_space(block) == space
|
||||
&& buf_block_get_page_no(block) == page_no) {
|
||||
|
||||
if (buf_LRU_free_block(&block->page, all, NULL, TRUE)
|
||||
!= BUF_LRU_FREED
|
||||
if (buf_LRU_free_block(&block->page, all, TRUE) != BUF_LRU_FREED
|
||||
&& all && block->page.zip.data
|
||||
/* Now, buf_LRU_free_block() may release mutex temporarily */
|
||||
&& buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE
|
||||
|
@ -4058,7 +3893,7 @@ btr_blob_free(
|
|||
/* Attempt to deallocate the uncompressed page
|
||||
if the whole block cannot be deallocted. */
|
||||
|
||||
buf_LRU_free_block(&block->page, FALSE, NULL, TRUE);
|
||||
buf_LRU_free_block(&block->page, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4075,8 +3910,8 @@ file segment of the index tree.
|
|||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_store_big_rec_extern_fields(
|
||||
/*============================*/
|
||||
btr_store_big_rec_extern_fields_func(
|
||||
/*=================================*/
|
||||
dict_index_t* index, /*!< in: index of rec; the index tree
|
||||
MUST be X-latched */
|
||||
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
||||
|
@ -4085,11 +3920,17 @@ btr_store_big_rec_extern_fields(
|
|||
the "external storage" flags in offsets
|
||||
will not correspond to rec when
|
||||
this function returns */
|
||||
big_rec_t* big_rec_vec, /*!< in: vector containing fields
|
||||
#ifdef UNIV_DEBUG
|
||||
mtr_t* local_mtr, /*!< in: mtr containing the
|
||||
latch to rec and to the tree */
|
||||
#endif /* UNIV_DEBUG */
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
ibool update_in_place,/*! in: TRUE if the record is updated
|
||||
in place (not delete+insert) */
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
const big_rec_t*big_rec_vec) /*!< in: vector containing fields
|
||||
to be stored externally */
|
||||
mtr_t* local_mtr __attribute__((unused))) /*!< in: mtr
|
||||
containing the latch to rec and to the
|
||||
tree */
|
||||
|
||||
{
|
||||
ulint rec_page_no;
|
||||
byte* field_ref;
|
||||
|
@ -4107,6 +3948,7 @@ btr_store_big_rec_extern_fields(
|
|||
z_stream c_stream;
|
||||
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
ut_ad(rec_offs_any_extern(offsets));
|
||||
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
|
||||
MTR_MEMO_X_LOCK));
|
||||
ut_ad(mtr_memo_contains(local_mtr, rec_block, MTR_MEMO_PAGE_X_FIX));
|
||||
|
@ -4138,21 +3980,37 @@ btr_store_big_rec_extern_fields(
|
|||
ut_a(err == Z_OK);
|
||||
}
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
/* All pointers to externally stored columns in the record
|
||||
must either be zero or they must be pointers to inherited
|
||||
columns, owned by this record or an earlier record version. */
|
||||
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
|
||||
if (!rec_offs_nth_extern(offsets, i)) {
|
||||
continue;
|
||||
}
|
||||
field_ref = btr_rec_get_field_ref(rec, offsets, i);
|
||||
|
||||
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
|
||||
/* Either this must be an update in place,
|
||||
or the BLOB must be inherited, or the BLOB pointer
|
||||
must be zero (will be written in this function). */
|
||||
ut_a(update_in_place
|
||||
|| (field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_INHERITED_FLAG)
|
||||
|| !memcmp(field_ref, field_ref_zero,
|
||||
BTR_EXTERN_FIELD_REF_SIZE));
|
||||
}
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
/* We have to create a file segment to the tablespace
|
||||
for each field and put the pointer to the field in rec */
|
||||
|
||||
for (i = 0; i < big_rec_vec->n_fields; i++) {
|
||||
ut_ad(rec_offs_nth_extern(offsets,
|
||||
big_rec_vec->fields[i].field_no));
|
||||
{
|
||||
ulint local_len;
|
||||
field_ref = rec_get_nth_field(
|
||||
rec, offsets, big_rec_vec->fields[i].field_no,
|
||||
&local_len);
|
||||
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
field_ref += local_len;
|
||||
}
|
||||
field_ref = btr_rec_get_field_ref(
|
||||
rec, offsets, big_rec_vec->fields[i].field_no);
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
/* A zero BLOB pointer should have been initially inserted. */
|
||||
ut_a(!memcmp(field_ref, field_ref_zero,
|
||||
BTR_EXTERN_FIELD_REF_SIZE));
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
extern_len = big_rec_vec->fields[i].len;
|
||||
UNIV_MEM_ASSERT_RW(big_rec_vec->fields[i].data,
|
||||
extern_len);
|
||||
|
@ -4434,6 +4292,23 @@ next_zip_page:
|
|||
mem_heap_free(heap);
|
||||
}
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
/* All pointers to externally stored columns in the record
|
||||
must be valid. */
|
||||
for (i = 0; i < rec_offs_n_fields(offsets); i++) {
|
||||
if (!rec_offs_nth_extern(offsets, i)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
field_ref = btr_rec_get_field_ref(rec, offsets, i);
|
||||
|
||||
/* The pointer must not be zero. */
|
||||
ut_a(0 != memcmp(field_ref, field_ref_zero,
|
||||
BTR_EXTERN_FIELD_REF_SIZE));
|
||||
/* The column must not be disowned by this record. */
|
||||
ut_a(!(field_ref[BTR_EXTERN_LEN] & BTR_EXTERN_OWNER_FLAG));
|
||||
}
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
|
@ -4456,6 +4331,7 @@ btr_check_blob_fil_page_type(
|
|||
if (UNIV_UNLIKELY(type != FIL_PAGE_TYPE_BLOB)) {
|
||||
ulint flags = fil_space_get_flags(space_id);
|
||||
|
||||
#ifndef UNIV_DEBUG /* Improve debug test coverage */
|
||||
if (UNIV_LIKELY
|
||||
((flags & DICT_TF_FORMAT_MASK) == DICT_TF_FORMAT_51)) {
|
||||
/* Old versions of InnoDB did not initialize
|
||||
|
@ -4464,6 +4340,7 @@ btr_check_blob_fil_page_type(
|
|||
a BLOB page that is in Antelope format.*/
|
||||
return;
|
||||
}
|
||||
#endif /* !UNIV_DEBUG */
|
||||
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
|
@ -4513,23 +4390,13 @@ btr_free_externally_stored_field(
|
|||
ulint page_no;
|
||||
ulint next_page_no;
|
||||
mtr_t mtr;
|
||||
#ifdef UNIV_DEBUG
|
||||
|
||||
ut_ad(mtr_memo_contains(local_mtr, dict_index_get_lock(index),
|
||||
MTR_MEMO_X_LOCK));
|
||||
ut_ad(mtr_memo_contains_page(local_mtr, field_ref,
|
||||
MTR_MEMO_PAGE_X_FIX));
|
||||
ut_ad(!rec || rec_offs_validate(rec, index, offsets));
|
||||
|
||||
if (rec) {
|
||||
ulint local_len;
|
||||
const byte* f = rec_get_nth_field(rec, offsets,
|
||||
i, &local_len);
|
||||
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
|
||||
f += local_len;
|
||||
ut_ad(f == field_ref);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
ut_ad(!rec || field_ref == btr_rec_get_field_ref(rec, offsets, i));
|
||||
|
||||
if (UNIV_UNLIKELY(!memcmp(field_ref, field_ref_zero,
|
||||
BTR_EXTERN_FIELD_REF_SIZE))) {
|
||||
|
@ -4694,13 +4561,8 @@ btr_rec_free_externally_stored_fields(
|
|||
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
if (rec_offs_nth_extern(offsets, i)) {
|
||||
ulint len;
|
||||
byte* data
|
||||
= rec_get_nth_field(rec, offsets, i, &len);
|
||||
ut_a(len >= BTR_EXTERN_FIELD_REF_SIZE);
|
||||
|
||||
btr_free_externally_stored_field(
|
||||
index, data + len - BTR_EXTERN_FIELD_REF_SIZE,
|
||||
index, btr_rec_get_field_ref(rec, offsets, i),
|
||||
rec, offsets, page_zip, i, rb_ctx, mtr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,7 +141,7 @@ btr_search_check_free_space_in_heap(void)
|
|||
be enough free space in the hash table. */
|
||||
|
||||
if (heap->free_block == NULL) {
|
||||
buf_block_t* block = buf_block_alloc(0);
|
||||
buf_block_t* block = buf_block_alloc();
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
|
||||
|
@ -1186,7 +1186,7 @@ btr_search_drop_page_hash_index_on_index(
|
|||
/*=====================================*/
|
||||
dict_index_t* index) /* in: record descriptor */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
|
||||
hash_table_t* table;
|
||||
buf_block_t* block;
|
||||
ulint n_fields;
|
||||
|
@ -1202,96 +1202,143 @@ btr_search_drop_page_hash_index_on_index(
|
|||
ulint i;
|
||||
mem_heap_t* heap = NULL;
|
||||
ulint* offsets;
|
||||
ibool released_search_latch;
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
mutex_enter(&LRU_list_mutex);
|
||||
rw_lock_s_lock(&btr_search_latch);
|
||||
|
||||
table = btr_search_sys->hash_index;
|
||||
|
||||
bpage = UT_LIST_GET_LAST(buf_pool->LRU);
|
||||
do {
|
||||
buf_chunk_t* chunks = buf_pool->chunks;
|
||||
buf_chunk_t* chunk = chunks + buf_pool->n_chunks;
|
||||
|
||||
while (bpage != NULL) {
|
||||
block = (buf_block_t*) bpage;
|
||||
if (block->index == index && block->is_hashed) {
|
||||
page = block->frame;
|
||||
released_search_latch = FALSE;
|
||||
|
||||
/* from btr_search_drop_page_hash_index() */
|
||||
n_fields = block->curr_n_fields;
|
||||
n_bytes = block->curr_n_bytes;
|
||||
while (--chunk >= chunks) {
|
||||
block = chunk->blocks;
|
||||
i = chunk->size;
|
||||
|
||||
ut_a(n_fields + n_bytes > 0);
|
||||
|
||||
n_recs = page_get_n_recs(page);
|
||||
|
||||
/* Calculate and cache fold values into an array for fast deletion
|
||||
from the hash index */
|
||||
|
||||
folds = mem_alloc(n_recs * sizeof(ulint));
|
||||
|
||||
n_cached = 0;
|
||||
|
||||
rec = page_get_infimum_rec(page);
|
||||
rec = page_rec_get_next_low(rec, page_is_comp(page));
|
||||
|
||||
index_id = btr_page_get_index_id(page);
|
||||
|
||||
ut_a(0 == ut_dulint_cmp(index_id, index->id));
|
||||
|
||||
prev_fold = 0;
|
||||
|
||||
offsets = NULL;
|
||||
|
||||
while (!page_rec_is_supremum(rec)) {
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
n_fields + (n_bytes > 0), &heap);
|
||||
ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0));
|
||||
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
|
||||
|
||||
if (fold == prev_fold && prev_fold != 0) {
|
||||
|
||||
goto next_rec;
|
||||
retry:
|
||||
for (; i--; block++) {
|
||||
if (buf_block_get_state(block)
|
||||
!= BUF_BLOCK_FILE_PAGE
|
||||
|| block->index != index
|
||||
|| !block->is_hashed) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Remove all hash nodes pointing to this page from the
|
||||
hash chain */
|
||||
page = block->frame;
|
||||
|
||||
folds[n_cached] = fold;
|
||||
n_cached++;
|
||||
next_rec:
|
||||
rec = page_rec_get_next_low(rec, page_rec_is_comp(rec));
|
||||
prev_fold = fold;
|
||||
}
|
||||
/* from btr_search_drop_page_hash_index() */
|
||||
n_fields = block->curr_n_fields;
|
||||
n_bytes = block->curr_n_bytes;
|
||||
|
||||
for (i = 0; i < n_cached; i++) {
|
||||
|
||||
ha_remove_all_nodes_to_page(table, folds[i], page);
|
||||
}
|
||||
/* keeping latch order */
|
||||
rw_lock_s_unlock(&btr_search_latch);
|
||||
released_search_latch = TRUE;
|
||||
rw_lock_x_lock(&block->lock);
|
||||
|
||||
ut_a(index->search_info->ref_count > 0);
|
||||
index->search_info->ref_count--;
|
||||
|
||||
block->is_hashed = FALSE;
|
||||
block->index = NULL;
|
||||
ut_a(n_fields + n_bytes > 0);
|
||||
|
||||
n_recs = page_get_n_recs(page);
|
||||
|
||||
/* Calculate and cache fold values into an array for fast deletion
|
||||
from the hash index */
|
||||
|
||||
folds = mem_alloc(n_recs * sizeof(ulint));
|
||||
|
||||
n_cached = 0;
|
||||
|
||||
rec = page_get_infimum_rec(page);
|
||||
rec = page_rec_get_next_low(rec, page_is_comp(page));
|
||||
|
||||
index_id = btr_page_get_index_id(page);
|
||||
|
||||
ut_a(0 == ut_dulint_cmp(index_id, index->id));
|
||||
|
||||
prev_fold = 0;
|
||||
|
||||
offsets = NULL;
|
||||
|
||||
while (!page_rec_is_supremum(rec)) {
|
||||
offsets = rec_get_offsets(rec, index, offsets,
|
||||
n_fields + (n_bytes > 0), &heap);
|
||||
ut_a(rec_offs_n_fields(offsets) == n_fields + (n_bytes > 0));
|
||||
fold = rec_fold(rec, offsets, n_fields, n_bytes, index_id);
|
||||
|
||||
if (fold == prev_fold && prev_fold != 0) {
|
||||
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
/* Remove all hash nodes pointing to this page from the
|
||||
hash chain */
|
||||
|
||||
folds[n_cached] = fold;
|
||||
n_cached++;
|
||||
next_rec:
|
||||
rec = page_rec_get_next_low(rec, page_rec_is_comp(rec));
|
||||
prev_fold = fold;
|
||||
}
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_empty(heap);
|
||||
}
|
||||
|
||||
rw_lock_x_lock(&btr_search_latch);
|
||||
|
||||
if (UNIV_UNLIKELY(!block->is_hashed)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
ut_a(block->index == index);
|
||||
|
||||
if (UNIV_UNLIKELY(block->curr_n_fields != n_fields)
|
||||
|| UNIV_UNLIKELY(block->curr_n_bytes != n_bytes)) {
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
rw_lock_x_unlock(&block->lock);
|
||||
|
||||
mem_free(folds);
|
||||
|
||||
rw_lock_s_lock(&btr_search_latch);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
for (i = 0; i < n_cached; i++) {
|
||||
|
||||
ha_remove_all_nodes_to_page(table, folds[i], page);
|
||||
}
|
||||
|
||||
ut_a(index->search_info->ref_count > 0);
|
||||
index->search_info->ref_count--;
|
||||
|
||||
block->is_hashed = FALSE;
|
||||
block->index = NULL;
|
||||
|
||||
cleanup:
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
if (UNIV_UNLIKELY(block->n_pointers)) {
|
||||
/* Corruption */
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
if (UNIV_UNLIKELY(block->n_pointers)) {
|
||||
/* Corruption */
|
||||
ut_print_timestamp(stderr);
|
||||
fprintf(stderr,
|
||||
" InnoDB: Corruption of adaptive hash index. After dropping\n"
|
||||
"InnoDB: the hash index to a page of %s, still %lu hash nodes remain.\n",
|
||||
index->name, (ulong) block->n_pointers);
|
||||
}
|
||||
index->name, (ulong) block->n_pointers);
|
||||
}
|
||||
#endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
rw_lock_x_unlock(&block->lock);
|
||||
|
||||
mem_free(folds);
|
||||
mem_free(folds);
|
||||
|
||||
rw_lock_s_lock(&btr_search_latch);
|
||||
}
|
||||
}
|
||||
} while (released_search_latch);
|
||||
|
||||
bpage = UT_LIST_GET_PREV(LRU, bpage);
|
||||
}
|
||||
|
||||
mutex_exit(&LRU_list_mutex);
|
||||
rw_lock_x_unlock(&btr_search_latch);
|
||||
rw_lock_s_unlock(&btr_search_latch);
|
||||
|
||||
if (UNIV_LIKELY_NULL(heap)) {
|
||||
mem_heap_free(heap);
|
||||
|
|
|
@ -346,7 +346,7 @@ buf_buddy_alloc_low(
|
|||
if (have_page_hash_mutex) {
|
||||
rw_lock_x_unlock(&page_hash_latch);
|
||||
}
|
||||
block = buf_LRU_get_free_block(0);
|
||||
block = buf_LRU_get_free_block();
|
||||
*lru = TRUE;
|
||||
//buf_pool_mutex_enter();
|
||||
mutex_enter(&LRU_list_mutex);
|
||||
|
@ -477,6 +477,7 @@ buf_buddy_relocate(
|
|||
if (size >= PAGE_ZIP_MIN_SIZE) {
|
||||
/* This is a compressed page. */
|
||||
mutex_t* mutex;
|
||||
ulint space, page_no;
|
||||
|
||||
if (!have_page_hash_mutex) {
|
||||
mutex_exit(&zip_free_mutex);
|
||||
|
|
|
@ -754,9 +754,9 @@ buf_block_init(
|
|||
|
||||
block->modify_clock = 0;
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
block->page.file_page_was_freed = FALSE;
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
|
||||
block->check_index_page_at_flush = FALSE;
|
||||
block->index = NULL;
|
||||
|
@ -839,11 +839,13 @@ buf_chunk_init(
|
|||
ulint zip_hash_mem_size = 0;
|
||||
hash_table_t* zip_hash_tmp = NULL;
|
||||
ulint i;
|
||||
ulint size_target;
|
||||
buf_shm_info_t* shm_info = NULL;
|
||||
|
||||
/* Round down to a multiple of page size,
|
||||
although it already should be. */
|
||||
mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE);
|
||||
size_target = (mem_size / UNIV_PAGE_SIZE) - 1;
|
||||
|
||||
srv_buffer_pool_shm_is_reused = FALSE;
|
||||
|
||||
|
@ -1044,6 +1046,10 @@ init_again:
|
|||
chunk->size = size;
|
||||
}
|
||||
|
||||
if (chunk->size > size_target) {
|
||||
chunk->size = size_target;
|
||||
}
|
||||
|
||||
if (shm_info && !(shm_info->is_new)) {
|
||||
/* convert the shared memory segment for reuse */
|
||||
ptrdiff_t phys_offset;
|
||||
|
@ -1830,7 +1836,7 @@ shrink_again:
|
|||
|
||||
buf_LRU_make_block_old(&block->page);
|
||||
dirty++;
|
||||
} else if (buf_LRU_free_block(&block->page, TRUE, NULL, FALSE)
|
||||
} else if (buf_LRU_free_block(&block->page, TRUE, FALSE)
|
||||
!= BUF_LRU_FREED) {
|
||||
nonfree++;
|
||||
}
|
||||
|
@ -2177,7 +2183,7 @@ buf_page_peek_if_search_hashed(
|
|||
return(is_hashed);
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
|
||||
This function should be called when we free a file page and want the
|
||||
|
@ -2199,6 +2205,8 @@ buf_page_set_file_page_was_freed(
|
|||
bpage = buf_page_hash_get(space, offset);
|
||||
|
||||
if (bpage) {
|
||||
/* bpage->file_page_was_freed can already hold
|
||||
when this code is invoked from dict_drop_index_tree() */
|
||||
bpage->file_page_was_freed = TRUE;
|
||||
}
|
||||
|
||||
|
@ -2237,7 +2245,7 @@ buf_page_reset_file_page_was_freed(
|
|||
|
||||
return(bpage);
|
||||
}
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
|
||||
/********************************************************************//**
|
||||
Get read access to a compressed page (usually of type
|
||||
|
@ -2333,8 +2341,7 @@ err_exit:
|
|||
ut_a(block_mutex == &((buf_block_t*) bpage)->mutex);
|
||||
|
||||
/* Discard the uncompressed page frame if possible. */
|
||||
if (buf_LRU_free_block(bpage, FALSE, NULL, FALSE)
|
||||
== BUF_LRU_FREED) {
|
||||
if (buf_LRU_free_block(bpage, FALSE, FALSE) == BUF_LRU_FREED) {
|
||||
|
||||
mutex_exit(block_mutex);
|
||||
goto lookup;
|
||||
|
@ -2358,7 +2365,7 @@ got_block:
|
|||
|
||||
buf_page_set_accessed_make_young(bpage, access_time);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ut_a(!bpage->file_page_was_freed);
|
||||
#endif
|
||||
|
||||
|
@ -2821,7 +2828,7 @@ wait_until_unfixed:
|
|||
//mutex_exit(&buf_pool_zip_mutex);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
block = buf_LRU_get_free_block(0);
|
||||
block = buf_LRU_get_free_block();
|
||||
ut_a(block);
|
||||
block_mutex = &block->mutex;
|
||||
|
||||
|
@ -2974,8 +2981,7 @@ wait_until_unfixed:
|
|||
/* Try to evict the block from the buffer pool, to use the
|
||||
insert buffer as much as possible. */
|
||||
|
||||
if (buf_LRU_free_block(&block->page, TRUE, NULL)
|
||||
== BUF_LRU_FREED) {
|
||||
if (buf_LRU_free_block(&block->page, TRUE, FALSE) == BUF_LRU_FREED) {
|
||||
buf_pool_mutex_exit();
|
||||
mutex_exit(&block->mutex);
|
||||
fprintf(stderr,
|
||||
|
@ -3007,7 +3013,7 @@ wait_until_unfixed:
|
|||
|
||||
buf_page_set_accessed_make_young(&block->page, access_time);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ut_a(!block->page.file_page_was_freed);
|
||||
#endif
|
||||
|
||||
|
@ -3183,7 +3189,7 @@ buf_page_optimistic_get(
|
|||
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ut_a(block->page.file_page_was_freed == FALSE);
|
||||
#endif
|
||||
if (innobase_get_slow_log()) {
|
||||
|
@ -3303,7 +3309,7 @@ buf_page_get_known_nowait(
|
|||
ut_a(block->page.buf_fix_count > 0);
|
||||
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ut_a(block->page.file_page_was_freed == FALSE);
|
||||
#endif
|
||||
|
||||
|
@ -3394,9 +3400,9 @@ buf_page_try_get_func(
|
|||
ut_a(block->page.buf_fix_count > 0);
|
||||
ut_a(buf_block_get_state(block) == BUF_BLOCK_FILE_PAGE);
|
||||
#endif /* UNIV_DEBUG || UNIV_BUF_DEBUG */
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ut_a(block->page.file_page_was_freed == FALSE);
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
|
||||
|
||||
buf_pool->stat.n_page_gets++;
|
||||
|
@ -3426,9 +3432,9 @@ buf_page_init_low(
|
|||
bpage->oldest_modification = 0;
|
||||
HASH_INVALIDATE(bpage, hash);
|
||||
bpage->is_corrupt = FALSE;
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
bpage->file_page_was_freed = FALSE;
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
|
@ -3556,7 +3562,7 @@ buf_page_init_for_read(
|
|||
&& UNIV_LIKELY(!recv_recovery_is_on())) {
|
||||
block = NULL;
|
||||
} else {
|
||||
block = buf_LRU_get_free_block(0);
|
||||
block = buf_LRU_get_free_block();
|
||||
ut_ad(block);
|
||||
}
|
||||
|
||||
|
@ -3682,6 +3688,7 @@ err_exit:
|
|||
bpage->state = BUF_BLOCK_ZIP_PAGE;
|
||||
bpage->space = space;
|
||||
bpage->offset = offset;
|
||||
bpage->space_was_being_deleted = FALSE;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
bpage->in_page_hash = FALSE;
|
||||
|
@ -3750,7 +3757,7 @@ buf_page_create(
|
|||
ut_ad(mtr->state == MTR_ACTIVE);
|
||||
ut_ad(space || !zip_size);
|
||||
|
||||
free_block = buf_LRU_get_free_block(0);
|
||||
free_block = buf_LRU_get_free_block();
|
||||
|
||||
//buf_pool_mutex_enter();
|
||||
mutex_enter(&LRU_list_mutex);
|
||||
|
@ -3762,9 +3769,9 @@ buf_page_create(
|
|||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
ut_a(ibuf_count_get(space, offset) == 0);
|
||||
#endif
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
block->page.file_page_was_freed = FALSE;
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
|
||||
/* Page can be found in buf_pool */
|
||||
//buf_pool_mutex_exit();
|
||||
|
|
|
@ -367,7 +367,7 @@ buf_flush_ready_for_replace(
|
|||
|
||||
if (UNIV_LIKELY(bpage->in_LRU_list && buf_page_in_file(bpage))) {
|
||||
|
||||
return(bpage->oldest_modification == 0
|
||||
return((bpage->oldest_modification == 0 || bpage->space_was_being_deleted)
|
||||
&& buf_page_get_io_fix(bpage) == BUF_IO_NONE
|
||||
&& bpage->buf_fix_count == 0);
|
||||
}
|
||||
|
@ -406,6 +406,13 @@ buf_flush_ready_for_flush(
|
|||
&& buf_page_get_io_fix(bpage) == BUF_IO_NONE) {
|
||||
ut_ad(bpage->in_flush_list);
|
||||
|
||||
if (bpage->space_was_being_deleted) {
|
||||
/* should be removed from flush_list here */
|
||||
/* because buf_flush_try_neighbors() cannot flush without fil_space_get_size(space) */
|
||||
buf_flush_remove(bpage);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (flush_type != BUF_FLUSH_LRU) {
|
||||
|
||||
return(TRUE);
|
||||
|
|
|
@ -530,6 +530,30 @@ next_page_no_mutex:
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_mark_space_was_deleted(
|
||||
/*===========================*/
|
||||
ulint id) /*!< in: space id */
|
||||
{
|
||||
buf_page_t* bpage;
|
||||
|
||||
mutex_enter(&LRU_list_mutex);
|
||||
|
||||
bpage = UT_LIST_GET_FIRST(buf_pool->LRU);
|
||||
|
||||
while (bpage != NULL) {
|
||||
if (buf_page_get_space(bpage) == id) {
|
||||
bpage->space_was_being_deleted = TRUE;
|
||||
}
|
||||
bpage = UT_LIST_GET_NEXT(LRU, bpage);
|
||||
}
|
||||
|
||||
mutex_exit(&LRU_list_mutex);
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
|
||||
UNIV_INTERN
|
||||
|
@ -618,7 +642,7 @@ restart:
|
|||
ut_ad(block->in_unzip_LRU_list);
|
||||
ut_ad(block->page.in_LRU_list);
|
||||
|
||||
freed = buf_LRU_free_block(&block->page, FALSE, NULL, have_LRU_mutex);
|
||||
freed = buf_LRU_free_block(&block->page, FALSE, have_LRU_mutex);
|
||||
mutex_exit(&block->mutex);
|
||||
|
||||
switch (freed) {
|
||||
|
@ -690,7 +714,7 @@ restart:
|
|||
ut_ad(bpage->in_LRU_list);
|
||||
|
||||
accessed = buf_page_is_accessed(bpage);
|
||||
freed = buf_LRU_free_block(bpage, TRUE, NULL, have_LRU_mutex);
|
||||
freed = buf_LRU_free_block(bpage, TRUE, have_LRU_mutex);
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
switch (freed) {
|
||||
|
@ -876,10 +900,8 @@ LRU list to the free list.
|
|||
@return the free control block, in state BUF_BLOCK_READY_FOR_USE */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_LRU_get_free_block(
|
||||
/*===================*/
|
||||
ulint zip_size) /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
buf_LRU_get_free_block(void)
|
||||
/*========================*/
|
||||
{
|
||||
buf_block_t* block = NULL;
|
||||
ibool freed;
|
||||
|
@ -955,28 +977,10 @@ loop:
|
|||
|
||||
/* If there is a block in the free list, take it */
|
||||
block = buf_LRU_get_free_only();
|
||||
//buf_pool_mutex_exit();
|
||||
|
||||
if (block) {
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
block->page.zip.m_start =
|
||||
#endif /* UNIV_DEBUG */
|
||||
block->page.zip.m_end =
|
||||
block->page.zip.m_nonempty =
|
||||
block->page.zip.n_blobs = 0;
|
||||
|
||||
if (UNIV_UNLIKELY(zip_size)) {
|
||||
ibool lru;
|
||||
page_zip_set_size(&block->page.zip, zip_size);
|
||||
mutex_enter(&LRU_list_mutex);
|
||||
block->page.zip.data = buf_buddy_alloc(zip_size, &lru, FALSE);
|
||||
mutex_exit(&LRU_list_mutex);
|
||||
UNIV_MEM_DESC(block->page.zip.data, zip_size, block);
|
||||
} else {
|
||||
page_zip_set_size(&block->page.zip, 0);
|
||||
block->page.zip.data = NULL;
|
||||
}
|
||||
|
||||
//buf_pool_mutex_exit();
|
||||
memset(&block->page.zip, 0, sizeof block->page.zip);
|
||||
|
||||
if (started_monitor) {
|
||||
srv_print_innodb_monitor = mon_value_was;
|
||||
|
@ -988,8 +992,6 @@ loop:
|
|||
/* If no block was in the free list, search from the end of the LRU
|
||||
list and try to free a block there */
|
||||
|
||||
//buf_pool_mutex_exit();
|
||||
|
||||
freed = buf_LRU_search_and_free_block(n_iterations);
|
||||
|
||||
if (freed > 0) {
|
||||
|
@ -1471,10 +1473,6 @@ buf_LRU_free_block(
|
|||
buf_page_t* bpage, /*!< in: block to be freed */
|
||||
ibool zip, /*!< in: TRUE if should remove also the
|
||||
compressed page of an uncompressed page */
|
||||
ibool* buf_pool_mutex_released,
|
||||
/*!< in: pointer to a variable that will
|
||||
be assigned TRUE if buf_pool_mutex
|
||||
was temporarily released, or NULL */
|
||||
ibool have_LRU_mutex)
|
||||
{
|
||||
buf_page_t* b = NULL;
|
||||
|
@ -1498,6 +1496,10 @@ buf_LRU_free_block(
|
|||
return(BUF_LRU_NOT_FREED);
|
||||
}
|
||||
|
||||
if (bpage->space_was_being_deleted && bpage->oldest_modification != 0) {
|
||||
buf_flush_remove(bpage);
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
ut_a(ibuf_count_get(bpage->space, bpage->offset) == 0);
|
||||
#endif /* UNIV_IBUF_COUNT_DEBUG */
|
||||
|
@ -1685,10 +1687,6 @@ not_freed:
|
|||
b->io_fix = BUF_IO_READ;
|
||||
}
|
||||
|
||||
if (buf_pool_mutex_released) {
|
||||
*buf_pool_mutex_released = TRUE;
|
||||
}
|
||||
|
||||
//buf_pool_mutex_exit();
|
||||
mutex_exit(&LRU_list_mutex);
|
||||
rw_lock_x_unlock(&page_hash_latch);
|
||||
|
@ -2369,8 +2367,7 @@ buf_LRU_file_restore(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (fil_area_is_exist(space_id, zip_size, page_no, 0,
|
||||
zip_size ? zip_size : UNIV_PAGE_SIZE)) {
|
||||
if (fil_is_exist(space_id, page_no)) {
|
||||
|
||||
tablespace_version = fil_space_get_version(space_id);
|
||||
|
||||
|
|
|
@ -465,16 +465,20 @@ dict_boot(void)
|
|||
ut_a(error == DB_SUCCESS);
|
||||
|
||||
/*-------------------------*/
|
||||
table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 3, 0);
|
||||
table = dict_mem_table_create("SYS_STATS", DICT_HDR_SPACE, 4, 0);
|
||||
table->n_mysql_handles_opened = 1; /* for pin */
|
||||
|
||||
dict_mem_table_add_col(table, heap, "INDEX_ID", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "KEY_COLS", DATA_INT, 0, 4);
|
||||
dict_mem_table_add_col(table, heap, "DIFF_VALS", DATA_BINARY, 0, 0);
|
||||
dict_mem_table_add_col(table, heap, "NON_NULL_VALS", DATA_BINARY, 0, 0);
|
||||
|
||||
/* The '+ 2' below comes from the fields DB_TRX_ID, DB_ROLL_PTR */
|
||||
#if DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2
|
||||
#error "DICT_SYS_STATS_DIFF_VALS_FIELD != 2 + 2"
|
||||
#endif
|
||||
#if DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2
|
||||
#error "DICT_SYS_STATS_NON_NULL_VALS_FIELD != 3 + 2"
|
||||
#endif
|
||||
|
||||
table->id = DICT_STATS_ID;
|
||||
|
|
|
@ -529,7 +529,7 @@ dict_create_sys_stats_tuple(
|
|||
|
||||
sys_stats = dict_sys->sys_stats;
|
||||
|
||||
entry = dtuple_create(heap, 3 + DATA_N_SYS_COLS);
|
||||
entry = dtuple_create(heap, 4 + DATA_N_SYS_COLS);
|
||||
|
||||
dict_table_copy_types(entry, sys_stats);
|
||||
|
||||
|
@ -548,6 +548,11 @@ dict_create_sys_stats_tuple(
|
|||
ptr = mem_heap_alloc(heap, 8);
|
||||
mach_write_to_8(ptr, ut_dulint_zero); /* initial value is 0 */
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
/* 5: NON_NULL_VALS ------------------*/
|
||||
dfield = dtuple_get_nth_field(entry, 3/*NON_NULL_VALS*/);
|
||||
ptr = mem_heap_alloc(heap, 8);
|
||||
mach_write_to_8(ptr, ut_dulint_zero); /* initial value is 0 */
|
||||
dfield_set_data(dfield, ptr, 8);
|
||||
|
||||
return(entry);
|
||||
}
|
||||
|
|
|
@ -1732,6 +1732,12 @@ undo_size_ok:
|
|||
new_index->heap,
|
||||
(1 + dict_index_get_n_unique(new_index))
|
||||
* sizeof(ib_int64_t));
|
||||
|
||||
new_index->stat_n_non_null_key_vals = mem_heap_zalloc(
|
||||
new_index->heap,
|
||||
(1 + dict_index_get_n_unique(new_index))
|
||||
* sizeof(*new_index->stat_n_non_null_key_vals));
|
||||
|
||||
/* Give some sensible values to stat_n_... in case we do
|
||||
not calculate statistics quickly enough */
|
||||
|
||||
|
@ -4331,15 +4337,18 @@ dict_reload_statistics(
|
|||
ulint key_cols;
|
||||
ulint n_cols;
|
||||
const rec_t* rec;
|
||||
ulint n_fields;
|
||||
const byte* field;
|
||||
ulint len;
|
||||
ib_int64_t* stat_n_diff_key_vals_tmp;
|
||||
ib_int64_t* stat_n_non_null_key_vals_tmp;
|
||||
byte* buf;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
|
||||
n_cols = dict_index_get_n_unique(index);
|
||||
stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
|
||||
stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
|
||||
|
||||
sys_stats = dict_sys->sys_stats;
|
||||
sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
|
||||
|
@ -4375,9 +4384,13 @@ dict_reload_statistics(
|
|||
}
|
||||
|
||||
if (rec_get_deleted_flag(rec, 0)) {
|
||||
/* don't count */
|
||||
i--;
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
n_fields = rec_get_n_fields_old(rec);
|
||||
|
||||
field = rec_get_nth_field_old(rec, 1, &len);
|
||||
ut_a(len == 4);
|
||||
|
||||
|
@ -4389,6 +4402,21 @@ dict_reload_statistics(
|
|||
ut_a(len == 8);
|
||||
|
||||
stat_n_diff_key_vals_tmp[i] = ut_conv_dulint_to_longlong(mach_read_from_8(field));
|
||||
|
||||
if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
|
||||
field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
|
||||
ut_a(len == 8);
|
||||
|
||||
stat_n_non_null_key_vals_tmp[i] = ut_conv_dulint_to_longlong(mach_read_from_8(field));
|
||||
} else {
|
||||
/* not enough fields: should be older */
|
||||
fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
|
||||
" in SYS_STATS seems older format. "
|
||||
"Please execute ANALYZE TABLE for it.\n",
|
||||
index->table_name, index->name, i, n_cols);
|
||||
|
||||
stat_n_non_null_key_vals_tmp[i] = ((ib_int64_t)(-1));
|
||||
}
|
||||
next_rec:
|
||||
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
||||
}
|
||||
|
@ -4398,6 +4426,12 @@ next_rec:
|
|||
|
||||
for (i = 0; i <= n_cols; i++) {
|
||||
index->stat_n_diff_key_vals[i] = stat_n_diff_key_vals_tmp[i];
|
||||
if (stat_n_non_null_key_vals_tmp[i] == ((ib_int64_t)(-1))) {
|
||||
/* approximate value */
|
||||
index->stat_n_non_null_key_vals[i] = stat_n_diff_key_vals_tmp[n_cols];
|
||||
} else {
|
||||
index->stat_n_non_null_key_vals[i] = stat_n_non_null_key_vals_tmp[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
/*===========================================*/
|
||||
|
@ -4442,18 +4476,22 @@ dict_store_statistics(
|
|||
ulint n_cols;
|
||||
ulint rests;
|
||||
const rec_t* rec;
|
||||
ulint n_fields;
|
||||
const byte* field;
|
||||
ulint len;
|
||||
ib_int64_t* stat_n_diff_key_vals_tmp;
|
||||
ib_int64_t* stat_n_non_null_key_vals_tmp;
|
||||
byte* buf;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
|
||||
n_cols = dict_index_get_n_unique(index);
|
||||
stat_n_diff_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
|
||||
stat_n_non_null_key_vals_tmp = mem_heap_zalloc(heap, (n_cols + 1) * sizeof(ib_int64_t));
|
||||
|
||||
for (i = 0; i <= n_cols; i++) {
|
||||
stat_n_diff_key_vals_tmp[i] = index->stat_n_diff_key_vals[i];
|
||||
stat_n_non_null_key_vals_tmp[i] = index->stat_n_non_null_key_vals[i];
|
||||
}
|
||||
|
||||
sys_stats = dict_sys->sys_stats;
|
||||
|
@ -4481,12 +4519,24 @@ dict_store_statistics(
|
|||
|| ut_dulint_cmp(mach_read_from_8(rec_get_nth_field_old(rec, 0, &len)),
|
||||
index->id)) {
|
||||
/* not found */
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (rec_get_deleted_flag(rec, 0)) {
|
||||
/* don't count */
|
||||
i--;
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
n_fields = rec_get_n_fields_old(rec);
|
||||
|
||||
if (n_fields <= DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
|
||||
/* not update for the older smaller format */
|
||||
fprintf(stderr, "InnoDB: Notice: stats for %s/%s (%lu/%lu)"
|
||||
" in SYS_STATS seems older format. Please ANALYZE TABLE it.\n",
|
||||
index->table_name, index->name, i, n_cols);
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
|
@ -4503,6 +4553,14 @@ dict_store_statistics(
|
|||
(ulint) stat_n_diff_key_vals_tmp[key_cols] & 0xFFFFFFFF),
|
||||
&mtr);
|
||||
|
||||
field = rec_get_nth_field_old(rec, DICT_SYS_STATS_NON_NULL_VALS_FIELD, &len);
|
||||
ut_a(len == 8);
|
||||
|
||||
mlog_write_dulint((byte*)field,
|
||||
ut_dulint_create((ulint) (stat_n_non_null_key_vals_tmp[key_cols] >> 32),
|
||||
(ulint) stat_n_non_null_key_vals_tmp[key_cols] & 0xFFFFFFFF),
|
||||
&mtr);
|
||||
|
||||
rests--;
|
||||
|
||||
next_rec:
|
||||
|
@ -4635,6 +4693,10 @@ dict_update_statistics(
|
|||
for (i = dict_index_get_n_unique(index); i; ) {
|
||||
index->stat_n_diff_key_vals[i--] = 1;
|
||||
}
|
||||
|
||||
memset(index->stat_n_non_null_key_vals, 0,
|
||||
(1 + dict_index_get_n_unique(index))
|
||||
* sizeof(*index->stat_n_non_null_key_vals));
|
||||
}
|
||||
|
||||
index = dict_table_get_next_index(index);
|
||||
|
@ -4662,6 +4724,78 @@ end:
|
|||
dict_table_stats_unlock(table, RW_X_LATCH);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dict_is_older_statistics(
|
||||
/*=====================*/
|
||||
dict_index_t* index)
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
dict_table_t* sys_stats;
|
||||
dict_index_t* sys_index;
|
||||
btr_pcur_t pcur;
|
||||
dtuple_t* tuple;
|
||||
dfield_t* dfield;
|
||||
const rec_t* rec;
|
||||
ulint n_fields;
|
||||
ulint len;
|
||||
byte* buf;
|
||||
mtr_t mtr;
|
||||
|
||||
heap = mem_heap_create(100);
|
||||
|
||||
sys_stats = dict_sys->sys_stats;
|
||||
sys_index = UT_LIST_GET_FIRST(sys_stats->indexes);
|
||||
ut_a(!dict_table_is_comp(sys_stats));
|
||||
|
||||
tuple = dtuple_create(heap, 1);
|
||||
dfield = dtuple_get_nth_field(tuple, 0);
|
||||
|
||||
buf = mem_heap_alloc(heap, 8);
|
||||
mach_write_to_8(buf, index->id);
|
||||
|
||||
dfield_set_data(dfield, buf, 8);
|
||||
dict_index_copy_types(tuple, sys_index, 1);
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE,
|
||||
BTR_SEARCH_LEAF, &pcur, &mtr);
|
||||
|
||||
next_rec:
|
||||
rec = btr_pcur_get_rec(&pcur);
|
||||
|
||||
if (!btr_pcur_is_on_user_rec(&pcur)
|
||||
|| ut_dulint_cmp(mach_read_from_8(rec_get_nth_field_old(rec, 0, &len)),
|
||||
index->id)) {
|
||||
/* not found */
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
mem_heap_free(heap);
|
||||
/* no statistics == not older statistics */
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
if (rec_get_deleted_flag(rec, 0)) {
|
||||
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
|
||||
goto next_rec;
|
||||
}
|
||||
|
||||
n_fields = rec_get_n_fields_old(rec);
|
||||
|
||||
btr_pcur_close(&pcur);
|
||||
mtr_commit(&mtr);
|
||||
mem_heap_free(heap);
|
||||
|
||||
if (n_fields > DICT_SYS_STATS_NON_NULL_VALS_FIELD) {
|
||||
return(FALSE);
|
||||
} else {
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
Prints info of a foreign key constraint. */
|
||||
static
|
||||
|
|
|
@ -242,6 +242,7 @@ the ib_logfiles form a 'space' and it is handled here */
|
|||
struct fil_system_struct {
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
mutex_t mutex; /*!< The mutex protecting the cache */
|
||||
mutex_t file_extend_mutex;
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
hash_table_t* spaces; /*!< The hash table of spaces in the
|
||||
system; they are hashed on the space
|
||||
|
@ -690,7 +691,7 @@ fil_node_open_file(
|
|||
ut_a(space->purpose != FIL_LOG);
|
||||
ut_a(!trx_sys_sys_space(space->id));
|
||||
|
||||
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
|
||||
if (size_bytes < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: the size of single-table"
|
||||
" tablespace file %s\n"
|
||||
|
@ -816,7 +817,7 @@ fil_node_close_file(
|
|||
ut_ad(node && system);
|
||||
ut_ad(mutex_own(&(system->mutex)));
|
||||
ut_a(node->open);
|
||||
ut_a(node->n_pending == 0);
|
||||
ut_a(node->n_pending == 0 || srv_lazy_drop_table);
|
||||
ut_a(node->n_pending_flushes == 0);
|
||||
ut_a(node->modification_counter == node->flush_counter);
|
||||
|
||||
|
@ -1028,7 +1029,7 @@ fil_node_free(
|
|||
ut_ad(node && system && space);
|
||||
ut_ad(mutex_own(&(system->mutex)));
|
||||
ut_a(node->magic_n == FIL_NODE_MAGIC_N);
|
||||
ut_a(node->n_pending == 0);
|
||||
ut_a(node->n_pending == 0 || srv_lazy_drop_table);
|
||||
|
||||
if (node->open) {
|
||||
/* We fool the assertion in fil_node_close_file() to think
|
||||
|
@ -1549,6 +1550,7 @@ fil_init(
|
|||
fil_system = mem_zalloc(sizeof(fil_system_t));
|
||||
|
||||
mutex_create(&fil_system->mutex, SYNC_ANY_LATCH);
|
||||
mutex_create(&fil_system->file_extend_mutex, SYNC_OUTER_ANY_LATCH);
|
||||
|
||||
fil_system->spaces = hash_create(hash_size);
|
||||
fil_system->name_hash = hash_create(hash_size);
|
||||
|
@ -2295,7 +2297,11 @@ try_again:
|
|||
completely and permanently. The flag is_being_deleted also prevents
|
||||
fil_flush() from being applied to this tablespace. */
|
||||
|
||||
if (srv_lazy_drop_table) {
|
||||
buf_LRU_mark_space_was_deleted(id);
|
||||
} else {
|
||||
buf_LRU_invalidate_tablespace(id);
|
||||
}
|
||||
#endif
|
||||
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
|
||||
|
||||
|
@ -3095,8 +3101,8 @@ fil_open_single_table_tablespace(
|
|||
space_id = fsp_header_get_space_id(page);
|
||||
space_flags = fsp_header_get_flags(page);
|
||||
|
||||
if (srv_expand_import
|
||||
&& (space_id != id || space_flags != (flags & ~(~0 << DICT_TF_BITS)))) {
|
||||
if (srv_expand_import) {
|
||||
|
||||
ibool file_is_corrupt = FALSE;
|
||||
byte* buf3;
|
||||
byte* descr_page;
|
||||
|
@ -3167,8 +3173,10 @@ fil_open_single_table_tablespace(
|
|||
|
||||
if (size_bytes < free_limit_bytes) {
|
||||
free_limit_bytes = size_bytes;
|
||||
fprintf(stderr, "InnoDB: free limit of %s is larger than its real size.\n", filepath);
|
||||
file_is_corrupt = TRUE;
|
||||
if (size_bytes >= (ib_int64_t) (FSP_EXTENT_SIZE * UNIV_PAGE_SIZE)) {
|
||||
fprintf(stderr, "InnoDB: free limit of %s is larger than its real size.\n", filepath);
|
||||
file_is_corrupt = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* get cruster index information */
|
||||
|
@ -3314,7 +3322,7 @@ skip_info:
|
|||
file_is_corrupt = TRUE;
|
||||
descr_is_corrupt = TRUE;
|
||||
} else {
|
||||
ut_a(fil_page_get_type(page) == FIL_PAGE_TYPE_XDES);
|
||||
|
||||
descr_is_corrupt = FALSE;
|
||||
}
|
||||
|
||||
|
@ -3778,7 +3786,7 @@ fil_load_single_table_tablespace(
|
|||
|
||||
size = (((ib_uint64_t)size_high) << 32) + (ib_uint64_t)size_low;
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
if (size < FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
|
||||
if (size < FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Error: the size of single-table tablespace"
|
||||
" file %s\n"
|
||||
|
@ -3798,7 +3806,7 @@ fil_load_single_table_tablespace(
|
|||
/* Align the memory for file i/o if we might have O_DIRECT set */
|
||||
page = ut_align(buf2, UNIV_PAGE_SIZE);
|
||||
|
||||
if (size >= FIL_IBD_FILE_INITIAL_SIZE * UNIV_PAGE_SIZE) {
|
||||
if (size >= FIL_IBD_FILE_INITIAL_SIZE * (lint)UNIV_PAGE_SIZE) {
|
||||
success = os_file_read(file, page, 0, 0, UNIV_PAGE_SIZE);
|
||||
|
||||
/* We have to read the tablespace id from the file */
|
||||
|
@ -4348,6 +4356,10 @@ fil_extend_space_to_desired_size(
|
|||
ulint page_size;
|
||||
ibool success = TRUE;
|
||||
|
||||
/* file_extend_mutex is for http://bugs.mysql.com/56433 */
|
||||
/* to protect from the other fil_extend_space_to_desired_size() */
|
||||
/* during temprary releasing &fil_system->mutex */
|
||||
mutex_enter(&fil_system->file_extend_mutex);
|
||||
fil_mutex_enter_and_prepare_for_io(space_id);
|
||||
|
||||
space = fil_space_get_by_id(space_id);
|
||||
|
@ -4359,6 +4371,7 @@ fil_extend_space_to_desired_size(
|
|||
*actual_size = space->size;
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
mutex_exit(&fil_system->file_extend_mutex);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
@ -4391,6 +4404,8 @@ fil_extend_space_to_desired_size(
|
|||
offset_low = ((start_page_no - file_start_page_no)
|
||||
% (4096 * ((1024 * 1024) / page_size)))
|
||||
* page_size;
|
||||
|
||||
mutex_exit(&fil_system->mutex);
|
||||
#ifdef UNIV_HOTBACKUP
|
||||
success = os_file_write(node->name, node->handle, buf,
|
||||
offset_low, offset_high,
|
||||
|
@ -4400,8 +4415,10 @@ fil_extend_space_to_desired_size(
|
|||
node->name, node->handle, buf,
|
||||
offset_low, offset_high,
|
||||
page_size * n_pages,
|
||||
NULL, NULL, NULL);
|
||||
NULL, NULL, space_id, NULL);
|
||||
#endif
|
||||
mutex_enter(&fil_system->mutex);
|
||||
|
||||
if (success) {
|
||||
node->size += n_pages;
|
||||
space->size += n_pages;
|
||||
|
@ -4447,6 +4464,7 @@ fil_extend_space_to_desired_size(
|
|||
printf("Extended %s to %lu, actual size %lu pages\n", space->name,
|
||||
size_after_extend, *actual_size); */
|
||||
mutex_exit(&fil_system->mutex);
|
||||
mutex_exit(&fil_system->file_extend_mutex);
|
||||
|
||||
fil_flush(space_id);
|
||||
|
||||
|
@ -4811,6 +4829,22 @@ _fil_io(
|
|||
srv_data_written+= len;
|
||||
}
|
||||
|
||||
/* if the table space was already deleted, space might not exist already. */
|
||||
if (message
|
||||
&& space_id < SRV_LOG_SPACE_FIRST_ID
|
||||
&& ((buf_page_t*)message)->space_was_being_deleted) {
|
||||
|
||||
if (mode == OS_AIO_NORMAL) {
|
||||
buf_page_io_complete(message, trx);
|
||||
return(DB_SUCCESS); /*fake*/
|
||||
}
|
||||
if (type == OS_FILE_READ) {
|
||||
return(DB_TABLESPACE_DELETED);
|
||||
} else {
|
||||
return(DB_SUCCESS); /*fake*/
|
||||
}
|
||||
}
|
||||
|
||||
/* Reserve the fil_system mutex and make sure that we can open at
|
||||
least one file while holding it, if the file is not already open */
|
||||
|
||||
|
@ -4940,10 +4974,24 @@ _fil_io(
|
|||
#else
|
||||
/* Queue the aio request */
|
||||
ret = os_aio(type, mode | wake_later, node->name, node->handle, buf,
|
||||
offset_low, offset_high, len, node, message, trx);
|
||||
offset_low, offset_high, len, node, message, space_id, trx);
|
||||
#endif
|
||||
} /**/
|
||||
|
||||
/* if the table space was already deleted, space might not exist already. */
|
||||
if (message
|
||||
&& space_id < SRV_LOG_SPACE_FIRST_ID
|
||||
&& ((buf_page_t*)message)->space_was_being_deleted) {
|
||||
|
||||
if (mode == OS_AIO_SYNC) {
|
||||
if (type == OS_FILE_READ) {
|
||||
return(DB_TABLESPACE_DELETED);
|
||||
} else {
|
||||
return(DB_SUCCESS); /*fake*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ut_a(ret);
|
||||
|
||||
if (mode == OS_AIO_SYNC) {
|
||||
|
@ -4966,21 +5014,10 @@ _fil_io(
|
|||
Confirm whether the parameters are valid or not */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fil_area_is_exist(
|
||||
fil_is_exist(
|
||||
/*==============*/
|
||||
ulint space_id, /*!< in: space id */
|
||||
ulint zip_size __attribute__((unused)),
|
||||
/*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint block_offset, /*!< in: offset in number of blocks */
|
||||
ulint byte_offset __attribute__((unused)),
|
||||
/*!< in: remainder of offset in bytes; in
|
||||
aio this must be divisible by the OS block
|
||||
size */
|
||||
ulint len __attribute__((unused)))
|
||||
/*!< in: how many bytes to read or write; this
|
||||
must not cross a file boundary; in aio this
|
||||
must be a block size multiple */
|
||||
ulint block_offset) /*!< in: offset in number of blocks */
|
||||
{
|
||||
fil_space_t* space;
|
||||
fil_node_t* node;
|
||||
|
@ -5054,6 +5091,7 @@ fil_aio_wait(
|
|||
fil_node_t* fil_node;
|
||||
void* message;
|
||||
ulint type;
|
||||
ulint space_id = 0;
|
||||
|
||||
ut_ad(fil_validate());
|
||||
|
||||
|
@ -5061,7 +5099,7 @@ fil_aio_wait(
|
|||
srv_set_io_thread_op_info(segment, "native aio handle");
|
||||
#ifdef WIN_ASYNC_IO
|
||||
ret = os_aio_windows_handle(segment, 0, &fil_node,
|
||||
&message, &type);
|
||||
&message, &type, &space_id);
|
||||
#else
|
||||
ret = 0; /* Eliminate compiler warning */
|
||||
ut_error;
|
||||
|
@ -5070,7 +5108,22 @@ fil_aio_wait(
|
|||
srv_set_io_thread_op_info(segment, "simulated aio handle");
|
||||
|
||||
ret = os_aio_simulated_handle(segment, &fil_node,
|
||||
&message, &type);
|
||||
&message, &type, &space_id);
|
||||
}
|
||||
|
||||
/* if the table space was already deleted, fil_node might not exist already. */
|
||||
if (message
|
||||
&& space_id < SRV_LOG_SPACE_FIRST_ID
|
||||
&& ((buf_page_t*)message)->space_was_being_deleted) {
|
||||
|
||||
/* intended not to be uncompress read page */
|
||||
ut_a(buf_page_get_io_fix(message) == BUF_IO_WRITE
|
||||
|| !buf_page_get_zip_size(message)
|
||||
|| buf_page_get_state(message) != BUF_BLOCK_FILE_PAGE);
|
||||
|
||||
srv_set_io_thread_op_info(segment, "complete io for buf page");
|
||||
buf_page_io_complete(message, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
ut_a(ret);
|
||||
|
|
|
@ -657,13 +657,18 @@ xdes_calc_descriptor_page(
|
|||
0 for uncompressed pages */
|
||||
ulint offset) /*!< in: page offset */
|
||||
{
|
||||
#ifndef DOXYGEN /* Doxygen gets confused of these */
|
||||
# if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET \
|
||||
+ (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
|
||||
# error
|
||||
# endif
|
||||
#endif /* !DOXYGEN */
|
||||
//#ifndef DOXYGEN /* Doxygen gets confused of these */
|
||||
//# if UNIV_PAGE_SIZE <= XDES_ARR_OFFSET
|
||||
// + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
|
||||
//# error
|
||||
//# endif
|
||||
//# if PAGE_ZIP_MIN_SIZE <= XDES_ARR_OFFSET
|
||||
// + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE
|
||||
//# error
|
||||
//# endif
|
||||
//#endif /* !DOXYGEN */
|
||||
ut_a(UNIV_PAGE_SIZE > XDES_ARR_OFFSET + (UNIV_PAGE_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE);
|
||||
ut_a(PAGE_ZIP_MIN_SIZE > XDES_ARR_OFFSET + (PAGE_ZIP_MIN_SIZE / FSP_EXTENT_SIZE) * XDES_SIZE);
|
||||
ut_ad(ut_is_2pow(zip_size));
|
||||
|
||||
if (!zip_size) {
|
||||
|
@ -3473,9 +3478,9 @@ fseg_free_page(
|
|||
|
||||
fseg_free_page_low(seg_inode, space, zip_size, page, mtr);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
buf_page_set_file_page_was_freed(space, page);
|
||||
#endif
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
@ -3542,13 +3547,13 @@ fseg_free_extent(
|
|||
|
||||
fsp_free_extent(space, zip_size, page, mtr);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
for (i = 0; i < FSP_EXTENT_SIZE; i++) {
|
||||
|
||||
buf_page_set_file_page_was_freed(space,
|
||||
first_page_in_extent + i);
|
||||
}
|
||||
#endif
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
}
|
||||
|
||||
/**********************************************************************//**
|
||||
|
|
|
@ -201,6 +201,25 @@ static char* internal_innobase_data_file_path = NULL;
|
|||
|
||||
static char* innodb_version_str = (char*) INNODB_VERSION_STR;
|
||||
|
||||
/** Possible values for system variable "innodb_stats_method". The values
|
||||
are defined the same as its corresponding MyISAM system variable
|
||||
"myisam_stats_method"(see "myisam_stats_method_names"), for better usability */
|
||||
static const char* innodb_stats_method_names[] = {
|
||||
"nulls_equal",
|
||||
"nulls_unequal",
|
||||
"nulls_ignored",
|
||||
NullS
|
||||
};
|
||||
|
||||
/** Used to define an enumerate type of the system variable innodb_stats_method.
|
||||
This is the same as "myisam_stats_method_typelib" */
|
||||
static TYPELIB innodb_stats_method_typelib = {
|
||||
array_elements(innodb_stats_method_names) - 1,
|
||||
"innodb_stats_method_typelib",
|
||||
innodb_stats_method_names,
|
||||
NULL
|
||||
};
|
||||
|
||||
/* The following counter is used to convey information to InnoDB
|
||||
about server activity: in selects it is not sensible to call
|
||||
srv_active_wake_master_thread after each fetch or search, we only do
|
||||
|
@ -5860,6 +5879,11 @@ ha_innobase::index_read(
|
|||
case DB_SUCCESS:
|
||||
error = 0;
|
||||
table->status = 0;
|
||||
#ifdef EXTENDED_FOR_USERSTAT
|
||||
rows_read++;
|
||||
if (active_index < MAX_KEY)
|
||||
index_rows_read[active_index]++;
|
||||
#endif
|
||||
break;
|
||||
case DB_RECORD_NOT_FOUND:
|
||||
error = HA_ERR_KEY_NOT_FOUND;
|
||||
|
@ -6084,7 +6108,7 @@ ha_innobase::general_fetch(
|
|||
table->status = 0;
|
||||
#ifdef EXTENDED_FOR_USERSTAT
|
||||
rows_read++;
|
||||
if (active_index >= 0 && active_index < MAX_KEY)
|
||||
if (active_index < MAX_KEY)
|
||||
index_rows_read[active_index]++;
|
||||
#endif
|
||||
break;
|
||||
|
@ -7956,6 +7980,65 @@ innobase_get_mysql_key_number_for_index(
|
|||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Calculate Record Per Key value. Need to exclude the NULL value if
|
||||
innodb_stats_method is set to "nulls_ignored"
|
||||
@return estimated record per key value */
|
||||
static
|
||||
ha_rows
|
||||
innodb_rec_per_key(
|
||||
/*===============*/
|
||||
dict_index_t* index, /*!< in: dict_index_t structure */
|
||||
ulint i, /*!< in: the column we are
|
||||
calculating rec per key */
|
||||
ha_rows records) /*!< in: estimated total records */
|
||||
{
|
||||
ha_rows rec_per_key;
|
||||
|
||||
ut_ad(i < dict_index_get_n_unique(index));
|
||||
|
||||
/* Note the stat_n_diff_key_vals[] stores the diff value with
|
||||
n-prefix indexing, so it is always stat_n_diff_key_vals[i + 1] */
|
||||
if (index->stat_n_diff_key_vals[i + 1] == 0) {
|
||||
|
||||
rec_per_key = records;
|
||||
} else if (srv_innodb_stats_method == SRV_STATS_NULLS_IGNORED) {
|
||||
ib_int64_t num_null;
|
||||
|
||||
/* Number of rows with NULL value in this
|
||||
field */
|
||||
num_null = records - index->stat_n_non_null_key_vals[i];
|
||||
|
||||
/* In theory, index->stat_n_non_null_key_vals[i]
|
||||
should always be less than the number of records.
|
||||
Since this is statistics value, the value could
|
||||
have slight discrepancy. But we will make sure
|
||||
the number of null values is not a negative number. */
|
||||
num_null = (num_null < 0) ? 0 : num_null;
|
||||
|
||||
/* If the number of NULL values is the same as or
|
||||
large than that of the distinct values, we could
|
||||
consider that the table consists mostly of NULL value.
|
||||
Set rec_per_key to 1. */
|
||||
if (index->stat_n_diff_key_vals[i + 1] <= num_null) {
|
||||
rec_per_key = 1;
|
||||
} else {
|
||||
/* Need to exclude rows with NULL values from
|
||||
rec_per_key calculation */
|
||||
rec_per_key = (ha_rows)(
|
||||
(records - num_null)
|
||||
/ (index->stat_n_diff_key_vals[i + 1]
|
||||
- num_null));
|
||||
}
|
||||
} else {
|
||||
rec_per_key = (ha_rows)
|
||||
(records / index->stat_n_diff_key_vals[i + 1]);
|
||||
}
|
||||
|
||||
return(rec_per_key);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Returns statistics information of the table to the MySQL interpreter,
|
||||
in various fields of the handle object. */
|
||||
|
@ -8014,6 +8097,10 @@ ha_innobase::info_low(
|
|||
for (index = dict_table_get_first_index(ib_table);
|
||||
index != NULL;
|
||||
index = dict_table_get_next_index(index)) {
|
||||
if (dict_is_older_statistics(index)) {
|
||||
row_delete_stats_for_mysql(index, prebuilt->trx);
|
||||
innobase_commit_low(prebuilt->trx);
|
||||
}
|
||||
row_insert_stats_for_mysql(index, prebuilt->trx);
|
||||
innobase_commit_low(prebuilt->trx);
|
||||
}
|
||||
|
@ -8206,13 +8293,8 @@ ha_innobase::info_low(
|
|||
break;
|
||||
}
|
||||
|
||||
if (index->stat_n_diff_key_vals[j + 1] == 0) {
|
||||
|
||||
rec_per_key = stats.records;
|
||||
} else {
|
||||
rec_per_key = (ha_rows)(stats.records /
|
||||
index->stat_n_diff_key_vals[j + 1]);
|
||||
}
|
||||
rec_per_key = innodb_rec_per_key(
|
||||
index, j, stats.records);
|
||||
|
||||
/* Since MySQL seems to favor table scans
|
||||
too much over index searches, we pretend
|
||||
|
@ -11368,25 +11450,6 @@ static MYSQL_SYSVAR_ULONGLONG(stats_sample_pages, srv_stats_sample_pages,
|
|||
"The number of index pages to sample when calculating statistics (default 8)",
|
||||
NULL, NULL, 8, 1, ~0ULL, 0);
|
||||
|
||||
const char *innobase_stats_method_names[]=
|
||||
{
|
||||
"nulls_equal",
|
||||
"nulls_unequal",
|
||||
"nulls_ignored",
|
||||
NullS
|
||||
};
|
||||
TYPELIB innobase_stats_method_typelib=
|
||||
{
|
||||
array_elements(innobase_stats_method_names) - 1, "innobase_stats_method_typelib",
|
||||
innobase_stats_method_names, NULL
|
||||
};
|
||||
static MYSQL_SYSVAR_ENUM(stats_method, srv_stats_method,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Specifies how InnoDB index statistics collection code should threat NULLs. "
|
||||
"Possible values of name are same to for 'myisam_stats_method'. "
|
||||
"This is startup parameter.",
|
||||
NULL, NULL, 0, &innobase_stats_method_typelib);
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(stats_auto_update, srv_stats_auto_update,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Enable/Disable InnoDB's auto update statistics of indexes. "
|
||||
|
@ -11575,6 +11638,13 @@ static MYSQL_SYSVAR_STR(change_buffering, innobase_change_buffering,
|
|||
innodb_change_buffering_validate,
|
||||
innodb_change_buffering_update, "inserts");
|
||||
|
||||
static MYSQL_SYSVAR_ENUM(stats_method, srv_innodb_stats_method,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"Specifies how InnoDB index statistics collection code should "
|
||||
"treat NULLs. Possible values are NULLS_EQUAL (default), "
|
||||
"NULLS_UNEQUAL and NULLS_IGNORED",
|
||||
NULL, NULL, SRV_STATS_NULLS_EQUAL, &innodb_stats_method_typelib);
|
||||
|
||||
#if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG
|
||||
static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
|
@ -11713,6 +11783,12 @@ static MYSQL_SYSVAR_ULINT(pass_corrupt_table, srv_pass_corrupt_table,
|
|||
"except for the deletion.",
|
||||
NULL, NULL, 0, 0, 1, 0);
|
||||
|
||||
static MYSQL_SYSVAR_ULONG(lazy_drop_table, srv_lazy_drop_table,
|
||||
PLUGIN_VAR_RQCMDARG,
|
||||
"At deleting tablespace, only miminum needed processes at the time are done. "
|
||||
"e.g. for http://bugs.mysql.com/51325",
|
||||
NULL, NULL, 0, 0, 1, 0);
|
||||
|
||||
static struct st_mysql_sys_var* innobase_system_variables[]= {
|
||||
MYSQL_SYSVAR(page_size),
|
||||
MYSQL_SYSVAR(log_block_size),
|
||||
|
@ -11762,12 +11838,12 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||
MYSQL_SYSVAR(overwrite_relay_log_info),
|
||||
MYSQL_SYSVAR(rollback_on_timeout),
|
||||
MYSQL_SYSVAR(stats_on_metadata),
|
||||
MYSQL_SYSVAR(stats_method),
|
||||
MYSQL_SYSVAR(stats_auto_update),
|
||||
MYSQL_SYSVAR(stats_update_need_lock),
|
||||
MYSQL_SYSVAR(use_sys_stats_table),
|
||||
MYSQL_SYSVAR(stats_sample_pages),
|
||||
MYSQL_SYSVAR(adaptive_hash_index),
|
||||
MYSQL_SYSVAR(stats_method),
|
||||
MYSQL_SYSVAR(replication_delay),
|
||||
MYSQL_SYSVAR(status_file),
|
||||
MYSQL_SYSVAR(strict_mode),
|
||||
|
@ -11804,6 +11880,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
|
|||
MYSQL_SYSVAR(auto_lru_dump),
|
||||
MYSQL_SYSVAR(use_purge_thread),
|
||||
MYSQL_SYSVAR(pass_corrupt_table),
|
||||
MYSQL_SYSVAR(lazy_drop_table),
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
|
@ -3280,6 +3280,14 @@ static ST_FIELD_INFO i_s_innodb_sys_stats_info[] =
|
|||
STRUCT_FLD(old_name, ""),
|
||||
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
|
||||
|
||||
{STRUCT_FLD(field_name, "NON_NULL_VALS"),
|
||||
STRUCT_FLD(field_length, MY_INT64_NUM_DECIMAL_DIGITS),
|
||||
STRUCT_FLD(field_type, MYSQL_TYPE_LONGLONG),
|
||||
STRUCT_FLD(value, 0),
|
||||
STRUCT_FLD(field_flags, MY_I_S_UNSIGNED | MY_I_S_MAYBE_NULL),
|
||||
STRUCT_FLD(old_name, ""),
|
||||
STRUCT_FLD(open_method, SKIP_OPEN_TABLE)},
|
||||
|
||||
END_OF_ST_FIELD_INFO
|
||||
};
|
||||
|
||||
|
@ -3548,6 +3556,9 @@ copy_sys_stats_rec(
|
|||
{
|
||||
int status;
|
||||
int field;
|
||||
ulint n_fields;
|
||||
|
||||
n_fields = rec_get_n_fields_old(rec);
|
||||
|
||||
/* INDEX_ID */
|
||||
field = dict_index_get_nth_col_pos(index, 0);
|
||||
|
@ -3567,6 +3578,16 @@ copy_sys_stats_rec(
|
|||
if (status) {
|
||||
return status;
|
||||
}
|
||||
/* NON_NULL_VALS */
|
||||
if (n_fields < 6) {
|
||||
table->field[3]->set_null();
|
||||
} else {
|
||||
field = dict_index_get_nth_col_pos(index, 3);
|
||||
status = copy_id_field(table, 3, rec, field);
|
||||
if (status) {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1881,9 +1881,9 @@ ibuf_remove_free_page(void)
|
|||
fseg_free_page(header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER,
|
||||
IBUF_SPACE_ID, page_no, &mtr);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
buf_page_reset_file_page_was_freed(IBUF_SPACE_ID, page_no);
|
||||
#endif
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
|
||||
ibuf_enter();
|
||||
|
||||
|
@ -1925,9 +1925,9 @@ ibuf_remove_free_page(void)
|
|||
ibuf_bitmap_page_set_bits(
|
||||
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
|
||||
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
buf_page_set_file_page_was_freed(IBUF_SPACE_ID, page_no);
|
||||
#endif
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
|
|
@ -478,7 +478,10 @@ btr_estimate_n_rows_in_range(
|
|||
/*******************************************************************//**
|
||||
Estimates the number of different key values in a given index, for
|
||||
each n-column prefix of the index where n <= dict_index_get_n_unique(index).
|
||||
The estimates are stored in the array index->stat_n_diff_key_vals. */
|
||||
The estimates are stored in the array index->stat_n_diff_key_vals.
|
||||
If innodb_stats_method is nulls_ignored, we also record the number of
|
||||
non-null values for each prefix and stored the estimates in
|
||||
array index->stat_n_non_null_key_vals. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
btr_estimate_number_of_different_key_vals(
|
||||
|
@ -509,8 +512,8 @@ file segment of the index tree.
|
|||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||
UNIV_INTERN
|
||||
ulint
|
||||
btr_store_big_rec_extern_fields(
|
||||
/*============================*/
|
||||
btr_store_big_rec_extern_fields_func(
|
||||
/*=================================*/
|
||||
dict_index_t* index, /*!< in: index of rec; the index tree
|
||||
MUST be X-latched */
|
||||
buf_block_t* rec_block, /*!< in/out: block containing rec */
|
||||
|
@ -519,10 +522,42 @@ btr_store_big_rec_extern_fields(
|
|||
the "external storage" flags in offsets
|
||||
will not correspond to rec when
|
||||
this function returns */
|
||||
big_rec_t* big_rec_vec, /*!< in: vector containing fields
|
||||
#ifdef UNIV_DEBUG
|
||||
mtr_t* local_mtr, /*!< in: mtr containing the
|
||||
latch to rec and to the tree */
|
||||
#endif /* UNIV_DEBUG */
|
||||
#if defined UNIV_DEBUG || defined UNIV_BLOB_LIGHT_DEBUG
|
||||
ibool update_in_place,/*! in: TRUE if the record is updated
|
||||
in place (not delete+insert) */
|
||||
#endif /* UNIV_DEBUG || UNIV_BLOB_LIGHT_DEBUG */
|
||||
const big_rec_t*big_rec_vec) /*!< in: vector containing fields
|
||||
to be stored externally */
|
||||
mtr_t* local_mtr); /*!< in: mtr containing the latch to
|
||||
rec and to the tree */
|
||||
__attribute__((nonnull));
|
||||
|
||||
/** Stores the fields in big_rec_vec to the tablespace and puts pointers to
|
||||
them in rec. The extern flags in rec will have to be set beforehand.
|
||||
The fields are stored on pages allocated from leaf node
|
||||
file segment of the index tree.
|
||||
@param index in: clustered index; MUST be X-latched by mtr
|
||||
@param b in/out: block containing rec; MUST be X-latched by mtr
|
||||
@param rec in/out: clustered index record
|
||||
@param offsets in: rec_get_offsets(rec, index);
|
||||
the "external storage" flags in offsets will not be adjusted
|
||||
@param mtr in: mini-transaction that holds x-latch on index and b
|
||||
@param upd in: TRUE if the record is updated in place (not delete+insert)
|
||||
@param big in: vector containing fields to be stored externally
|
||||
@return DB_SUCCESS or DB_OUT_OF_FILE_SPACE */
|
||||
#ifdef UNIV_DEBUG
|
||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,mtr,upd,big)
|
||||
#elif defined UNIV_BLOB_LIGHT_DEBUG
|
||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,upd,big)
|
||||
#else
|
||||
# define btr_store_big_rec_extern_fields(index,b,rec,offsets,mtr,upd,big) \
|
||||
btr_store_big_rec_extern_fields_func(index,b,rec,offsets,big)
|
||||
#endif
|
||||
|
||||
/*******************************************************************//**
|
||||
Frees the space in an externally stored field to the file space
|
||||
management if the field in data is owned the externally stored field,
|
||||
|
|
|
@ -166,10 +166,8 @@ Allocates a buffer block.
|
|||
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_block_alloc(
|
||||
/*============*/
|
||||
ulint zip_size); /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
buf_block_alloc(void);
|
||||
/*=================*/
|
||||
/********************************************************************//**
|
||||
Frees a buffer block which does not contain a file page. */
|
||||
UNIV_INLINE
|
||||
|
@ -371,7 +369,7 @@ buf_reset_check_index_page_at_flush(
|
|||
/*================================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset);/*!< in: page number */
|
||||
#ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
#if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
Sets file_page_was_freed TRUE if the page is found in the buffer pool.
|
||||
This function should be called when we free a file page and want the
|
||||
|
@ -396,7 +394,7 @@ buf_page_reset_file_page_was_freed(
|
|||
/*===============================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset); /*!< in: page number */
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
#endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
/********************************************************************//**
|
||||
Reads the freed_page_clock of a buffer block.
|
||||
@return freed_page_clock */
|
||||
|
@ -1157,12 +1155,13 @@ struct buf_page_struct{
|
|||
0 if the block was never accessed
|
||||
in the buffer pool */
|
||||
/* @} */
|
||||
ibool space_was_being_deleted;
|
||||
ibool is_corrupt;
|
||||
# ifdef UNIV_DEBUG_FILE_ACCESSES
|
||||
# if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
|
||||
ibool file_page_was_freed;
|
||||
/*!< this is set to TRUE when fsp
|
||||
frees a page in buffer pool */
|
||||
# endif /* UNIV_DEBUG_FILE_ACCESSES */
|
||||
# endif /* UNIV_DEBUG_FILE_ACCESSES || UNIV_DEBUG */
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
};
|
||||
|
||||
|
|
|
@ -384,6 +384,7 @@ buf_block_set_file_page(
|
|||
buf_block_set_state(block, BUF_BLOCK_FILE_PAGE);
|
||||
block->page.space = space;
|
||||
block->page.offset = page_no;
|
||||
block->page.space_was_being_deleted = FALSE;
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
|
@ -757,14 +758,12 @@ Allocates a buffer block.
|
|||
@return own: the allocated block, in state BUF_BLOCK_MEMORY */
|
||||
UNIV_INLINE
|
||||
buf_block_t*
|
||||
buf_block_alloc(
|
||||
/*============*/
|
||||
ulint zip_size) /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
buf_block_alloc(void)
|
||||
/*=================*/
|
||||
{
|
||||
buf_block_t* block;
|
||||
|
||||
block = buf_LRU_get_free_block(zip_size);
|
||||
block = buf_LRU_get_free_block();
|
||||
|
||||
buf_block_set_state(block, BUF_BLOCK_MEMORY);
|
||||
|
||||
|
|
|
@ -84,6 +84,13 @@ void
|
|||
buf_LRU_invalidate_tablespace(
|
||||
/*==========================*/
|
||||
ulint id); /*!< in: space id */
|
||||
/******************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
void
|
||||
buf_LRU_mark_space_was_deleted(
|
||||
/*===========================*/
|
||||
ulint id); /*!< in: space id */
|
||||
/********************************************************************//**
|
||||
Insert a compressed block into buf_pool->zip_clean in the LRU order. */
|
||||
UNIV_INTERN
|
||||
|
@ -112,11 +119,8 @@ buf_LRU_free_block(
|
|||
buf_page_t* bpage, /*!< in: block to be freed */
|
||||
ibool zip, /*!< in: TRUE if should remove also the
|
||||
compressed page of an uncompressed page */
|
||||
ibool* buf_pool_mutex_released,
|
||||
/*!< in: pointer to a variable that will
|
||||
be assigned TRUE if buf_pool_mutex
|
||||
was temporarily released, or NULL */
|
||||
ibool have_LRU_mutex);
|
||||
ibool have_LRU_mutex)
|
||||
__attribute__((nonnull));
|
||||
/******************************************************************//**
|
||||
Try to free a replaceable block.
|
||||
@return TRUE if found and freed */
|
||||
|
@ -147,10 +151,9 @@ LRU list to the free list.
|
|||
@return the free control block, in state BUF_BLOCK_READY_FOR_USE */
|
||||
UNIV_INTERN
|
||||
buf_block_t*
|
||||
buf_LRU_get_free_block(
|
||||
/*===================*/
|
||||
ulint zip_size); /*!< in: compressed page size in bytes,
|
||||
or 0 if uncompressed tablespace */
|
||||
buf_LRU_get_free_block(void)
|
||||
/*========================*/
|
||||
__attribute__((warn_unused_result));
|
||||
|
||||
/******************************************************************//**
|
||||
Puts a block back to the free list. */
|
||||
|
|
|
@ -76,7 +76,7 @@ enum buf_io_fix {
|
|||
/** twice the maximum block size of the buddy system;
|
||||
the underlying memory is aligned by this amount:
|
||||
this must be equal to UNIV_PAGE_SIZE */
|
||||
#define BUF_BUDDY_HIGH (BUF_BUDDY_LOW << BUF_BUDDY_SIZES)
|
||||
#define BUF_BUDDY_HIGH ((ulint)BUF_BUDDY_LOW << BUF_BUDDY_SIZES)
|
||||
/* @} */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -146,6 +146,7 @@ clustered index */
|
|||
#define DICT_SYS_INDEXES_NAME_FIELD 4
|
||||
|
||||
#define DICT_SYS_STATS_DIFF_VALS_FIELD 4
|
||||
#define DICT_SYS_STATS_NON_NULL_VALS_FIELD 5
|
||||
|
||||
/* When a row id which is zero modulo this number (which must be a power of
|
||||
two) is assigned, the field DICT_HDR_ROW_ID on the dictionary header page is
|
||||
|
|
|
@ -1062,6 +1062,13 @@ dict_update_statistics(
|
|||
not been initialized yet, otherwise
|
||||
do nothing */
|
||||
ibool sync);
|
||||
/*********************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
dict_is_older_statistics(
|
||||
/*=====================*/
|
||||
dict_index_t* index);
|
||||
/********************************************************************//**
|
||||
Reserves the dictionary system mutex for MySQL. */
|
||||
UNIV_INTERN
|
||||
|
|
|
@ -321,6 +321,12 @@ struct dict_index_struct{
|
|||
dict_get_n_unique(index); we
|
||||
periodically calculate new
|
||||
estimates */
|
||||
ib_int64_t* stat_n_non_null_key_vals;
|
||||
/* approximate number of non-null key values
|
||||
for this index, for each column where
|
||||
n < dict_get_n_unique(index); This
|
||||
is used when innodb_stats_method is
|
||||
"nulls_ignored". */
|
||||
ulint stat_index_size;
|
||||
/*!< approximate index size in
|
||||
database pages */
|
||||
|
|
|
@ -33,11 +33,6 @@ typedef struct dict_index_struct dict_index_t;
|
|||
typedef struct dict_table_struct dict_table_t;
|
||||
typedef struct dict_foreign_struct dict_foreign_t;
|
||||
|
||||
/* A cluster object is a table object with the type field set to
|
||||
DICT_CLUSTERED */
|
||||
|
||||
typedef dict_table_t dict_cluster_t;
|
||||
|
||||
typedef struct ind_node_struct ind_node_t;
|
||||
typedef struct tab_node_struct tab_node_t;
|
||||
|
||||
|
|
|
@ -648,18 +648,10 @@ _fil_io(
|
|||
Confirm whether the parameters are valid or not */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
fil_area_is_exist(
|
||||
fil_is_exist(
|
||||
/*==============*/
|
||||
ulint space_id, /*!< in: space id */
|
||||
ulint zip_size, /*!< in: compressed page size in bytes;
|
||||
0 for uncompressed pages */
|
||||
ulint block_offset, /*!< in: offset in number of blocks */
|
||||
ulint byte_offset, /*!< in: remainder of offset in bytes; in
|
||||
aio this must be divisible by the OS block
|
||||
size */
|
||||
ulint len); /*!< in: how many bytes to read or write; this
|
||||
must not cross a file boundary; in aio this
|
||||
must be a block size multiple */
|
||||
ulint block_offset); /*!< in: offset in number of blocks */
|
||||
/**********************************************************************//**
|
||||
Waits for an aio operation to complete. This function is used to write the
|
||||
handler for completed requests. The aio array of pending requests is divided
|
||||
|
|
|
@ -657,6 +657,7 @@ os_aio(
|
|||
(can be used to identify a completed
|
||||
aio operation); ignored if mode is
|
||||
OS_AIO_SYNC */
|
||||
ulint space_id,
|
||||
trx_t* trx);
|
||||
/************************************************************************//**
|
||||
Wakes up all async i/o threads so that they know to exit themselves in
|
||||
|
@ -717,7 +718,8 @@ os_aio_windows_handle(
|
|||
parameters are valid and can be used to
|
||||
restart the operation, for example */
|
||||
void** message2,
|
||||
ulint* type); /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* space_id);
|
||||
#endif
|
||||
|
||||
/**********************************************************************//**
|
||||
|
@ -739,7 +741,8 @@ os_aio_simulated_handle(
|
|||
parameters are valid and can be used to
|
||||
restart the operation, for example */
|
||||
void** message2,
|
||||
ulint* type); /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* space_id);
|
||||
/**********************************************************************//**
|
||||
Validates the consistency of the aio system.
|
||||
@return TRUE if ok */
|
||||
|
|
|
@ -293,22 +293,6 @@ page_cur_open_on_rnd_user_rec(
|
|||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: page */
|
||||
page_cur_t* cursor);/*!< out: page cursor */
|
||||
|
||||
UNIV_INTERN
|
||||
void
|
||||
page_cur_open_on_nth_user_rec(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: page */
|
||||
page_cur_t* cursor, /*!< out: page cursor */
|
||||
ulint nth);
|
||||
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
page_cur_open_on_rnd_user_rec_after_nth(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: page */
|
||||
page_cur_t* cursor, /*!< out: page cursor */
|
||||
ulint nth);
|
||||
#endif /* !UNIV_HOTBACKUP */
|
||||
/***********************************************************//**
|
||||
Parses a log record of a record insert on a page.
|
||||
|
|
|
@ -165,15 +165,18 @@ cmp_rec_rec_with_match(
|
|||
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */
|
||||
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */
|
||||
dict_index_t* index, /*!< in: data dictionary index */
|
||||
ibool nulls_unequal,
|
||||
/* in: TRUE if this is for index statistics
|
||||
cardinality estimation, and innodb_stats_method
|
||||
is "nulls_unequal" or "nulls_ignored" */
|
||||
ulint* matched_fields, /*!< in/out: number of already completely
|
||||
matched fields; when the function returns,
|
||||
contains the value the for current
|
||||
comparison */
|
||||
ulint* matched_bytes, /*!< in/out: number of already matched
|
||||
ulint* matched_bytes);/*!< in/out: number of already matched
|
||||
bytes within the first field not completely
|
||||
matched; when the function returns, contains
|
||||
the value for the current comparison */
|
||||
ulint stats_method);
|
||||
/*************************************************************//**
|
||||
This function is used to compare two physical records. Only the common
|
||||
first fields are compared.
|
||||
|
|
|
@ -87,5 +87,5 @@ cmp_rec_rec(
|
|||
ulint match_b = 0;
|
||||
|
||||
return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index,
|
||||
&match_f, &match_b, 0));
|
||||
FALSE, &match_f, &match_b));
|
||||
}
|
||||
|
|
|
@ -384,6 +384,14 @@ row_insert_stats_for_mysql(
|
|||
dict_index_t* index,
|
||||
trx_t* trx);
|
||||
/*********************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
int
|
||||
row_delete_stats_for_mysql(
|
||||
/*=======================*/
|
||||
dict_index_t* index,
|
||||
trx_t* trx);
|
||||
/*********************************************************************//**
|
||||
Scans a table create SQL string and adds to the data dictionary
|
||||
the foreign key constraints declared in the string. This function
|
||||
should be called after the indexes for a table have been created.
|
||||
|
|
|
@ -280,19 +280,29 @@ NOTE: we compare the fields as binary strings!
|
|||
@return TRUE if update vector changes an ordering field in the index record */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
row_upd_changes_ord_field_binary(
|
||||
/*=============================*/
|
||||
row_upd_changes_ord_field_binary_func(
|
||||
/*==================================*/
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update, /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
#ifdef UNIV_DEBUG
|
||||
const que_thr_t*thr, /*!< in: query thread */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const dtuple_t* row, /*!< in: old value of row, or NULL if the
|
||||
row and the data values in update are not
|
||||
known when this function is called, e.g., at
|
||||
compile time */
|
||||
const row_ext_t*ext, /*!< NULL, or prefixes of the externally
|
||||
const row_ext_t*ext) /*!< NULL, or prefixes of the externally
|
||||
stored columns in the old row */
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update) /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
__attribute__((nonnull(3,4), warn_unused_result));
|
||||
__attribute__((nonnull(1,2), warn_unused_result));
|
||||
#ifdef UNIV_DEBUG
|
||||
# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
|
||||
row_upd_changes_ord_field_binary_func(index,update,thr,row,ext)
|
||||
#else /* UNIV_DEBUG */
|
||||
# define row_upd_changes_ord_field_binary(index,update,thr,row,ext) \
|
||||
row_upd_changes_ord_field_binary_func(index,update,row,ext)
|
||||
#endif /* UNIV_DEBUG */
|
||||
/***********************************************************//**
|
||||
Checks if an update vector changes an ordering field of an index record.
|
||||
This function is fast if the update vector is short or the number of ordering
|
||||
|
|
|
@ -177,6 +177,11 @@ capacity. PCT_IO(5) -> returns the number of IO operations that
|
|||
is 5% of the max where max is srv_io_capacity. */
|
||||
#define PCT_IO(p) ((ulong) (srv_io_capacity * ((double) p / 100.0)))
|
||||
|
||||
/* The "innodb_stats_method" setting, decides how InnoDB is going
|
||||
to treat NULL value when collecting statistics. It is not defined
|
||||
as enum type because the configure option takes unsigned integer type. */
|
||||
extern ulong srv_innodb_stats_method;
|
||||
|
||||
#ifdef UNIV_LOG_ARCHIVE
|
||||
extern ibool srv_log_archive_on;
|
||||
extern ibool srv_archive_recovery;
|
||||
|
@ -208,10 +213,6 @@ extern ulint srv_fast_shutdown; /* If this is 1, do not do a
|
|||
extern ibool srv_innodb_status;
|
||||
|
||||
extern unsigned long long srv_stats_sample_pages;
|
||||
extern ulong srv_stats_method;
|
||||
#define SRV_STATS_METHOD_NULLS_EQUAL 0
|
||||
#define SRV_STATS_METHOD_NULLS_NOT_EQUAL 1
|
||||
#define SRV_STATS_METHOD_IGNORE_NULLS 2
|
||||
extern ulong srv_stats_auto_update;
|
||||
extern ulint srv_stats_update_need_lock;
|
||||
extern ibool srv_use_sys_stats_table;
|
||||
|
@ -242,6 +243,8 @@ extern ulint srv_pass_corrupt_table;
|
|||
|
||||
extern ulong srv_extra_rsegments;
|
||||
extern ulong srv_dict_size_limit;
|
||||
|
||||
extern ulint srv_lazy_drop_table;
|
||||
/*-------------------------------------------*/
|
||||
|
||||
extern ulint srv_n_rows_inserted;
|
||||
|
@ -413,6 +416,19 @@ enum {
|
|||
in connection with recovery */
|
||||
};
|
||||
|
||||
/* Alternatives for srv_innodb_stats_method, which could be changed by
|
||||
setting innodb_stats_method */
|
||||
enum srv_stats_method_name_enum {
|
||||
SRV_STATS_NULLS_EQUAL, /* All NULL values are treated as
|
||||
equal. This is the default setting
|
||||
for innodb_stats_method */
|
||||
SRV_STATS_NULLS_UNEQUAL, /* All NULL values are treated as
|
||||
NOT equal. */
|
||||
SRV_STATS_NULLS_IGNORED /* NULL values are ignored */
|
||||
};
|
||||
|
||||
typedef enum srv_stats_method_name_enum srv_stats_method_name_t;
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
/** Types of threads existing in the system. */
|
||||
enum srv_thread_type {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2010, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
|
@ -113,14 +113,14 @@ is necessary only if the memory block containing it is freed. */
|
|||
#ifdef UNIV_DEBUG
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
# define rw_lock_create(L, level) \
|
||||
rw_lock_create_func((L), (level), #L, __FILE__, __LINE__)
|
||||
rw_lock_create_func((L), (level), __FILE__, __LINE__, #L)
|
||||
# else /* UNIV_SYNC_DEBUG */
|
||||
# define rw_lock_create(L, level) \
|
||||
rw_lock_create_func((L), #L, __FILE__, __LINE__)
|
||||
rw_lock_create_func((L), __FILE__, __LINE__, #L)
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
#else /* UNIV_DEBUG */
|
||||
# define rw_lock_create(L, level) \
|
||||
rw_lock_create_func((L), #L, NULL, 0)
|
||||
rw_lock_create_func((L), #L)
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/******************************************************************//**
|
||||
|
@ -137,10 +137,10 @@ rw_lock_create_func(
|
|||
# ifdef UNIV_SYNC_DEBUG
|
||||
ulint level, /*!< in: level */
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cmutex_name, /*!< in: mutex name */
|
||||
const char* cfile_name, /*!< in: file name where created */
|
||||
ulint cline); /*!< in: file line where created */
|
||||
ulint cline, /*!< in: file line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cmutex_name); /*!< in: mutex name */
|
||||
/******************************************************************//**
|
||||
Calling this function is obligatory only if the memory buffer containing
|
||||
the rw-lock is freed. Removes an rw-lock object from the global list. The
|
||||
|
@ -490,6 +490,7 @@ UNIV_INTERN
|
|||
void
|
||||
rw_lock_debug_print(
|
||||
/*================*/
|
||||
FILE* f, /*!< in: output stream */
|
||||
rw_lock_debug_t* info); /*!< in: debug struct */
|
||||
#endif /* UNIV_SYNC_DEBUG */
|
||||
|
||||
|
|
|
@ -73,14 +73,14 @@ necessary only if the memory block containing it is freed. */
|
|||
#ifdef UNIV_DEBUG
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
# define mutex_create(M, level) \
|
||||
mutex_create_func((M), #M, (level), __FILE__, __LINE__)
|
||||
mutex_create_func((M), (level), __FILE__, __LINE__, #M)
|
||||
# else
|
||||
# define mutex_create(M, level) \
|
||||
mutex_create_func((M), #M, __FILE__, __LINE__)
|
||||
mutex_create_func((M), __FILE__, __LINE__, #M)
|
||||
# endif
|
||||
#else
|
||||
# define mutex_create(M, level) \
|
||||
mutex_create_func((M), #M, NULL, 0)
|
||||
mutex_create_func((M), #M)
|
||||
#endif
|
||||
|
||||
/******************************************************************//**
|
||||
|
@ -93,14 +93,14 @@ void
|
|||
mutex_create_func(
|
||||
/*==============*/
|
||||
mutex_t* mutex, /*!< in: pointer to memory */
|
||||
const char* cmutex_name, /*!< in: mutex name */
|
||||
#ifdef UNIV_DEBUG
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
ulint level, /*!< in: level */
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cfile_name, /*!< in: file name where created */
|
||||
ulint cline); /*!< in: file line where created */
|
||||
ulint cline, /*!< in: file line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cmutex_name); /*!< in: mutex name */
|
||||
|
||||
#undef mutex_free /* Fix for MacOS X */
|
||||
|
||||
|
@ -496,6 +496,7 @@ or row lock! */
|
|||
#define SYNC_BUF_POOL 150
|
||||
#define SYNC_BUF_FLUSH_LIST 149
|
||||
#define SYNC_DOUBLEWRITE 140
|
||||
#define SYNC_OUTER_ANY_LATCH 136
|
||||
#define SYNC_ANY_LATCH 135
|
||||
#define SYNC_THR_LOCAL 133
|
||||
#define SYNC_MEM_HASH 131
|
||||
|
|
|
@ -149,9 +149,7 @@ struct trx_rseg_struct{
|
|||
ulint id; /*!< rollback segment id == the index of
|
||||
its slot in the trx system file copy */
|
||||
mutex_t mutex; /*!< mutex protecting the fields in this
|
||||
struct except id; NOTE that the latching
|
||||
order must always be kernel mutex ->
|
||||
rseg mutex */
|
||||
struct except id, which is constant */
|
||||
ulint space; /*!< space where the rollback segment is
|
||||
header is placed */
|
||||
ulint zip_size;/* compressed page size of space
|
||||
|
|
|
@ -214,12 +214,12 @@ trx_recover_for_mysql(
|
|||
/*******************************************************************//**
|
||||
This function is used to find one X/Open XA distributed transaction
|
||||
which is in the prepared state
|
||||
@return trx or NULL */
|
||||
@return trx or NULL; on match, the trx->xid will be invalidated */
|
||||
UNIV_INTERN
|
||||
trx_t *
|
||||
trx_get_trx_by_xid(
|
||||
/*===============*/
|
||||
XID* xid); /*!< in: X/Open XA transaction identification */
|
||||
const XID* xid); /*!< in: X/Open XA transaction identifier */
|
||||
/**********************************************************************//**
|
||||
If required, flushes the log to disk if we called trx_commit_for_mysql()
|
||||
with trx->flush_log_later == TRUE.
|
||||
|
|
|
@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri
|
|||
#define INNODB_VERSION_MAJOR 1
|
||||
#define INNODB_VERSION_MINOR 0
|
||||
#define INNODB_VERSION_BUGFIX 15
|
||||
#define PERCONA_INNODB_VERSION 12.5
|
||||
#define PERCONA_INNODB_VERSION 12.7
|
||||
|
||||
/* The following is the InnoDB version as shown in
|
||||
SELECT plugin_version FROM information_schema.plugins;
|
||||
|
@ -180,14 +180,15 @@ command. Not tested on Windows. */
|
|||
debugging without UNIV_DEBUG */
|
||||
#define UNIV_BUF_DEBUG /* Enable buffer pool
|
||||
debugging without UNIV_DEBUG */
|
||||
#define UNIV_BLOB_LIGHT_DEBUG /* Enable off-page column
|
||||
debugging without UNIV_DEBUG */
|
||||
#define UNIV_DEBUG /* Enable ut_ad() assertions
|
||||
and disable UNIV_INLINE */
|
||||
#define UNIV_DEBUG_LOCK_VALIDATE /* Enable
|
||||
ut_ad(lock_rec_validate_page())
|
||||
assertions. */
|
||||
#define UNIV_DEBUG_FILE_ACCESSES /* Debug .ibd file access
|
||||
(field file_page_was_freed
|
||||
in buf_page_t) */
|
||||
#define UNIV_DEBUG_FILE_ACCESSES /* Enable freed block access
|
||||
debugging without UNIV_DEBUG */
|
||||
#define UNIV_LRU_DEBUG /* debug the buffer pool LRU */
|
||||
#define UNIV_HASH_DEBUG /* debug HASH_ macros */
|
||||
#define UNIV_LIST_DEBUG /* debug UT_LIST_ macros */
|
||||
|
@ -433,7 +434,7 @@ it is read or written. */
|
|||
/* Use sun_prefetch when compile with Sun Studio */
|
||||
# define UNIV_EXPECT(expr,value) (expr)
|
||||
# define UNIV_LIKELY_NULL(expr) (expr)
|
||||
# define UNIV_PREFETCH_R(addr) sun_prefetch_read_many(addr)
|
||||
# define UNIV_PREFETCH_R(addr) sun_prefetch_read_many((void*) addr)
|
||||
# define UNIV_PREFETCH_RW(addr) sun_prefetch_write_many(addr)
|
||||
#else
|
||||
/* Dummy versions of the macros */
|
||||
|
|
|
@ -347,7 +347,7 @@ mem_heap_create_block(
|
|||
return(NULL);
|
||||
}
|
||||
} else {
|
||||
buf_block = buf_block_alloc(0);
|
||||
buf_block = buf_block_alloc();
|
||||
}
|
||||
|
||||
block = (mem_block_t*) buf_block->frame;
|
||||
|
|
|
@ -408,7 +408,7 @@ mlog_parse_string(
|
|||
ptr += 2;
|
||||
|
||||
if (UNIV_UNLIKELY(offset >= UNIV_PAGE_SIZE)
|
||||
|| UNIV_UNLIKELY(len + offset > UNIV_PAGE_SIZE)) {
|
||||
|| UNIV_UNLIKELY(len + offset > UNIV_PAGE_SIZE)) {
|
||||
recv_sys->found_corrupt_log = TRUE;
|
||||
|
||||
return(NULL);
|
||||
|
|
|
@ -142,6 +142,7 @@ struct os_aio_slot_struct{
|
|||
// made and only the slot message
|
||||
// needs to be passed to the caller
|
||||
// of os_aio_simulated_handle */
|
||||
ulint space_id;
|
||||
fil_node_t* message1; /*!< message which is given by the */
|
||||
void* message2; /*!< the requester of an aio operation
|
||||
and which can be used to identify
|
||||
|
@ -3390,7 +3391,8 @@ os_aio_array_reserve_slot(
|
|||
offset */
|
||||
ulint offset_high, /*!< in: most significant 32 bits of
|
||||
offset */
|
||||
ulint len) /*!< in: length of the block to read or write */
|
||||
ulint len, /*!< in: length of the block to read or write */
|
||||
ulint space_id)
|
||||
{
|
||||
os_aio_slot_t* slot;
|
||||
ulint i;
|
||||
|
@ -3472,6 +3474,7 @@ found:
|
|||
slot->offset_high = offset_high;
|
||||
// slot->io_already_done = FALSE;
|
||||
slot->status = OS_AIO_NOT_ISSUED;
|
||||
slot->space_id = space_id;
|
||||
|
||||
#ifdef WIN_ASYNC_IO
|
||||
control = &(slot->control);
|
||||
|
@ -3680,6 +3683,7 @@ os_aio(
|
|||
(can be used to identify a completed
|
||||
aio operation); ignored if mode is
|
||||
OS_AIO_SYNC */
|
||||
ulint space_id,
|
||||
trx_t* trx)
|
||||
{
|
||||
os_aio_array_t* array;
|
||||
|
@ -3762,7 +3766,7 @@ try_again:
|
|||
trx->io_read += n;
|
||||
}
|
||||
slot = os_aio_array_reserve_slot(type, array, message1, message2, file,
|
||||
name, buf, offset, offset_high, n);
|
||||
name, buf, offset, offset_high, n, space_id);
|
||||
if (type == OS_FILE_READ) {
|
||||
if (os_aio_use_native_aio) {
|
||||
#ifdef WIN_ASYNC_IO
|
||||
|
@ -3872,7 +3876,8 @@ os_aio_windows_handle(
|
|||
parameters are valid and can be used to
|
||||
restart the operation, for example */
|
||||
void** message2,
|
||||
ulint* type) /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* space_id)
|
||||
{
|
||||
ulint orig_seg = segment;
|
||||
os_aio_array_t* array;
|
||||
|
@ -3926,6 +3931,7 @@ os_aio_windows_handle(
|
|||
*message2 = slot->message2;
|
||||
|
||||
*type = slot->type;
|
||||
*space_id = slot->space_id;
|
||||
|
||||
if (ret && len == slot->len) {
|
||||
ret_val = TRUE;
|
||||
|
@ -4009,7 +4015,8 @@ os_aio_simulated_handle(
|
|||
parameters are valid and can be used to
|
||||
restart the operation, for example */
|
||||
void** message2,
|
||||
ulint* type) /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* type, /*!< out: OS_FILE_WRITE or ..._READ */
|
||||
ulint* space_id)
|
||||
{
|
||||
os_aio_array_t* array;
|
||||
ulint segment;
|
||||
|
@ -4300,6 +4307,7 @@ slot_io_done:
|
|||
*message2 = slot->message2;
|
||||
|
||||
*type = slot->type;
|
||||
*space_id = slot->space_id;
|
||||
|
||||
os_mutex_exit(array->mutex);
|
||||
|
||||
|
|
|
@ -564,74 +564,6 @@ page_cur_open_on_rnd_user_rec(
|
|||
} while (rnd--);
|
||||
}
|
||||
|
||||
UNIV_INTERN
|
||||
void
|
||||
page_cur_open_on_nth_user_rec(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: page */
|
||||
page_cur_t* cursor, /*!< out: page cursor */
|
||||
ulint nth)
|
||||
{
|
||||
ulint n_recs = page_get_n_recs(buf_block_get_frame(block));
|
||||
|
||||
page_cur_set_before_first(block, cursor);
|
||||
|
||||
if (UNIV_UNLIKELY(n_recs == 0)) {
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
nth--;
|
||||
|
||||
if (nth >= n_recs) {
|
||||
nth = n_recs - 1;
|
||||
}
|
||||
|
||||
do {
|
||||
page_cur_move_to_next(cursor);
|
||||
} while (nth--);
|
||||
}
|
||||
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
page_cur_open_on_rnd_user_rec_after_nth(
|
||||
/*==========================*/
|
||||
buf_block_t* block, /*!< in: page */
|
||||
page_cur_t* cursor, /*!< out: page cursor */
|
||||
ulint nth)
|
||||
{
|
||||
ulint rnd;
|
||||
ulint n_recs = page_get_n_recs(buf_block_get_frame(block));
|
||||
ibool ret;
|
||||
|
||||
page_cur_set_before_first(block, cursor);
|
||||
|
||||
if (UNIV_UNLIKELY(n_recs == 0)) {
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
nth--;
|
||||
|
||||
if (nth >= n_recs) {
|
||||
nth = n_recs - 1;
|
||||
}
|
||||
|
||||
rnd = (ulint) (nth + page_cur_lcg_prng() % (n_recs - nth));
|
||||
|
||||
if (rnd == nth) {
|
||||
ret = TRUE;
|
||||
} else {
|
||||
ret = FALSE;
|
||||
}
|
||||
|
||||
do {
|
||||
page_cur_move_to_next(cursor);
|
||||
} while (rnd--);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/***********************************************************//**
|
||||
Writes the log record of a record insert on a page. */
|
||||
static
|
||||
|
|
|
@ -4443,7 +4443,7 @@ page_zip_reorganize(
|
|||
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
|
||||
|
||||
#ifndef UNIV_HOTBACKUP
|
||||
temp_block = buf_block_alloc(0);
|
||||
temp_block = buf_block_alloc();
|
||||
btr_search_drop_page_hash_index(block);
|
||||
block->check_index_page_at_flush = TRUE;
|
||||
#else /* !UNIV_HOTBACKUP */
|
||||
|
|
|
@ -862,15 +862,18 @@ cmp_rec_rec_with_match(
|
|||
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */
|
||||
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */
|
||||
dict_index_t* index, /*!< in: data dictionary index */
|
||||
ibool nulls_unequal,
|
||||
/* in: TRUE if this is for index statistics
|
||||
cardinality estimation, and innodb_stats_method
|
||||
is "nulls_unequal" or "nulls_ignored" */
|
||||
ulint* matched_fields, /*!< in/out: number of already completely
|
||||
matched fields; when the function returns,
|
||||
contains the value the for current
|
||||
comparison */
|
||||
ulint* matched_bytes, /*!< in/out: number of already matched
|
||||
ulint* matched_bytes) /*!< in/out: number of already matched
|
||||
bytes within the first field not completely
|
||||
matched; when the function returns, contains
|
||||
the value for the current comparison */
|
||||
ulint stats_method)
|
||||
{
|
||||
ulint rec1_n_fields; /* the number of fields in rec */
|
||||
ulint rec1_f_len; /* length of current field in rec */
|
||||
|
@ -962,13 +965,13 @@ cmp_rec_rec_with_match(
|
|||
|| rec2_f_len == UNIV_SQL_NULL) {
|
||||
|
||||
if (rec1_f_len == rec2_f_len) {
|
||||
|
||||
if (stats_method == SRV_STATS_METHOD_NULLS_EQUAL) {
|
||||
goto next_field;
|
||||
} else {
|
||||
/* This is limited to stats collection,
|
||||
cannot use it for regular search */
|
||||
if (nulls_unequal) {
|
||||
ret = -1;
|
||||
} else {
|
||||
goto next_field;
|
||||
}
|
||||
|
||||
} else if (rec2_f_len == UNIV_SQL_NULL) {
|
||||
|
||||
/* We define the SQL null to be the
|
||||
|
|
|
@ -2026,6 +2026,8 @@ row_ins_index_entry_low(
|
|||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (!srv_use_sys_stats_table
|
||||
|| index != UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes))
|
||||
{
|
||||
page_t* page = btr_cur_get_page(&cursor);
|
||||
rec_t* first_rec = page_rec_get_next(
|
||||
|
@ -2136,7 +2138,7 @@ function_exit:
|
|||
|
||||
err = btr_store_big_rec_extern_fields(
|
||||
index, btr_cur_get_block(&cursor),
|
||||
rec, offsets, big_rec, &mtr);
|
||||
rec, offsets, &mtr, FALSE, big_rec);
|
||||
|
||||
if (modify) {
|
||||
dtuple_big_rec_free(big_rec);
|
||||
|
|
|
@ -52,6 +52,7 @@ Created 9/17/2000 Heikki Tuuri
|
|||
#include "btr0sea.h"
|
||||
#include "fil0fil.h"
|
||||
#include "ibuf0ibuf.h"
|
||||
#include "ha_prototypes.h"
|
||||
|
||||
/** Provide optional 4.x backwards compatibility for 5.0 and above */
|
||||
UNIV_INTERN ibool row_rollback_on_timeout = FALSE;
|
||||
|
@ -2095,6 +2096,32 @@ row_insert_stats_for_mysql(
|
|||
return((int) err);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
*/
|
||||
UNIV_INTERN
|
||||
int
|
||||
row_delete_stats_for_mysql(
|
||||
/*=============================*/
|
||||
dict_index_t* index,
|
||||
trx_t* trx)
|
||||
{
|
||||
pars_info_t* info = pars_info_create();
|
||||
|
||||
trx->op_info = "delete rows from SYS_STATS";
|
||||
|
||||
trx_start_if_not_started(trx);
|
||||
trx->error_state = DB_SUCCESS;
|
||||
|
||||
pars_info_add_dulint_literal(info, "indexid", index->id);
|
||||
|
||||
return((int) que_eval_sql(info,
|
||||
"PROCEDURE DELETE_STATISTICS_PROC () IS\n"
|
||||
"BEGIN\n"
|
||||
"DELETE FROM SYS_STATS WHERE INDEX_ID = :indexid;\n"
|
||||
"END;\n"
|
||||
, TRUE, trx));
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
Scans a table create SQL string and adds to the data dictionary
|
||||
the foreign key constraints declared in the string. This function
|
||||
|
|
|
@ -387,8 +387,11 @@ Purges an update of an existing record. Also purges an update of a delete
|
|||
marked record if that record contained an externally stored field. */
|
||||
static
|
||||
void
|
||||
row_purge_upd_exist_or_extern(
|
||||
/*==========================*/
|
||||
row_purge_upd_exist_or_extern_func(
|
||||
/*===============================*/
|
||||
#ifdef UNIV_DEBUG
|
||||
const que_thr_t*thr, /*!< in: query thread */
|
||||
#endif /* UNIV_DEBUG */
|
||||
purge_node_t* node) /*!< in: row purge node */
|
||||
{
|
||||
mem_heap_t* heap;
|
||||
|
@ -413,8 +416,8 @@ row_purge_upd_exist_or_extern(
|
|||
while (node->index != NULL) {
|
||||
index = node->index;
|
||||
|
||||
if (row_upd_changes_ord_field_binary(NULL, NULL, node->index,
|
||||
node->update)) {
|
||||
if (row_upd_changes_ord_field_binary(node->index, node->update,
|
||||
thr, NULL, NULL)) {
|
||||
/* Build the older version of the index entry */
|
||||
entry = row_build_index_entry(node->row, NULL,
|
||||
index, heap);
|
||||
|
@ -496,6 +499,14 @@ skip_secondaries:
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
# define row_purge_upd_exist_or_extern(thr,node) \
|
||||
row_purge_upd_exist_or_extern_func(thr,node)
|
||||
#else /* UNIV_DEBUG */
|
||||
# define row_purge_upd_exist_or_extern(thr,node) \
|
||||
row_purge_upd_exist_or_extern_func(node)
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/***********************************************************//**
|
||||
Parses the row reference and other info in a modify undo log record.
|
||||
@return TRUE if purge operation required: NOTE that then the CALLER
|
||||
|
@ -602,47 +613,32 @@ err_exit:
|
|||
/***********************************************************//**
|
||||
Fetches an undo log record and does the purge for the recorded operation.
|
||||
If none left, or the current purge completed, returns the control to the
|
||||
parent node, which is always a query thread node.
|
||||
@return DB_SUCCESS if operation successfully completed, else error code */
|
||||
static
|
||||
ulint
|
||||
parent node, which is always a query thread node. */
|
||||
static __attribute__((nonnull))
|
||||
void
|
||||
row_purge(
|
||||
/*======*/
|
||||
purge_node_t* node, /*!< in: row purge node */
|
||||
que_thr_t* thr) /*!< in: query thread */
|
||||
{
|
||||
roll_ptr_t roll_ptr;
|
||||
ibool purge_needed;
|
||||
ibool updated_extern;
|
||||
trx_t* trx;
|
||||
|
||||
ut_ad(node && thr);
|
||||
ut_ad(node);
|
||||
ut_ad(thr);
|
||||
|
||||
trx = thr_get_trx(thr);
|
||||
|
||||
node->undo_rec = trx_purge_fetch_next_rec(&roll_ptr,
|
||||
&(node->reservation),
|
||||
node->undo_rec = trx_purge_fetch_next_rec(&node->roll_ptr,
|
||||
&node->reservation,
|
||||
node->heap);
|
||||
if (!node->undo_rec) {
|
||||
/* Purge completed for this query thread */
|
||||
|
||||
thr->run_node = que_node_get_parent(node);
|
||||
|
||||
return(DB_SUCCESS);
|
||||
return;
|
||||
}
|
||||
|
||||
node->roll_ptr = roll_ptr;
|
||||
|
||||
if (node->undo_rec == &trx_purge_dummy_rec) {
|
||||
purge_needed = FALSE;
|
||||
} else {
|
||||
purge_needed = row_purge_parse_undo_rec(node, &updated_extern,
|
||||
thr);
|
||||
/* If purge_needed == TRUE, we must also remember to unfreeze
|
||||
data dictionary! */
|
||||
}
|
||||
|
||||
if (purge_needed) {
|
||||
if (node->undo_rec != &trx_purge_dummy_rec
|
||||
&& row_purge_parse_undo_rec(node, &updated_extern, thr)) {
|
||||
node->found_clust = FALSE;
|
||||
|
||||
node->index = dict_table_get_next_index(
|
||||
|
@ -654,14 +650,14 @@ row_purge(
|
|||
} else if (updated_extern
|
||||
|| node->rec_type == TRX_UNDO_UPD_EXIST_REC) {
|
||||
|
||||
row_purge_upd_exist_or_extern(node);
|
||||
row_purge_upd_exist_or_extern(thr, node);
|
||||
}
|
||||
|
||||
if (node->found_clust) {
|
||||
btr_pcur_close(&(node->pcur));
|
||||
}
|
||||
|
||||
row_mysql_unfreeze_data_dictionary(trx);
|
||||
row_mysql_unfreeze_data_dictionary(thr_get_trx(thr));
|
||||
}
|
||||
|
||||
/* Do some cleanup */
|
||||
|
@ -669,8 +665,6 @@ row_purge(
|
|||
mem_heap_empty(node->heap);
|
||||
|
||||
thr->run_node = node;
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/***********************************************************//**
|
||||
|
@ -684,9 +678,6 @@ row_purge_step(
|
|||
que_thr_t* thr) /*!< in: query thread */
|
||||
{
|
||||
purge_node_t* node;
|
||||
#ifdef UNIV_DEBUG
|
||||
ulint err;
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
ut_ad(thr);
|
||||
|
||||
|
@ -694,12 +685,7 @@ row_purge_step(
|
|||
|
||||
ut_ad(que_node_get_type(node) == QUE_NODE_PURGE);
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
err =
|
||||
#endif /* UNIV_DEBUG */
|
||||
row_purge(node, thr);
|
||||
|
||||
ut_ad(err == DB_SUCCESS);
|
||||
|
||||
return(thr);
|
||||
}
|
||||
|
|
|
@ -347,6 +347,14 @@ row_rec_to_index_entry_low(
|
|||
|
||||
rec_len = rec_offs_n_fields(offsets);
|
||||
|
||||
if (srv_use_sys_stats_table
|
||||
&& index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
|
||||
if (rec_len < dict_index_get_n_fields(index)) {
|
||||
/* the new record should be extended */
|
||||
rec_len = dict_index_get_n_fields(index);
|
||||
}
|
||||
}
|
||||
|
||||
entry = dtuple_create(heap, rec_len);
|
||||
|
||||
dtuple_set_n_fields_cmp(entry,
|
||||
|
@ -358,6 +366,14 @@ row_rec_to_index_entry_low(
|
|||
for (i = 0; i < rec_len; i++) {
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, i);
|
||||
|
||||
if (srv_use_sys_stats_table
|
||||
&& index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
|
||||
&& i >= rec_offs_n_fields(offsets)) {
|
||||
dfield_set_null(dfield);
|
||||
continue;
|
||||
}
|
||||
|
||||
field = rec_get_nth_field(rec, offsets, i, &len);
|
||||
|
||||
dfield_set_data(dfield, field, len);
|
||||
|
|
|
@ -173,40 +173,26 @@ row_undo_mod_remove_clust_low(
|
|||
mtr_t* mtr, /*!< in: mtr */
|
||||
ulint mode) /*!< in: BTR_MODIFY_LEAF or BTR_MODIFY_TREE */
|
||||
{
|
||||
btr_pcur_t* pcur;
|
||||
btr_cur_t* btr_cur;
|
||||
ulint err;
|
||||
ibool success;
|
||||
|
||||
ut_ad(node->rec_type == TRX_UNDO_UPD_DEL_REC);
|
||||
pcur = &(node->pcur);
|
||||
btr_cur = btr_pcur_get_btr_cur(pcur);
|
||||
|
||||
success = btr_pcur_restore_position(mode, pcur, mtr);
|
||||
/* Find out if the record has been purged already
|
||||
or if we can remove it. */
|
||||
|
||||
if (!success) {
|
||||
if (!btr_pcur_restore_position(mode, &node->pcur, mtr)
|
||||
|| row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
|
||||
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
|
||||
/* Find out if we can remove the whole clustered index record */
|
||||
|
||||
if (node->rec_type == TRX_UNDO_UPD_DEL_REC
|
||||
&& !row_vers_must_preserve_del_marked(node->new_trx_id, mtr)) {
|
||||
|
||||
/* Ok, we can remove */
|
||||
} else {
|
||||
return(DB_SUCCESS);
|
||||
}
|
||||
btr_cur = btr_pcur_get_btr_cur(&node->pcur);
|
||||
|
||||
if (mode == BTR_MODIFY_LEAF) {
|
||||
success = btr_cur_optimistic_delete(btr_cur, mtr);
|
||||
|
||||
if (success) {
|
||||
err = DB_SUCCESS;
|
||||
} else {
|
||||
err = DB_FAIL;
|
||||
}
|
||||
err = btr_cur_optimistic_delete(btr_cur, mtr)
|
||||
? DB_SUCCESS
|
||||
: DB_FAIL;
|
||||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
|
||||
|
@ -668,8 +654,9 @@ row_undo_mod_upd_exist_sec(
|
|||
while (node->index != NULL) {
|
||||
index = node->index;
|
||||
|
||||
if (row_upd_changes_ord_field_binary(
|
||||
node->row, node->ext, node->index, node->update)) {
|
||||
if (row_upd_changes_ord_field_binary(node->index, node->update,
|
||||
thr,
|
||||
node->row, node->ext)) {
|
||||
|
||||
/* Build the newest version of the index entry */
|
||||
entry = row_build_index_entry(node->row, node->ext,
|
||||
|
|
|
@ -439,6 +439,12 @@ row_upd_changes_field_size_or_external(
|
|||
0);
|
||||
}
|
||||
|
||||
if (srv_use_sys_stats_table
|
||||
&& index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
|
||||
&& upd_field->field_no >= rec_offs_n_fields(offsets)) {
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
old_len = rec_offs_nth_size(offsets, upd_field->field_no);
|
||||
|
||||
if (rec_offs_comp(offsets)
|
||||
|
@ -844,6 +850,18 @@ row_upd_build_difference_binary(
|
|||
|
||||
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
|
||||
|
||||
if (srv_use_sys_stats_table
|
||||
&& index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)
|
||||
&& i >= rec_offs_n_fields(offsets)) {
|
||||
dfield = dtuple_get_nth_field(entry, i);
|
||||
|
||||
upd_field = upd_get_nth_field(update, n_diff);
|
||||
dfield_copy(&(upd_field->new_val), dfield);
|
||||
upd_field_set_field_no(upd_field, i, index, trx);
|
||||
n_diff++;
|
||||
goto skip_compare;
|
||||
}
|
||||
|
||||
data = rec_get_nth_field(rec, offsets, i, &len);
|
||||
|
||||
dfield = dtuple_get_nth_field(entry, i);
|
||||
|
@ -1192,25 +1210,31 @@ NOTE: we compare the fields as binary strings!
|
|||
@return TRUE if update vector changes an ordering field in the index record */
|
||||
UNIV_INTERN
|
||||
ibool
|
||||
row_upd_changes_ord_field_binary(
|
||||
/*=============================*/
|
||||
row_upd_changes_ord_field_binary_func(
|
||||
/*==================================*/
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update, /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
#ifdef UNIV_DEBUG
|
||||
const que_thr_t*thr, /*!< in: query thread */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const dtuple_t* row, /*!< in: old value of row, or NULL if the
|
||||
row and the data values in update are not
|
||||
known when this function is called, e.g., at
|
||||
compile time */
|
||||
const row_ext_t*ext, /*!< NULL, or prefixes of the externally
|
||||
const row_ext_t*ext) /*!< NULL, or prefixes of the externally
|
||||
stored columns in the old row */
|
||||
dict_index_t* index, /*!< in: index of the record */
|
||||
const upd_t* update) /*!< in: update vector for the row; NOTE: the
|
||||
field numbers in this MUST be clustered index
|
||||
positions! */
|
||||
{
|
||||
ulint n_unique;
|
||||
ulint i;
|
||||
const dict_index_t* clust_index;
|
||||
|
||||
ut_ad(update);
|
||||
ut_ad(index);
|
||||
ut_ad(update);
|
||||
ut_ad(thr);
|
||||
ut_ad(thr->graph);
|
||||
ut_ad(thr->graph->trx);
|
||||
|
||||
n_unique = dict_index_get_n_unique(index);
|
||||
|
||||
|
@ -1252,6 +1276,10 @@ row_upd_changes_ord_field_binary(
|
|||
|| dfield_is_null(dfield)) {
|
||||
/* do nothing special */
|
||||
} else if (UNIV_LIKELY_NULL(ext)) {
|
||||
/* Silence a compiler warning without
|
||||
silencing a Valgrind error. */
|
||||
dfield_len = 0;
|
||||
UNIV_MEM_INVALID(&dfield_len, sizeof dfield_len);
|
||||
/* See if the column is stored externally. */
|
||||
buf = row_ext_lookup(ext, col_no, &dfield_len);
|
||||
|
||||
|
@ -1259,9 +1287,14 @@ row_upd_changes_ord_field_binary(
|
|||
|
||||
if (UNIV_LIKELY_NULL(buf)) {
|
||||
if (UNIV_UNLIKELY(buf == field_ref_zero)) {
|
||||
/* This should never happen, but
|
||||
we try to fail safe here. */
|
||||
ut_ad(0);
|
||||
/* The externally stored field
|
||||
was not written yet. This
|
||||
record should only be seen by
|
||||
recv_recovery_rollback_active(),
|
||||
when the server had crashed before
|
||||
storing the field. */
|
||||
ut_ad(thr->graph->trx->is_recovered);
|
||||
ut_ad(trx_is_recv(thr->graph->trx));
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
@ -1608,8 +1641,8 @@ row_upd_sec_step(
|
|||
ut_ad(!dict_index_is_clust(node->index));
|
||||
|
||||
if (node->state == UPD_NODE_UPDATE_ALL_SEC
|
||||
|| row_upd_changes_ord_field_binary(node->row, node->ext,
|
||||
node->index, node->update)) {
|
||||
|| row_upd_changes_ord_field_binary(node->index, node->update,
|
||||
thr, node->row, node->ext)) {
|
||||
return(row_upd_sec_index_entry(node, thr));
|
||||
}
|
||||
|
||||
|
@ -1937,7 +1970,7 @@ row_upd_clust_rec(
|
|||
index, btr_cur_get_block(btr_cur), rec,
|
||||
rec_get_offsets(rec, index, offsets_,
|
||||
ULINT_UNDEFINED, &heap),
|
||||
big_rec, mtr);
|
||||
mtr, TRUE, big_rec);
|
||||
mtr_commit(mtr);
|
||||
}
|
||||
|
||||
|
@ -2136,8 +2169,8 @@ exit_func:
|
|||
|
||||
row_upd_store_row(node);
|
||||
|
||||
if (row_upd_changes_ord_field_binary(node->row, node->ext, index,
|
||||
node->update)) {
|
||||
if (row_upd_changes_ord_field_binary(index, node->update, thr,
|
||||
node->row, node->ext)) {
|
||||
|
||||
/* Update causes an ordering field (ordering fields within
|
||||
the B-tree) of the clustered index record to change: perform
|
||||
|
|
|
@ -669,11 +669,15 @@ row_vers_build_for_semi_consistent_read(
|
|||
|
||||
mutex_enter(&kernel_mutex);
|
||||
version_trx = trx_get_on_id(version_trx_id);
|
||||
if (version_trx
|
||||
&& (version_trx->conc_state == TRX_COMMITTED_IN_MEMORY
|
||||
|| version_trx->conc_state == TRX_NOT_STARTED)) {
|
||||
|
||||
version_trx = NULL;
|
||||
}
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
if (!version_trx
|
||||
|| version_trx->conc_state == TRX_NOT_STARTED
|
||||
|| version_trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
|
||||
if (!version_trx) {
|
||||
|
||||
/* We found a version that belongs to a
|
||||
committed transaction: return it. */
|
||||
|
|
|
@ -269,6 +269,11 @@ UNIV_INTERN ulong srv_max_buf_pool_modified_pct = 75;
|
|||
/* variable counts amount of data read in total (in bytes) */
|
||||
UNIV_INTERN ulint srv_data_read = 0;
|
||||
|
||||
/* Internal setting for "innodb_stats_method". Decides how InnoDB treats
|
||||
NULL value when collecting statistics. By default, it is set to
|
||||
SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */
|
||||
ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL;
|
||||
|
||||
/* here we count the amount of data written in total (in bytes) */
|
||||
UNIV_INTERN ulint srv_data_written = 0;
|
||||
|
||||
|
@ -388,7 +393,6 @@ UNIV_INTERN ibool srv_innodb_status = FALSE;
|
|||
/* When estimating number of different key values in an index, sample
|
||||
this many index pages */
|
||||
UNIV_INTERN unsigned long long srv_stats_sample_pages = 8;
|
||||
UNIV_INTERN ulong srv_stats_method = 0;
|
||||
UNIV_INTERN ulong srv_stats_auto_update = 1;
|
||||
UNIV_INTERN ulint srv_stats_update_need_lock = 1;
|
||||
UNIV_INTERN ibool srv_use_sys_stats_table = FALSE;
|
||||
|
@ -419,6 +423,8 @@ UNIV_INTERN ulint srv_pass_corrupt_table = 0; /* 0:disable 1:enable */
|
|||
|
||||
UNIV_INTERN ulong srv_extra_rsegments = 0; /* extra rseg for users */
|
||||
UNIV_INTERN ulong srv_dict_size_limit = 0;
|
||||
|
||||
UNIV_INTERN ulint srv_lazy_drop_table = 0;
|
||||
/*-------------------------------------------*/
|
||||
UNIV_INTERN ulong srv_n_spin_wait_rounds = 30;
|
||||
UNIV_INTERN ulong srv_n_free_tickets_to_enter = 500;
|
||||
|
@ -2709,7 +2715,8 @@ srv_master_thread(
|
|||
unsigned space:32;
|
||||
unsigned offset:32;
|
||||
ib_uint64_t oldest_modification;
|
||||
} prev_flush_info;
|
||||
};
|
||||
struct t_prev_flush_info_struct prev_flush_info = {0,0,0,0};
|
||||
|
||||
ib_uint64_t lsn_old;
|
||||
|
||||
|
@ -2768,6 +2775,8 @@ loop:
|
|||
for (i = 0; i < 10; i++) {
|
||||
ulint cur_time = ut_time_ms();
|
||||
|
||||
n_pages_flushed = 0; /* initialize */
|
||||
|
||||
n_ios_old = log_sys->n_log_ios + buf_pool->stat.n_pages_read
|
||||
+ buf_pool->stat.n_pages_written;
|
||||
srv_main_thread_op_info = "sleeping";
|
||||
|
@ -3033,7 +3042,8 @@ retry_flush_batch:
|
|||
|
||||
if (prev_adaptive_checkpoint == 3) {
|
||||
lint n_flush;
|
||||
lint blocks_sum, new_blocks_sum, flushed_blocks_sum;
|
||||
lint blocks_sum;
|
||||
ulint new_blocks_sum, flushed_blocks_sum;
|
||||
|
||||
blocks_sum = new_blocks_sum = flushed_blocks_sum = 0;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
|
@ -714,7 +714,7 @@ print:
|
|||
fprintf(stderr, "rw-lock %p ",
|
||||
(void*) lock);
|
||||
sync_array_cell_print(stderr, cell);
|
||||
rw_lock_debug_print(debug);
|
||||
rw_lock_debug_print(stderr, debug);
|
||||
return(TRUE);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*****************************************************************************
|
||||
|
||||
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
|
||||
Copyright (c) 1995, 2011, Oracle and/or its affiliates. All Rights Reserved.
|
||||
Copyright (c) 2008, Google Inc.
|
||||
|
||||
Portions of this file contain modifications contributed and copyrighted by
|
||||
|
@ -231,10 +231,10 @@ rw_lock_create_func(
|
|||
# ifdef UNIV_SYNC_DEBUG
|
||||
ulint level, /*!< in: level */
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cmutex_name, /*!< in: mutex name */
|
||||
const char* cfile_name, /*!< in: file name where created */
|
||||
ulint cline) /*!< in: file line where created */
|
||||
ulint cline, /*!< in: file line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cmutex_name) /*!< in: mutex name */
|
||||
{
|
||||
/* If this is the very first time a synchronization object is
|
||||
created, then the following call initializes the sync system. */
|
||||
|
@ -247,11 +247,12 @@ rw_lock_create_func(
|
|||
|
||||
lock->mutex.cmutex_name = cmutex_name;
|
||||
ut_d(lock->mutex.mutex_type = 1);
|
||||
#else /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
# ifdef UNIV_DEBUG
|
||||
UT_NOT_USED(cfile_name);
|
||||
UT_NOT_USED(cline);
|
||||
# endif
|
||||
#endif /* INNODB_RW_LOCKS_USE_ATOMICS */
|
||||
#if defined(INNODB_RW_LOCKS_USE_ATOMICS) || !defined(UNIV_DEBUG)
|
||||
(void) cfile_name;
|
||||
(void) cline;
|
||||
#endif
|
||||
|
||||
lock->lock_word = X_LOCK_DECR;
|
||||
lock->waiters = 0;
|
||||
|
@ -923,7 +924,7 @@ rw_lock_list_print_info(
|
|||
|
||||
info = UT_LIST_GET_FIRST(lock->debug_list);
|
||||
while (info != NULL) {
|
||||
rw_lock_debug_print(info);
|
||||
rw_lock_debug_print(file, info);
|
||||
info = UT_LIST_GET_NEXT(list, info);
|
||||
}
|
||||
}
|
||||
|
@ -971,7 +972,7 @@ rw_lock_print(
|
|||
|
||||
info = UT_LIST_GET_FIRST(lock->debug_list);
|
||||
while (info != NULL) {
|
||||
rw_lock_debug_print(info);
|
||||
rw_lock_debug_print(stderr, info);
|
||||
info = UT_LIST_GET_NEXT(list, info);
|
||||
}
|
||||
}
|
||||
|
@ -983,28 +984,29 @@ UNIV_INTERN
|
|||
void
|
||||
rw_lock_debug_print(
|
||||
/*================*/
|
||||
FILE* f, /*!< in: output stream */
|
||||
rw_lock_debug_t* info) /*!< in: debug struct */
|
||||
{
|
||||
ulint rwt;
|
||||
|
||||
rwt = info->lock_type;
|
||||
|
||||
fprintf(stderr, "Locked: thread %lu file %s line %lu ",
|
||||
fprintf(f, "Locked: thread %lu file %s line %lu ",
|
||||
(ulong) os_thread_pf(info->thread_id), info->file_name,
|
||||
(ulong) info->line);
|
||||
if (rwt == RW_LOCK_SHARED) {
|
||||
fputs("S-LOCK", stderr);
|
||||
fputs("S-LOCK", f);
|
||||
} else if (rwt == RW_LOCK_EX) {
|
||||
fputs("X-LOCK", stderr);
|
||||
fputs("X-LOCK", f);
|
||||
} else if (rwt == RW_LOCK_WAIT_EX) {
|
||||
fputs("WAIT X-LOCK", stderr);
|
||||
fputs("WAIT X-LOCK", f);
|
||||
} else {
|
||||
ut_error;
|
||||
}
|
||||
if (info->pass != 0) {
|
||||
fprintf(stderr, " pass value %lu", (ulong) info->pass);
|
||||
fprintf(f, " pass value %lu", (ulong) info->pass);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
putc('\n', f);
|
||||
}
|
||||
|
||||
/***************************************************************//**
|
||||
|
|
|
@ -238,14 +238,14 @@ void
|
|||
mutex_create_func(
|
||||
/*==============*/
|
||||
mutex_t* mutex, /*!< in: pointer to memory */
|
||||
const char* cmutex_name, /*!< in: mutex name */
|
||||
#ifdef UNIV_DEBUG
|
||||
# ifdef UNIV_SYNC_DEBUG
|
||||
ulint level, /*!< in: level */
|
||||
# endif /* UNIV_SYNC_DEBUG */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cfile_name, /*!< in: file name where created */
|
||||
ulint cline) /*!< in: file line where created */
|
||||
ulint cline, /*!< in: file line where created */
|
||||
#endif /* UNIV_DEBUG */
|
||||
const char* cmutex_name) /*!< in: mutex name */
|
||||
{
|
||||
#if defined(HAVE_ATOMIC_BUILTINS)
|
||||
mutex_reset_lock_word(mutex);
|
||||
|
@ -266,9 +266,6 @@ mutex_create_func(
|
|||
#ifdef UNIV_DEBUG
|
||||
mutex->cfile_name = cfile_name;
|
||||
mutex->cline = cline;
|
||||
#else
|
||||
(void) cfile_name;
|
||||
(void) cline;
|
||||
#endif /* UNIV_DEBUG */
|
||||
mutex->count_os_wait = 0;
|
||||
mutex->cmutex_name= cmutex_name;
|
||||
|
@ -1164,6 +1161,7 @@ sync_thread_add_level(
|
|||
case SYNC_LOG:
|
||||
case SYNC_THR_LOCAL:
|
||||
case SYNC_ANY_LATCH:
|
||||
case SYNC_OUTER_ANY_LATCH:
|
||||
case SYNC_TRX_SYS_HEADER:
|
||||
case SYNC_FILE_FORMAT_TAG:
|
||||
case SYNC_DOUBLEWRITE:
|
||||
|
|
|
@ -665,14 +665,27 @@ trx_undo_page_report_modify(
|
|||
/* Save to the undo log the old values of the columns to be updated. */
|
||||
|
||||
if (update) {
|
||||
ulint extended = 0;
|
||||
|
||||
if (trx_undo_left(undo_page, ptr) < 5) {
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
ptr += mach_write_compressed(ptr, upd_get_n_fields(update));
|
||||
if (srv_use_sys_stats_table
|
||||
&& index == UT_LIST_GET_FIRST(dict_sys->sys_stats->indexes)) {
|
||||
for (i = 0; i < upd_get_n_fields(update); i++) {
|
||||
ulint pos = upd_get_nth_field(update, i)->field_no;
|
||||
|
||||
for (i = 0; i < upd_get_n_fields(update); i++) {
|
||||
if (pos >= rec_offs_n_fields(offsets)) {
|
||||
extended++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ptr += mach_write_compressed(ptr, upd_get_n_fields(update) - extended);
|
||||
|
||||
for (i = 0; i < upd_get_n_fields(update) - extended; i++) {
|
||||
|
||||
ulint pos = upd_get_nth_field(update, i)->field_no;
|
||||
|
||||
|
|
|
@ -48,8 +48,8 @@ Created 3/26/1996 Heikki Tuuri
|
|||
rollback */
|
||||
#define TRX_ROLL_TRUNC_THRESHOLD 1
|
||||
|
||||
/** In crash recovery, the current trx to be rolled back */
|
||||
static trx_t* trx_roll_crash_recv_trx = NULL;
|
||||
/** In crash recovery, the current trx to be rolled back; NULL otherwise */
|
||||
static const trx_t* trx_roll_crash_recv_trx = NULL;
|
||||
|
||||
/** In crash recovery we set this to the undo n:o of the current trx to be
|
||||
rolled back. Then we can print how many % the rollback has progressed. */
|
||||
|
|
|
@ -2106,18 +2106,18 @@ trx_recover_for_mysql(
|
|||
/*******************************************************************//**
|
||||
This function is used to find one X/Open XA distributed transaction
|
||||
which is in the prepared state
|
||||
@return trx or NULL */
|
||||
@return trx or NULL; on match, the trx->xid will be invalidated */
|
||||
UNIV_INTERN
|
||||
trx_t*
|
||||
trx_get_trx_by_xid(
|
||||
/*===============*/
|
||||
XID* xid) /*!< in: X/Open XA transaction identification */
|
||||
const XID* xid) /*!< in: X/Open XA transaction identifier */
|
||||
{
|
||||
trx_t* trx;
|
||||
|
||||
if (xid == NULL) {
|
||||
|
||||
return (NULL);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
mutex_enter(&kernel_mutex);
|
||||
|
@ -2130,10 +2130,16 @@ trx_get_trx_by_xid(
|
|||
of gtrid_lenght+bqual_length bytes should be
|
||||
the same */
|
||||
|
||||
if (xid->gtrid_length == trx->xid.gtrid_length
|
||||
if (trx->conc_state == TRX_PREPARED
|
||||
&& xid->gtrid_length == trx->xid.gtrid_length
|
||||
&& xid->bqual_length == trx->xid.bqual_length
|
||||
&& memcmp(xid->data, trx->xid.data,
|
||||
xid->gtrid_length + xid->bqual_length) == 0) {
|
||||
|
||||
/* Invalidate the XID, so that subsequent calls
|
||||
will not find it. */
|
||||
memset(&trx->xid, 0, sizeof(trx->xid));
|
||||
trx->xid.formatID = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2142,14 +2148,5 @@ trx_get_trx_by_xid(
|
|||
|
||||
mutex_exit(&kernel_mutex);
|
||||
|
||||
if (trx) {
|
||||
if (trx->conc_state != TRX_PREPARED) {
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
return(trx);
|
||||
} else {
|
||||
return(NULL);
|
||||
}
|
||||
return(trx);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue