Merge mysql-5.5-innodb -> mysql-5.5-bugfixing
This commit is contained in:
commit
932285774b
@ -528,6 +528,7 @@ long long thd_test_options(const MYSQL_THD thd, long long test_options);
|
||||
int thd_sql_command(const MYSQL_THD thd);
|
||||
const char *thd_proc_info(MYSQL_THD thd, const char *info);
|
||||
void **thd_ha_data(const MYSQL_THD thd, const struct handlerton *hton);
|
||||
void thd_storage_lock_wait(MYSQL_THD thd, long long value);
|
||||
int thd_tx_isolation(const MYSQL_THD thd);
|
||||
char *thd_security_context(MYSQL_THD thd, char *buffer, unsigned int length,
|
||||
unsigned int max_query_len);
|
||||
|
@ -151,6 +151,7 @@ long long thd_test_options(const void* thd, long long test_options);
|
||||
int thd_sql_command(const void* thd);
|
||||
const char *thd_proc_info(void* thd, const char *info);
|
||||
void **thd_ha_data(const void* thd, const struct handlerton *hton);
|
||||
void thd_storage_lock_wait(void* thd, long long value);
|
||||
int thd_tx_isolation(const void* thd);
|
||||
char *thd_security_context(void* thd, char *buffer, unsigned int length,
|
||||
unsigned int max_query_len);
|
||||
|
@ -54,8 +54,8 @@ text1 like 'teststring_%' ORDER BY text1;
|
||||
text1
|
||||
teststring
|
||||
teststring
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
concat('|', text1, '|')
|
||||
select concat('|', text1, '|') as c from t1 where text1='teststring' or text1 like 'teststring_%' order by c;
|
||||
c
|
||||
|teststring |
|
||||
|teststring|
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
|
||||
@ -105,11 +105,11 @@ select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
|
||||
concat('|', text1, '|')
|
||||
|teststring |
|
||||
|teststring |
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
concat('|', text1, '|')
|
||||
select concat('|', text1, '|') as c from t1 where text1='teststring' or text1 like 'teststring_%' order by c;
|
||||
c
|
||||
|teststring |
|
||||
|teststring|
|
||||
|teststring |
|
||||
|teststring|
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
|
||||
concat('|', text1, '|')
|
||||
|teststring|
|
||||
@ -123,8 +123,8 @@ concat('|', text1, '|')
|
||||
drop table t1;
|
||||
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
|
||||
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
concat('|', text1, '|')
|
||||
select concat('|', text1, '|') as c from t1 where text1='teststring' or text1 like 'teststring_%' order by c;
|
||||
c
|
||||
|teststring |
|
||||
|teststring|
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 >= 'teststring\t';
|
||||
@ -203,13 +203,13 @@ teststring
|
||||
teststring
|
||||
select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
text1 length(text1)
|
||||
teststring 11
|
||||
teststring 10
|
||||
teststring 11
|
||||
teststring 11
|
||||
select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t';
|
||||
text1 length(text1)
|
||||
teststring 11
|
||||
teststring 10
|
||||
teststring 11
|
||||
teststring 11
|
||||
select concat('|', text1, '|') from t1 order by text1;
|
||||
concat('|', text1, '|')
|
||||
|
@ -15,7 +15,7 @@ insert into t1 values (-5, 1, 1),
|
||||
(10, 1, 1);
|
||||
explain select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 4 Using sort_union(key1,key2); Using where
|
||||
1 SIMPLE t1 index_merge key1,key2 key1,key2 5,5 NULL 5 Using sort_union(key1,key2); Using where
|
||||
select * from t1 force index(key1, key2) where key1 < 3 or key2 < 3;
|
||||
pk1 key1 key2
|
||||
-100 1 1
|
||||
|
@ -233,7 +233,7 @@ a+0 b+0
|
||||
127 403
|
||||
explain select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range a a 2 NULL 19 Using where; Using index; Using filesort
|
||||
1 SIMPLE t1 range a a 2 NULL 27 Using where; Using index; Using filesort
|
||||
select a+0, b+0 from t1 where a > 40 and b > 200 order by 1;
|
||||
a+0 b+0
|
||||
44 307
|
||||
|
@ -572,7 +572,7 @@ COUNT(*)
|
||||
EXPLAIN
|
||||
SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)');
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 ref p p 28 const 1 Using where
|
||||
1 SIMPLE t2 ref p p 28 const 2 Using where
|
||||
SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)');
|
||||
COUNT(*)
|
||||
2
|
||||
|
@ -889,13 +889,13 @@ EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
|
||||
id 1
|
||||
select_type SIMPLE
|
||||
table t1
|
||||
type range
|
||||
type index
|
||||
possible_keys bkey
|
||||
key bkey
|
||||
key_len 5
|
||||
key PRIMARY
|
||||
key_len 4
|
||||
ref NULL
|
||||
rows 16
|
||||
Extra Using where; Using index; Using filesort
|
||||
rows 32
|
||||
Extra Using where
|
||||
SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY a;
|
||||
a b
|
||||
1 2
|
||||
@ -934,12 +934,12 @@ EXPLAIN SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
|
||||
id 1
|
||||
select_type SIMPLE
|
||||
table t1
|
||||
type range
|
||||
type index
|
||||
possible_keys bkey
|
||||
key bkey
|
||||
key_len 5
|
||||
ref NULL
|
||||
rows 16
|
||||
rows 32
|
||||
Extra Using where; Using index
|
||||
SELECT * FROM t1 WHERE b BETWEEN 1 AND 2 ORDER BY b,a;
|
||||
a b
|
||||
@ -989,7 +989,7 @@ possible_keys bkey
|
||||
key bkey
|
||||
key_len 5
|
||||
ref const
|
||||
rows 8
|
||||
rows 16
|
||||
Extra Using where; Using index; Using filesort
|
||||
SELECT * FROM t2 WHERE b=1 ORDER BY a;
|
||||
a b c
|
||||
@ -1018,7 +1018,7 @@ possible_keys bkey
|
||||
key bkey
|
||||
key_len 10
|
||||
ref const,const
|
||||
rows 8
|
||||
rows 16
|
||||
Extra Using where; Using index
|
||||
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY a;
|
||||
a b c
|
||||
@ -1047,7 +1047,7 @@ possible_keys bkey
|
||||
key bkey
|
||||
key_len 10
|
||||
ref const,const
|
||||
rows 8
|
||||
rows 16
|
||||
Extra Using where; Using index
|
||||
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY b,c,a;
|
||||
a b c
|
||||
@ -1076,7 +1076,7 @@ possible_keys bkey
|
||||
key bkey
|
||||
key_len 10
|
||||
ref const,const
|
||||
rows 8
|
||||
rows 16
|
||||
Extra Using where; Using index
|
||||
SELECT * FROM t2 WHERE b=1 AND c=1 ORDER BY c,a;
|
||||
a b c
|
||||
@ -1213,7 +1213,7 @@ possible_keys b
|
||||
key b
|
||||
key_len 5
|
||||
ref const
|
||||
rows 1
|
||||
rows 2
|
||||
Extra Using where; Using index
|
||||
SELECT * FROM t1 WHERE b=2 ORDER BY a ASC;
|
||||
a b
|
||||
@ -1228,7 +1228,7 @@ possible_keys b
|
||||
key b
|
||||
key_len 5
|
||||
ref const
|
||||
rows 1
|
||||
rows 2
|
||||
Extra Using where; Using index
|
||||
SELECT * FROM t1 WHERE b=2 ORDER BY a DESC;
|
||||
a b
|
||||
@ -1372,7 +1372,7 @@ INSERT INTO t1 (a,b,c) VALUES (1,1,1), (2,1,1), (3,1,1), (4,1,1);
|
||||
INSERT INTO t1 (a,b,c) SELECT a+4,b,c FROM t1;
|
||||
EXPLAIN SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 index t1_b PRIMARY 4 NULL 8 Using where
|
||||
1 SIMPLE t1 range t1_b t1_b 5 NULL 8 Using where
|
||||
SELECT a, b, c FROM t1 WHERE b = 1 ORDER BY a DESC LIMIT 5;
|
||||
a b c
|
||||
8 1 1
|
||||
@ -1735,7 +1735,7 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
|
||||
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
|
||||
2 DERIVED t1 index c3,c2 c2 10 NULL 5
|
||||
2 DERIVED t1 ALL c3,c2 c3 5 5 Using filesort
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 REAL, c2 REAL, c3 REAL, KEY (c3), KEY (c2, c3))
|
||||
ENGINE=InnoDB;
|
||||
@ -1749,7 +1749,7 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
|
||||
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
|
||||
2 DERIVED t1 index c3,c2 c2 18 NULL 5
|
||||
2 DERIVED t1 ALL c3,c2 c3 9 5 Using filesort
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (c1 DECIMAL(12,2), c2 DECIMAL(12,2), c3 DECIMAL(12,2),
|
||||
KEY (c3), KEY (c2, c3))
|
||||
@ -1764,7 +1764,7 @@ SELECT 1 FROM (SELECT COUNT(DISTINCT c1)
|
||||
FROM t1 WHERE c2 IN (1, 1) AND c3 = 2 GROUP BY c2) x;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 PRIMARY <derived2> system NULL NULL NULL NULL 1
|
||||
2 DERIVED t1 index c3,c2 c2 14 NULL 5
|
||||
2 DERIVED t1 ALL c3,c2 c3 7 5 Using filesort
|
||||
DROP TABLE t1;
|
||||
End of 5.1 tests
|
||||
#
|
||||
@ -1871,7 +1871,7 @@ possible_keys b
|
||||
key b
|
||||
key_len 5
|
||||
ref NULL
|
||||
rows 3
|
||||
rows 5
|
||||
Extra Using where; Using index
|
||||
EXPLAIN SELECT c FROM bar WHERE c>2;;
|
||||
id 1
|
||||
@ -2536,7 +2536,7 @@ f1 f2 f3 f4
|
||||
EXPLAIN SELECT * FROM t1 WHERE f2 = 1 AND f4 = TRUE
|
||||
ORDER BY f1 DESC LIMIT 5;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 range f2,f4 f4 1 NULL 11 Using where
|
||||
1 SIMPLE t1 range f2,f4 f4 1 NULL 22 Using where
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#54117 crash in thr_multi_unlock, temporary table
|
||||
|
@ -1,32 +1,32 @@
|
||||
SET @start_global_value = @@global.innodb_strict_mode;
|
||||
SELECT @start_global_value;
|
||||
@start_global_value
|
||||
1
|
||||
0
|
||||
Valid values are 'ON' and 'OFF'
|
||||
select @@global.innodb_strict_mode in (0, 1);
|
||||
@@global.innodb_strict_mode in (0, 1)
|
||||
1
|
||||
select @@global.innodb_strict_mode;
|
||||
@@global.innodb_strict_mode
|
||||
1
|
||||
0
|
||||
select @@session.innodb_strict_mode in (0, 1);
|
||||
@@session.innodb_strict_mode in (0, 1)
|
||||
1
|
||||
select @@session.innodb_strict_mode;
|
||||
@@session.innodb_strict_mode
|
||||
1
|
||||
0
|
||||
show global variables like 'innodb_strict_mode';
|
||||
Variable_name Value
|
||||
innodb_strict_mode ON
|
||||
innodb_strict_mode OFF
|
||||
show session variables like 'innodb_strict_mode';
|
||||
Variable_name Value
|
||||
innodb_strict_mode ON
|
||||
innodb_strict_mode OFF
|
||||
select * from information_schema.global_variables where variable_name='innodb_strict_mode';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_STRICT_MODE ON
|
||||
INNODB_STRICT_MODE OFF
|
||||
select * from information_schema.session_variables where variable_name='innodb_strict_mode';
|
||||
VARIABLE_NAME VARIABLE_VALUE
|
||||
INNODB_STRICT_MODE ON
|
||||
INNODB_STRICT_MODE OFF
|
||||
set global innodb_strict_mode='OFF';
|
||||
set session innodb_strict_mode='OFF';
|
||||
select @@global.innodb_strict_mode;
|
||||
@ -117,4 +117,4 @@ INNODB_STRICT_MODE ON
|
||||
SET @@global.innodb_strict_mode = @start_global_value;
|
||||
SELECT @@global.innodb_strict_mode;
|
||||
@@global.innodb_strict_mode
|
||||
1
|
||||
0
|
||||
|
@ -27,7 +27,7 @@ alter table t1 modify text1 char(32) binary not null;
|
||||
check table t1;
|
||||
select * from t1 ignore key (key1) where text1='teststring' or
|
||||
text1 like 'teststring_%' ORDER BY text1;
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
select concat('|', text1, '|') as c from t1 where text1='teststring' or text1 like 'teststring_%' order by c;
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
|
||||
select text1, length(text1) from t1 order by text1;
|
||||
select text1, length(text1) from t1 order by binary text1;
|
||||
@ -44,14 +44,14 @@ select concat('|', text1, '|') from t1 where text1='teststring';
|
||||
select concat('|', text1, '|') from t1 where text1='teststring ';
|
||||
explain select concat('|', text1, '|') from t1 where text1='teststring ';
|
||||
select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
select concat('|', text1, '|') as c from t1 where text1='teststring' or text1 like 'teststring_%' order by c;
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
|
||||
select concat('|', text1, '|') from t1 order by text1;
|
||||
drop table t1;
|
||||
|
||||
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
|
||||
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
|
||||
select concat('|', text1, '|') as c from t1 where text1='teststring' or text1 like 'teststring_%' order by c;
|
||||
select concat('|', text1, '|') from t1 where text1='teststring' or text1 >= 'teststring\t';
|
||||
drop table t1;
|
||||
|
||||
|
@ -306,6 +306,11 @@ void **thd_ha_data(const THD *thd, const struct handlerton *hton)
|
||||
return (void **) &thd->ha_data[hton->slot].ha_ptr;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
void thd_storage_lock_wait(THD *thd, long long value)
|
||||
{
|
||||
thd->utime_after_lock+= value;
|
||||
}
|
||||
|
||||
/**
|
||||
Provide a handler data getter to simplify coding
|
||||
|
@ -1501,7 +1501,7 @@ public:
|
||||
// track down slow pthread_create
|
||||
ulonglong prior_thr_create_utime, thr_create_utime;
|
||||
ulonglong start_utime, utime_after_lock;
|
||||
|
||||
|
||||
thr_lock_type update_lock_default;
|
||||
Delayed_insert *di;
|
||||
|
||||
|
@ -3153,6 +3153,7 @@ btr_cur_add_path_info(
|
||||
{
|
||||
btr_path_t* slot;
|
||||
rec_t* rec;
|
||||
page_t* page;
|
||||
|
||||
ut_a(cursor->path_arr);
|
||||
|
||||
@ -3175,8 +3176,155 @@ btr_cur_add_path_info(
|
||||
|
||||
slot = cursor->path_arr + (root_height - height);
|
||||
|
||||
page = page_align(rec);
|
||||
|
||||
slot->nth_rec = page_rec_get_n_recs_before(rec);
|
||||
slot->n_recs = page_get_n_recs(page_align(rec));
|
||||
slot->n_recs = page_get_n_recs(page);
|
||||
slot->page_no = page_get_page_no(page);
|
||||
slot->page_level = btr_page_get_level_low(page);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
Estimate the number of rows between slot1 and slot2 for any level on a
|
||||
B-tree. This function starts from slot1->page and reads a few pages to
|
||||
the right, counting their records. If we reach slot2->page quickly then
|
||||
we know exactly how many records there are between slot1 and slot2 and
|
||||
we set is_n_rows_exact to TRUE. If we cannot reach slot2->page quickly
|
||||
then we calculate the average number of records in the pages scanned
|
||||
so far and assume that all pages that we did not scan up to slot2->page
|
||||
contain the same number of records, then we multiply that average to
|
||||
the number of pages between slot1->page and slot2->page (which is
|
||||
n_rows_on_prev_level). In this case we set is_n_rows_exact to FALSE.
|
||||
@return number of rows (exact or estimated) */
|
||||
static
|
||||
ib_int64_t
|
||||
btr_estimate_n_rows_in_range_on_level(
|
||||
/*==================================*/
|
||||
dict_index_t* index, /*!< in: index */
|
||||
btr_path_t* slot1, /*!< in: left border */
|
||||
btr_path_t* slot2, /*!< in: right border */
|
||||
ib_int64_t n_rows_on_prev_level, /*!< in: number of rows
|
||||
on the previous level for the
|
||||
same descend paths; used to
|
||||
determine the numbe of pages
|
||||
on this level */
|
||||
ibool* is_n_rows_exact) /*!< out: TRUE if the returned
|
||||
value is exact i.e. not an
|
||||
estimation */
|
||||
{
|
||||
ulint space;
|
||||
ib_int64_t n_rows;
|
||||
ulint n_pages_read;
|
||||
ulint page_no;
|
||||
ulint zip_size;
|
||||
ulint level;
|
||||
|
||||
space = dict_index_get_space(index);
|
||||
|
||||
n_rows = 0;
|
||||
n_pages_read = 0;
|
||||
|
||||
/* Assume by default that we will scan all pages between
|
||||
slot1->page_no and slot2->page_no */
|
||||
*is_n_rows_exact = TRUE;
|
||||
|
||||
/* add records from slot1->page_no which are to the right of
|
||||
the record which serves as a left border of the range, if any */
|
||||
if (slot1->nth_rec < slot1->n_recs) {
|
||||
n_rows += slot1->n_recs - slot1->nth_rec;
|
||||
}
|
||||
|
||||
/* add records from slot2->page_no which are to the left of
|
||||
the record which servers as a right border of the range, if any */
|
||||
if (slot2->nth_rec > 1) {
|
||||
n_rows += slot2->nth_rec - 1;
|
||||
}
|
||||
|
||||
/* count the records in the pages between slot1->page_no and
|
||||
slot2->page_no (non inclusive), if any */
|
||||
|
||||
zip_size = fil_space_get_zip_size(space);
|
||||
|
||||
/* Do not read more than this number of pages in order not to hurt
|
||||
performance with this code which is just an estimation. If we read
|
||||
this many pages before reaching slot2->page_no then we estimate the
|
||||
average from the pages scanned so far */
|
||||
#define N_PAGES_READ_LIMIT 10
|
||||
|
||||
page_no = slot1->page_no;
|
||||
level = slot1->page_level;
|
||||
|
||||
do {
|
||||
mtr_t mtr;
|
||||
page_t* page;
|
||||
buf_block_t* block;
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
/* fetch the page */
|
||||
block = buf_page_get(space, zip_size, page_no, RW_S_LATCH,
|
||||
&mtr);
|
||||
|
||||
page = buf_block_get_frame(block);
|
||||
|
||||
/* It is possible that the tree has been reorganized in the
|
||||
meantime and this is a different page. If this happens the
|
||||
calculated estimate will be bogus, which is not fatal as
|
||||
this is only an estimate. We are sure that a page with
|
||||
page_no exists because InnoDB never frees pages, only
|
||||
reuses them. */
|
||||
if (fil_page_get_type(page) != FIL_PAGE_INDEX
|
||||
|| btr_page_get_index_id(page) != index->id
|
||||
|| btr_page_get_level_low(page) != level) {
|
||||
|
||||
/* The page got reused for something else */
|
||||
goto inexact;
|
||||
}
|
||||
|
||||
n_pages_read++;
|
||||
|
||||
if (page_no != slot1->page_no) {
|
||||
/* Do not count the records on slot1->page_no,
|
||||
we already counted them before this loop. */
|
||||
n_rows += page_get_n_recs(page);
|
||||
}
|
||||
|
||||
page_no = btr_page_get_next(page, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
if (n_pages_read == N_PAGES_READ_LIMIT
|
||||
|| page_no == FIL_NULL) {
|
||||
/* Either we read too many pages or
|
||||
we reached the end of the level without passing
|
||||
through slot2->page_no, the tree must have changed
|
||||
in the meantime */
|
||||
goto inexact;
|
||||
}
|
||||
|
||||
} while (page_no != slot2->page_no);
|
||||
|
||||
return(n_rows);
|
||||
|
||||
inexact:
|
||||
|
||||
*is_n_rows_exact = FALSE;
|
||||
|
||||
/* We did interrupt before reaching slot2->page */
|
||||
|
||||
if (n_pages_read > 0) {
|
||||
/* The number of pages on this level is
|
||||
n_rows_on_prev_level, multiply it by the
|
||||
average number of recs per page so far */
|
||||
n_rows = n_rows_on_prev_level
|
||||
* n_rows / n_pages_read;
|
||||
} else {
|
||||
/* The tree changed before we could even
|
||||
start with slot1->page_no */
|
||||
n_rows = 10;
|
||||
}
|
||||
|
||||
return(n_rows);
|
||||
}
|
||||
|
||||
/*******************************************************************//**
|
||||
@ -3201,6 +3349,7 @@ btr_estimate_n_rows_in_range(
|
||||
ibool diverged_lot;
|
||||
ulint divergence_level;
|
||||
ib_int64_t n_rows;
|
||||
ibool is_n_rows_exact;
|
||||
ulint i;
|
||||
mtr_t mtr;
|
||||
|
||||
@ -3243,6 +3392,7 @@ btr_estimate_n_rows_in_range(
|
||||
/* We have the path information for the range in path1 and path2 */
|
||||
|
||||
n_rows = 1;
|
||||
is_n_rows_exact = TRUE;
|
||||
diverged = FALSE; /* This becomes true when the path is not
|
||||
the same any more */
|
||||
diverged_lot = FALSE; /* This becomes true when the paths are
|
||||
@ -3258,7 +3408,7 @@ btr_estimate_n_rows_in_range(
|
||||
if (slot1->nth_rec == ULINT_UNDEFINED
|
||||
|| slot2->nth_rec == ULINT_UNDEFINED) {
|
||||
|
||||
if (i > divergence_level + 1) {
|
||||
if (i > divergence_level + 1 && !is_n_rows_exact) {
|
||||
/* In trees whose height is > 1 our algorithm
|
||||
tends to underestimate: multiply the estimate
|
||||
by 2: */
|
||||
@ -3270,7 +3420,9 @@ btr_estimate_n_rows_in_range(
|
||||
to over 1 / 2 of the estimated rows in the whole
|
||||
table */
|
||||
|
||||
if (n_rows > index->table->stat_n_rows / 2) {
|
||||
if (n_rows > index->table->stat_n_rows / 2
|
||||
&& !is_n_rows_exact) {
|
||||
|
||||
n_rows = index->table->stat_n_rows / 2;
|
||||
|
||||
/* If there are just 0 or 1 rows in the table,
|
||||
@ -3296,10 +3448,15 @@ btr_estimate_n_rows_in_range(
|
||||
divergence_level = i;
|
||||
}
|
||||
} else {
|
||||
/* Maybe the tree has changed between
|
||||
searches */
|
||||
|
||||
return(10);
|
||||
/* It is possible that
|
||||
slot1->nth_rec >= slot2->nth_rec
|
||||
if, for example, we have a single page
|
||||
tree which contains (inf, 5, 6, supr)
|
||||
and we select where x > 20 and x < 30;
|
||||
in this case slot1->nth_rec will point
|
||||
to the supr record and slot2->nth_rec
|
||||
will point to 6 */
|
||||
n_rows = 0;
|
||||
}
|
||||
|
||||
} else if (diverged && !diverged_lot) {
|
||||
@ -3323,8 +3480,9 @@ btr_estimate_n_rows_in_range(
|
||||
}
|
||||
} else if (diverged_lot) {
|
||||
|
||||
n_rows = (n_rows * (slot1->n_recs + slot2->n_recs))
|
||||
/ 2;
|
||||
n_rows = btr_estimate_n_rows_in_range_on_level(
|
||||
index, slot1, slot2, n_rows,
|
||||
&is_n_rows_exact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1746,6 +1746,7 @@ function_exit:
|
||||
}
|
||||
}
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
Validates the search system.
|
||||
@return TRUE if ok */
|
||||
@ -1913,3 +1914,4 @@ btr_search_validate(void)
|
||||
|
||||
return(ok);
|
||||
}
|
||||
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
|
||||
|
@ -1248,8 +1248,12 @@ buf_flush_try_neighbors(
|
||||
/*====================*/
|
||||
ulint space, /*!< in: space id */
|
||||
ulint offset, /*!< in: page offset */
|
||||
enum buf_flush flush_type) /*!< in: BUF_FLUSH_LRU or
|
||||
enum buf_flush flush_type, /*!< in: BUF_FLUSH_LRU or
|
||||
BUF_FLUSH_LIST */
|
||||
ulint n_flushed, /*!< in: number of pages
|
||||
flushed so far in this batch */
|
||||
ulint n_to_flush) /*!< in: maximum number of pages
|
||||
we are allowed to flush */
|
||||
{
|
||||
ulint i;
|
||||
ulint low;
|
||||
@ -1290,6 +1294,21 @@ buf_flush_try_neighbors(
|
||||
|
||||
buf_page_t* bpage;
|
||||
|
||||
if ((count + n_flushed) >= n_to_flush) {
|
||||
|
||||
/* We have already flushed enough pages and
|
||||
should call it a day. There is, however, one
|
||||
exception. If the page whose neighbors we
|
||||
are flushing has not been flushed yet then
|
||||
we'll try to flush the victim that we
|
||||
selected originally. */
|
||||
if (i <= offset) {
|
||||
i = offset;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
buf_pool = buf_pool_get(space, i);
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
@ -1357,6 +1376,8 @@ buf_flush_page_and_try_neighbors(
|
||||
buf_page_in_file(bpage) */
|
||||
enum buf_flush flush_type, /*!< in: BUF_FLUSH_LRU
|
||||
or BUF_FLUSH_LIST */
|
||||
ulint n_to_flush, /*!< in: number of pages to
|
||||
flush */
|
||||
ulint* count) /*!< in/out: number of pages
|
||||
flushed */
|
||||
{
|
||||
@ -1390,7 +1411,11 @@ buf_flush_page_and_try_neighbors(
|
||||
mutex_exit(block_mutex);
|
||||
|
||||
/* Try to flush also all the neighbors */
|
||||
*count += buf_flush_try_neighbors(space, offset, flush_type);
|
||||
*count += buf_flush_try_neighbors(space,
|
||||
offset,
|
||||
flush_type,
|
||||
*count,
|
||||
n_to_flush);
|
||||
|
||||
buf_pool_mutex_enter(buf_pool);
|
||||
flushed = TRUE;
|
||||
@ -1430,7 +1455,7 @@ buf_flush_LRU_list_batch(
|
||||
a page that isn't ready for flushing. */
|
||||
while (bpage != NULL
|
||||
&& !buf_flush_page_and_try_neighbors(
|
||||
bpage, BUF_FLUSH_LRU, &count)) {
|
||||
bpage, BUF_FLUSH_LRU, max, &count)) {
|
||||
|
||||
bpage = UT_LIST_GET_PREV(LRU, bpage);
|
||||
}
|
||||
@ -1511,7 +1536,7 @@ buf_flush_flush_list_batch(
|
||||
while (bpage != NULL
|
||||
&& len > 0
|
||||
&& !buf_flush_page_and_try_neighbors(
|
||||
bpage, BUF_FLUSH_LIST, &count)) {
|
||||
bpage, BUF_FLUSH_LIST, min_n, &count)) {
|
||||
|
||||
buf_flush_list_mutex_enter(buf_pool);
|
||||
|
||||
|
@ -1175,23 +1175,23 @@ static const char* dict_load_index_id_err = "SYS_INDEXES.TABLE_ID mismatch";
|
||||
|
||||
/********************************************************************//**
|
||||
Loads an index definition from a SYS_INDEXES record to dict_index_t.
|
||||
If "cached" is set to "TRUE", we will create a dict_index_t structure
|
||||
and fill it accordingly. Otherwise, the dict_index_t will
|
||||
be supplied by the caller and filled with information read from
|
||||
the record.
|
||||
@return error message, or NULL on success */
|
||||
If allocate=TRUE, we will create a dict_index_t structure and fill it
|
||||
accordingly. If allocated=FALSE, the dict_index_t will be supplied by
|
||||
the caller and filled with information read from the record. @return
|
||||
error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_load_index_low(
|
||||
/*================*/
|
||||
byte* table_id, /*!< in/out: table id (8 bytes),
|
||||
an "in" value if cached=TRUE
|
||||
and "out" when cached=FALSE */
|
||||
an "in" value if allocate=TRUE
|
||||
and "out" when allocate=FALSE */
|
||||
const char* table_name, /*!< in: table name */
|
||||
mem_heap_t* heap, /*!< in/out: temporary memory heap */
|
||||
const rec_t* rec, /*!< in: SYS_INDEXES record */
|
||||
ibool cached, /*!< in: TRUE = add to cache,
|
||||
FALSE = do not */
|
||||
ibool allocate, /*!< in: TRUE=allocate *index,
|
||||
FALSE=fill in a pre-allocated
|
||||
*index */
|
||||
dict_index_t** index) /*!< out,own: index, or NULL */
|
||||
{
|
||||
const byte* field;
|
||||
@ -1203,8 +1203,8 @@ dict_load_index_low(
|
||||
ulint type;
|
||||
ulint space;
|
||||
|
||||
if (cached) {
|
||||
/* If "cached" is set to TRUE, no dict_index_t will
|
||||
if (allocate) {
|
||||
/* If allocate=TRUE, no dict_index_t will
|
||||
be supplied. Initialize "*index" to NULL */
|
||||
*index = NULL;
|
||||
}
|
||||
@ -1223,7 +1223,7 @@ err_len:
|
||||
return("incorrect column length in SYS_INDEXES");
|
||||
}
|
||||
|
||||
if (!cached) {
|
||||
if (!allocate) {
|
||||
/* We are reading a SYS_INDEXES record. Copy the table_id */
|
||||
memcpy(table_id, (const char*)field, 8);
|
||||
} else if (memcmp(field, table_id, 8)) {
|
||||
@ -1279,7 +1279,7 @@ err_len:
|
||||
goto err_len;
|
||||
}
|
||||
|
||||
if (cached) {
|
||||
if (allocate) {
|
||||
*index = dict_mem_index_create(table_name, name_buf,
|
||||
space, type, n_fields);
|
||||
} else {
|
||||
|
@ -354,6 +354,7 @@ ha_remove_all_nodes_to_page(
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/*************************************************************//**
|
||||
Validates a given range of the cells in hash table.
|
||||
@return TRUE if ok */
|
||||
@ -400,6 +401,7 @@ ha_validate(
|
||||
|
||||
return(ok);
|
||||
}
|
||||
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
|
||||
|
||||
/*************************************************************//**
|
||||
Prints info of a hash table. */
|
||||
|
@ -425,7 +425,7 @@ static MYSQL_THDVAR_BOOL(table_locks, PLUGIN_VAR_OPCMDARG,
|
||||
|
||||
static MYSQL_THDVAR_BOOL(strict_mode, PLUGIN_VAR_OPCMDARG,
|
||||
"Use strict mode when evaluating create options.",
|
||||
NULL, NULL, TRUE);
|
||||
NULL, NULL, FALSE);
|
||||
|
||||
static MYSQL_THDVAR_ULONG(lock_wait_timeout, PLUGIN_VAR_RQCMDARG,
|
||||
"Timeout in seconds an InnoDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
|
||||
@ -807,6 +807,20 @@ thd_lock_wait_timeout(
|
||||
return(THDVAR((THD*) thd, lock_wait_timeout));
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
Set the time waited for the lock for the current query. */
|
||||
extern "C" UNIV_INTERN
|
||||
void
|
||||
thd_set_lock_wait_time(
|
||||
/*===================*/
|
||||
void* thd, /*!< in: thread handle (THD*) */
|
||||
ulint value) /*!< in: time waited for the lock */
|
||||
{
|
||||
if (thd) {
|
||||
thd_storage_lock_wait((THD*)thd, value);
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************//**
|
||||
Obtain the InnoDB transaction of a MySQL thread.
|
||||
@return reference to transaction pointer */
|
||||
|
@ -55,6 +55,7 @@ Created 7/19/1997 Heikki Tuuri
|
||||
#include "lock0lock.h"
|
||||
#include "log0recv.h"
|
||||
#include "que0que.h"
|
||||
#include "srv0start.h" /* srv_shutdown_state */
|
||||
|
||||
/* STRUCTURE OF AN INSERT BUFFER RECORD
|
||||
|
||||
@ -395,8 +396,10 @@ ibuf_tree_root_get(
|
||||
mtr_t* mtr) /*!< in: mtr */
|
||||
{
|
||||
buf_block_t* block;
|
||||
page_t* root;
|
||||
|
||||
ut_ad(ibuf_inside());
|
||||
ut_ad(mutex_own(&ibuf_mutex));
|
||||
|
||||
mtr_x_lock(dict_index_get_lock(ibuf->index), mtr);
|
||||
|
||||
@ -405,7 +408,13 @@ ibuf_tree_root_get(
|
||||
|
||||
buf_block_dbg_add_level(block, SYNC_TREE_NODE);
|
||||
|
||||
return(buf_block_get_frame(block));
|
||||
root = buf_block_get_frame(block);
|
||||
|
||||
ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
|
||||
ut_ad(page_get_page_no(root) == FSP_IBUF_TREE_ROOT_PAGE_NO);
|
||||
ut_ad(ibuf->empty == (page_get_n_recs(root) == 0));
|
||||
|
||||
return(root);
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
@ -482,8 +491,6 @@ ibuf_size_update(
|
||||
|
||||
/* the '1 +' is the ibuf header page */
|
||||
ibuf->size = ibuf->seg_size - (1 + ibuf->free_list_len);
|
||||
|
||||
ibuf->empty = page_get_n_recs(root) == 0;
|
||||
}
|
||||
|
||||
/******************************************************************//**
|
||||
@ -554,6 +561,7 @@ ibuf_init_at_db_start(void)
|
||||
ibuf_size_update(root, &mtr);
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf->empty = (page_get_n_recs(root) == 0);
|
||||
mtr_commit(&mtr);
|
||||
|
||||
ibuf_exit();
|
||||
@ -1350,10 +1358,18 @@ ibuf_add_ops(
|
||||
const ulint* ops) /*!< in: operation counts */
|
||||
|
||||
{
|
||||
#ifndef HAVE_ATOMIC_BUILTINS
|
||||
ut_ad(mutex_own(&ibuf_mutex));
|
||||
#endif /* !HAVE_ATOMIC_BUILTINS */
|
||||
|
||||
ulint i;
|
||||
|
||||
for (i = 0; i < IBUF_OP_COUNT; i++) {
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
os_atomic_increment_ulint(&arr[i], ops[i]);
|
||||
#else /* HAVE_ATOMIC_BUILTINS */
|
||||
arr[i] += ops[i];
|
||||
#endif /* HAVE_ATOMIC_BUILTINS */
|
||||
}
|
||||
}
|
||||
|
||||
@ -2017,9 +2033,9 @@ ibuf_data_too_much_free(void)
|
||||
/*********************************************************************//**
|
||||
Allocates a new page from the ibuf file segment and adds it to the free
|
||||
list.
|
||||
@return DB_SUCCESS, or DB_STRONG_FAIL if no space left */
|
||||
@return TRUE on success, FALSE if no space left */
|
||||
static
|
||||
ulint
|
||||
ibool
|
||||
ibuf_add_free_page(void)
|
||||
/*====================*/
|
||||
{
|
||||
@ -2055,10 +2071,10 @@ ibuf_add_free_page(void)
|
||||
header_page + IBUF_HEADER + IBUF_TREE_SEG_HEADER, 0, FSP_UP,
|
||||
&mtr);
|
||||
|
||||
if (page_no == FIL_NULL) {
|
||||
if (UNIV_UNLIKELY(page_no == FIL_NULL)) {
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return(DB_STRONG_FAIL);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
{
|
||||
@ -2096,16 +2112,16 @@ ibuf_add_free_page(void)
|
||||
bitmap_page = ibuf_bitmap_get_map_page(
|
||||
IBUF_SPACE_ID, page_no, zip_size, &mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_bitmap_page_set_bits(
|
||||
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, TRUE, &mtr);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_exit();
|
||||
|
||||
return(DB_SUCCESS);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -2135,20 +2151,17 @@ ibuf_remove_free_page(void)
|
||||
header_page = ibuf_header_page_get(&mtr);
|
||||
|
||||
/* Prevent pessimistic inserts to insert buffer trees for a while */
|
||||
mutex_enter(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
ibuf_enter();
|
||||
|
||||
mutex_enter(&ibuf_pessimistic_insert_mutex);
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
if (!ibuf_data_too_much_free()) {
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
ibuf_exit();
|
||||
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
return;
|
||||
@ -2158,6 +2171,8 @@ ibuf_remove_free_page(void)
|
||||
|
||||
root = ibuf_tree_root_get(&mtr2);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
page_no = flst_get_last(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
||||
&mtr2).page;
|
||||
|
||||
@ -2166,7 +2181,6 @@ ibuf_remove_free_page(void)
|
||||
is a level 2 page. */
|
||||
|
||||
mtr_commit(&mtr2);
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_exit();
|
||||
|
||||
@ -2209,17 +2223,19 @@ ibuf_remove_free_page(void)
|
||||
flst_remove(root + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST,
|
||||
page + PAGE_HEADER + PAGE_BTR_IBUF_FREE_LIST_NODE, &mtr);
|
||||
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
ibuf->seg_size--;
|
||||
ibuf->free_list_len--;
|
||||
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
/* Set the bit indicating that this page is no more an ibuf tree page
|
||||
(level 2 page) */
|
||||
|
||||
bitmap_page = ibuf_bitmap_get_map_page(
|
||||
IBUF_SPACE_ID, page_no, zip_size, &mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_bitmap_page_set_bits(
|
||||
bitmap_page, page_no, zip_size, IBUF_BITMAP_IBUF, FALSE, &mtr);
|
||||
|
||||
@ -2228,8 +2244,6 @@ ibuf_remove_free_page(void)
|
||||
#endif
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_exit();
|
||||
}
|
||||
|
||||
@ -2270,17 +2284,16 @@ ibuf_free_excess_pages(void)
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
|
||||
ibool too_much_free;
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
too_much_free = ibuf_data_too_much_free();
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
if (!ibuf_data_too_much_free()) {
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
if (!too_much_free) {
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_remove_free_page();
|
||||
}
|
||||
}
|
||||
@ -2476,18 +2489,20 @@ ibuf_contract_ext(
|
||||
ulint page_nos[IBUF_MAX_N_PAGES_MERGED];
|
||||
ulint space_ids[IBUF_MAX_N_PAGES_MERGED];
|
||||
ib_int64_t space_versions[IBUF_MAX_N_PAGES_MERGED];
|
||||
ulint n_stored;
|
||||
ulint sum_sizes;
|
||||
mtr_t mtr;
|
||||
|
||||
*n_pages = 0;
|
||||
ut_ad(!ibuf_inside());
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
/* We perform a dirty read of ibuf->empty, without latching
|
||||
the insert buffer root page. We trust this dirty read except
|
||||
when a slow shutdown is being executed. During a slow
|
||||
shutdown, the insert buffer merge must be completed. */
|
||||
|
||||
if (ibuf->empty) {
|
||||
if (UNIV_UNLIKELY(ibuf->empty)
|
||||
&& UNIV_LIKELY(!srv_shutdown_state)) {
|
||||
ibuf_is_empty:
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
#if 0 /* TODO */
|
||||
if (srv_shutdown_state) {
|
||||
@ -2519,13 +2534,14 @@ ibuf_is_empty:
|
||||
ut_ad(page_validate(btr_pcur_get_page(&pcur), ibuf->index));
|
||||
|
||||
if (page_get_n_recs(btr_pcur_get_page(&pcur)) == 0) {
|
||||
/* When the ibuf tree is emptied completely, the last record
|
||||
is removed using an optimistic delete and ibuf_size_update
|
||||
is not called, causing ibuf->empty to remain FALSE. If we do
|
||||
not reset it to TRUE here then database shutdown will hang
|
||||
in the loop in ibuf_contract_for_n_pages. */
|
||||
|
||||
ibuf->empty = TRUE;
|
||||
/* If a B-tree page is empty, it must be the root page
|
||||
and the whole B-tree must be empty. InnoDB does not
|
||||
allow empty B-tree pages other than the root. */
|
||||
ut_ad(ibuf->empty);
|
||||
ut_ad(page_get_space_id(btr_pcur_get_page(&pcur))
|
||||
== IBUF_SPACE_ID);
|
||||
ut_ad(page_get_page_no(btr_pcur_get_page(&pcur))
|
||||
== FSP_IBUF_TREE_ROOT_PAGE_NO);
|
||||
|
||||
ibuf_exit();
|
||||
|
||||
@ -2535,14 +2551,12 @@ ibuf_is_empty:
|
||||
goto ibuf_is_empty;
|
||||
}
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
|
||||
space_ids, space_versions,
|
||||
page_nos, &n_stored);
|
||||
page_nos, n_pages);
|
||||
#if 0 /* defined UNIV_IBUF_DEBUG */
|
||||
fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
|
||||
sync, n_stored, sum_sizes);
|
||||
sync, *n_pages, sum_sizes);
|
||||
#endif
|
||||
ibuf_exit();
|
||||
|
||||
@ -2550,8 +2564,7 @@ ibuf_is_empty:
|
||||
btr_pcur_close(&pcur);
|
||||
|
||||
buf_read_ibuf_merge_pages(sync, space_ids, space_versions, page_nos,
|
||||
n_stored);
|
||||
*n_pages = n_stored;
|
||||
*n_pages);
|
||||
|
||||
return(sum_sizes + 1);
|
||||
}
|
||||
@ -2621,33 +2634,33 @@ ibuf_contract_after_insert(
|
||||
ibool sync;
|
||||
ulint sum_sizes;
|
||||
ulint size;
|
||||
ulint max_size;
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
if (ibuf->size < ibuf->max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) {
|
||||
mutex_exit(&ibuf_mutex);
|
||||
/* Perform dirty reads of ibuf->size and ibuf->max_size, to
|
||||
reduce ibuf_mutex contention. ibuf->max_size remains constant
|
||||
after ibuf_init_at_db_start(), but ibuf->size should be
|
||||
protected by ibuf_mutex. Given that ibuf->size fits in a
|
||||
machine word, this should be OK; at worst we are doing some
|
||||
excessive ibuf_contract() or occasionally skipping a
|
||||
ibuf_contract(). */
|
||||
size = ibuf->size;
|
||||
max_size = ibuf->max_size;
|
||||
|
||||
if (size < max_size + IBUF_CONTRACT_ON_INSERT_NON_SYNC) {
|
||||
return;
|
||||
}
|
||||
|
||||
sync = FALSE;
|
||||
|
||||
if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_ON_INSERT_SYNC) {
|
||||
|
||||
sync = TRUE;
|
||||
}
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
sync = (size >= max_size + IBUF_CONTRACT_ON_INSERT_SYNC);
|
||||
|
||||
/* Contract at least entry_size many bytes */
|
||||
sum_sizes = 0;
|
||||
size = 1;
|
||||
|
||||
while ((size > 0) && (sum_sizes < entry_size)) {
|
||||
do {
|
||||
|
||||
size = ibuf_contract(sync);
|
||||
sum_sizes += size;
|
||||
}
|
||||
} while (size > 0 && sum_sizes < entry_size);
|
||||
}
|
||||
|
||||
/*********************************************************************//**
|
||||
@ -3265,7 +3278,7 @@ ibuf_set_entry_counter(
|
||||
/*********************************************************************//**
|
||||
Buffer an operation in the insert/delete buffer, instead of doing it
|
||||
directly to the disk page, if this is possible.
|
||||
@return DB_SUCCESS, DB_FAIL, DB_STRONG_FAIL */
|
||||
@return DB_SUCCESS, DB_STRONG_FAIL or other error */
|
||||
static
|
||||
ulint
|
||||
ibuf_insert_low(
|
||||
@ -3295,6 +3308,7 @@ ibuf_insert_low(
|
||||
rec_t* ins_rec;
|
||||
ibool old_bit_value;
|
||||
page_t* bitmap_page;
|
||||
buf_block_t* block;
|
||||
page_t* root;
|
||||
ulint err;
|
||||
ibool do_merge;
|
||||
@ -3315,13 +3329,17 @@ ibuf_insert_low(
|
||||
|
||||
do_merge = FALSE;
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
/* Perform dirty reads of ibuf->size and ibuf->max_size, to
|
||||
reduce ibuf_mutex contention. ibuf->max_size remains constant
|
||||
after ibuf_init_at_db_start(), but ibuf->size should be
|
||||
protected by ibuf_mutex. Given that ibuf->size fits in a
|
||||
machine word, this should be OK; at worst we are doing some
|
||||
excessive ibuf_contract() or occasionally skipping a
|
||||
ibuf_contract(). */
|
||||
if (ibuf->size >= ibuf->max_size + IBUF_CONTRACT_DO_NOT_INSERT) {
|
||||
/* Insert buffer is now too big, contract it but do not try
|
||||
to insert */
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
#ifdef UNIV_IBUF_DEBUG
|
||||
fputs("Ibuf too big\n", stderr);
|
||||
@ -3332,40 +3350,6 @@ ibuf_insert_low(
|
||||
return(DB_STRONG_FAIL);
|
||||
}
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
if (mode == BTR_MODIFY_TREE) {
|
||||
mutex_enter(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
ibuf_enter();
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
while (!ibuf_data_enough_free_for_insert()) {
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf_exit();
|
||||
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
err = ibuf_add_free_page();
|
||||
|
||||
if (err == DB_STRONG_FAIL) {
|
||||
|
||||
return(err);
|
||||
}
|
||||
|
||||
mutex_enter(&ibuf_pessimistic_insert_mutex);
|
||||
|
||||
ibuf_enter();
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
}
|
||||
} else {
|
||||
ibuf_enter();
|
||||
}
|
||||
|
||||
heap = mem_heap_create(512);
|
||||
|
||||
/* Build the entry which contains the space id and the page number
|
||||
@ -3384,6 +3368,31 @@ ibuf_insert_low(
|
||||
the new entry to it without exceeding the free space limit for the
|
||||
page. */
|
||||
|
||||
if (mode == BTR_MODIFY_TREE) {
|
||||
for (;;) {
|
||||
ibuf_enter();
|
||||
mutex_enter(&ibuf_pessimistic_insert_mutex);
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
if (UNIV_LIKELY(ibuf_data_enough_free_for_insert())) {
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
ibuf_exit();
|
||||
|
||||
if (UNIV_UNLIKELY(!ibuf_add_free_page())) {
|
||||
|
||||
mem_heap_free(heap);
|
||||
return(DB_STRONG_FAIL);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ibuf_enter();
|
||||
}
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
btr_pcur_open(ibuf->index, ibuf_entry, PAGE_CUR_LE, mode, &pcur, &mtr);
|
||||
@ -3417,9 +3426,14 @@ ibuf_insert_low(
|
||||
before mtr_commit(&mtr). We must not mtr_commit(&mtr)
|
||||
until after the IBUF_OP_DELETE has been buffered. */
|
||||
|
||||
err = DB_STRONG_FAIL;
|
||||
fail_exit:
|
||||
if (mode == BTR_MODIFY_TREE) {
|
||||
mutex_exit(&ibuf_mutex);
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
}
|
||||
|
||||
goto function_exit;
|
||||
err = DB_STRONG_FAIL;
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
/* After this point, the page could still be loaded to the
|
||||
@ -3465,9 +3479,7 @@ ibuf_insert_low(
|
||||
space_ids, space_versions,
|
||||
page_nos, &n_stored);
|
||||
|
||||
err = DB_STRONG_FAIL;
|
||||
|
||||
goto function_exit;
|
||||
goto fail_exit;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3478,11 +3490,9 @@ ibuf_insert_low(
|
||||
&& !ibuf_set_entry_counter(ibuf_entry, space, page_no, &pcur,
|
||||
mode == BTR_MODIFY_PREV, &mtr)) {
|
||||
bitmap_fail:
|
||||
err = DB_STRONG_FAIL;
|
||||
|
||||
mtr_commit(&bitmap_mtr);
|
||||
|
||||
goto function_exit;
|
||||
goto fail_exit;
|
||||
}
|
||||
|
||||
/* Set the bitmap bit denoting that the insert buffer contains
|
||||
@ -3506,10 +3516,19 @@ bitmap_fail:
|
||||
err = btr_cur_optimistic_insert(BTR_NO_LOCKING_FLAG, cursor,
|
||||
ibuf_entry, &ins_rec,
|
||||
&dummy_big_rec, 0, thr, &mtr);
|
||||
if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
|
||||
/* Update the page max trx id field */
|
||||
page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
|
||||
thr_get_trx(thr)->id, &mtr);
|
||||
block = btr_cur_get_block(cursor);
|
||||
ut_ad(buf_block_get_space(block) == IBUF_SPACE_ID);
|
||||
|
||||
/* If this is the root page, update ibuf->empty. */
|
||||
if (UNIV_UNLIKELY(buf_block_get_page_no(block)
|
||||
== FSP_IBUF_TREE_ROOT_PAGE_NO)) {
|
||||
const page_t* root = buf_block_get_frame(block);
|
||||
|
||||
ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
|
||||
ut_ad(page_get_page_no(root)
|
||||
== FSP_IBUF_TREE_ROOT_PAGE_NO);
|
||||
|
||||
ibuf->empty = (page_get_n_recs(root) == 0);
|
||||
}
|
||||
} else {
|
||||
ut_ad(mode == BTR_MODIFY_TREE);
|
||||
@ -3526,16 +3545,22 @@ bitmap_fail:
|
||||
cursor,
|
||||
ibuf_entry, &ins_rec,
|
||||
&dummy_big_rec, 0, thr, &mtr);
|
||||
if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
|
||||
/* Update the page max trx id field */
|
||||
page_update_max_trx_id(btr_cur_get_block(cursor), NULL,
|
||||
thr_get_trx(thr)->id, &mtr);
|
||||
}
|
||||
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
ibuf_size_update(root, &mtr);
|
||||
mutex_exit(&ibuf_mutex);
|
||||
ibuf->empty = (page_get_n_recs(root) == 0);
|
||||
|
||||
block = btr_cur_get_block(cursor);
|
||||
ut_ad(buf_block_get_space(block) == IBUF_SPACE_ID);
|
||||
}
|
||||
|
||||
function_exit:
|
||||
if (err == DB_SUCCESS && op != IBUF_OP_DELETE) {
|
||||
/* Update the page max trx id field */
|
||||
page_update_max_trx_id(block, NULL,
|
||||
thr_get_trx(thr)->id, &mtr);
|
||||
}
|
||||
|
||||
func_exit:
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
if (err == DB_SUCCESS) {
|
||||
fprintf(stderr,
|
||||
@ -3547,11 +3572,6 @@ function_exit:
|
||||
ibuf_count_get(space, page_no) + 1);
|
||||
}
|
||||
#endif
|
||||
if (mode == BTR_MODIFY_TREE) {
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
mutex_exit(&ibuf_pessimistic_insert_mutex);
|
||||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
btr_pcur_close(&pcur);
|
||||
@ -3559,16 +3579,8 @@ function_exit:
|
||||
|
||||
mem_heap_free(heap);
|
||||
|
||||
if (err == DB_SUCCESS) {
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
ibuf->empty = FALSE;
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
if (mode == BTR_MODIFY_TREE) {
|
||||
ibuf_contract_after_insert(entry_size);
|
||||
}
|
||||
if (err == DB_SUCCESS && mode == BTR_MODIFY_TREE) {
|
||||
ibuf_contract_after_insert(entry_size);
|
||||
}
|
||||
|
||||
if (do_merge) {
|
||||
@ -4075,6 +4087,22 @@ ibuf_delete_rec(
|
||||
success = btr_cur_optimistic_delete(btr_pcur_get_btr_cur(pcur), mtr);
|
||||
|
||||
if (success) {
|
||||
if (UNIV_UNLIKELY(!page_get_n_recs(btr_pcur_get_page(pcur)))) {
|
||||
/* If a B-tree page is empty, it must be the root page
|
||||
and the whole B-tree must be empty. InnoDB does not
|
||||
allow empty B-tree pages other than the root. */
|
||||
root = btr_pcur_get_page(pcur);
|
||||
|
||||
ut_ad(page_get_space_id(root) == IBUF_SPACE_ID);
|
||||
ut_ad(page_get_page_no(root)
|
||||
== FSP_IBUF_TREE_ROOT_PAGE_NO);
|
||||
|
||||
/* ibuf->empty is protected by the root page latch.
|
||||
Before the deletion, it had to be FALSE. */
|
||||
ut_ad(!ibuf->empty);
|
||||
ibuf->empty = TRUE;
|
||||
}
|
||||
|
||||
#ifdef UNIV_IBUF_COUNT_DEBUG
|
||||
fprintf(stderr,
|
||||
"Decrementing ibuf count of space %lu page %lu\n"
|
||||
@ -4102,6 +4130,7 @@ ibuf_delete_rec(
|
||||
if (!ibuf_restore_pos(space, page_no, search_tuple,
|
||||
BTR_MODIFY_TREE, pcur, mtr)) {
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
goto func_exit;
|
||||
}
|
||||
|
||||
@ -4115,13 +4144,14 @@ ibuf_delete_rec(
|
||||
ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1);
|
||||
#endif
|
||||
ibuf_size_update(root, mtr);
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
ibuf->empty = (page_get_n_recs(root) == 0);
|
||||
btr_pcur_commit_specify_mtr(pcur, mtr);
|
||||
|
||||
func_exit:
|
||||
btr_pcur_close(pcur);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
@ -4495,6 +4525,11 @@ reset_bit:
|
||||
btr_pcur_close(&pcur);
|
||||
mem_heap_free(heap);
|
||||
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
os_atomic_increment_ulint(&ibuf->n_merges, 1);
|
||||
ibuf_add_ops(ibuf->n_merged_ops, mops);
|
||||
ibuf_add_ops(ibuf->n_discarded_ops, dops);
|
||||
#else /* HAVE_ATOMIC_BUILTINS */
|
||||
/* Protect our statistics keeping from race conditions */
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
@ -4503,6 +4538,7 @@ reset_bit:
|
||||
ibuf_add_ops(ibuf->n_discarded_ops, dops);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
#endif /* HAVE_ATOMIC_BUILTINS */
|
||||
|
||||
if (update_ibuf_bitmap && !tablespace_being_deleted) {
|
||||
|
||||
@ -4604,10 +4640,14 @@ leave_loop:
|
||||
mtr_commit(&mtr);
|
||||
btr_pcur_close(&pcur);
|
||||
|
||||
#ifdef HAVE_ATOMIC_BUILTINS
|
||||
ibuf_add_ops(ibuf->n_discarded_ops, dops);
|
||||
#else /* HAVE_ATOMIC_BUILTINS */
|
||||
/* Protect our statistics keeping from race conditions */
|
||||
mutex_enter(&ibuf_mutex);
|
||||
ibuf_add_ops(ibuf->n_discarded_ops, dops);
|
||||
mutex_exit(&ibuf_mutex);
|
||||
#endif /* HAVE_ATOMIC_BUILTINS */
|
||||
|
||||
ibuf_exit();
|
||||
|
||||
@ -4627,37 +4667,18 @@ ibuf_is_empty(void)
|
||||
mtr_t mtr;
|
||||
|
||||
ibuf_enter();
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
|
||||
mtr_start(&mtr);
|
||||
|
||||
mutex_enter(&ibuf_mutex);
|
||||
root = ibuf_tree_root_get(&mtr);
|
||||
|
||||
if (page_get_n_recs(root) == 0) {
|
||||
|
||||
is_empty = TRUE;
|
||||
|
||||
if (ibuf->empty == FALSE) {
|
||||
fprintf(stderr,
|
||||
"InnoDB: Warning: insert buffer tree is empty"
|
||||
" but the data struct does not\n"
|
||||
"InnoDB: know it. This condition is legal"
|
||||
" if the master thread has not yet\n"
|
||||
"InnoDB: run to completion.\n");
|
||||
}
|
||||
} else {
|
||||
ut_a(ibuf->empty == FALSE);
|
||||
|
||||
is_empty = FALSE;
|
||||
}
|
||||
|
||||
mtr_commit(&mtr);
|
||||
|
||||
mutex_exit(&ibuf_mutex);
|
||||
|
||||
is_empty = (page_get_n_recs(root) == 0);
|
||||
mtr_commit(&mtr);
|
||||
ibuf_exit();
|
||||
|
||||
ut_a(is_empty == ibuf->empty);
|
||||
|
||||
return(is_empty);
|
||||
}
|
||||
|
||||
|
@ -615,6 +615,11 @@ struct btr_path_struct{
|
||||
order); value ULINT_UNDEFINED
|
||||
denotes array end */
|
||||
ulint n_recs; /*!< number of records on the page */
|
||||
ulint page_no; /*!< no of the page containing the record */
|
||||
ulint page_level; /*!< level of the page, if later we fetch
|
||||
the page under page_no and it is no different
|
||||
level then we know that the tree has been
|
||||
reorganized */
|
||||
};
|
||||
|
||||
#define BTR_PATH_ARRAY_N_SLOTS 250 /*!< size of path array (in slots) */
|
||||
|
@ -180,6 +180,7 @@ btr_search_update_hash_on_delete(
|
||||
btr_cur_t* cursor);/*!< in: cursor which was positioned on the
|
||||
record to delete using btr_cur_search_...,
|
||||
the record is not yet deleted */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/********************************************************************//**
|
||||
Validates the search system.
|
||||
@return TRUE if ok */
|
||||
@ -187,6 +188,9 @@ UNIV_INTERN
|
||||
ibool
|
||||
btr_search_validate(void);
|
||||
/*======================*/
|
||||
#else
|
||||
# define btr_search_validate() TRUE
|
||||
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
|
||||
|
||||
/** Flag: has the search system been enabled?
|
||||
Protected by btr_search_latch and btr_search_enabled_mutex. */
|
||||
|
@ -116,19 +116,23 @@ dict_load_column_low(
|
||||
const rec_t* rec); /*!< in: SYS_COLUMNS record */
|
||||
/********************************************************************//**
|
||||
Loads an index definition from a SYS_INDEXES record to dict_index_t.
|
||||
@return error message, or NULL on success */
|
||||
If allocate=TRUE, we will create a dict_index_t structure and fill it
|
||||
accordingly. If allocated=FALSE, the dict_index_t will be supplied by
|
||||
the caller and filled with information read from the record. @return
|
||||
error message, or NULL on success */
|
||||
UNIV_INTERN
|
||||
const char*
|
||||
dict_load_index_low(
|
||||
/*================*/
|
||||
byte* table_id, /*!< in/out: table id (8 bytes_,
|
||||
an "in" value if cached=TRUE
|
||||
and "out" when cached=FALSE */
|
||||
byte* table_id, /*!< in/out: table id (8 bytes),
|
||||
an "in" value if allocate=TRUE
|
||||
and "out" when allocate=FALSE */
|
||||
const char* table_name, /*!< in: table name */
|
||||
mem_heap_t* heap, /*!< in/out: temporary memory heap */
|
||||
const rec_t* rec, /*!< in: SYS_INDEXES record */
|
||||
ibool cached, /*!< in: TRUE = add to cache
|
||||
FALSE = do not */
|
||||
ibool allocate, /*!< in: TRUE=allocate *index,
|
||||
FALSE=fill in a pre-allocated
|
||||
*index */
|
||||
dict_index_t** index); /*!< out,own: index, or NULL */
|
||||
/********************************************************************//**
|
||||
Loads an index field definition from a SYS_FIELDS record to
|
||||
|
@ -186,6 +186,7 @@ ha_remove_all_nodes_to_page(
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint fold, /*!< in: fold value */
|
||||
const page_t* page); /*!< in: buffer page */
|
||||
#if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG
|
||||
/*************************************************************//**
|
||||
Validates a given range of the cells in hash table.
|
||||
@return TRUE if ok */
|
||||
@ -196,6 +197,7 @@ ha_validate(
|
||||
hash_table_t* table, /*!< in: hash table */
|
||||
ulint start_index, /*!< in: start index */
|
||||
ulint end_index); /*!< in: end index */
|
||||
#endif /* defined UNIV_AHI_DEBUG || defined UNIV_DEBUG */
|
||||
/*************************************************************//**
|
||||
Prints info of a hash table. */
|
||||
UNIV_INTERN
|
||||
|
@ -267,5 +267,13 @@ thd_lock_wait_timeout(
|
||||
/*==================*/
|
||||
void* thd); /*!< in: thread handle (THD*), or NULL to query
|
||||
the global innodb_lock_wait_timeout */
|
||||
/******************************************************************//**
|
||||
Add up the time waited for the lock for the current query. */
|
||||
UNIV_INTERN
|
||||
void
|
||||
thd_set_lock_wait_time(
|
||||
/*===================*/
|
||||
void* thd, /*!< in: thread handle (THD*) */
|
||||
ulint value); /*!< in: time waited for the lock */
|
||||
|
||||
#endif
|
||||
|
@ -46,11 +46,12 @@ struct ibuf_struct{
|
||||
ulint seg_size; /*!< allocated pages of the file
|
||||
segment containing ibuf header and
|
||||
tree */
|
||||
ibool empty; /*!< after an insert to the ibuf tree
|
||||
is performed, this is set to FALSE,
|
||||
and if a contract operation finds
|
||||
the tree empty, this is set to
|
||||
TRUE */
|
||||
ibool empty; /*!< Protected by the page
|
||||
latch of the root page of the
|
||||
insert buffer tree
|
||||
(FSP_IBUF_TREE_ROOT_PAGE_NO). TRUE
|
||||
if and only if the insert
|
||||
buffer tree is empty. */
|
||||
ulint free_list_len; /*!< length of the free list */
|
||||
ulint height; /*!< tree height */
|
||||
dict_index_t* index; /*!< insert buffer index */
|
||||
|
@ -254,8 +254,10 @@ by one. */
|
||||
option off; also some ibuf tests are suppressed */
|
||||
|
||||
/* Linkage specifier for non-static InnoDB symbols (variables and functions)
|
||||
that are only referenced from within InnoDB, not from MySQL */
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4) || defined(__INTEL_COMPILER)
|
||||
that are only referenced from within InnoDB, not from MySQL. We disable the
|
||||
GCC visibility directive on all Sun operating systems because there is no
|
||||
easy way to get it to work. See http://bugs.mysql.com/bug.php?id=52263. */
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(sun) || defined(__INTEL_COMPILER)
|
||||
# define UNIV_INTERN __attribute__((visibility ("hidden")))
|
||||
#else
|
||||
# define UNIV_INTERN
|
||||
|
@ -1643,6 +1643,9 @@ srv_suspend_mysql_thread(
|
||||
start_time != -1 && finish_time != -1) {
|
||||
srv_n_lock_max_wait_time = diff_time;
|
||||
}
|
||||
|
||||
/* Record the lock wait time for this thread */
|
||||
thd_set_lock_wait_time(trx->mysql_thd, diff_time);
|
||||
}
|
||||
|
||||
if (trx->was_chosen_as_deadlock_victim) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user