From 5a9e7bc6fede860affc71454e3d59d1b4b39203b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marko=20M=C3=A4kel=C3=A4?= Date: Mon, 9 Apr 2018 09:39:58 +0300 Subject: [PATCH] MDEV-13603 innodb_fast_shutdown=0 may fail to purge all history srv_purge_should_exit(): Remove the parameter n_purged. If we happened to have n_purged==0 while some transaction was still active, and then that transaction was added to the history list, we were prematurely stopping the purge. It is more appropriate to first check for trx_sys.any_active_transactions() == 0 (this count can only decrease during shutdown) and then for trx_sys.history_size() == 0 (that count typically decreases, but can increase when any remaining active transactions are committed or rolled back). innodb.dml_purge: Remove a server restart, and explicitly wait for purge, and use FLUSH TABLE FOR EXPORT to read the file contents. This will make the test run faster, easier to debug, and also allow it to run with --embedded. This might also help repeat MDEV-11802 better. The issue MDEV-13603 remains will remain tested by innodb.table_flags. --- mysql-test/suite/innodb/r/dml_purge.result | 7 +++++- mysql-test/suite/innodb/t/dml_purge.test | 12 +++++++---- storage/innobase/srv/srv0srv.cc | 25 +++++++--------------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/mysql-test/suite/innodb/r/dml_purge.result b/mysql-test/suite/innodb/r/dml_purge.result index f5a919f7a12..c6ea5e80f28 100644 --- a/mysql-test/suite/innodb/r/dml_purge.result +++ b/mysql-test/suite/innodb/r/dml_purge.result @@ -1,3 +1,5 @@ +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; # # MDEV-12288 Reset DB_TRX_ID when the history is removed, # to speed up MVCC @@ -7,7 +9,8 @@ CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL) ROW_FORMAT=REDUNDANT ENGINE=InnoDB; INSERT INTO t1 VALUES(1,2),(3,4); UPDATE t1 SET b=-3 WHERE a=3; -SET GLOBAL innodb_fast_shutdown=0; +InnoDB 0 transactions not purged +FLUSH TABLE t1 FOR EXPORT; Clustered index root page contents: N_RECS=2; LEVEL=0 header=0x010000030087 (a=0x696e66696d756d00) @@ -20,8 +23,10 @@ header=0x000018090074 (a=0x80000003, DB_ROLL_PTR=0x80000000000000, b=0x7ffffffd) header=0x030008030000 (a=0x73757072656d756d00) +UNLOCK TABLES; SELECT * FROM t1; a b 1 2 3 -3 DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/t/dml_purge.test b/mysql-test/suite/innodb/t/dml_purge.test index 720acfb1577..93b7f56111c 100644 --- a/mysql-test/suite/innodb/t/dml_purge.test +++ b/mysql-test/suite/innodb/t/dml_purge.test @@ -1,8 +1,9 @@ --source include/innodb_page_size.inc ---source include/not_embedded.inc let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let MYSQLD_DATADIR=`select @@datadir`; +SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; +SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; --echo # --echo # MDEV-12288 Reset DB_TRX_ID when the history is removed, @@ -13,12 +14,14 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL) ROW_FORMAT=REDUNDANT ENGINE=InnoDB; + INSERT INTO t1 VALUES(1,2),(3,4); UPDATE t1 SET b=-3 WHERE a=3; # Initiate a full purge, which should reset all DB_TRX_ID. -SET GLOBAL innodb_fast_shutdown=0; ---source include/shutdown_mysqld.inc +--source include/wait_all_purged.inc + +FLUSH TABLE t1 FOR EXPORT; # The following is based on innodb.table_flags: --perl use strict; @@ -54,6 +57,7 @@ for (my $offset= 0x65; $offset; } close(FILE) || die "Unable to close $file\n"; EOF ---source include/start_mysqld.inc +UNLOCK TABLES; SELECT * FROM t1; DROP TABLE t1; +SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index ef2435e9443..248bd184dbf 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -2446,12 +2446,8 @@ suspend_thread: goto loop; } -/** Check if purge should stop. -@param[in] n_purged pages purged in the last batch -@return whether purge should exit */ -static -bool -srv_purge_should_exit(ulint n_purged) +/** @return whether purge should exit due to shutdown */ +static bool srv_purge_should_exit() { ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP); @@ -2463,12 +2459,7 @@ srv_purge_should_exit(ulint n_purged) return(true); } /* Slow shutdown was requested. */ - if (n_purged) { - /* The previous round still did some work. */ - return(false); - } - /* Exit if there are no active transactions to roll back. */ - return(trx_sys.any_active_transactions() == 0); + return !trx_sys.any_active_transactions() && !trx_sys.history_size(); } /*********************************************************************//** @@ -2643,9 +2634,9 @@ srv_do_purge(ulint* n_total_purged) *n_total_purged += n_pages_purged; - } while (!srv_purge_should_exit(n_pages_purged) - && n_pages_purged > 0 - && purge_sys.state == PURGE_STATE_RUN); + } while (n_pages_purged > 0 + && purge_sys.state == PURGE_STATE_RUN + && !srv_purge_should_exit()); return(rseg_history_len); } @@ -2776,14 +2767,14 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( ut_ad(!slot->suspended); - if (srv_purge_should_exit(n_total_purged)) { + if (srv_purge_should_exit()) { break; } n_total_purged = 0; rseg_history_len = srv_do_purge(&n_total_purged); - } while (!srv_purge_should_exit(n_total_purged)); + } while (!srv_purge_should_exit()); /* The task queue should always be empty, independent of fast shutdown state. */