diff --git a/mysql-test/r/bug117426.result b/mysql-test/r/bug117426.result new file mode 100644 index 00000000000..a2612a9a503 --- /dev/null +++ b/mysql-test/r/bug117426.result @@ -0,0 +1,69 @@ +# +# 1) Prepare +# +CREATE DATABASE my_test; +USE my_test; +CREATE TABLE `t1` ( +`id` int NOT NULL AUTO_INCREMENT, +`k` int NOT NULL DEFAULT '0', +`c` char(120) NOT NULL DEFAULT '', +`pad` char(60) NOT NULL DEFAULT '', +PRIMARY KEY (`id`), +KEY `k_1` (`k`) +); +CREATE TABLE `t2` LIKE `t1`; +ALTER TABLE `t2` PARTITION BY RANGE(id) ( +PARTITION `p0` VALUES LESS THAN (5001), +PARTITION `p1` VALUES LESS THAN (10001) +); +CREATE PROCEDURE insert_into_tables(IN num INTEGER) +BEGIN +DECLARE x INT; +SET x = 1; +while x < num do +INSERT INTO `t1` (`k`, `c`, `pad`) VALUES (6666666, REPEAT('rds', 40), REPEAT('mysql', 12)); +SET x = x + 1; +END while; +END$$ +CALL insert_into_tables(5001); +INSERT INTO `t1` (`k`, `c`, `pad`) SELECT `k`, `c`, `pad` FROM `t1`; +INSERT INTO `t2` (`k`, `c`, `pad`) SELECT `k`, `c`, `pad` FROM `t1`; +# +# 2) SHOW TABLE STATUS +# +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't1'; +DATA_FREE +4194304 +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't2'; +DATA_FREE +8388608 +# +# 3) OPTIMIZE and SHOW TABLE STATUS +# +OPTIMIZE TABLE `t1`; +Table Op Msg_type Msg_text +my_test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +my_test.t1 optimize status OK +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't1'; +DATA_FREE +2097152 +ALTER TABLE `t2` OPTIMIZE PARTITION `p0`; +Table Op Msg_type Msg_text +my_test.t2 optimize note Table does not support optimize on partitions. All partitions will be rebuilt and analyzed. +my_test.t2 optimize status OK +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't2'; +DATA_FREE +4194304 +# +# 4) Simulate update failed +# +SET DEBUG = "+d, simulate_update_failed"; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +my_test.t1 optimize note Table does not support optimize, doing recreate + analyze instead +my_test.t1 optimize status Unable to write table statistics to DD tables +SET DEBUG = "-d, simulate_update_failed"; +# +# 5) Cleanup +# +DROP DATABASE my_test; diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index d435a29994a..fc48d2855d3 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -1835,10 +1835,10 @@ variable_value {checked_valid} SELECT sum(variable_value) - @innodb_rows_deleted_orig FROM performance_schema.global_status WHERE LOWER(variable_name) like 'innodb%_rows_deleted'; sum(variable_value) - @innodb_rows_deleted_orig -1830 +1833 SELECT sum(variable_value) - @innodb_rows_inserted_orig FROM performance_schema.global_status WHERE LOWER(variable_name) like 'innodb%_rows_inserted'; sum(variable_value) - @innodb_rows_inserted_orig -2733 +2736 SELECT sum(variable_value) - @innodb_rows_updated_orig FROM performance_schema.global_status WHERE LOWER(variable_name) like 'innodb%_rows_updated'; sum(variable_value) - @innodb_rows_updated_orig 2635 diff --git a/mysql-test/t/bug117426.test b/mysql-test/t/bug117426.test new file mode 100644 index 00000000000..2b5a7bd0180 --- /dev/null +++ b/mysql-test/t/bug117426.test @@ -0,0 +1,69 @@ +--source include/have_binlog_format_row.inc +--source include/have_debug.inc + +--echo # +--echo # 1) Prepare +--echo # +CREATE DATABASE my_test; +USE my_test; + +CREATE TABLE `t1` ( + `id` int NOT NULL AUTO_INCREMENT, + `k` int NOT NULL DEFAULT '0', + `c` char(120) NOT NULL DEFAULT '', + `pad` char(60) NOT NULL DEFAULT '', + PRIMARY KEY (`id`), + KEY `k_1` (`k`) +); + +CREATE TABLE `t2` LIKE `t1`; +ALTER TABLE `t2` PARTITION BY RANGE(id) ( + PARTITION `p0` VALUES LESS THAN (5001), + PARTITION `p1` VALUES LESS THAN (10001) +); + +DELIMITER $$; +CREATE PROCEDURE insert_into_tables(IN num INTEGER) + BEGIN + DECLARE x INT; + SET x = 1; + while x < num do + INSERT INTO `t1` (`k`, `c`, `pad`) VALUES (6666666, REPEAT('rds', 40), REPEAT('mysql', 12)); + SET x = x + 1; + END while; +END$$ +DELIMITER ;$$ + +CALL insert_into_tables(5001); +INSERT INTO `t1` (`k`, `c`, `pad`) SELECT `k`, `c`, `pad` FROM `t1`; +INSERT INTO `t2` (`k`, `c`, `pad`) SELECT `k`, `c`, `pad` FROM `t1`; + + +--echo # +--echo # 2) SHOW TABLE STATUS +--echo # +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't1'; +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't2'; + + +--echo # +--echo # 3) OPTIMIZE and SHOW TABLE STATUS +--echo # +OPTIMIZE TABLE `t1`; +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't1'; +ALTER TABLE `t2` OPTIMIZE PARTITION `p0`; +SELECT DATA_FREE FROM information_schema.tables WHERE TABLE_NAME = 't2'; + + +--echo # +--echo # 4) Simulate update failed +--echo # +SET DEBUG = "+d, simulate_update_failed"; +OPTIMIZE TABLE t1; +SET DEBUG = "-d, simulate_update_failed"; + + +--echo # +--echo # 5) Cleanup +--echo # +DROP DATABASE my_test; \ No newline at end of file diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 953d9564ea1..0522172017c 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1328,6 +1328,17 @@ static bool mysql_admin_table( */ alter_info->flags &= ~(Alter_info::ALTER_ADMIN_PARTITION); result_code = table->table->file->ha_analyze(thd, check_opt); + + if (dd::info_schema::update_table_stats(thd, table) || + dd::info_schema::update_index_stats(thd, table) || + DBUG_EVALUATE_IF("simulate_update_failed", true, false)) { + // Play safe, rollback possible changes to the data-dictionary. + trans_rollback_stmt(thd); + trans_rollback_implicit(thd); + result_code = HA_ADMIN_STATS_UPD_ERR; + goto send_result; + } + if (result_code == HA_ADMIN_ALREADY_DONE) result_code = HA_ADMIN_OK; else if (result_code) // analyze failed