Merge bb-10.2-ext into 10.3

This commit is contained in:
Marko Mäkelä 2018-01-24 14:00:33 +02:00
commit 9875d5c3e1
48 changed files with 1442 additions and 930 deletions

View file

@ -307,3 +307,4 @@ gprof_compile_flags="-O2 -pg -g"
gprof_link_flags="--disable-shared $static_link"
disable_gprof_plugins="--with-zlib-dir=bundled --without-plugin-oqgraph --without-plugin-mroonga"

View file

@ -19,6 +19,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium_cflags $gprof_compile_flags"
extra_configs="$pentium_configs $debug_configs $gprof_link_flags $disable_64_bit_plugins"
extra_configs="$pentium_configs $debug_configs $gprof_link_flags $disable_64_bit_plugins $disable_gprof_plugins"
. "$path/FINISH.sh"

View file

@ -28,6 +28,6 @@ export LDFLAGS="$gcov_link_flags"
extra_flags="$pentium64_cflags $max_cflags $gcov_compile_flags"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs"
extra_configs="$pentium_configs $debug_configs $gcov_configs $max_configs --without-oqgraph"
. "$path/FINISH.sh"

View file

@ -20,6 +20,6 @@ path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium64_cflags $gprof_compile_flags"
extra_configs="$pentium_configs $max_configs $gprof_link_flags --with-zlib-dir=bundled"
extra_configs="$pentium_configs $max_configs $gprof_link_flags $disable_gprof_plugins"
. "$path/FINISH.sh"

View file

@ -434,6 +434,22 @@ datafiles_iter_free(datafiles_iter_t *it)
free(it);
}
void mdl_lock_all()
{
mdl_lock_init();
datafiles_iter_t *it = datafiles_iter_new(fil_system);
if (!it)
return;
while (fil_node_t *node = datafiles_iter_next(it)){
if (fil_is_user_tablespace_id(node->space->id)
&& check_if_skip_table(node->space->name))
continue;
mdl_lock_table(node->space->id);
}
datafiles_iter_free(it);
}
/* ======== Date copying thread context ======== */
typedef struct {
@ -1208,8 +1224,8 @@ static int prepare_export()
if (strncmp(orig_argv1,"--defaults-file=",16) == 0)
{
sprintf(cmdline,
IF_WIN("\"","") "\"%s\" --mysqld \"%s\" --defaults-group-suffix=%s"
" --defaults-extra-file=./backup-my.cnf --datadir=."
IF_WIN("\"","") "\"%s\" --mysqld \"%s\" "
" --defaults-extra-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=."
" --innodb --innodb-fast-shutdown=0"
" --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu"
" --console --skip-log-error --bootstrap < " BOOTSTRAP_FILENAME IF_WIN("\"",""),
@ -1221,11 +1237,12 @@ static int prepare_export()
{
sprintf(cmdline,
IF_WIN("\"","") "\"%s\" --mysqld"
" --defaults-file=./backup-my.cnf --datadir=."
" --defaults-file=./backup-my.cnf --defaults-group-suffix=%s --datadir=."
" --innodb --innodb-fast-shutdown=0"
" --innodb_purge_rseg_truncate_frequency=1 --innodb-buffer-pool-size=%llu"
" --console --log-error= --bootstrap < " BOOTSTRAP_FILENAME IF_WIN("\"",""),
mariabackup_exe,
(my_defaults_group_suffix?my_defaults_group_suffix:""),
xtrabackup_use_memory);
}
@ -2200,10 +2217,6 @@ xtrabackup_copy_datafile(fil_node_t* node, uint thread_n)
return(FALSE);
}
if (opt_lock_ddl_per_table) {
mdl_lock_table(node->space->id);
}
if (!changed_page_bitmap) {
read_filter = &rf_pass_through;
}
@ -3563,9 +3576,7 @@ xtrabackup_backup_func()
"or RENAME TABLE during the backup, inconsistent backup will be "
"produced.\n");
if (opt_lock_ddl_per_table) {
mdl_lock_init();
}
/* initialize components */
if(innodb_init_param()) {
@ -3880,6 +3891,10 @@ reread_log_header:
"files transfer\n", xtrabackup_parallel);
}
if (opt_lock_ddl_per_table) {
mdl_lock_all();
}
it = datafiles_iter_new(fil_system);
if (it == NULL) {
msg("mariabackup: Error: datafiles_iter_new() failed.\n");

View file

@ -1295,3 +1295,77 @@ TERM03 TERM03
TERM01 NULL
NULL TERM04
drop table t1,t2;
#
# MDEV-14969: view using subquery with attached CTE
#
create table region (
r_regionkey int,
r_name char(25),
primary key (r_regionkey)
);
insert into region values
(0,'AFRICA'), (1,'AMERICA'), (2,'ASIA'), (3,'EUROPE'), (4,'MIDDLE EAST');
create table nation (
n_nationkey int,
n_name char(25),
n_regionkey int,
primary key (n_nationkey),
key i_n_regionkey (n_regionkey)
);
insert into nation values
(0,'ALGERIA',0), (1,'ARGENTINA',1), (2,'BRAZIL',1), (3,'CANADA',1),
(4,'EGYPT',4), (5,'ETHIOPIA',0), (6,'FRANCE',3), (7,'GERMANY',3),
(8,'INDIA',2), (9,'INDONESIA',2), (10,'IRAN',4), (11,'IRAQ',4),
(12,'JAPAN',2), (13,'JORDAN',4), (14,'KENYA',0), (15,'MOROCCO',0),
(16,'MOZAMBIQUE',0), (17,'PERU',1), (18,'CHINA',2), (19,'ROMANIA',3),
(20,'SAUDI ARABIA',4), (21,'VIETNAM',2), (22,'RUSSIA',3),
(23,'UNITED KINGDOM',3), (24,'UNITED STATES',1);
select * from nation n ,region r
where n.n_regionkey = r.r_regionkey and
r.r_regionkey in
(with t as (select * from region where r_regionkey <= 3 )
select r_regionkey from t where r_name <> "ASIA");
n_nationkey n_name n_regionkey r_regionkey r_name
0 ALGERIA 0 0 AFRICA
5 ETHIOPIA 0 0 AFRICA
14 KENYA 0 0 AFRICA
15 MOROCCO 0 0 AFRICA
16 MOZAMBIQUE 0 0 AFRICA
1 ARGENTINA 1 1 AMERICA
2 BRAZIL 1 1 AMERICA
3 CANADA 1 1 AMERICA
17 PERU 1 1 AMERICA
24 UNITED STATES 1 1 AMERICA
6 FRANCE 3 3 EUROPE
7 GERMANY 3 3 EUROPE
19 ROMANIA 3 3 EUROPE
22 RUSSIA 3 3 EUROPE
23 UNITED KINGDOM 3 3 EUROPE
create view v as
select * from nation n ,region r
where n.n_regionkey = r.r_regionkey and
r.r_regionkey in
(with t as (select * from region where r_regionkey <= 3)
select r_regionkey from t where r_name <> "ASIA");
show create view v;
View Create View character_set_client collation_connection
v CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v` AS select `n`.`n_nationkey` AS `n_nationkey`,`n`.`n_name` AS `n_name`,`n`.`n_regionkey` AS `n_regionkey`,`r`.`r_regionkey` AS `r_regionkey`,`r`.`r_name` AS `r_name` from (`nation` `n` join `region` `r`) where `n`.`n_regionkey` = `r`.`r_regionkey` and `r`.`r_regionkey` in (with t as (select `region`.`r_regionkey` AS `r_regionkey`,`region`.`r_name` AS `r_name` from `region` where `region`.`r_regionkey` <= 3)select `t`.`r_regionkey` from `t` where `t`.`r_name` <> 'ASIA') latin1 latin1_swedish_ci
select * from v;
n_nationkey n_name n_regionkey r_regionkey r_name
0 ALGERIA 0 0 AFRICA
5 ETHIOPIA 0 0 AFRICA
14 KENYA 0 0 AFRICA
15 MOROCCO 0 0 AFRICA
16 MOZAMBIQUE 0 0 AFRICA
1 ARGENTINA 1 1 AMERICA
2 BRAZIL 1 1 AMERICA
3 CANADA 1 1 AMERICA
17 PERU 1 1 AMERICA
24 UNITED STATES 1 1 AMERICA
6 FRANCE 3 3 EUROPE
7 GERMANY 3 3 EUROPE
19 ROMANIA 3 3 EUROPE
22 RUSSIA 3 3 EUROPE
23 UNITED KINGDOM 3 3 EUROPE
drop view v;
drop table region, nation;

View file

@ -5198,3 +5198,45 @@ t1 CREATE TABLE `t1` (
`b` bigint(10) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
#
# MDEV-14603 signal 11 with short stacktrace
#
SET NAMES utf8;
CREATE TABLE t1(i INT);
CREATE PROCEDURE p1(tn VARCHAR(32))
EXECUTE IMMEDIATE CONCAT('ANALYZE TABLE ',tn);
CALL p1('t1');
Table Op Msg_type Msg_text
test.t1 analyze status Table is already up to date
DROP PROCEDURE p1;
DROP TABLE t1;
SET NAMES utf8;
CREATE PROCEDURE p1()
EXECUTE IMMEDIATE CONCAT('SELECT ',CONVERT(RAND() USING latin1));
CALL p1();
DROP PROCEDURE p1;
SET NAMES utf8;
CREATE PROCEDURE p1()
BEGIN
PREPARE stmt FROM CONCAT('SELECT ',CONVERT(RAND() USING latin1));
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
$$
CALL p1();
DROP PROCEDURE p1;
SET NAMES utf8;
CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8)
EXECUTE IMMEDIATE 'SELECT ?' USING CONCAT(a, CONVERT(RAND() USING latin1));
CALL p1('x');
DROP PROCEDURE p1;
SET NAMES utf8;
CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8)
BEGIN
PREPARE stmt FROM 'SELECT ?';
EXECUTE stmt USING CONCAT(a, CONVERT(RAND() USING latin1));
DEALLOCATE PREPARE stmt;
END;
$$
CALL p1('x');
DROP PROCEDURE p1;

View file

@ -3290,5 +3290,15 @@ FROM door as window;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'window' at line 2
DROP TABLE door;
#
# MDEV-13352: Server crashes in st_join_table::remove_duplicates
#
CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (1),(2);
SELECT DISTINCT ROW_NUMBER() OVER(), i FROM t1 WHERE 0;
ROW_NUMBER() OVER() i
SELECT ROW_NUMBER() OVER(), i FROM t1 WHERE 0;
ROW_NUMBER() OVER() i
DROP TABLE t1;
#
# Start of 10.3 tests
#

View file

@ -1,12 +0,0 @@
call mtr.add_suppression("InnoDB: Cannot save (table|index) statistics for table `test`\\.`t1`.*: Persistent statistics do not exist");
CREATE TABLE t1 (a INT, KEY(a)) ENGINE=INNODB STATS_PERSISTENT=1;
SET @save_debug= @@SESSION.debug_dbug;
SET debug_dbug= '+d,stats_index_error';
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status Operation failed
SET debug_dbug= @save_debug;
ANALYZE TABLE t1;
Table Op Msg_type Msg_text
test.t1 analyze status OK
DROP TABLE t1;

View file

@ -1,13 +0,0 @@
--source include/have_innodb.inc
--source include/have_debug.inc
call mtr.add_suppression("InnoDB: Cannot save (table|index) statistics for table `test`\\.`t1`.*: Persistent statistics do not exist");
CREATE TABLE t1 (a INT, KEY(a)) ENGINE=INNODB STATS_PERSISTENT=1;
SET @save_debug= @@SESSION.debug_dbug;
SET debug_dbug= '+d,stats_index_error';
ANALYZE TABLE t1;
SET debug_dbug= @save_debug;
ANALYZE TABLE t1;
DROP TABLE t1;

View file

@ -57,5 +57,5 @@ SELECT table_name FROM mysql.innodb_index_stats
WHERE table_name='innodb_stats_drop_locked';
--disable_query_log
call mtr.add_suppression("Unable to delete statistics for table test\\.innodb_stats_drop_locked: Lock wait");
call mtr.add_suppression("Unable to delete statistics for table test.innodb_stats_drop_locked: Lock wait timeout. They can be deleted later using DELETE FROM mysql.innodb_index_stats WHERE database_name");
--enable_query_log

View file

@ -54,3 +54,108 @@ Table Op Msg_type Msg_text
test.t1 check warning Datafile is almost full, 268230656 of 268320768 used
test.t1 check status OK
drop table t1,t2;
create table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=FIXED min_rows=1000000;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(10) unsigned DEFAULT NULL,
`c2` char(80) DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1 MIN_ROWS=1000000 PAGE_CHECKSUM=1 ROW_FORMAT=FIXED
insert into t1 select seq,seq from seq_1_to_100000;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=FIXED;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(10) unsigned DEFAULT NULL,
`c2` char(80) DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 ROW_FORMAT=FIXED
insert into t1 select seq,seq from seq_1_to_100000;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=PAGE TRANSACTIONAL=0;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(10) unsigned DEFAULT NULL,
`c2` char(80) DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 ROW_FORMAT=PAGE TRANSACTIONAL=0
insert into t1 select seq,seq from seq_1_to_100000;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=FIXED MAX_ROWS=10;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(10) unsigned DEFAULT NULL,
`c2` char(80) DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1 MAX_ROWS=10 PAGE_CHECKSUM=1 ROW_FORMAT=FIXED
insert into t1 select seq,seq from seq_1_to_100000;
ERROR HY000: The table 't1' is full
select count(*) from t1;
count(*)
65535
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=DYNAMIC MAX_ROWS=10;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(10) unsigned DEFAULT NULL,
`c2` char(80) DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1 MAX_ROWS=10 PAGE_CHECKSUM=1 ROW_FORMAT=DYNAMIC
insert into t1 select seq,seq from seq_1_to_100000;
ERROR HY000: The table 't1' is full
select count(*) from t1;
count(*)
3276
check table t1;
Table Op Msg_type Msg_text
test.t1 check warning Datafile is almost full, 65520 of 65535 used
test.t1 check status OK
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=PAGE MAX_ROWS=10;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(10) unsigned DEFAULT NULL,
`c2` char(80) DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1 MAX_ROWS=10 PAGE_CHECKSUM=1 ROW_FORMAT=PAGE
insert into t1 select seq,seq from seq_1_to_100000;
select count(*) from t1;
count(*)
100000
check table t1;
Table Op Msg_type Msg_text
test.t1 check status OK
drop table t1;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=PAGE MAX_ROWS=10;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`c1` int(10) unsigned DEFAULT NULL,
`c2` char(80) DEFAULT NULL
) ENGINE=Aria DEFAULT CHARSET=latin1 MAX_ROWS=10 PAGE_CHECKSUM=1 ROW_FORMAT=PAGE
insert into t1 select seq,seq from seq_1_to_10000000;
ERROR HY000: The table 't1' is full
select count(*) from t1;
count(*)
6189940
check table t1;
Table Op Msg_type Msg_text
test.t1 check warning Datafile is almost full, 268320768 of 268320768 used
test.t1 check status OK
drop table t1;

View file

@ -2,6 +2,7 @@
# This test will use around 1.3G of disk space!
--source include/have_maria.inc
--source include/have_sequence.inc
--source include/big_test.inc
drop table if exists t1,t2;
@ -50,3 +51,74 @@ insert into t1 (v,b) select v,b from t2;
check table t1;
drop table t1,t2;
#
# Check that we don't get table-is-full
#
create table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=FIXED min_rows=1000000;
show create table t1;
insert into t1 select seq,seq from seq_1_to_100000;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=FIXED;
show create table t1;
insert into t1 select seq,seq from seq_1_to_100000;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=PAGE TRANSACTIONAL=0;
show create table t1;
insert into t1 select seq,seq from seq_1_to_100000;
#
# For these we should get table is full error
#
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=FIXED MAX_ROWS=10;
show create table t1;
--error ER_RECORD_FILE_FULL
insert into t1 select seq,seq from seq_1_to_100000;
select count(*) from t1;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=DYNAMIC MAX_ROWS=10;
show create table t1;
--error ER_RECORD_FILE_FULL
insert into t1 select seq,seq from seq_1_to_100000;
select count(*) from t1;
check table t1;
# PAGE uses 3 byte pointers as minimum, which can handle up to 200M files
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=PAGE MAX_ROWS=10;
show create table t1;
insert into t1 select seq,seq from seq_1_to_100000;
select count(*) from t1;
check table t1;
drop table t1;
create or replace table t1 (
c1 int unsigned,
c2 char(80)
) Engine=ARIA ROW_FORMAT=PAGE MAX_ROWS=10;
show create table t1;
--error ER_RECORD_FILE_FULL
insert into t1 select seq,seq from seq_1_to_10000000;
select count(*) from t1;
check table t1;
drop table t1;

View file

@ -882,3 +882,50 @@ union all
where c1.term is null);
drop table t1,t2;
--echo #
--echo # MDEV-14969: view using subquery with attached CTE
--echo #
create table region (
r_regionkey int,
r_name char(25),
primary key (r_regionkey)
);
insert into region values
(0,'AFRICA'), (1,'AMERICA'), (2,'ASIA'), (3,'EUROPE'), (4,'MIDDLE EAST');
create table nation (
n_nationkey int,
n_name char(25),
n_regionkey int,
primary key (n_nationkey),
key i_n_regionkey (n_regionkey)
);
insert into nation values
(0,'ALGERIA',0), (1,'ARGENTINA',1), (2,'BRAZIL',1), (3,'CANADA',1),
(4,'EGYPT',4), (5,'ETHIOPIA',0), (6,'FRANCE',3), (7,'GERMANY',3),
(8,'INDIA',2), (9,'INDONESIA',2), (10,'IRAN',4), (11,'IRAQ',4),
(12,'JAPAN',2), (13,'JORDAN',4), (14,'KENYA',0), (15,'MOROCCO',0),
(16,'MOZAMBIQUE',0), (17,'PERU',1), (18,'CHINA',2), (19,'ROMANIA',3),
(20,'SAUDI ARABIA',4), (21,'VIETNAM',2), (22,'RUSSIA',3),
(23,'UNITED KINGDOM',3), (24,'UNITED STATES',1);
select * from nation n ,region r
where n.n_regionkey = r.r_regionkey and
r.r_regionkey in
(with t as (select * from region where r_regionkey <= 3 )
select r_regionkey from t where r_name <> "ASIA");
create view v as
select * from nation n ,region r
where n.n_regionkey = r.r_regionkey and
r.r_regionkey in
(with t as (select * from region where r_regionkey <= 3)
select r_regionkey from t where r_name <> "ASIA");
show create view v;
select * from v;
drop view v;
drop table region, nation;

View file

@ -4615,3 +4615,60 @@ DROP TABLE t1;
EXECUTE IMMEDIATE 'CREATE OR REPLACE TABLE t1 AS SELECT 2147483647 AS a,? AS b' USING 2147483647;
SHOW CREATE TABLE t1;
DROP TABLE t1;
--echo #
--echo # MDEV-14603 signal 11 with short stacktrace
--echo #
SET NAMES utf8;
CREATE TABLE t1(i INT);
CREATE PROCEDURE p1(tn VARCHAR(32))
EXECUTE IMMEDIATE CONCAT('ANALYZE TABLE ',tn);
CALL p1('t1');
DROP PROCEDURE p1;
DROP TABLE t1;
SET NAMES utf8;
CREATE PROCEDURE p1()
EXECUTE IMMEDIATE CONCAT('SELECT ',CONVERT(RAND() USING latin1));
--disable_result_log
CALL p1();
--enable_result_log
DROP PROCEDURE p1;
SET NAMES utf8;
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
PREPARE stmt FROM CONCAT('SELECT ',CONVERT(RAND() USING latin1));
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END;
$$
DELIMITER ;$$
--disable_result_log
CALL p1();
--enable_result_log
DROP PROCEDURE p1;
SET NAMES utf8;
CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8)
EXECUTE IMMEDIATE 'SELECT ?' USING CONCAT(a, CONVERT(RAND() USING latin1));
--disable_result_log
CALL p1('x');
--enable_result_log
DROP PROCEDURE p1;
SET NAMES utf8;
DELIMITER $$;
CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8)
BEGIN
PREPARE stmt FROM 'SELECT ?';
EXECUTE stmt USING CONCAT(a, CONVERT(RAND() USING latin1));
DEALLOCATE PREPARE stmt;
END;
$$
DELIMITER ;$$
--disable_result_log
CALL p1('x');
DROP PROCEDURE p1;

View file

@ -2058,6 +2058,15 @@ FROM door as window;
DROP TABLE door;
--echo #
--echo # MDEV-13352: Server crashes in st_join_table::remove_duplicates
--echo #
CREATE TABLE t1 (i INT);
INSERT INTO t1 VALUES (1),(2);
SELECT DISTINCT ROW_NUMBER() OVER(), i FROM t1 WHERE 0;
SELECT ROW_NUMBER() OVER(), i FROM t1 WHERE 0;
DROP TABLE t1;
--echo #
--echo # Start of 10.3 tests
--echo #

View file

@ -4365,6 +4365,9 @@ table_map subselect_union_engine::upper_select_const_tables()
void subselect_single_select_engine::print(String *str,
enum_query_type query_type)
{
With_clause* with_clause= select_lex->get_with_clause();
if (with_clause)
with_clause->print(str, query_type);
select_lex->print(get_thd(), str, query_type);
}

View file

@ -67,6 +67,7 @@ sp_rcontext *sp_rcontext::create(THD *thd,
Field *return_value_fld,
Row_definition_list &field_def_lst)
{
SELECT_LEX *save_current_select;
sp_rcontext *ctx= new (thd->mem_root) sp_rcontext(owner,
root_parsing_ctx,
return_value_fld,
@ -74,14 +75,19 @@ sp_rcontext *sp_rcontext::create(THD *thd,
if (!ctx)
return NULL;
/* Reset current_select as it's checked in Item_ident::Item_ident */
save_current_select= thd->lex->current_select;
thd->lex->current_select= 0;
if (ctx->alloc_arrays(thd) ||
ctx->init_var_table(thd, field_def_lst) ||
ctx->init_var_items(thd, field_def_lst))
{
delete ctx;
return NULL;
ctx= 0;
}
thd->lex->current_select= save_current_select;
return ctx;
}

View file

@ -1338,6 +1338,25 @@ public:
};
class Item_change_list_savepoint: public Item_change_list
{
public:
Item_change_list_savepoint(Item_change_list *list)
{
list->move_elements_to(this);
}
void rollback(Item_change_list *list)
{
list->rollback_item_tree_changes();
move_elements_to(list);
}
~Item_change_list_savepoint()
{
DBUG_ASSERT(is_empty());
}
};
/**
Type of locked tables mode.
See comment for THD::locked_tables_mode for complete description.

View file

@ -2909,6 +2909,12 @@ static bool do_execute_sp(THD *thd, sp_head *sp)
ha_rows select_limit= thd->variables.select_limit;
thd->variables.select_limit= HA_POS_ERROR;
/*
Reset current_select as it may point to random data as a
result of previous parsing.
*/
thd->lex->current_select= NULL;
/*
We never write CALL statements into binlog:
- If the mode is non-prelocked, each statement will be logged

View file

@ -2769,6 +2769,25 @@ void mysql_sql_stmt_prepare(THD *thd)
DBUG_VOID_RETURN;
}
/*
Make sure we call Prepared_statement::prepare() with an empty
THD::change_list. It can be non-empty as LEX::get_dynamic_sql_string()
calls fix_fields() for the Item containing the PS source,
e.g. on character set conversion:
SET NAMES utf8;
DELIMITER $$
CREATE PROCEDURE p1()
BEGIN
PREPARE stmt FROM CONCAT('SELECT ',CONVERT(RAND() USING latin1));
EXECUTE stmt;
END;
$$
DELIMITER ;
CALL p1();
*/
Item_change_list_savepoint change_list_savepoint(thd);
if (stmt->prepare(query.str, (uint) query.length))
{
/* Statement map deletes the statement on erase */
@ -2779,6 +2798,7 @@ void mysql_sql_stmt_prepare(THD *thd)
SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
my_ok(thd, 0L, 0L, "Statement prepared");
}
change_list_savepoint.rollback(thd);
DBUG_VOID_RETURN;
}
@ -2810,7 +2830,28 @@ void mysql_sql_stmt_execute_immediate(THD *thd)
// See comments on thd->free_list in mysql_sql_stmt_execute()
Item *free_list_backup= thd->free_list;
thd->free_list= NULL;
/*
Make sure we call Prepared_statement::execute_immediate()
with an empty THD::change_list. It can be non empty as the above
LEX::prepared_stmt_params_fix_fields() and LEX::get_dynamic_str_string()
call fix_fields() for the PS source and PS parameter Items and
can do Item tree changes, e.g. on character set conversion:
- Example #1: Item tree changes in get_dynamic_str_string()
SET NAMES utf8;
CREATE PROCEDURE p1()
EXECUTE IMMEDIATE CONCAT('SELECT ',CONVERT(RAND() USING latin1));
CALL p1();
- Example #2: Item tree changes in prepared_stmt_param_fix_fields():
SET NAMES utf8;
CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8)
EXECUTE IMMEDIATE 'SELECT ?' USING CONCAT(a, CONVERT(RAND() USING latin1));
CALL p1('x');
*/
Item_change_list_savepoint change_list_savepoint(thd);
(void) stmt->execute_immediate(query.str, (uint) query.length);
change_list_savepoint.rollback(thd);
thd->free_items();
thd->free_list= free_list_backup;
@ -3208,7 +3249,27 @@ void mysql_sql_stmt_execute(THD *thd)
*/
Item *free_list_backup= thd->free_list;
thd->free_list= NULL; // Hide the external (e.g. "SET STATEMENT") Items
/*
Make sure we call Prepared_statement::execute_loop() with an empty
THD::change_list. It can be non-empty because the above
LEX::prepared_stmt_params_fix_fields() calls fix_fields() for
the PS parameter Items and can do some Item tree changes,
e.g. on character set conversion:
SET NAMES utf8;
DELIMITER $$
CREATE PROCEDURE p1(a VARCHAR(10) CHARACTER SET utf8)
BEGIN
PREPARE stmt FROM 'SELECT ?';
EXECUTE stmt USING CONCAT(a, CONVERT(RAND() USING latin1));
END;
$$
DELIMITER ;
CALL p1('x');
*/
Item_change_list_savepoint change_list_savepoint(thd);
(void) stmt->execute_loop(&expanded_query, FALSE, NULL, NULL);
change_list_savepoint.rollback(thd);
thd->free_items(); // Free items created by execute_loop()
/*
Now restore the "external" (e.g. "SET STATEMENT") Item list.

View file

@ -3154,7 +3154,15 @@ bool JOIN::make_aggr_tables_info()
curr_tab->having= having;
having->update_used_tables();
}
curr_tab->distinct= true;
/*
We only need DISTINCT operation if the join is not degenerate.
If it is, we must not request DISTINCT processing, because
remove_duplicates() assumes there is a preceding computation step (and
in the degenerate join, there's none)
*/
if (top_join_tab_count)
curr_tab->distinct= true;
having= NULL;
select_distinct= false;
}

View file

@ -751,8 +751,6 @@ DECLARE_THREAD(btr_defragment_thread)(void*)
buf_block_t* first_block;
buf_block_t* last_block;
trx_t* trx = trx_allocate_for_background();
while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
ut_ad(btr_defragment_thread_active);
@ -828,36 +826,31 @@ DECLARE_THREAD(btr_defragment_thread)(void*)
/* Update the last_processed time of this index. */
item->last_processed = now;
} else {
dberr_t err = DB_SUCCESS;
mtr_commit(&mtr);
/* Reaching the end of the index. */
dict_stats_empty_defrag_stats(index);
trx->error_state = DB_SUCCESS;
ut_d(trx->persistent_stats = true);
++trx->will_lock;
dberr_t err = dict_stats_save_defrag_stats(index, trx);
if (err == DB_SUCCESS) {
err = dict_stats_save_defrag_summary(
index, trx);
}
err = dict_stats_save_defrag_stats(index);
if (err != DB_SUCCESS) {
trx_rollback_to_savepoint(trx, NULL);
ib::error() << "Saving defragmentation stats for table "
<< index->table->name
<< " index " << index->name
<< " failed with error "
<< ut_strerr(err);
} else if (trx->state != TRX_STATE_NOT_STARTED) {
trx_commit_for_mysql(trx);
<< index->table->name.m_name
<< " index " << index->name()
<< " failed with error " << err;
} else {
err = dict_stats_save_defrag_summary(index);
if (err != DB_SUCCESS) {
ib::error() << "Saving defragmentation summary for table "
<< index->table->name.m_name
<< " index " << index->name()
<< " failed with error " << err;
}
}
ut_d(trx->persistent_stats = false);
btr_defragment_remove_item(item);
}
}
trx_free_for_background(trx);
btr_defragment_thread_active = false;
os_thread_exit();
OS_THREAD_DUMMY_RETURN;

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2013, 2017, MariaDB Corporation.
Copyright (c) 2013, 2018, MariaDB Corporation.
Copyright (c) 2013, 2014, Fusion-io
This program is free software; you can redistribute it and/or modify it under
@ -175,7 +175,7 @@ struct page_cleaner_t {
requests for all slots */
ulint flush_pass; /*!< count to finish to flush
requests for all slots */
page_cleaner_slot_t* slots; /*!< pointer to the slots */
page_cleaner_slot_t slots[MAX_BUFFER_POOLS];
bool is_running; /*!< false if attempt
to shutdown */
@ -186,7 +186,7 @@ struct page_cleaner_t {
#endif /* UNIV_DEBUG */
};
static page_cleaner_t* page_cleaner = NULL;
static page_cleaner_t page_cleaner;
#ifdef UNIV_DEBUG
my_bool innodb_page_cleaner_disabled_debug;
@ -2507,23 +2507,23 @@ page_cleaner_flush_pages_recommendation(
lsn_avg_rate = (lsn_avg_rate + lsn_rate) / 2;
/* aggregate stats of all slots */
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
ulint flush_tm = page_cleaner->flush_time;
ulint flush_pass = page_cleaner->flush_pass;
ulint flush_tm = page_cleaner.flush_time;
ulint flush_pass = page_cleaner.flush_pass;
page_cleaner->flush_time = 0;
page_cleaner->flush_pass = 0;
page_cleaner.flush_time = 0;
page_cleaner.flush_pass = 0;
ulint lru_tm = 0;
ulint list_tm = 0;
ulint lru_pass = 0;
ulint list_pass = 0;
for (ulint i = 0; i < page_cleaner->n_slots; i++) {
for (ulint i = 0; i < page_cleaner.n_slots; i++) {
page_cleaner_slot_t* slot;
slot = &page_cleaner->slots[i];
slot = &page_cleaner.slots[i];
lru_tm += slot->flush_lru_time;
lru_pass += slot->flush_lru_pass;
@ -2536,7 +2536,7 @@ page_cleaner_flush_pages_recommendation(
slot->flush_list_pass = 0;
}
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
/* minimum values are 1, to avoid dividing by zero. */
if (lru_tm < 1) {
@ -2577,9 +2577,9 @@ page_cleaner_flush_pages_recommendation(
MONITOR_SET(MONITOR_FLUSH_AVG_TIME, flush_tm / flush_pass);
MONITOR_SET(MONITOR_FLUSH_ADAPTIVE_AVG_PASS,
list_pass / page_cleaner->n_slots);
list_pass / page_cleaner.n_slots);
MONITOR_SET(MONITOR_LRU_BATCH_FLUSH_AVG_PASS,
lru_pass / page_cleaner->n_slots);
lru_pass / page_cleaner.n_slots);
MONITOR_SET(MONITOR_FLUSH_AVG_PASS, flush_pass);
prev_lsn = cur_lsn;
@ -2623,12 +2623,12 @@ page_cleaner_flush_pages_recommendation(
sum_pages_for_lsn += pages_for_lsn;
mutex_enter(&page_cleaner->mutex);
ut_ad(page_cleaner->slots[i].state
mutex_enter(&page_cleaner.mutex);
ut_ad(page_cleaner.slots[i].state
== PAGE_CLEANER_STATE_NONE);
page_cleaner->slots[i].n_pages_requested
page_cleaner.slots[i].n_pages_requested
= pages_for_lsn / buf_flush_lsn_scan_factor + 1;
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
}
sum_pages_for_lsn /= buf_flush_lsn_scan_factor;
@ -2648,20 +2648,20 @@ page_cleaner_flush_pages_recommendation(
}
/* Normalize request for each instance */
mutex_enter(&page_cleaner->mutex);
ut_ad(page_cleaner->n_slots_requested == 0);
ut_ad(page_cleaner->n_slots_flushing == 0);
ut_ad(page_cleaner->n_slots_finished == 0);
mutex_enter(&page_cleaner.mutex);
ut_ad(page_cleaner.n_slots_requested == 0);
ut_ad(page_cleaner.n_slots_flushing == 0);
ut_ad(page_cleaner.n_slots_finished == 0);
for (ulint i = 0; i < srv_buf_pool_instances; i++) {
/* if REDO has enough of free space,
don't care about age distribution of pages */
page_cleaner->slots[i].n_pages_requested = pct_for_lsn > 30 ?
page_cleaner->slots[i].n_pages_requested
page_cleaner.slots[i].n_pages_requested = pct_for_lsn > 30 ?
page_cleaner.slots[i].n_pages_requested
* n_pages / sum_pages_for_lsn + 1
: n_pages / srv_buf_pool_instances;
}
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
MONITOR_SET(MONITOR_FLUSH_N_TO_FLUSH_REQUESTED, n_pages);
@ -2720,26 +2720,18 @@ void
buf_flush_page_cleaner_init(void)
/*=============================*/
{
ut_ad(page_cleaner == NULL);
ut_ad(!page_cleaner.is_running);
page_cleaner = static_cast<page_cleaner_t*>(
ut_zalloc_nokey(sizeof(*page_cleaner)));
mutex_create(LATCH_ID_PAGE_CLEANER, &page_cleaner.mutex);
mutex_create(LATCH_ID_PAGE_CLEANER, &page_cleaner->mutex);
page_cleaner.is_requested = os_event_create("pc_is_requested");
page_cleaner.is_finished = os_event_create("pc_is_finished");
page_cleaner.is_started = os_event_create("pc_is_started");
page_cleaner.n_slots = static_cast<ulint>(srv_buf_pool_instances);
page_cleaner->is_requested = os_event_create("pc_is_requested");
page_cleaner->is_finished = os_event_create("pc_is_finished");
page_cleaner->is_started = os_event_create("pc_is_started");
ut_d(page_cleaner.n_disabled_debug = 0);
page_cleaner->n_slots = static_cast<ulint>(srv_buf_pool_instances);
page_cleaner->slots = static_cast<page_cleaner_slot_t*>(
ut_zalloc_nokey(page_cleaner->n_slots
* sizeof(*page_cleaner->slots)));
ut_d(page_cleaner->n_disabled_debug = 0);
page_cleaner->is_running = true;
page_cleaner.is_running = true;
}
/**
@ -2748,22 +2740,18 @@ static
void
buf_flush_page_cleaner_close(void)
{
ut_ad(!page_cleaner.is_running);
/* waiting for all worker threads exit */
while (page_cleaner->n_workers > 0) {
while (page_cleaner.n_workers) {
os_thread_sleep(10000);
}
mutex_destroy(&page_cleaner->mutex);
mutex_destroy(&page_cleaner.mutex);
ut_free(page_cleaner->slots);
os_event_destroy(page_cleaner->is_finished);
os_event_destroy(page_cleaner->is_requested);
os_event_destroy(page_cleaner->is_started);
ut_free(page_cleaner);
page_cleaner = NULL;
os_event_destroy(page_cleaner.is_finished);
os_event_destroy(page_cleaner.is_requested);
os_event_destroy(page_cleaner.is_started);
}
/**
@ -2789,17 +2777,17 @@ pc_request(
/ srv_buf_pool_instances;
}
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
ut_ad(page_cleaner->n_slots_requested == 0);
ut_ad(page_cleaner->n_slots_flushing == 0);
ut_ad(page_cleaner->n_slots_finished == 0);
ut_ad(page_cleaner.n_slots_requested == 0);
ut_ad(page_cleaner.n_slots_flushing == 0);
ut_ad(page_cleaner.n_slots_finished == 0);
page_cleaner->requested = (min_n > 0);
page_cleaner->lsn_limit = lsn_limit;
page_cleaner.requested = (min_n > 0);
page_cleaner.lsn_limit = lsn_limit;
for (ulint i = 0; i < page_cleaner->n_slots; i++) {
page_cleaner_slot_t* slot = &page_cleaner->slots[i];
for (ulint i = 0; i < page_cleaner.n_slots; i++) {
page_cleaner_slot_t* slot = &page_cleaner.slots[i];
ut_ad(slot->state == PAGE_CLEANER_STATE_NONE);
@ -2815,13 +2803,13 @@ pc_request(
slot->state = PAGE_CLEANER_STATE_REQUESTED;
}
page_cleaner->n_slots_requested = page_cleaner->n_slots;
page_cleaner->n_slots_flushing = 0;
page_cleaner->n_slots_finished = 0;
page_cleaner.n_slots_requested = page_cleaner.n_slots;
page_cleaner.n_slots_flushing = 0;
page_cleaner.n_slots_finished = 0;
os_event_set(page_cleaner->is_requested);
os_event_set(page_cleaner.is_requested);
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
}
/**
@ -2836,14 +2824,16 @@ pc_flush_slot(void)
int lru_pass = 0;
int list_pass = 0;
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
if (page_cleaner->n_slots_requested > 0) {
if (!page_cleaner.n_slots_requested) {
os_event_reset(page_cleaner.is_requested);
} else {
page_cleaner_slot_t* slot = NULL;
ulint i;
for (i = 0; i < page_cleaner->n_slots; i++) {
slot = &page_cleaner->slots[i];
for (i = 0; i < page_cleaner.n_slots; i++) {
slot = &page_cleaner.slots[i];
if (slot->state == PAGE_CLEANER_STATE_REQUESTED) {
break;
@ -2851,26 +2841,26 @@ pc_flush_slot(void)
}
/* slot should be found because
page_cleaner->n_slots_requested > 0 */
ut_a(i < page_cleaner->n_slots);
page_cleaner.n_slots_requested > 0 */
ut_a(i < page_cleaner.n_slots);
buf_pool_t* buf_pool = buf_pool_from_array(i);
page_cleaner->n_slots_requested--;
page_cleaner->n_slots_flushing++;
page_cleaner.n_slots_requested--;
page_cleaner.n_slots_flushing++;
slot->state = PAGE_CLEANER_STATE_FLUSHING;
if (page_cleaner->n_slots_requested == 0) {
os_event_reset(page_cleaner->is_requested);
}
if (!page_cleaner->is_running) {
if (UNIV_UNLIKELY(!page_cleaner.is_running)) {
slot->n_flushed_lru = 0;
slot->n_flushed_list = 0;
goto finish_mutex;
}
mutex_exit(&page_cleaner->mutex);
if (page_cleaner.n_slots_requested == 0) {
os_event_reset(page_cleaner.is_requested);
}
mutex_exit(&page_cleaner.mutex);
lru_tm = ut_time_ms();
@ -2880,13 +2870,13 @@ pc_flush_slot(void)
lru_tm = ut_time_ms() - lru_tm;
lru_pass++;
if (!page_cleaner->is_running) {
if (UNIV_UNLIKELY(!page_cleaner.is_running)) {
slot->n_flushed_list = 0;
goto finish;
}
/* Flush pages from flush_list if required */
if (page_cleaner->requested) {
if (page_cleaner.requested) {
flush_counters_t n;
memset(&n, 0, sizeof(flush_counters_t));
list_tm = ut_time_ms();
@ -2894,7 +2884,7 @@ pc_flush_slot(void)
slot->succeeded_list = buf_flush_do_batch(
buf_pool, BUF_FLUSH_LIST,
slot->n_pages_requested,
page_cleaner->lsn_limit,
page_cleaner.lsn_limit,
&n);
slot->n_flushed_list = n.flushed;
@ -2906,10 +2896,10 @@ pc_flush_slot(void)
slot->succeeded_list = true;
}
finish:
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
finish_mutex:
page_cleaner->n_slots_flushing--;
page_cleaner->n_slots_finished++;
page_cleaner.n_slots_flushing--;
page_cleaner.n_slots_finished++;
slot->state = PAGE_CLEANER_STATE_FINISHED;
slot->flush_lru_time += lru_tm;
@ -2917,15 +2907,15 @@ finish_mutex:
slot->flush_lru_pass += lru_pass;
slot->flush_list_pass += list_pass;
if (page_cleaner->n_slots_requested == 0
&& page_cleaner->n_slots_flushing == 0) {
os_event_set(page_cleaner->is_finished);
if (page_cleaner.n_slots_requested == 0
&& page_cleaner.n_slots_flushing == 0) {
os_event_set(page_cleaner.is_finished);
}
}
ulint ret = page_cleaner->n_slots_requested;
ulint ret = page_cleaner.n_slots_requested;
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
return(ret);
}
@ -2947,16 +2937,16 @@ pc_wait_finished(
*n_flushed_lru = 0;
*n_flushed_list = 0;
os_event_wait(page_cleaner->is_finished);
os_event_wait(page_cleaner.is_finished);
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
ut_ad(page_cleaner->n_slots_requested == 0);
ut_ad(page_cleaner->n_slots_flushing == 0);
ut_ad(page_cleaner->n_slots_finished == page_cleaner->n_slots);
ut_ad(page_cleaner.n_slots_requested == 0);
ut_ad(page_cleaner.n_slots_flushing == 0);
ut_ad(page_cleaner.n_slots_finished == page_cleaner.n_slots);
for (ulint i = 0; i < page_cleaner->n_slots; i++) {
page_cleaner_slot_t* slot = &page_cleaner->slots[i];
for (ulint i = 0; i < page_cleaner.n_slots; i++) {
page_cleaner_slot_t* slot = &page_cleaner.slots[i];
ut_ad(slot->state == PAGE_CLEANER_STATE_FINISHED);
@ -2969,11 +2959,11 @@ pc_wait_finished(
slot->n_pages_requested = 0;
}
page_cleaner->n_slots_finished = 0;
page_cleaner.n_slots_finished = 0;
os_event_reset(page_cleaner->is_finished);
os_event_reset(page_cleaner.is_finished);
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
return(all_succeeded);
}
@ -3001,20 +2991,18 @@ static
void
buf_flush_page_cleaner_disabled_loop(void)
{
ut_ad(page_cleaner != NULL);
if (!innodb_page_cleaner_disabled_debug) {
/* We return to avoid entering and exiting mutex. */
return;
}
mutex_enter(&page_cleaner->mutex);
page_cleaner->n_disabled_debug++;
mutex_exit(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
page_cleaner.n_disabled_debug++;
mutex_exit(&page_cleaner.mutex);
while (innodb_page_cleaner_disabled_debug
&& srv_shutdown_state == SRV_SHUTDOWN_NONE
&& page_cleaner->is_running) {
&& page_cleaner.is_running) {
os_thread_sleep(100000); /* [A] */
}
@ -3032,9 +3020,9 @@ buf_flush_page_cleaner_disabled_loop(void)
Therefore we are waiting in step 2 for this thread exiting here. */
mutex_enter(&page_cleaner->mutex);
page_cleaner->n_disabled_debug--;
mutex_exit(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
page_cleaner.n_disabled_debug--;
mutex_exit(&page_cleaner.mutex);
}
/** Disables page cleaner threads (coordinator and workers).
@ -3050,7 +3038,7 @@ buf_flush_page_cleaner_disabled_debug_update(
void* var_ptr,
const void* save)
{
if (page_cleaner == NULL) {
if (!page_cleaner.is_running) {
return;
}
@ -3063,9 +3051,9 @@ buf_flush_page_cleaner_disabled_debug_update(
/* Enable page cleaner threads. */
while (srv_shutdown_state == SRV_SHUTDOWN_NONE) {
mutex_enter(&page_cleaner->mutex);
const ulint n = page_cleaner->n_disabled_debug;
mutex_exit(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
const ulint n = page_cleaner.n_disabled_debug;
mutex_exit(&page_cleaner.mutex);
/* Check if all threads have been enabled, to avoid
problem when we decide to re-disable them soon. */
if (n == 0) {
@ -3090,21 +3078,21 @@ buf_flush_page_cleaner_disabled_debug_update(
That's why we have sleep-loop instead of simply
waiting on some disabled_debug_event. */
os_event_set(page_cleaner->is_requested);
os_event_set(page_cleaner.is_requested);
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
ut_ad(page_cleaner->n_disabled_debug
ut_ad(page_cleaner.n_disabled_debug
<= srv_n_page_cleaners);
if (page_cleaner->n_disabled_debug
if (page_cleaner.n_disabled_debug
== srv_n_page_cleaners) {
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
break;
}
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
os_thread_sleep(100000);
}
@ -3258,10 +3246,10 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
&& srv_flush_sync
&& buf_flush_sync_lsn > 0) {
/* woke up for flush_sync */
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
lsn_t lsn_limit = buf_flush_sync_lsn;
buf_flush_sync_lsn = 0;
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
/* Request flushing for threads */
pc_request(ULINT_MAX, lsn_limit);
@ -3273,8 +3261,8 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
/* only coordinator is using these counters,
so no need to protect by lock. */
page_cleaner->flush_time += ut_time_ms() - tm;
page_cleaner->flush_pass++;
page_cleaner.flush_time += ut_time_ms() - tm;
page_cleaner.flush_pass++;
/* Wait for all slots to be finished */
ulint n_flushed_lru = 0;
@ -3319,8 +3307,8 @@ DECLARE_THREAD(buf_flush_page_cleaner_coordinator)(void*)
/* only coordinator is using these counters,
so no need to protect by lock. */
page_cleaner->flush_time += ut_time_ms() - tm;
page_cleaner->flush_pass++ ;
page_cleaner.flush_time += ut_time_ms() - tm;
page_cleaner.flush_pass++ ;
/* Wait for all slots to be finished */
ulint n_flushed_lru = 0;
@ -3466,8 +3454,8 @@ thread_exit:
/* All worker threads are waiting for the event here,
and no more access to page_cleaner structure by them.
Wakes worker threads up just to make them exit. */
page_cleaner->is_running = false;
os_event_set(page_cleaner->is_requested);
page_cleaner.is_running = false;
os_event_set(page_cleaner.is_requested);
buf_flush_page_cleaner_close();
@ -3486,27 +3474,27 @@ thread_exit:
void
buf_flush_set_page_cleaner_thread_cnt(ulong new_cnt)
{
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
srv_n_page_cleaners = new_cnt;
if (new_cnt > page_cleaner->n_workers) {
if (new_cnt > page_cleaner.n_workers) {
/* User has increased the number of page
cleaner threads. */
uint add = new_cnt - page_cleaner->n_workers;
uint add = new_cnt - page_cleaner.n_workers;
for (uint i = 0; i < add; i++) {
os_thread_id_t cleaner_thread_id;
os_thread_create(buf_flush_page_cleaner_worker, NULL, &cleaner_thread_id);
}
}
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
/* Wait until defined number of workers has started. */
while (page_cleaner->is_running &&
page_cleaner->n_workers != (srv_n_page_cleaners - 1)) {
os_event_set(page_cleaner->is_requested);
os_event_reset(page_cleaner->is_started);
os_event_wait_time(page_cleaner->is_started, 1000000);
while (page_cleaner.is_running &&
page_cleaner.n_workers != (srv_n_page_cleaners - 1)) {
os_event_set(page_cleaner.is_requested);
os_event_reset(page_cleaner.is_started);
os_event_wait_time(page_cleaner.is_started, 1000000);
}
}
@ -3524,18 +3512,15 @@ DECLARE_THREAD(buf_flush_page_cleaner_worker)(
my_thread_init();
os_thread_id_t cleaner_thread_id = os_thread_get_curr_id();
mutex_enter(&page_cleaner->mutex);
ulint thread_no = page_cleaner->n_workers;
page_cleaner->n_workers++;
mutex_enter(&page_cleaner.mutex);
ulint thread_no = page_cleaner.n_workers++;
DBUG_LOG("ib_buf", "Thread "
<< cleaner_thread_id
<< " started n_workers "
<< page_cleaner->n_workers << ".");
DBUG_LOG("ib_buf", "Thread " << cleaner_thread_id
<< " started; n_workers=" << page_cleaner.n_workers);
/* Signal that we have started */
os_event_set(page_cleaner->is_started);
mutex_exit(&page_cleaner->mutex);
os_event_set(page_cleaner.is_started);
mutex_exit(&page_cleaner.mutex);
#ifdef UNIV_LINUX
/* linux might be able to set different setting for each thread
@ -3549,11 +3534,11 @@ DECLARE_THREAD(buf_flush_page_cleaner_worker)(
#endif /* UNIV_LINUX */
while (true) {
os_event_wait(page_cleaner->is_requested);
os_event_wait(page_cleaner.is_requested);
ut_d(buf_flush_page_cleaner_disabled_loop());
if (!page_cleaner->is_running) {
if (!page_cleaner.is_running) {
break;
}
@ -3574,15 +3559,15 @@ DECLARE_THREAD(buf_flush_page_cleaner_worker)(
pc_flush_slot();
}
mutex_enter(&page_cleaner->mutex);
page_cleaner->n_workers--;
mutex_enter(&page_cleaner.mutex);
page_cleaner.n_workers--;
DBUG_LOG("ib_buf", "Thread " << cleaner_thread_id
<< " exiting n_workers " << page_cleaner->n_workers<< ".");
<< " exiting; n_workers=" << page_cleaner.n_workers);
/* Signal that we have stopped */
os_event_set(page_cleaner->is_started);
mutex_exit(&page_cleaner->mutex);
os_event_set(page_cleaner.is_started);
mutex_exit(&page_cleaner.mutex);
my_thread_end();
@ -3617,11 +3602,11 @@ buf_flush_request_force(
/* adjust based on lsn_avg_rate not to get old */
lsn_t lsn_target = lsn_limit + lsn_avg_rate * 3;
mutex_enter(&page_cleaner->mutex);
mutex_enter(&page_cleaner.mutex);
if (lsn_target > buf_flush_sync_lsn) {
buf_flush_sync_lsn = lsn_target;
}
mutex_exit(&page_cleaner->mutex);
mutex_exit(&page_cleaner.mutex);
os_event_set(buf_flush_event);
}

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2016, 2017, MariaDB Corporation.
Copyright (c) 2016, MariaDB Corporation. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -29,7 +29,6 @@ Created 25/08/2016 Jan Lindström
#include "dict0defrag_bg.h"
#include "row0mysql.h"
#include "srv0start.h"
#include "trx0roll.h"
#include "ut0new.h"
#include <vector>
@ -202,18 +201,17 @@ dict_stats_defrag_pool_del(
mutex_exit(&defrag_pool_mutex);
}
/** Get the first index that has been added for updating persistent defrag
stats and eventually save its stats.
@param[in,out] trx transaction that will be started and committed */
/*****************************************************************//**
Get the first index that has been added for updating persistent defrag
stats and eventually save its stats. */
static
void
dict_stats_process_entry_from_defrag_pool(trx_t* trx)
dict_stats_process_entry_from_defrag_pool()
{
table_id_t table_id;
index_id_t index_id;
ut_ad(!srv_read_only_mode);
ut_ad(trx->persistent_stats);
/* pop the first index from the auto defrag pool */
if (!dict_stats_defrag_pool_get(&table_id, &index_id)) {
@ -242,64 +240,62 @@ dict_stats_process_entry_from_defrag_pool(trx_t* trx)
return;
}
mutex_exit(&dict_sys->mutex);
trx->error_state = DB_SUCCESS;
++trx->will_lock;
dberr_t err = dict_stats_save_defrag_stats(index, trx);
if (err != DB_SUCCESS) {
trx_rollback_to_savepoint(trx, NULL);
ib::error() << "Saving defragmentation status for table "
<< index->table->name
<< " index " << index->name
<< " failed " << err;
} else if (trx->state != TRX_STATE_NOT_STARTED) {
trx_commit_for_mysql(trx);
}
dict_stats_save_defrag_stats(index);
dict_table_close(table, FALSE, FALSE);
}
/** Process indexes that have been scheduled for defragmenting.
@param[in,out] trx transaction that will be started and committed */
/*****************************************************************//**
Get the first index that has been added for updating persistent defrag
stats and eventually save its stats. */
void
dict_defrag_process_entries_from_defrag_pool(trx_t* trx)
dict_defrag_process_entries_from_defrag_pool()
/*==========================================*/
{
while (defrag_pool->size() && !dict_stats_start_shutdown) {
dict_stats_process_entry_from_defrag_pool(trx);
dict_stats_process_entry_from_defrag_pool();
}
}
/** Save defragmentation result.
@param[in] index index that was defragmented
@param[in,out] trx transaction
/*********************************************************************//**
Save defragmentation result.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_save_defrag_summary(dict_index_t* index, trx_t* trx)
dict_stats_save_defrag_summary(
/*============================*/
dict_index_t* index) /*!< in: index */
{
ut_ad(trx->persistent_stats);
dberr_t ret=DB_SUCCESS;
lint now = (lint) ut_time();
if (dict_index_is_ibuf(index)) {
return DB_SUCCESS;
}
return dict_stats_save_index_stat(index, ut_time(), "n_pages_freed",
index->stat_defrag_n_pages_freed,
NULL,
"Number of pages freed during"
" last defragmentation run.",
trx);
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
ret = dict_stats_save_index_stat(index, now, "n_pages_freed",
index->stat_defrag_n_pages_freed,
NULL,
"Number of pages freed during"
" last defragmentation run.",
NULL);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
return (ret);
}
/** Save defragmentation stats for a given index.
@param[in] index index that is being defragmented
@param[in,out] trx transaction
/*********************************************************************//**
Save defragmentation stats for a given index.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_save_defrag_stats(dict_index_t* index, trx_t* trx)
dict_stats_save_defrag_stats(
/*============================*/
dict_index_t* index) /*!< in: index */
{
ut_ad(trx->error_state == DB_SUCCESS);
ut_ad(trx->persistent_stats);
dberr_t ret;
if (dict_index_is_ibuf(index)) {
return DB_SUCCESS;
@ -309,6 +305,7 @@ dict_stats_save_defrag_stats(dict_index_t* index, trx_t* trx)
return dict_stats_report_error(index->table, true);
}
lint now = (lint) ut_time();
mtr_t mtr;
ulint n_leaf_pages;
ulint n_leaf_reserved;
@ -325,33 +322,40 @@ dict_stats_save_defrag_stats(dict_index_t* index, trx_t* trx)
return DB_SUCCESS;
}
ib_time_t now = ut_time();
dberr_t err = dict_stats_save_index_stat(
index, now, "n_page_split",
index->stat_defrag_n_page_split,
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
ret = dict_stats_save_index_stat(index, now, "n_page_split",
index->stat_defrag_n_page_split,
NULL,
"Number of new page splits on leaves"
" since last defragmentation.",
NULL);
if (ret != DB_SUCCESS) {
goto end;
}
ret = dict_stats_save_index_stat(
index, now, "n_leaf_pages_defrag",
n_leaf_pages,
NULL,
"Number of new page splits on leaves"
" since last defragmentation.",
trx);
if (err == DB_SUCCESS) {
err = dict_stats_save_index_stat(
index, now, "n_leaf_pages_defrag",
n_leaf_pages,
NULL,
"Number of leaf pages when this stat is saved to disk",
trx);
"Number of leaf pages when this stat is saved to disk",
NULL);
if (ret != DB_SUCCESS) {
goto end;
}
if (err == DB_SUCCESS) {
err = dict_stats_save_index_stat(
index, now, "n_leaf_pages_reserved",
n_leaf_reserved,
NULL,
"Number of pages reserved for this "
"index leaves when this stat "
"is saved to disk",
trx);
}
ret = dict_stats_save_index_stat(
index, now, "n_leaf_pages_reserved",
n_leaf_reserved,
NULL,
"Number of pages reserved for this index leaves when this stat "
"is saved to disk",
NULL);
return err;
end:
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
return (ret);
}

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2009, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2017, MariaDB Corporation.
Copyright (c) 2015, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -276,7 +276,9 @@ This function will free the pinfo object.
@param[in,out] pinfo pinfo to pass to que_eval_sql() must already
have any literals bound to it
@param[in] sql SQL string to execute
@param[in,out] trx transaction
@param[in,out] trx in case of NULL the function will allocate and
free the trx object. If it is not NULL then it will be rolled back
only in the case of error, but not freed.
@return DB_SUCCESS or error code */
static
dberr_t
@ -286,12 +288,53 @@ dict_stats_exec_sql(
trx_t* trx)
{
dberr_t err;
bool trx_started = false;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
if (!dict_stats_persistent_storage_check(true)) {
pars_info_free(pinfo);
return(DB_STATS_DO_NOT_EXIST);
}
if (trx == NULL) {
trx = trx_allocate_for_background();
trx_started = true;
if (srv_read_only_mode) {
trx_start_internal_read_only(trx);
} else {
trx_start_internal(trx);
}
}
err = que_eval_sql(pinfo, sql, FALSE, trx); /* pinfo is freed here */
DBUG_EXECUTE_IF("stats_index_error",
if (!trx_started) {
err = DB_STATS_DO_NOT_EXIST;
trx->error_state = DB_STATS_DO_NOT_EXIST;);
trx->error_state = DB_STATS_DO_NOT_EXIST;
});
if (!trx_started && err == DB_SUCCESS) {
return(DB_SUCCESS);
}
if (err == DB_SUCCESS) {
trx_commit_for_mysql(trx);
} else {
trx->op_info = "rollback of internal trx on stats tables";
trx->dict_operation_lock_mode = RW_X_LATCH;
trx_rollback_to_savepoint(trx, NULL);
trx->dict_operation_lock_mode = 0;
trx->op_info = "";
ut_a(trx->error_state == DB_SUCCESS);
}
if (trx_started) {
trx_free_for_background(trx);
}
return(err);
}
@ -500,12 +543,16 @@ dict_stats_empty_index(
}
}
/** Reset the table and index statsistics, corresponding to an empty table.
@param[in,out] table table whose statistics are to be reset
@param[in] empty_defrag_stats whether to empty the defrag statistics
*/
/*********************************************************************//**
Write all zeros (or 1 where it makes sense) into a table and its indexes'
statistics members. The resulting stats correspond to an empty table. */
static
void
dict_stats_empty_table(dict_table_t* table, bool empty_defrag_stats)
dict_stats_empty_table(
/*===================*/
dict_table_t* table, /*!< in/out: table */
bool empty_defrag_stats)
/*!< in: whether to empty defrag stats */
{
/* Zero the stats members */
@ -2259,7 +2306,9 @@ storage.
@param[in] stat_value value of the stat
@param[in] sample_size n pages sampled or NULL
@param[in] stat_description description of the stat
@param[in,out] trx transaction
@param[in,out] trx in case of NULL the function will
allocate and free the trx object. If it is not NULL then it will be
rolled back only in the case of error, but not freed.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_save_index_stat(
@ -2276,7 +2325,9 @@ dict_stats_save_index_stat(
char db_utf8[MAX_DB_UTF8_LEN];
char table_utf8[MAX_TABLE_UTF8_LEN];
ut_ad(trx->persistent_stats || trx->in_mysql_trx_list);
ut_ad(!trx || trx->internal || trx->in_mysql_trx_list);
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
dict_fs2utf8(index->table->name.m_name, db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8));
@ -2302,8 +2353,6 @@ dict_stats_save_index_stat(
pars_info_add_str_literal(pinfo, "stat_description",
stat_description);
mutex_enter(&dict_sys->mutex);
ret = dict_stats_exec_sql(
pinfo,
"PROCEDURE INDEX_STATS_SAVE () IS\n"
@ -2330,8 +2379,6 @@ dict_stats_save_index_stat(
");\n"
"END;", trx);
mutex_exit(&dict_sys->mutex);
if (ret != DB_SUCCESS) {
if (innodb_index_stats_not_found == false &&
index->stats_error_printed == false) {
@ -2384,7 +2431,6 @@ dict_stats_report_error(dict_table_t* table, bool defragment)
/** Save the table's statistics into the persistent statistics storage.
@param[in] table_orig table whose stats to save
@param[in,out] trx transaction
@param[in] only_for_index if this is non-NULL, then stats for indexes
that are not equal to it will not be saved, if NULL, then all indexes' stats
are saved
@ -2393,8 +2439,7 @@ static
dberr_t
dict_stats_save(
dict_table_t* table_orig,
trx_t* trx,
const index_id_t* only_for_index = NULL)
const index_id_t* only_for_index)
{
pars_info_t* pinfo;
ib_time_t now;
@ -2403,10 +2448,11 @@ dict_stats_save(
char db_utf8[MAX_DB_UTF8_LEN];
char table_utf8[MAX_TABLE_UTF8_LEN];
ut_ad(trx->persistent_stats || trx->in_mysql_trx_list);
if (high_level_read_only) {
return DB_READ_ONLY;
}
if (table_orig->is_readable()) {
} else {
if (!table_orig->is_readable()) {
return (dict_stats_report_error(table_orig));
}
@ -2415,8 +2461,9 @@ dict_stats_save(
dict_fs2utf8(table->name.m_name, db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8));
now = ut_time();
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
pinfo = pars_info_create();
@ -2429,8 +2476,6 @@ dict_stats_save(
pars_info_add_ull_literal(pinfo, "sum_of_other_index_sizes",
table->stat_sum_of_other_index_sizes);
mutex_enter(&dict_sys->mutex);
ret = dict_stats_exec_sql(
pinfo,
"PROCEDURE TABLE_STATS_SAVE () IS\n"
@ -2451,18 +2496,28 @@ dict_stats_save(
":clustered_index_size,\n"
":sum_of_other_index_sizes\n"
");\n"
"END;", trx);
"END;", NULL);
mutex_exit(&dict_sys->mutex);
if (ret != DB_SUCCESS) {
ib::error() << "Cannot save table statistics for table "
<< table->name << ": " << ut_strerr(ret);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_stats_snapshot_free(table);
return(ret);
}
trx_t* trx = trx_allocate_for_background();
trx_start_internal(trx);
dict_index_t* index;
index_map_t indexes(
(ut_strcmp_functor()),
index_map_t_allocator(mem_key_dict_stats_index_map_t));
if (ret != DB_SUCCESS) {
goto end;
}
/* Below we do all the modifications in innodb_index_stats in a single
transaction for performance reasons. Modifying more than one row in a
single transaction may deadlock with other transactions if they
@ -2475,17 +2530,18 @@ dict_stats_save(
stat_name). This is why below we sort the indexes by name and then
for each index, do the mods ordered by stat_name. */
for (dict_index_t* index = dict_table_get_first_index(table);
for (index = dict_table_get_first_index(table);
index != NULL;
index = dict_table_get_next_index(index)) {
indexes[index->name] = index;
}
for (index_map_t::const_iterator it = indexes.begin();
it != indexes.end(); ++it) {
index_map_t::const_iterator it;
dict_index_t* index = it->second;
for (it = indexes.begin(); it != indexes.end(); ++it) {
index = it->second;
if (only_for_index != NULL && index->id != *only_for_index) {
continue;
@ -2548,11 +2604,13 @@ dict_stats_save(
}
}
if (ret != DB_SUCCESS) {
trx_commit_for_mysql(trx);
end:
ib::error() << "Cannot save table statistics for table "
<< table->name << ": " << ut_strerr(ret);
}
trx_free_for_background(trx);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
dict_stats_snapshot_free(table);
@ -3050,13 +3108,12 @@ dict_stats_empty_defrag_modified_counter(
}
}
/** Calculate index statistics.
@param[in,out] index index tree
@param[in,out] trx transaction (for persistent statistics)
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
dict_stats_update_for_index(dict_index_t* index, trx_t* trx)
/*********************************************************************//**
Fetches or calculates new estimates for index statistics. */
void
dict_stats_update_for_index(
/*========================*/
dict_index_t* index) /*!< in/out: index */
{
DBUG_ENTER("dict_stats_update_for_index");
@ -3068,8 +3125,8 @@ dict_stats_update_for_index(dict_index_t* index, trx_t* trx)
dict_table_stats_lock(index->table, RW_X_LATCH);
dict_stats_analyze_index(index);
dict_table_stats_unlock(index->table, RW_X_LATCH);
DBUG_RETURN(dict_stats_save(index->table, trx,
&index->id));
dict_stats_save(index->table, &index->id);
DBUG_VOID_RETURN;
}
/* else */
@ -3092,20 +3149,22 @@ dict_stats_update_for_index(dict_index_t* index, trx_t* trx)
dict_stats_update_transient_for_index(index);
dict_table_stats_unlock(index->table, RW_X_LATCH);
DBUG_RETURN(DB_SUCCESS);
DBUG_VOID_RETURN;
}
/** Calculate new estimates for table and index statistics.
@param[in,out] table table
@param[in] stats_upd_option how to update statistics
@param[in,out] trx transaction
@return DB_* error code or DB_SUCCESS */
UNIV_INTERN
/*********************************************************************//**
Calculates new estimates for table and index statistics. The statistics
are used in query optimization.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_update(
dict_table_t* table,
dict_stats_upd_option_t stats_upd_option,
trx_t* trx)
/*==============*/
dict_table_t* table, /*!< in/out: table */
dict_stats_upd_option_t stats_upd_option)
/*!< in: whether to (re) calc
the stats or to fetch them from
the persistent statistics
storage */
{
ut_ad(!mutex_own(&dict_sys->mutex));
@ -3150,7 +3209,7 @@ dict_stats_update(
return(err);
}
err = dict_stats_save(table, trx);
err = dict_stats_save(table, NULL);
return(err);
}
@ -3186,7 +3245,7 @@ dict_stats_update(
if (dict_stats_persistent_storage_check(false)) {
return(dict_stats_save(table, trx));
return(dict_stats_save(table, NULL));
}
return(DB_STATS_DO_NOT_EXIST);
@ -3265,9 +3324,9 @@ dict_stats_update(
}
if (dict_stats_auto_recalc_is_enabled(table)) {
return dict_stats_update(
table, DICT_STATS_RECALC_PERSISTENT,
trx);
return(dict_stats_update(
table,
DICT_STATS_RECALC_PERSISTENT));
}
ib::info() << "Trying to use table " << table->name
@ -3315,20 +3374,25 @@ transient:
return(DB_SUCCESS);
}
/** Remove the persistent statistics for an index.
@param[in] db_and_table schema and table name, e.g., 'db/table'
@param[in] iname index name
@param[out] errstr error message (when not returning DB_SUCCESS)
@param[in] errstr_sz sizeof errstr
@param[in,out] trx transaction
/*********************************************************************//**
Removes the information for a particular index's stats from the persistent
storage if it exists and if there is data stored for this index.
This function creates its own trx and commits it.
A note from Marko why we cannot edit user and sys_* tables in one trx:
marko: The problem is that ibuf merges should be disabled while we are
rolling back dict transactions.
marko: If ibuf merges are not disabled, we need to scan the *.ibd files.
But we shouldn't open *.ibd files before we have rolled back dict
transactions and opened the SYS_* records for the *.ibd files.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_drop_index(
const char* db_and_table,
const char* iname,
char* errstr,
size_t errstr_sz,
trx_t* trx)
/*==================*/
const char* db_and_table,/*!< in: db and table, e.g. 'db/table' */
const char* iname, /*!< in: index name */
char* errstr, /*!< out: error message if != DB_SUCCESS
is returned */
ulint errstr_sz)/*!< in: size of the errstr buffer */
{
char db_utf8[MAX_DB_UTF8_LEN];
char table_utf8[MAX_TABLE_UTF8_LEN];
@ -3344,11 +3408,6 @@ dict_stats_drop_index(
return(DB_SUCCESS);
}
if (!dict_stats_persistent_storage_check(false)) {
/* Statistics tables do not exist. */
return(DB_SUCCESS);
}
dict_fs2utf8(db_and_table, db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8));
@ -3360,6 +3419,7 @@ dict_stats_drop_index(
pars_info_add_str_literal(pinfo, "index_name", iname);
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
ret = dict_stats_exec_sql(
@ -3370,18 +3430,16 @@ dict_stats_drop_index(
"database_name = :database_name AND\n"
"table_name = :table_name AND\n"
"index_name = :index_name;\n"
"END;\n", trx);
"END;\n", NULL);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
switch (ret) {
case DB_STATS_DO_NOT_EXIST:
case DB_SUCCESS:
return(DB_SUCCESS);
case DB_QUE_THR_SUSPENDED:
ret = DB_LOCK_WAIT;
/* fall through */
default:
if (ret == DB_STATS_DO_NOT_EXIST) {
ret = DB_SUCCESS;
}
if (ret != DB_SUCCESS) {
snprintf(errstr, errstr_sz,
"Unable to delete statistics for index %s"
" from %s%s: %s. They can be deleted later using"
@ -3407,71 +3465,98 @@ dict_stats_drop_index(
return(ret);
}
/** Delete table statistics.
@param[in] db schema name
@param[in] t table name
@param[in,out] trx transaction
/*********************************************************************//**
Executes
DELETE FROM mysql.innodb_table_stats
WHERE database_name = '...' AND table_name = '...';
Creates its own transaction and commits it.
@return DB_SUCCESS or error code */
UNIV_INLINE
dberr_t
dict_stats_delete_from_table_stats(const char* db, const char* t, trx_t* trx)
dict_stats_delete_from_table_stats(
/*===============================*/
const char* database_name, /*!< in: database name, e.g. 'db' */
const char* table_name) /*!< in: table name, e.g. 'table' */
{
pars_info_t* pinfo = pars_info_create();
pars_info_t* pinfo;
dberr_t ret;
pars_info_add_str_literal(pinfo, "database_name", db);
pars_info_add_str_literal(pinfo, "table_name", t);
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
return dict_stats_exec_sql(
pinfo = pars_info_create();
pars_info_add_str_literal(pinfo, "database_name", database_name);
pars_info_add_str_literal(pinfo, "table_name", table_name);
ret = dict_stats_exec_sql(
pinfo,
"PROCEDURE DELETE_FROM_TABLE_STATS () IS\n"
"BEGIN\n"
"DELETE FROM \"" TABLE_STATS_NAME "\" WHERE\n"
"database_name = :database_name AND\n"
"table_name = :table_name;\n"
"END;\n", trx);
"END;\n", NULL);
return(ret);
}
/** Delete index statistics.
@param[in] db schema name
@param[in] t table name
@param[in,out] trx transaction
/*********************************************************************//**
Executes
DELETE FROM mysql.innodb_index_stats
WHERE database_name = '...' AND table_name = '...';
Creates its own transaction and commits it.
@return DB_SUCCESS or error code */
UNIV_INLINE
dberr_t
dict_stats_delete_from_index_stats(const char* db, const char* t, trx_t* trx)
dict_stats_delete_from_index_stats(
/*===============================*/
const char* database_name, /*!< in: database name, e.g. 'db' */
const char* table_name) /*!< in: table name, e.g. 'table' */
{
pars_info_t* pinfo = pars_info_create();
pars_info_t* pinfo;
dberr_t ret;
pars_info_add_str_literal(pinfo, "database_name", db);
pars_info_add_str_literal(pinfo, "table_name", t);
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
return dict_stats_exec_sql(
pinfo = pars_info_create();
pars_info_add_str_literal(pinfo, "database_name", database_name);
pars_info_add_str_literal(pinfo, "table_name", table_name);
ret = dict_stats_exec_sql(
pinfo,
"PROCEDURE DELETE_FROM_INDEX_STATS () IS\n"
"BEGIN\n"
"DELETE FROM \"" INDEX_STATS_NAME "\" WHERE\n"
"database_name = :database_name AND\n"
"table_name = :table_name;\n"
"END;\n", trx);
"END;\n", NULL);
return(ret);
}
/** Remove the persistent statistics for a table and all of its indexes.
@param[in] db_and_table schema and table name, e.g., 'db/table'
@param[out] errstr error message (when not returning DB_SUCCESS)
@param[in] errstr_sz sizeof errstr
@param[in,out] trx transaction
/*********************************************************************//**
Removes the statistics for a table and all of its indexes from the
persistent statistics storage if it exists and if there is data stored for
the table. This function creates its own transaction and commits it.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_drop_table(
const char* db_and_table,
char* errstr,
size_t errstr_sz,
trx_t* trx)
/*==================*/
const char* db_and_table, /*!< in: db and table, e.g. 'db/table' */
char* errstr, /*!< out: error message
if != DB_SUCCESS is returned */
ulint errstr_sz) /*!< in: size of errstr buffer */
{
char db_utf8[MAX_DB_UTF8_LEN];
char table_utf8[MAX_TABLE_UTF8_LEN];
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
/* skip tables that do not contain a database name
e.g. if we are dropping SYS_TABLES */
if (strchr(db_and_table, '/') == NULL) {
@ -3486,32 +3571,24 @@ dict_stats_drop_table(
return(DB_SUCCESS);
}
if (!dict_stats_persistent_storage_check(true)) {
/* Statistics tables do not exist. */
return(DB_SUCCESS);
}
dict_fs2utf8(db_and_table, db_utf8, sizeof(db_utf8),
table_utf8, sizeof(table_utf8));
ret = dict_stats_delete_from_table_stats(db_utf8, table_utf8, trx);
ret = dict_stats_delete_from_table_stats(db_utf8, table_utf8);
if (ret == DB_SUCCESS) {
ret = dict_stats_delete_from_index_stats(
db_utf8, table_utf8, trx);
ret = dict_stats_delete_from_index_stats(db_utf8, table_utf8);
}
switch (ret) {
case DB_SUCCESS:
case DB_STATS_DO_NOT_EXIST:
return(DB_SUCCESS);
case DB_QUE_THR_SUSPENDED:
ret = DB_LOCK_WAIT;
/* fall through */
default:
if (ret == DB_STATS_DO_NOT_EXIST) {
ret = DB_SUCCESS;
}
if (ret != DB_SUCCESS) {
snprintf(errstr, errstr_sz,
"Unable to delete statistics for table %s.%s: %s. "
"They can be deleted later using "
"Unable to delete statistics for table %s.%s: %s."
" They can be deleted later using"
" DELETE FROM %s WHERE"
" database_name = '%s' AND"
@ -3534,30 +3611,36 @@ dict_stats_drop_table(
return(ret);
}
/** Rename table statistics.
@param[in] old_dbname_utf8 old schema name
@param[in] old_tablename_utf8 old table name
@param[in] new_dbname_utf8 new schema name
@param[in] new_tablename_utf8 new schema name
@param[in,out] trx transaction
/*********************************************************************//**
Executes
UPDATE mysql.innodb_table_stats SET
database_name = '...', table_name = '...'
WHERE database_name = '...' AND table_name = '...';
Creates its own transaction and commits it.
@return DB_SUCCESS or error code */
UNIV_INLINE
dberr_t
dict_stats_rename_in_table_stats(
const char* old_dbname_utf8,
const char* old_tablename_utf8,
const char* new_dbname_utf8,
const char* new_tablename_utf8,
trx_t* trx)
dict_stats_rename_table_in_table_stats(
/*===================================*/
const char* old_dbname_utf8,/*!< in: database name, e.g. 'olddb' */
const char* old_tablename_utf8,/*!< in: table name, e.g. 'oldtable' */
const char* new_dbname_utf8,/*!< in: database name, e.g. 'newdb' */
const char* new_tablename_utf8)/*!< in: table name, e.g. 'newtable' */
{
pars_info_t* pinfo = pars_info_create();
pars_info_t* pinfo;
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
pinfo = pars_info_create();
pars_info_add_str_literal(pinfo, "old_dbname_utf8", old_dbname_utf8);
pars_info_add_str_literal(pinfo, "old_tablename_utf8", old_tablename_utf8);
pars_info_add_str_literal(pinfo, "new_dbname_utf8", new_dbname_utf8);
pars_info_add_str_literal(pinfo, "new_tablename_utf8", new_tablename_utf8);
return dict_stats_exec_sql(
ret = dict_stats_exec_sql(
pinfo,
"PROCEDURE RENAME_TABLE_IN_TABLE_STATS () IS\n"
"BEGIN\n"
@ -3567,33 +3650,41 @@ dict_stats_rename_in_table_stats(
"WHERE\n"
"database_name = :old_dbname_utf8 AND\n"
"table_name = :old_tablename_utf8;\n"
"END;\n", trx);
"END;\n", NULL);
return(ret);
}
/** Rename index statistics.
@param[in] old_dbname_utf8 old schema name
@param[in] old_tablename_utf8 old table name
@param[in] new_dbname_utf8 new schema name
@param[in] new_tablename_utf8 new schema name
@param[in,out] trx transaction
/*********************************************************************//**
Executes
UPDATE mysql.innodb_index_stats SET
database_name = '...', table_name = '...'
WHERE database_name = '...' AND table_name = '...';
Creates its own transaction and commits it.
@return DB_SUCCESS or error code */
UNIV_INLINE
dberr_t
dict_stats_rename_in_index_stats(
const char* old_dbname_utf8,
const char* old_tablename_utf8,
const char* new_dbname_utf8,
const char* new_tablename_utf8,
trx_t* trx)
dict_stats_rename_table_in_index_stats(
/*===================================*/
const char* old_dbname_utf8,/*!< in: database name, e.g. 'olddb' */
const char* old_tablename_utf8,/*!< in: table name, e.g. 'oldtable' */
const char* new_dbname_utf8,/*!< in: database name, e.g. 'newdb' */
const char* new_tablename_utf8)/*!< in: table name, e.g. 'newtable' */
{
pars_info_t* pinfo = pars_info_create();
pars_info_t* pinfo;
dberr_t ret;
ut_ad(rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(mutex_own(&dict_sys->mutex));
pinfo = pars_info_create();
pars_info_add_str_literal(pinfo, "old_dbname_utf8", old_dbname_utf8);
pars_info_add_str_literal(pinfo, "old_tablename_utf8", old_tablename_utf8);
pars_info_add_str_literal(pinfo, "new_dbname_utf8", new_dbname_utf8);
pars_info_add_str_literal(pinfo, "new_tablename_utf8", new_tablename_utf8);
return dict_stats_exec_sql(
ret = dict_stats_exec_sql(
pinfo,
"PROCEDURE RENAME_TABLE_IN_INDEX_STATS () IS\n"
"BEGIN\n"
@ -3603,23 +3694,23 @@ dict_stats_rename_in_index_stats(
"WHERE\n"
"database_name = :old_dbname_utf8 AND\n"
"table_name = :old_tablename_utf8;\n"
"END;\n", trx);
"END;\n", NULL);
return(ret);
}
/** Rename a table in the InnoDB persistent statistics storage.
@param[in] old_name old schema and table name, e.g., 'db/table'
@param[in] new_name new schema and table name, e.g., 'db/table'
@param[out] errstr error message (when not returning DB_SUCCESS)
@param[in] errstr_sz sizeof errstr
@param[in,out] trx transaction
/*********************************************************************//**
Renames a table in InnoDB persistent stats storage.
This function creates its own transaction and commits it.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_rename_table(
const char* old_name,
const char* new_name,
char* errstr,
size_t errstr_sz,
trx_t* trx)
/*====================*/
const char* old_name, /*!< in: old name, e.g. 'db/table' */
const char* new_name, /*!< in: new name, e.g. 'db/table' */
char* errstr, /*!< out: error string if != DB_SUCCESS
is returned */
size_t errstr_sz) /*!< in: errstr size */
{
char old_db_utf8[MAX_DB_UTF8_LEN];
char new_db_utf8[MAX_DB_UTF8_LEN];
@ -3627,6 +3718,9 @@ dict_stats_rename_table(
char new_table_utf8[MAX_TABLE_UTF8_LEN];
dberr_t ret;
ut_ad(!rw_lock_own(dict_operation_lock, RW_LOCK_X));
ut_ad(!mutex_own(&dict_sys->mutex));
/* skip innodb_table_stats and innodb_index_stats themselves */
if (strcmp(old_name, TABLE_STATS_NAME) == 0
|| strcmp(old_name, INDEX_STATS_NAME) == 0
@ -3636,95 +3730,45 @@ dict_stats_rename_table(
return(DB_SUCCESS);
}
if (!dict_stats_persistent_storage_check(false)) {
/* Statistics tables do not exist. */
return(DB_SUCCESS);
}
dict_fs2utf8(old_name, old_db_utf8, sizeof(old_db_utf8),
old_table_utf8, sizeof(old_table_utf8));
dict_fs2utf8(new_name, new_db_utf8, sizeof(new_db_utf8),
new_table_utf8, sizeof(new_table_utf8));
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
ulint n_attempts = 0;
do {
trx_savept_t savept = trx_savept_take(trx);
n_attempts++;
mutex_enter(&dict_sys->mutex);
ret = dict_stats_rename_in_table_stats(
ret = dict_stats_rename_table_in_table_stats(
old_db_utf8, old_table_utf8,
new_db_utf8, new_table_utf8, trx);
new_db_utf8, new_table_utf8);
mutex_exit(&dict_sys->mutex);
switch (ret) {
case DB_DUPLICATE_KEY:
trx_rollback_to_savepoint(trx, &savept);
mutex_enter(&dict_sys->mutex);
if (ret == DB_DUPLICATE_KEY) {
dict_stats_delete_from_table_stats(
new_db_utf8, new_table_utf8, trx);
mutex_exit(&dict_sys->mutex);
/* fall through */
case DB_LOCK_WAIT_TIMEOUT:
trx->error_state = DB_SUCCESS;
os_thread_sleep(200000 /* 0.2 sec */);
continue;
case DB_STATS_DO_NOT_EXIST:
ret = DB_SUCCESS;
break;
default:
break;
new_db_utf8, new_table_utf8);
}
break;
} while (++n_attempts < 5);
if (ret == DB_STATS_DO_NOT_EXIST) {
ret = DB_SUCCESS;
}
const char* table_name = TABLE_STATS_NAME_PRINT;
if (ret != DB_SUCCESS) {
goto err_exit;
}
table_name = INDEX_STATS_NAME_PRINT;
n_attempts = 0;
do {
trx_savept_t savept = trx_savept_take(trx);
mutex_enter(&dict_sys->mutex);
ret = dict_stats_rename_in_index_stats(
old_db_utf8, old_table_utf8,
new_db_utf8, new_table_utf8, trx);
mutex_exit(&dict_sys->mutex);
switch (ret) {
case DB_DUPLICATE_KEY:
trx_rollback_to_savepoint(trx, &savept);
if (ret != DB_SUCCESS) {
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
os_thread_sleep(200000 /* 0.2 sec */);
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
dict_stats_delete_from_index_stats(
new_db_utf8, new_table_utf8, trx);
mutex_exit(&dict_sys->mutex);
/* fall through */
case DB_LOCK_WAIT_TIMEOUT:
trx->error_state = DB_SUCCESS;
os_thread_sleep(200000 /* 0.2 sec */);
continue;
case DB_STATS_DO_NOT_EXIST:
ret = DB_SUCCESS;
break;
default:
break;
}
break;
} while (++n_attempts < 5);
} while ((ret == DB_DEADLOCK
|| ret == DB_DUPLICATE_KEY
|| ret == DB_LOCK_WAIT_TIMEOUT)
&& n_attempts < 5);
if (ret != DB_SUCCESS) {
err_exit:
snprintf(errstr, errstr_sz,
"Unable to rename statistics from"
" %s.%s to %s.%s in %s: %s."
@ -3739,10 +3783,69 @@ err_exit:
old_db_utf8, old_table_utf8,
new_db_utf8, new_table_utf8,
table_name,
TABLE_STATS_NAME_PRINT,
ut_strerr(ret),
table_name,
TABLE_STATS_NAME_PRINT,
new_db_utf8, new_table_utf8,
old_db_utf8, old_table_utf8);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
return(ret);
}
/* else */
n_attempts = 0;
do {
n_attempts++;
ret = dict_stats_rename_table_in_index_stats(
old_db_utf8, old_table_utf8,
new_db_utf8, new_table_utf8);
if (ret == DB_DUPLICATE_KEY) {
dict_stats_delete_from_index_stats(
new_db_utf8, new_table_utf8);
}
if (ret == DB_STATS_DO_NOT_EXIST) {
ret = DB_SUCCESS;
}
if (ret != DB_SUCCESS) {
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
os_thread_sleep(200000 /* 0.2 sec */);
rw_lock_x_lock(dict_operation_lock);
mutex_enter(&dict_sys->mutex);
}
} while ((ret == DB_DEADLOCK
|| ret == DB_DUPLICATE_KEY
|| ret == DB_LOCK_WAIT_TIMEOUT)
&& n_attempts < 5);
mutex_exit(&dict_sys->mutex);
rw_lock_x_unlock(dict_operation_lock);
if (ret != DB_SUCCESS) {
snprintf(errstr, errstr_sz,
"Unable to rename statistics from"
" %s.%s to %s.%s in %s: %s."
" They can be renamed later using"
" UPDATE %s SET"
" database_name = '%s',"
" table_name = '%s'"
" WHERE"
" database_name = '%s' AND"
" table_name = '%s';",
old_db_utf8, old_table_utf8,
new_db_utf8, new_table_utf8,
INDEX_STATS_NAME_PRINT,
ut_strerr(ret),
INDEX_STATS_NAME_PRINT,
new_db_utf8, new_table_utf8,
old_db_utf8, old_table_utf8);
}
@ -3750,6 +3853,7 @@ err_exit:
return(ret);
}
#ifdef MYSQL_RENAME_INDEX
/*********************************************************************//**
Renames an index in InnoDB persistent stats storage.
This function creates its own transaction and commits it.
@ -3806,6 +3910,7 @@ dict_stats_rename_index(
return(ret);
}
#endif /* MYSQL_RENAME_INDEX */
/* tests @{ */
#ifdef UNIV_ENABLE_UNIT_TEST_DICT_STATS

View file

@ -32,7 +32,6 @@ Created Apr 25, 2012 Vasil Dimov
#include "srv0start.h"
#include "ut0new.h"
#include "fil0fil.h"
#include "trx0trx.h"
#include <vector>
@ -181,7 +180,7 @@ dict_stats_update_if_needed(dict_table_t* table)
if (counter > threshold) {
/* this will reset table->stat_modified_counter to 0 */
dict_stats_update(table, DICT_STATS_RECALC_TRANSIENT, NULL);
dict_stats_update(table, DICT_STATS_RECALC_TRANSIENT);
}
}
@ -324,7 +323,8 @@ Get the first table that has been added for auto recalc and eventually
update its stats. */
static
void
dict_stats_process_entry_from_recalc_pool(trx_t* trx)
dict_stats_process_entry_from_recalc_pool()
/*=======================================*/
{
table_id_t table_id;
@ -378,12 +378,8 @@ dict_stats_process_entry_from_recalc_pool(trx_t* trx)
dict_stats_recalc_pool_add(table);
} else {
trx->error_state = DB_SUCCESS;
++trx->will_lock;
dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT, trx);
if (trx->state != TRX_STATE_NOT_STARTED) {
trx_commit_for_mysql(trx);
}
dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT);
}
mutex_enter(&dict_sys->mutex);
@ -444,9 +440,6 @@ DECLARE_THREAD(dict_stats_thread)(void*)
*/
#endif /* UNIV_PFS_THREAD */
trx_t* trx = trx_allocate_for_background();
ut_d(trx->persistent_stats = true);
while (!dict_stats_start_shutdown) {
/* Wake up periodically even if not signaled. This is
@ -472,14 +465,12 @@ DECLARE_THREAD(dict_stats_thread)(void*)
break;
}
dict_stats_process_entry_from_recalc_pool(trx);
dict_defrag_process_entries_from_defrag_pool(trx);
dict_stats_process_entry_from_recalc_pool();
dict_defrag_process_entries_from_defrag_pool();
os_event_reset(dict_stats_event);
}
ut_d(trx->persistent_stats = false);
trx_free_for_background(trx);
srv_dict_stats_thread_active = false;
os_event_set(dict_stats_shutdown_event);

View file

@ -2085,7 +2085,7 @@ convert_error_code_to_mysql(
case DB_TOO_BIG_INDEX_COL:
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
(ulong) DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
return(HA_ERR_INDEX_COL_TOO_LONG);
case DB_NO_SAVEPOINT:
@ -5105,7 +5105,6 @@ innobase_close_connection(
"MariaDB is closing a connection that has an active "
"InnoDB transaction. " TRX_ID_FMT " row modifications "
"will roll back.",
" row modifications will roll back.",
trx->undo_no);
ut_d(ib::warn()
<< "trx: " << trx << " started on: "
@ -6289,22 +6288,7 @@ no_such_table:
/* No point to init any statistics if tablespace is still encrypted. */
if (ib_table->is_readable()) {
trx_t* trx = check_trx_exists(thd);
bool alloc = !trx_state_eq(trx, TRX_STATE_NOT_STARTED);
if (alloc) {
trx = trx_allocate_for_background();
}
ut_ad(!trx->persistent_stats);
ut_d(trx->persistent_stats = true);
trx->error_state = DB_SUCCESS;
++trx->will_lock;
dict_stats_init(ib_table, trx);
innobase_commit_low(trx);
ut_d(trx->persistent_stats = false);
if (alloc) {
trx_free_for_background(trx);
}
dict_stats_init(ib_table);
} else {
ib_table->stat_initialized = 1;
}
@ -11972,7 +11956,7 @@ create_table_info_t::create_options_are_invalid()
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: invalid KEY_BLOCK_SIZE = %u."
" Valid values are [1, 2, 4, 8, 16]",
m_create_info->key_block_size);
(uint) m_create_info->key_block_size);
ret = "KEY_BLOCK_SIZE";
break;
}
@ -12421,7 +12405,7 @@ index_bad:
m_thd, Sql_condition::WARN_LEVEL_WARN,
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ignoring KEY_BLOCK_SIZE=%u.",
m_create_info->key_block_size);
(uint) m_create_info->key_block_size);
}
}
@ -12444,7 +12428,7 @@ index_bad:
ER_ILLEGAL_HA_CREATE_OPTION,
"InnoDB: ignoring KEY_BLOCK_SIZE=%u"
" unless ROW_FORMAT=COMPRESSED.",
m_create_info->key_block_size);
(uint) m_create_info->key_block_size);
zip_allowed = false;
}
} else {
@ -13070,10 +13054,7 @@ create_table_info_t::create_table_update_dict()
innobase_copy_frm_flags_from_create_info(innobase_table, m_create_info);
++m_trx->will_lock;
m_trx->error_state = DB_SUCCESS;
dict_stats_update(innobase_table, DICT_STATS_EMPTY_TABLE, m_trx);
innobase_commit_low(m_trx);
dict_stats_update(innobase_table, DICT_STATS_EMPTY_TABLE);
/* Load server stopword into FTS cache */
if (m_flags2 & DICT_TF2_FTS) {
@ -13330,8 +13311,7 @@ ha_innobase::discard_or_import_tablespace(
/* Adjust the persistent statistics. */
ret = dict_stats_update(dict_table,
DICT_STATS_RECALC_PERSISTENT,
m_prebuilt->trx);
DICT_STATS_RECALC_PERSISTENT);
if (ret != DB_SUCCESS) {
push_warning_printf(
@ -13339,11 +13319,8 @@ ha_innobase::discard_or_import_tablespace(
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Error updating stats for table '%s'"
" after table import: %s",
" after table rebuild: %s",
dict_table->name.m_name, ut_strerr(ret));
trx_rollback_to_savepoint(m_prebuilt->trx, NULL);
} else {
trx_commit_for_mysql(m_prebuilt->trx);
}
}
@ -13817,6 +13794,8 @@ ha_innobase::rename_table(
innobase_commit_low(trx);
trx_free_for_mysql(trx);
if (error == DB_SUCCESS) {
char norm_from[MAX_FULL_NAME_LEN];
char norm_to[MAX_FULL_NAME_LEN];
@ -13826,24 +13805,17 @@ ha_innobase::rename_table(
normalize_table_name(norm_from, from);
normalize_table_name(norm_to, to);
trx->error_state = DB_SUCCESS;
++trx->will_lock;
ret = dict_stats_rename_table(norm_from, norm_to,
errstr, sizeof errstr, trx);
errstr, sizeof(errstr));
if (ret != DB_SUCCESS) {
trx_rollback_to_savepoint(trx, NULL);
ib::error() << errstr;
push_warning(thd, Sql_condition::WARN_LEVEL_WARN,
ER_LOCK_WAIT_TIMEOUT, errstr);
} else {
innobase_commit_low(trx);
}
}
trx_free_for_mysql(trx);
/* Add a special case to handle the Duplicated Key error
and return DB_ERROR instead.
This is to avoid a possible SIGSEGV error from mysql error
@ -13984,7 +13956,8 @@ ha_innobase::records_in_range(
push_warning_printf(
ha_thd(), Sql_condition::WARN_LEVEL_WARN,
ER_NO_DEFAULT,
"btr_estimate_n_rows_in_range(): %f", n_rows);
"btr_estimate_n_rows_in_range(): %lld",
(longlong) n_rows);
);
func_exit:
@ -14380,34 +14353,18 @@ ha_innobase::info_low(
}
ut_ad(!mutex_own(&dict_sys->mutex));
/* Do not use prebuilt->trx in case this is
called in the middle of a transaction. We
should commit the transaction after
dict_stats_update() in order not to hog locks
on the mysql.innodb_table_stats,
mysql.innodb_index_stats tables. */
trx_t* trx = trx_allocate_for_background();
ut_d(trx->persistent_stats = true);
++trx->will_lock;
ret = dict_stats_update(ib_table, opt, trx);
ret = dict_stats_update(ib_table, opt);
if (ret != DB_SUCCESS) {
m_prebuilt->trx->op_info = "";
trx_rollback_to_savepoint(trx, NULL);
} else {
m_prebuilt->trx->op_info =
"returning various info to MySQL";
trx_commit_for_mysql(trx);
}
ut_d(trx->persistent_stats = false);
trx_free_for_background(trx);
if (ret != DB_SUCCESS) {
DBUG_RETURN(HA_ERR_GENERIC);
}
m_prebuilt->trx->op_info =
"returning various info to MariaDB";
}
stats.update_time = (ulong) ib_table->update_time;
}
@ -16565,7 +16522,7 @@ innodb_show_mutex_status(
DBUG_ASSERT(hton == innodb_hton_ptr);
mutex_monitor->iterate(collector);
mutex_monitor.iterate(collector);
if (!collector.to_string(hton, thd, stat_print)) {
DBUG_RETURN(1);
@ -17708,12 +17665,14 @@ innobase_commit_by_xid(
}
if (trx_t* trx = trx_get_trx_by_xid(xid)) {
TrxInInnoDB trx_in_innodb(trx);
innobase_commit_low(trx);
ut_ad(trx->mysql_thd == NULL);
ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE);
/* use cases are: disconnected xa, slave xa, recovery */
trx_deregister_from_2pc(trx);
{
TrxInInnoDB trx_in_innodb(trx);
innobase_commit_low(trx);
ut_ad(trx->mysql_thd == NULL);
trx_deregister_from_2pc(trx);
}
ut_ad(!trx->will_lock); /* trx cache requirement */
trx_free_for_background(trx);
@ -17742,12 +17701,14 @@ innobase_rollback_by_xid(
}
if (trx_t* trx = trx_get_trx_by_xid(xid)) {
TrxInInnoDB trx_in_innodb(trx);
int ret = innobase_rollback_trx(trx);
trx_deregister_from_2pc(trx);
ut_ad(!trx->will_lock);
int ret;
ut_ad(trx->in_innodb & TRX_FORCE_ROLLBACK_DISABLE);
{
TrxInInnoDB trx_in_innodb(trx);
ret = innobase_rollback_trx(trx);
trx_deregister_from_2pc(trx);
ut_ad(!trx->will_lock);
}
trx_free_for_background(trx);
return(ret);
@ -18453,7 +18414,7 @@ innodb_monitor_set_option(
if (MONITOR_IS_ON(MONITOR_LATCHES)) {
mutex_monitor->enable();
mutex_monitor.enable();
}
break;
@ -18468,7 +18429,7 @@ innodb_monitor_set_option(
if (!MONITOR_IS_ON(MONITOR_LATCHES)) {
mutex_monitor->disable();
mutex_monitor.disable();
}
break;
@ -18477,13 +18438,13 @@ innodb_monitor_set_option(
if (monitor_id == (MONITOR_LATCHES)) {
mutex_monitor->reset();
mutex_monitor.reset();
}
break;
case MONITOR_RESET_ALL_VALUE:
srv_mon_reset_all(monitor_id);
mutex_monitor->reset();
mutex_monitor.reset();
break;
default:
@ -22364,7 +22325,7 @@ ib_push_frm_error(
"installations? See "
REFMAN
"innodb-troubleshooting.html\n",
ib_table->name);
ib_table->name.m_name);
if (push_warning) {
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
@ -22408,7 +22369,7 @@ ib_push_frm_error(
"installations? See "
REFMAN
"innodb-troubleshooting.html\n",
ib_table->name, n_keys,
ib_table->name.m_name, n_keys,
table->s->keys);
if (push_warning) {

View file

@ -358,7 +358,7 @@ my_error_innodb(
break;
case DB_TOO_BIG_INDEX_COL:
my_error(ER_INDEX_COLUMN_TOO_LONG, MYF(0),
DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
(ulong) DICT_MAX_FIELD_LEN_BY_FORMAT_FLAG(flags));
break;
case DB_TOO_MANY_CONCURRENT_TRXS:
my_error(ER_TOO_MANY_CONCURRENT_TRXS, MYF(0));
@ -1799,7 +1799,7 @@ innobase_get_foreign_key_info(
/* Not possible to add a foreign key without a
referenced column */
mutex_exit(&dict_sys->mutex);
my_error(ER_CANNOT_ADD_FOREIGN, MYF(0), tbl_namep);
my_error(ER_CANNOT_ADD_FOREIGN, MYF(0));
goto err_exit;
}
@ -2199,7 +2199,8 @@ innobase_check_index_keys(
}
#endif /* MYSQL_RENAME_INDEX */
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key.name);
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0),
key.name);
return(ER_WRONG_NAME_FOR_INDEX);
}
@ -8841,27 +8842,29 @@ commit_cache_norebuild(
/** Adjust the persistent statistics after non-rebuilding ALTER TABLE.
Remove statistics for dropped indexes, add statistics for created indexes
and rename statistics for renamed indexes.
@param ha_alter_info Data used during in-place alter
@param ctx In-place ALTER TABLE context
@param table_name Table name in MySQL
@param trx transaction
@return error code */
@param ha_alter_info Data used during in-place alter
@param ctx In-place ALTER TABLE context
@param altered_table MySQL table that is being altered
@param table_name Table name in MySQL
@param thd MySQL connection
*/
static
dberr_t
void
alter_stats_norebuild(
/*==================*/
Alter_inplace_info* ha_alter_info,
ha_innobase_inplace_ctx* ctx,
TABLE* altered_table,
const char* table_name,
trx_t* trx)
THD* thd)
{
dberr_t err = DB_SUCCESS;
ulint i;
DBUG_ENTER("alter_stats_norebuild");
DBUG_ASSERT(!ctx->need_rebuild());
if (!dict_stats_is_persistent_enabled(ctx->new_table)) {
DBUG_RETURN(err);
DBUG_VOID_RETURN;
}
/* Delete corresponding rows from the stats table. We do this
@ -8890,13 +8893,10 @@ alter_stats_norebuild(
char errstr[1024];
dberr_t err2 = dict_stats_drop_index(
ctx->new_table->name.m_name, key->name.str,
errstr, sizeof errstr, trx);
if (err2 != DB_SUCCESS) {
err = err2;
push_warning(trx->mysql_thd,
if (dict_stats_drop_index(
ctx->new_table->name.m_name, key->name.str,
errstr, sizeof errstr) != DB_SUCCESS) {
push_warning(thd,
Sql_condition::WARN_LEVEL_WARN,
ER_LOCK_WAIT_TIMEOUT, errstr);
}
@ -8932,36 +8932,34 @@ alter_stats_norebuild(
DBUG_ASSERT(index->table == ctx->new_table);
if (!(index->type & DICT_FTS)) {
dict_stats_init(ctx->new_table, trx);
dberr_t err2 = dict_stats_update_for_index(index, trx);
if (err2 != DB_SUCCESS) {
err = err2;
}
dict_stats_init(ctx->new_table);
dict_stats_update_for_index(index);
}
}
DBUG_RETURN(err);
DBUG_VOID_RETURN;
}
/** Adjust the persistent statistics after rebuilding ALTER TABLE.
Remove statistics for dropped indexes, add statistics for created indexes
and rename statistics for renamed indexes.
@param table InnoDB table that was rebuilt by ALTER TABLE
@param table_name Table name in MySQL
@param trx transaction
@return error code */
@param table InnoDB table that was rebuilt by ALTER TABLE
@param table_name Table name in MySQL
@param thd MySQL connection
*/
static
dberr_t
void
alter_stats_rebuild(
/*================*/
dict_table_t* table,
const char* table_name,
trx_t* trx)
THD* thd)
{
DBUG_ENTER("alter_stats_rebuild");
if (dict_table_is_discarded(table)
|| !dict_stats_is_persistent_enabled(table)) {
DBUG_RETURN(DB_SUCCESS);
DBUG_VOID_RETURN;
}
#ifndef DBUG_OFF
@ -8974,24 +8972,7 @@ alter_stats_rebuild(
table->file_unreadable = true;
);
char errstr[1024];
mutex_enter(&dict_sys->mutex);
dberr_t ret = dict_stats_drop_table(table->name.m_name,
errstr, sizeof errstr, trx);
mutex_exit(&dict_sys->mutex);
if (ret != DB_SUCCESS) {
push_warning_printf(
trx->mysql_thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Deleting persistent statistics"
" for rebuilt table '%s' in"
" InnoDB failed: %s",
table_name, errstr);
DBUG_RETURN(ret);
}
ret = dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT, trx);
dberr_t ret = dict_stats_update(table, DICT_STATS_RECALC_PERSISTENT);
DBUG_EXECUTE_IF(
"ib_rename_index_fail2",
@ -9000,7 +8981,7 @@ alter_stats_rebuild(
if (ret != DB_SUCCESS) {
push_warning_printf(
trx->mysql_thd,
thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Error updating stats for table '%s'"
@ -9008,7 +8989,7 @@ alter_stats_rebuild(
table_name, ut_strerr(ret));
}
DBUG_RETURN(ret);
DBUG_VOID_RETURN;
}
#ifndef DBUG_OFF
@ -9322,36 +9303,6 @@ ha_innobase::commit_inplace_alter_table(
ctx->rollback_instant();
}
} else if (!new_clustered) {
if (ctx0->num_to_drop_vcol || ctx0->num_to_add_vcol) {
DBUG_ASSERT(ctx0->old_table->get_ref_count() == 1);
bool warned = false;
for (inplace_alter_handler_ctx** pctx = ctx_array;
*pctx; pctx++) {
ha_innobase_inplace_ctx* ctx
= static_cast<ha_innobase_inplace_ctx*>
(*pctx);
DBUG_ASSERT(!ctx->need_rebuild());
char errstr[1024];
if (dict_stats_drop_table(
ctx->old_table->name.m_name,
errstr, sizeof errstr, trx)
!= DB_SUCCESS && !warned) {
warned = true;
push_warning_printf(
m_user_thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Deleting persistent "
"statistics for table '%s' in"
" InnoDB failed: %s",
table_share->table_name.str,
errstr);
}
}
}
trx_commit_for_mysql(trx);
} else {
mtr_t mtr;
@ -9598,6 +9549,23 @@ foreign_fail:
m_prebuilt->table = dict_table_open_on_name(
tb_name, TRUE, TRUE, DICT_ERR_IGNORE_NONE);
/* Drop outdated table stats. */
char errstr[1024];
if (dict_stats_drop_table(
m_prebuilt->table->name.m_name,
errstr, sizeof(errstr))
!= DB_SUCCESS) {
push_warning_printf(
m_user_thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Deleting persistent statistics"
" for table '%s' in"
" InnoDB failed: %s",
table->s->table_name.str,
errstr);
}
row_mysql_unlock_data_dictionary(trx);
trx_free_for_mysql(trx);
MONITOR_ATOMIC_DEC(MONITOR_PENDING_ALTER_TABLE);
@ -9653,6 +9621,41 @@ foreign_fail:
}
#endif
if (new_clustered) {
/* Since the table has been rebuilt, we remove
all persistent statistics corresponding to the
old copy of the table (which was renamed to
ctx->tmp_name). */
char errstr[1024];
DBUG_ASSERT(0 == strcmp(ctx->old_table->name.m_name,
ctx->tmp_name));
DBUG_EXECUTE_IF(
"ib_rename_index_fail3",
DBUG_SET("+d,innodb_report_deadlock");
);
if (dict_stats_drop_table(
ctx->new_table->name.m_name,
errstr, sizeof(errstr))
!= DB_SUCCESS) {
push_warning_printf(
m_user_thd,
Sql_condition::WARN_LEVEL_WARN,
ER_ALTER_INFO,
"Deleting persistent statistics"
" for rebuilt table '%s' in"
" InnoDB failed: %s",
table->s->table_name.str,
errstr);
}
DBUG_EXECUTE_IF(
"ib_rename_index_fail3",
DBUG_SET("-d,innodb_report_deadlock");
);
DBUG_EXECUTE_IF("ib_ddl_crash_before_commit",
DBUG_SUICIDE(););
@ -9698,14 +9701,11 @@ foreign_fail:
}
row_mysql_unlock_data_dictionary(trx);
trx->error_state = DB_SUCCESS;
++trx->will_lock;
trx_free_for_mysql(trx);
/* TODO: The following code could be executed
while allowing concurrent access to the table
(MDL downgrade). */
trx->mysql_thd = m_user_thd;
dberr_t stats_err = DB_SUCCESS;
if (new_clustered) {
for (inplace_alter_handler_ctx** pctx = ctx_array;
@ -9714,11 +9714,10 @@ foreign_fail:
= static_cast<ha_innobase_inplace_ctx*>
(*pctx);
DBUG_ASSERT(ctx->need_rebuild());
stats_err = alter_stats_rebuild(
ctx->new_table, table->s->table_name.str, trx);
if (stats_err != DB_SUCCESS) {
break;
}
alter_stats_rebuild(
ctx->new_table, table->s->table_name.str,
m_user_thd);
DBUG_INJECT_CRASH("ib_commit_inplace_crash",
crash_inject_count++);
}
@ -9730,25 +9729,14 @@ foreign_fail:
(*pctx);
DBUG_ASSERT(!ctx->need_rebuild());
stats_err = alter_stats_norebuild(
ha_alter_info, ctx,
table->s->table_name.str, trx);
if (stats_err != DB_SUCCESS) {
break;
}
alter_stats_norebuild(
ha_alter_info, ctx, altered_table,
table->s->table_name.str, m_user_thd);
DBUG_INJECT_CRASH("ib_commit_inplace_crash",
crash_inject_count++);
}
}
if (stats_err != DB_SUCCESS) {
trx_rollback_to_savepoint(trx, NULL);
} else {
trx_commit_for_mysql(trx);
}
trx_free_for_mysql(trx);
innobase_parse_hint_from_comment(
m_user_thd, m_prebuilt->table, altered_table->s);

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2016, 2017, MariaDB Corporation.
Copyright (c) 2016, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -4494,7 +4494,7 @@ ibuf_merge_or_delete_for_page(
return;
}
space = fil_space_acquire(page_id.space());
space = fil_space_acquire_silent(page_id.space());
if (UNIV_UNLIKELY(!space)) {
/* Do not try to read the bitmap page from the

View file

@ -1,6 +1,6 @@
/*****************************************************************************
Copyright (c) 2016, 2017, MariaDB Corporation.
Copyright (c) 2016, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -66,24 +66,27 @@ dict_stats_defrag_pool_del(
all entries for the table */
const dict_index_t* index); /*!< in: index to remove */
/** Process indexes that have been scheduled for defragmenting.
@param[in,out] trx transaction that will be started and committed */
/*****************************************************************//**
Get the first index that has been added for updating persistent defrag
stats and eventually save its stats. */
void
dict_defrag_process_entries_from_defrag_pool(trx_t* trx);
dict_defrag_process_entries_from_defrag_pool();
/*===========================================*/
/** Save defragmentation result.
@param[in] index index that was defragmented
@param[in,out] trx transaction
/*********************************************************************//**
Save defragmentation result.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_save_defrag_summary(dict_index_t* index, trx_t* trx)
MY_ATTRIBUTE((nonnull, warn_unused_result));
dict_stats_save_defrag_summary(
/*============================*/
dict_index_t* index) /*!< in: index */
MY_ATTRIBUTE((warn_unused_result));
/** Save defragmentation stats for a given index.
@param[in] index index that is being defragmented
@param[in,out] trx transaction
/*********************************************************************//**
Save defragmentation stats for a given index.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_save_defrag_stats(dict_index_t* index, trx_t* trx)
MY_ATTRIBUTE((nonnull, warn_unused_result));
dict_stats_save_defrag_stats(
/*============================*/
dict_index_t* index); /*!< in: index */
#endif /* dict0defrag_bg_h */

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2009, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -92,12 +92,13 @@ bool
dict_stats_auto_recalc_is_enabled(const dict_table_t* table)
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Initialize table statistics for the first time when opening a table.
@param[in,out] table freshly opened table
@param[in,out] trx transaction */
/*********************************************************************//**
Initialize table's stats for the first time when opening a table. */
UNIV_INLINE
void
dict_stats_init(dict_table_t* table, trx_t* trx);
dict_stats_init(
/*============*/
dict_table_t* table); /*!< in/out: table */
/*********************************************************************//**
Deinitialize table's stats after the last close of the table. This is
@ -116,68 +117,67 @@ void
dict_stats_update_if_needed(dict_table_t* table)
MY_ATTRIBUTE((nonnull));
/** Calculate new estimates for table and index statistics.
@param[in,out] table table
@param[in] stats_upd_option how to update statistics
@param[in,out] trx transaction
/*********************************************************************//**
Calculates new estimates for table and index statistics. The statistics
are used in query optimization.
@return DB_* error code or DB_SUCCESS */
dberr_t
dict_stats_update(
dict_table_t* table,
dict_stats_upd_option_t stats_upd_option,
trx_t* trx);
/*==============*/
dict_table_t* table, /*!< in/out: table */
dict_stats_upd_option_t stats_upd_option);
/*!< in: whether to (re) calc
the stats or to fetch them from
the persistent storage */
/** Remove the persistent statistics for an index.
@param[in] db_and_table schema and table name, e.g., 'db/table'
@param[in] iname index name
@param[out] errstr error message (when not returning DB_SUCCESS)
@param[in] errstr_sz sizeof errstr
@param[in,out] trx transaction
/*********************************************************************//**
Removes the information for a particular index's stats from the persistent
storage if it exists and if there is data stored for this index.
This function creates its own trx and commits it.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_drop_index(
const char* db_and_table,
const char* iname,
char* errstr,
size_t errstr_sz,
trx_t* trx);
/*==================*/
const char* tname, /*!< in: table name */
const char* iname, /*!< in: index name */
char* errstr, /*!< out: error message if != DB_SUCCESS
is returned */
ulint errstr_sz);/*!< in: size of the errstr buffer */
/** Remove the persistent statistics for a table and all of its indexes.
@param[in] db_and_table schema and table name, e.g., 'db/table'
@param[out] errstr error message (when not returning DB_SUCCESS)
@param[in] errstr_sz sizeof errstr
@param[in,out] trx transaction
/*********************************************************************//**
Removes the statistics for a table and all of its indexes from the
persistent storage if it exists and if there is data stored for the table.
This function creates its own transaction and commits it.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_drop_table(
const char* db_and_table,
char* errstr,
size_t errstr_sz,
trx_t* trx);
/*==================*/
const char* table_name, /*!< in: table name */
char* errstr, /*!< out: error message
if != DB_SUCCESS is returned */
ulint errstr_sz); /*!< in: size of errstr buffer */
/** Calculate index statistics.
@param[in,out] index index tree
@param[in,out] trx transaction (for persistent statistics)
@return DB_SUCCESS or error code */
UNIV_INTERN
dberr_t
dict_stats_update_for_index(dict_index_t* index, trx_t* trx)
/*********************************************************************//**
Fetches or calculates new estimates for index statistics. */
void
dict_stats_update_for_index(
/*========================*/
dict_index_t* index) /*!< in/out: index */
MY_ATTRIBUTE((nonnull));
/** Rename a table in the InnoDB persistent statistics storage.
@param[in] old_name old schema and table name, e.g., 'db/table'
@param[in] new_name new schema and table name, e.g., 'db/table'
@param[out] errstr error message (when not returning DB_SUCCESS)
@param[in] errstr_sz sizeof errstr
@param[in,out] trx transaction
/*********************************************************************//**
Renames a table in InnoDB persistent stats storage.
This function creates its own transaction and commits it.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_rename_table(
const char* old_name,
const char* new_name,
char* errstr,
size_t errstr_sz,
trx_t* trx);
/*====================*/
const char* old_name, /*!< in: old table name */
const char* new_name, /*!< in: new table name */
char* errstr, /*!< out: error string if != DB_SUCCESS
is returned */
size_t errstr_sz); /*!< in: errstr size */
#ifdef MYSQL_RENAME_INDEX
/*********************************************************************//**
Renames an index in InnoDB persistent stats storage.
This function creates its own transaction and commits it.
@ -191,13 +191,7 @@ dict_stats_rename_index(
const char* old_index_name, /*!< in: old index name */
const char* new_index_name) /*!< in: new index name */
__attribute__((warn_unused_result));
/** Reset the table and index statsistics, corresponding to an empty table.
@param[in,out] table table whose statistics are to be reset
@param[in] empty_defrag_stats whether to empty the defrag statistics
*/
void
dict_stats_empty_table(dict_table_t* table, bool empty_defrag_stats = true);
#endif /* MYSQL_RENAME_INDEX */
/** Save an individual index's statistic into the persistent statistics
storage.
@ -207,7 +201,9 @@ storage.
@param[in] stat_value value of the stat
@param[in] sample_size n pages sampled or NULL
@param[in] stat_description description of the stat
@param[in,out] trx dictionary transaction
@param[in,out] trx in case of NULL the function will
allocate and free the trx object. If it is not NULL then it will be
rolled back only in the case of error, but not freed.
@return DB_SUCCESS or error code */
dberr_t
dict_stats_save_index_stat(
@ -217,8 +213,7 @@ dict_stats_save_index_stat(
ib_uint64_t stat_value,
ib_uint64_t* sample_size,
const char* stat_description,
trx_t* trx)
MY_ATTRIBUTE((nonnull(1,3,7), warn_unused_result));
trx_t* trx);
/** Report an error if updating table statistics failed because
.ibd file is missing, table decryption failed or table is corrupted.

View file

@ -141,12 +141,13 @@ dict_stats_auto_recalc_is_enabled(const dict_table_t* table)
}
}
/** Initialize table statistics for the first time when opening a table.
@param[in,out] table freshly opened table
@param[in,out] trx transaction */
/*********************************************************************//**
Initialize table's stats for the first time when opening a table. */
UNIV_INLINE
void
dict_stats_init(dict_table_t* table, trx_t* trx)
dict_stats_init(
/*============*/
dict_table_t* table) /*!< in/out: table */
{
ut_ad(!mutex_own(&dict_sys->mutex));
@ -162,7 +163,7 @@ dict_stats_init(dict_table_t* table, trx_t* trx)
opt = DICT_STATS_RECALC_TRANSIENT;
}
dict_stats_update(table, opt, trx);
dict_stats_update(table, opt);
}
/*********************************************************************//**

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2013, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -454,14 +454,7 @@ public:
void destroy()
UNIV_NOTHROW
{
latch_meta_t& meta = sync_latch_get_meta(m_id);
ut_ad(meta.get_id() == m_id);
meta.get_counter()->sum_deregister(m_count);
m_count = NULL;
ut_d(MutexDebug<MutexType>::destroy());
}

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2018, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
@ -638,14 +638,6 @@ public:
return(count);
}
/** Deregister the count. We don't do anything
@param[in] count The count instance to deregister */
void sum_deregister(Count* count)
UNIV_NOTHROW
{
/* Do nothing */
}
/** Register a single instance counter */
void single_register(Count* count)
UNIV_NOTHROW

View file

@ -1109,9 +1109,6 @@ public:
mysql_trx_list; /*!< list of transactions created for
MySQL; protected by trx_sys.mutex */
#ifdef UNIV_DEBUG
/** whether this transaction is updating persistent statistics
(used for silencing a debug assertion at shutdown) */
bool persistent_stats;
bool in_mysql_trx_list;
/*!< true if in
trx_sys.mysql_trx_list */

View file

@ -164,7 +164,7 @@ public:
};
/** Defined in sync0sync.cc */
extern MutexMonitor* mutex_monitor;
extern MutexMonitor mutex_monitor;
/**
Creates, or rather, initializes a mutex object in a specified memory

View file

@ -1632,7 +1632,18 @@ RecLock::prepare() const
ut_error;
}
ut_ad(trx_get_dict_operation(m_trx) == TRX_DICT_OP_NONE);
switch (trx_get_dict_operation(m_trx)) {
case TRX_DICT_OP_NONE:
break;
case TRX_DICT_OP_TABLE:
case TRX_DICT_OP_INDEX:
ib::error() << "A record lock wait happens in a dictionary"
" operation. index " << m_index->name
<< " of table " << m_index->table->name
<< ". " << BUG_REPORT_MSG;
ut_ad(0);
}
ut_ad(m_index->table->n_ref_count > 0
|| !m_index->table->can_be_evicted);
}
@ -2200,24 +2211,6 @@ RecLock::add_to_waitq(lock_t* wait_for, const lock_prdt_t* prdt)
/* Do the preliminary checks, and set query thread state */
switch (UNIV_EXPECT(trx_get_dict_operation(m_trx), TRX_DICT_OP_NONE)) {
case TRX_DICT_OP_NONE:
break;
case TRX_DICT_OP_TABLE:
case TRX_DICT_OP_INDEX:
ut_ad(!prdt);
if (m_trx->dict_operation_lock_mode != RW_X_LATCH) {
} else if (!strcmp(m_index->table->name.m_name,
"mysql/innodb_table_stats")
|| !strcmp(m_index->table->name.m_name,
"mysql/innodb_index_stats")) {
/* Statistics can be updated as part of a DDL
transaction, but only as the very last operation. */
return(DB_QUE_THR_SUSPENDED);
}
}
prepare();
bool high_priority = trx_is_high_priority(m_trx);
@ -4645,16 +4638,6 @@ lock_table_enqueue_waiting(
break;
case TRX_DICT_OP_TABLE:
case TRX_DICT_OP_INDEX:
if (trx->dict_operation_lock_mode != RW_X_LATCH) {
} else if (!strcmp(table->name.m_name,
"mysql/innodb_table_stats")
|| !strcmp(table->name.m_name,
"mysql/innodb_index_stats")) {
/* Statistics can be updated as part of a DDL
transaction, but only as the very last operation. */
return(DB_QUE_THR_SUSPENDED);
}
ib::error() << "A table lock wait happens in a dictionary"
" operation. Table " << table->name
<< ". " << BUG_REPORT_MSG;

View file

@ -2483,7 +2483,7 @@ row_import_cfg_read_index_fields(
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading index fields.");
return(DB_IO_ERROR);
@ -2519,7 +2519,7 @@ row_import_cfg_read_index_fields(
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while parsing table name.");
return(err);
@ -2589,7 +2589,7 @@ row_import_read_index_data(
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno), msg);
(ulong) errno, strerror(errno), msg);
ib::error() << "IO Error: " << msg;
@ -2664,7 +2664,7 @@ row_import_read_index_data(
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while parsing index name.");
return(err);
@ -2703,7 +2703,7 @@ row_import_read_indexes(
if (fread(row, 1, sizeof(row), file) != sizeof(row)) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading number of indexes.");
return(DB_IO_ERROR);
@ -2789,7 +2789,7 @@ row_import_read_columns(
if (fread(row, 1, sizeof(row), file) != sizeof(row)) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading table column meta-data.");
return(DB_IO_ERROR);
@ -2853,7 +2853,7 @@ row_import_read_columns(
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while parsing table column name.");
return(err);
@ -2884,7 +2884,7 @@ row_import_read_v1(
if (fread(value, 1, sizeof(value), file) != sizeof(value)) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading meta-data export hostname length.");
return(DB_IO_ERROR);
@ -2912,7 +2912,7 @@ row_import_read_v1(
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while parsing export hostname.");
return(err);
@ -2926,7 +2926,7 @@ row_import_read_v1(
if (fread(value, 1, sizeof(value), file) != sizeof(value)) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading meta-data table name length.");
return(DB_IO_ERROR);
@ -2953,7 +2953,7 @@ row_import_read_v1(
if (err != DB_SUCCESS) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while parsing table name.");
return(err);
@ -2972,7 +2972,7 @@ row_import_read_v1(
if (fread(row, 1, sizeof(ib_uint64_t), file) != sizeof(ib_uint64_t)) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading autoinc value.");
return(DB_IO_ERROR);
@ -2988,7 +2988,7 @@ row_import_read_v1(
if (fread(row, 1, sizeof(row), file) != sizeof(row)) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading meta-data header.");
return(DB_IO_ERROR);
@ -3059,7 +3059,7 @@ row_import_read_meta_data(
if (fread(&row, 1, sizeof(row), file) != sizeof(row)) {
ib_senderrf(
thd, IB_LOG_LEVEL_ERROR, ER_IO_READ_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while reading meta-data version.");
return(DB_IO_ERROR);
@ -3110,7 +3110,7 @@ row_import_read_cfg(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_READ_ERROR,
errno, strerror(errno), msg);
(ulong) errno, strerror(errno), msg);
cfg.m_missing = true;

View file

@ -4771,8 +4771,8 @@ row_merge_build_indexes(
"Table %s is encrypted but encryption service or"
" used key_id is not available. "
" Can't continue reading table.",
!old_table->is_readable() ? old_table->name :
new_table->name);
!old_table->is_readable() ? old_table->name.m_name :
new_table->name.m_name);
goto func_exit;
}

View file

@ -3463,9 +3463,31 @@ run_again:
que_thr_stop_for_mysql_no_error(thr, trx);
} else {
que_thr_stop_for_mysql(thr);
ut_ad(err != DB_QUE_THR_SUSPENDED);
if (row_mysql_handle_errors(&err, trx, thr, NULL)) {
if (err != DB_QUE_THR_SUSPENDED) {
ibool was_lock_wait;
was_lock_wait = row_mysql_handle_errors(
&err, trx, thr, NULL);
if (was_lock_wait) {
goto run_again;
}
} else {
que_thr_t* run_thr;
que_node_t* parent;
parent = que_node_get_parent(thr);
run_thr = que_fork_start_command(
static_cast<que_fork_t*>(parent));
ut_a(run_thr == thr);
/* There was a lock wait but the thread was not
in a ready to run or running state. */
trx->error_state = DB_LOCK_WAIT;
goto run_again;
}
}
@ -3743,6 +3765,7 @@ row_drop_table_for_mysql(
if (!dict_table_is_temporary(table) && !table->no_rollback()) {
dict_stats_recalc_pool_del(table);
dict_stats_defrag_pool_del(table, NULL);
if (btr_defragment_thread_active) {
/* During fts_drop_orphaned_tables() in
@ -3751,6 +3774,17 @@ row_drop_table_for_mysql(
initialized by btr_defragment_init(). */
btr_defragment_remove_table(table);
}
/* Remove stats for this table and all of its indexes from the
persistent storage if it exists and if there are stats for this
table in there. This function creates its own trx and commits
it. */
char errstr[1024];
err = dict_stats_drop_table(name, errstr, sizeof(errstr));
if (err != DB_SUCCESS) {
ib::warn() << errstr;
}
}
dict_table_prevent_eviction(table);
@ -4047,12 +4081,6 @@ defer:
ut_ad(!dict_table_is_temporary(table));
if (!table->no_rollback()) {
char errstr[1024];
if (dict_stats_drop_table(name, errstr, sizeof errstr,
trx) != DB_SUCCESS) {
ib::warn() << errstr;
}
err = row_drop_ancillary_fts_tables(table, trx);
if (err != DB_SUCCESS) {
break;

View file

@ -67,7 +67,7 @@ row_quiesce_write_index_fields(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing index fields.");
return(DB_IO_ERROR);
@ -87,7 +87,7 @@ row_quiesce_write_index_fields(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing index column.");
return(DB_IO_ERROR);
@ -121,7 +121,7 @@ row_quiesce_write_indexes(
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing index count.");
return(DB_IO_ERROR);
@ -175,7 +175,7 @@ row_quiesce_write_indexes(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing index meta-data.");
return(DB_IO_ERROR);
@ -196,7 +196,7 @@ row_quiesce_write_indexes(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing index name.");
return(DB_IO_ERROR);
@ -256,7 +256,7 @@ row_quiesce_write_table(
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing table column data.");
return(DB_IO_ERROR);
@ -283,7 +283,7 @@ row_quiesce_write_table(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing column name.");
return(DB_IO_ERROR);
@ -315,7 +315,7 @@ row_quiesce_write_header(
if (fwrite(&value, 1, sizeof(value), file) != sizeof(value)) {
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing meta-data version number.");
return(DB_IO_ERROR);
@ -345,7 +345,7 @@ row_quiesce_write_header(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing hostname.");
return(DB_IO_ERROR);
@ -365,7 +365,7 @@ row_quiesce_write_header(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing table name.");
return(DB_IO_ERROR);
@ -381,7 +381,7 @@ row_quiesce_write_header(
if (fwrite(row, 1, sizeof(ib_uint64_t), file) != sizeof(ib_uint64_t)) {
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing table autoinc value.");
return(DB_IO_ERROR);
@ -405,7 +405,7 @@ row_quiesce_write_header(
if (fwrite(row, 1, sizeof(row), file) != sizeof(row)) {
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno),
(ulong) errno, strerror(errno),
"while writing table meta-data.");
return(DB_IO_ERROR);
@ -458,7 +458,7 @@ row_quiesce_write_cfg(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno), msg);
(ulong) errno, strerror(errno), msg);
}
if (fclose(file) != 0) {
@ -468,7 +468,7 @@ row_quiesce_write_cfg(
ib_senderrf(
thd, IB_LOG_LEVEL_WARN, ER_IO_WRITE_ERROR,
errno, strerror(errno), msg);
(ulong) errno, strerror(errno), msg);
}
}

View file

@ -1271,6 +1271,10 @@ row_truncate_complete(
}
}
if (err == DB_SUCCESS) {
dict_stats_update(table, DICT_STATS_EMPTY_TABLE);
}
trx->op_info = "";
/* For temporary tables or if there was an error, we need to reset
@ -2098,17 +2102,8 @@ row_truncate_table_for_mysql(
dict_table_autoinc_unlock(table);
if (trx_is_started(trx)) {
char errstr[1024];
if (dict_stats_drop_table(table->name.m_name, errstr,
sizeof errstr, trx) != DB_SUCCESS) {
ib::warn() << "Deleting persistent "
"statistics for table " << table->name
<< " failed: " << errstr;
}
trx_commit_for_mysql(trx);
dict_stats_empty_table(table);
}
ut_ad(!table->is_instant());

View file

@ -1,7 +1,7 @@
/*****************************************************************************
Copyright (c) 2014, 2016, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, MariaDB Corporation.
Copyright (c) 2017, 2018, MariaDB Corporation.
Portions of this file contain modifications contributed and copyrighted by
Google, Inc. Those modifications are gratefully acknowledged and are described
@ -1700,7 +1700,7 @@ private:
};
/** Track latch creation location. For reducing the size of the latches */
static CreateTracker* create_tracker;
static CreateTracker create_tracker;
/** Register a latch, called when it is created
@param[in] ptr Latch instance that was created
@ -1712,7 +1712,7 @@ sync_file_created_register(
const char* filename,
uint16_t line)
{
create_tracker->register_latch(ptr, filename, line);
create_tracker.register_latch(ptr, filename, line);
}
/** Deregister a latch, called when it is destroyed
@ -1720,7 +1720,7 @@ sync_file_created_register(
void
sync_file_created_deregister(const void* ptr)
{
create_tracker->deregister_latch(ptr);
create_tracker.deregister_latch(ptr);
}
/** Get the string where the file was created. Its format is "name:line"
@ -1729,7 +1729,7 @@ sync_file_created_deregister(const void* ptr)
std::string
sync_file_created_get(const void* ptr)
{
return(create_tracker->get(ptr));
return(create_tracker.get(ptr));
}
/** Initializes the synchronization data structures. */
@ -1739,12 +1739,6 @@ sync_check_init()
ut_ad(!LatchDebug::s_initialized);
ut_d(LatchDebug::s_initialized = true);
/** For collecting latch statistic - SHOW ... MUTEX */
mutex_monitor = UT_NEW_NOKEY(MutexMonitor());
/** For trcking mutex creation location */
create_tracker = UT_NEW_NOKEY(CreateTracker());
sync_latch_meta_init();
/* Init the rw-lock & mutex list and create the mutex to protect it. */
@ -1768,14 +1762,6 @@ sync_check_close()
sync_array_close();
UT_DELETE(mutex_monitor);
mutex_monitor = NULL;
UT_DELETE(create_tracker);
create_tracker = NULL;
sync_latch_meta_destroy();
}

View file

@ -118,7 +118,7 @@ mysql_pfs_key_t trx_purge_latch_key;
#endif /* UNIV_PFS_RWLOCK */
/** For monitoring active mutexes */
MutexMonitor* mutex_monitor;
MutexMonitor mutex_monitor;
/**
Prints wait info of the sync system.

View file

@ -305,7 +305,7 @@ trx_purge_add_undo_to_history(const trx_t* trx, trx_undo_t*& undo, mtr_t* mtr)
|| (srv_force_recovery >= SRV_FORCE_NO_BACKGROUND
&& purge_sys->state == PURGE_STATE_DISABLED)
|| ((trx->undo_no == 0 || trx->in_mysql_trx_list
|| trx->persistent_stats)
|| trx->internal)
&& srv_fast_shutdown));
/* Add the log as the first in the history list */

View file

@ -571,7 +571,7 @@ trx_validate_state_before_free(trx_t* trx)
ut_ad(!trx->declared_to_be_inside_innodb);
ut_ad(!trx->n_mysql_tables_in_use);
ut_ad(!trx->mysql_n_tables_locked);
ut_ad(!trx->persistent_stats);
ut_ad(!trx->internal);
if (trx->declared_to_be_inside_innodb) {
@ -901,10 +901,12 @@ trx_lists_init_at_db_start()
purge_sys = UT_NEW_NOKEY(purge_sys_t());
if (srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) {
trx_rseg_array_init();
if (srv_force_recovery >= SRV_FORCE_NO_UNDO_LOG_SCAN) {
return;
}
trx_rseg_array_init();
/* Look from the rollback segments if there exist undo logs for
transactions. */
const ib_time_t start_time = ut_time();
@ -913,8 +915,9 @@ trx_lists_init_at_db_start()
trx_undo_t* undo;
trx_rseg_t* rseg = trx_sys.rseg_array[i];
/* At this stage non-redo rseg slots are all NULL as they are
re-created on server start and existing slots are not read. */
/* Some rollback segment may be unavailable,
especially if the server was previously run with a
non-default value of innodb_undo_logs. */
if (rseg == NULL) {
continue;
}

View file

@ -70,7 +70,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
myf create_flag;
uint length,max_key_length,packed,pack_bytes,pointer,real_length_diff,
key_length,info_length,key_segs,options,min_key_length,
base_pos,long_varchar_count,varchar_length,
base_pos,long_varchar_count,
unique_key_parts,fulltext_keys,offset, not_block_record_extra_length;
uint max_field_lengths, extra_header_size, column_nr;
uint internal_table= flags & HA_CREATE_INTERNAL_TABLE;
@ -144,9 +144,6 @@ int maria_create(const char *name, enum data_file_type datafile_type,
datafile_type= BLOCK_RECORD;
}
if (ci->reloc_rows > ci->max_rows)
ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */
if (!(rec_per_key_part=
(double*) my_malloc((keys + uniques)*HA_MAX_KEY_SEG*sizeof(double) +
(keys + uniques)*HA_MAX_KEY_SEG*sizeof(ulong) +
@ -160,7 +157,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
/* Start by checking fields and field-types used */
varchar_length=long_varchar_count=packed= not_block_record_extra_length=
long_varchar_count=packed= not_block_record_extra_length=
pack_reclength= max_field_lengths= 0;
reclength= min_pack_length= ci->null_bytes;
forced_packed= 0;
@ -232,7 +229,6 @@ int maria_create(const char *name, enum data_file_type datafile_type,
}
else if (type == FIELD_VARCHAR)
{
varchar_length+= column->length-1; /* Used for min_pack_length */
pack_reclength++;
not_block_record_extra_length++;
max_field_lengths++;
@ -368,6 +364,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
pack_bytes);
if (!ci->data_file_length && ci->max_rows)
{
set_if_bigger(ci->max_rows, ci->reloc_rows);
if (pack_reclength == INT_MAX32 ||
(~(ulonglong) 0)/ci->max_rows < (ulonglong) pack_reclength)
ci->data_file_length= ~(ulonglong) 0;
@ -401,13 +398,14 @@ int maria_create(const char *name, enum data_file_type datafile_type,
else
ci->max_rows= data_file_length / (min_pack_length +
extra_header_size +
DIR_ENTRY_SIZE)+1;
DIR_ENTRY_SIZE);
}
else
ci->max_rows=(ha_rows) (ci->data_file_length/(min_pack_length +
((options &
HA_OPTION_PACK_RECORD) ?
3 : 0)))+1;
3 : 0)));
set_if_smaller(ci->reloc_rows, ci->max_rows);
}
max_rows= (ulonglong) ci->max_rows;
if (datafile_type == BLOCK_RECORD)
@ -800,6 +798,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
share.state.state.data_file_length= maria_block_size;
/* Add length of packed fields + length */
share.base.pack_reclength+= share.base.max_field_lengths+3;
share.base.max_pack_length= share.base.pack_reclength;
/* Adjust max_pack_length, to be used if we have short rows */
if (share.base.max_pack_length < maria_block_size)