--source include/have_innodb.inc --source include/have_sequence.inc SET @saved_include_delete_marked = @@GLOBAL.innodb_stats_include_delete_marked; SET GLOBAL innodb_stats_include_delete_marked = ON; SET @saved_traditional = @@GLOBAL.innodb_stats_traditional; SET GLOBAL innodb_stats_traditional=false; SET @saved_modified_counter = @@GLOBAL.innodb_stats_modified_counter; SET GLOBAL innodb_stats_modified_counter=1; CREATE TABLE t1 (id SERIAL, val INT UNSIGNED NOT NULL, KEY(val)) ENGINE=INNODB STATS_PERSISTENT=1,STATS_AUTO_RECALC=1; CREATE TABLE t2 LIKE t1; INSERT INTO t1 (val) SELECT 4 FROM seq_1_to_16; SET STATEMENT use_stat_tables=never FOR ANALYZE TABLE t1; connect(con1, localhost, root,,); START TRANSACTION; DELETE FROM t1; send SELECT COUNT(*) FROM t1; connection default; --echo # With innodb_stats_include_delete_marked=ON, --echo # DELETE must not affect statistics before COMMIT. EXPLAIN SELECT * FROM t1 WHERE val=4; connection con1; reap; ROLLBACK; SELECT COUNT(*) FROM t1; EXPLAIN SELECT * FROM t1 WHERE val=4; BEGIN; DELETE FROM t1; COMMIT; SELECT COUNT(*) FROM t1; connection default; BEGIN; INSERT INTO t2 (val) SELECT 4 FROM seq_1_to_16; --echo # The INSERT will show up before COMMIT. EXPLAIN SELECT * FROM t2 WHERE val=4; SELECT COUNT(*) FROM t2; --echo # The ROLLBACK of the INSERT must affect the statistics. ROLLBACK; SELECT COUNT(*) FROM t2; connection con1; EXPLAIN SELECT * FROM t2 WHERE val=4; SET GLOBAL innodb_max_purge_lag_wait=0; --echo # After COMMIT and purge, the DELETE must show up. EXPLAIN SELECT * FROM t1 WHERE val=4; SET GLOBAL innodb_stats_include_delete_marked = OFF; BEGIN; INSERT INTO t1 (val) SELECT 4 FROM seq_1_to_16; EXPLAIN SELECT * FROM t1 WHERE val=4; ROLLBACK; EXPLAIN SELECT * FROM t1 WHERE val=4; BEGIN; INSERT INTO t1 (val) SELECT 4 FROM seq_1_to_16; COMMIT; EXPLAIN SELECT * FROM t1 WHERE val=4; BEGIN; DELETE FROM t1; SELECT COUNT(*) FROM t1; --echo # With innodb_stats_include_delete_marked=OFF, --echo # DELETE must affect statistics even before COMMIT. --echo # However, if there was a WHERE condition, --echo # ha_innobase::records_in_range() would count the delete-marked records. EXPLAIN SELECT * FROM t1; ROLLBACK; EXPLAIN SELECT * FROM t1; SELECT COUNT(*) FROM t1; disconnect con1; connection default; DROP TABLE t1,t2; SET GLOBAL innodb_stats_include_delete_marked = @saved_include_delete_marked; SET GLOBAL innodb_stats_traditional = @saved_traditional; SET GLOBAL innodb_stats_modified_counter = @saved_modified_counter; # # Bug#12429573 TIMESTAMP COLUMN OF INNODB.INDEX_STATS ARE NOT UPDATED # WHEN RE-RUNNING ANALYZE # CREATE TABLE bug12429573 (i INTEGER PRIMARY KEY, j INTEGER, KEY(j)) ENGINE=INNODB STATS_PERSISTENT=1; SET STATEMENT use_stat_tables=never FOR ANALYZE TABLE bug12429573; # Cannot check the exact timestamp here because it is always different # but at least check that both timestamps in innodb_table_stats and in # innodb_index_stats have been updated to the same value. If the bug is # present this check will fail. --disable_cursor_protocol SELECT last_update INTO @last FROM mysql.innodb_table_stats WHERE table_name = 'bug12429573'; --enable_cursor_protocol SELECT * FROM mysql.innodb_index_stats WHERE table_name = 'bug12429573' AND last_update!=@last; # The first ANALYZE would insert timestamp e.g. 17:23:39 in both # innodb_table_stats and innodb_index_stats. The bug is that the second # ANALYZE only updates the timestamp in innodb_table_stats. In order to # check if the timestamp in innodb_index_stats has really been updated we # need it to be different from the previous one (17:23:39) with at least # one second. -- sleep 1 SET STATEMENT use_stat_tables=never FOR ANALYZE TABLE bug12429573; SELECT * FROM mysql.innodb_table_stats WHERE table_name = 'bug12429573' AND last_update=@last; SELECT * FROM mysql.innodb_index_stats WHERE table_name = 'bug12429573' AND last_update=@last; DROP TABLE bug12429573;