Commit 5a9e7bc6 authored by Marko Mäkelä's avatar Marko Mäkelä

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.
parent df44e75b
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, # MDEV-12288 Reset DB_TRX_ID when the history is removed,
# to speed up MVCC # to speed up MVCC
...@@ -7,7 +9,8 @@ CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL) ...@@ -7,7 +9,8 @@ CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL)
ROW_FORMAT=REDUNDANT ENGINE=InnoDB; ROW_FORMAT=REDUNDANT ENGINE=InnoDB;
INSERT INTO t1 VALUES(1,2),(3,4); INSERT INTO t1 VALUES(1,2),(3,4);
UPDATE t1 SET b=-3 WHERE a=3; 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: Clustered index root page contents:
N_RECS=2; LEVEL=0 N_RECS=2; LEVEL=0
header=0x010000030087 (a=0x696e66696d756d00) header=0x010000030087 (a=0x696e66696d756d00)
...@@ -20,8 +23,10 @@ header=0x000018090074 (a=0x80000003, ...@@ -20,8 +23,10 @@ header=0x000018090074 (a=0x80000003,
DB_ROLL_PTR=0x80000000000000, DB_ROLL_PTR=0x80000000000000,
b=0x7ffffffd) b=0x7ffffffd)
header=0x030008030000 (a=0x73757072656d756d00) header=0x030008030000 (a=0x73757072656d756d00)
UNLOCK TABLES;
SELECT * FROM t1; SELECT * FROM t1;
a b a b
1 2 1 2
3 -3 3 -3
DROP TABLE t1; DROP TABLE t1;
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
--source include/innodb_page_size.inc --source include/innodb_page_size.inc
--source include/not_embedded.inc
let INNODB_PAGE_SIZE=`select @@innodb_page_size`; let INNODB_PAGE_SIZE=`select @@innodb_page_size`;
let MYSQLD_DATADIR=`select @@datadir`; let MYSQLD_DATADIR=`select @@datadir`;
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
--echo # --echo #
--echo # MDEV-12288 Reset DB_TRX_ID when the history is removed, --echo # MDEV-12288 Reset DB_TRX_ID when the history is removed,
...@@ -13,12 +14,14 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = 1; ...@@ -13,12 +14,14 @@ SET GLOBAL innodb_purge_rseg_truncate_frequency = 1;
CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL) CREATE TABLE t1(a INT PRIMARY KEY, b INT NOT NULL)
ROW_FORMAT=REDUNDANT ENGINE=InnoDB; ROW_FORMAT=REDUNDANT ENGINE=InnoDB;
INSERT INTO t1 VALUES(1,2),(3,4); INSERT INTO t1 VALUES(1,2),(3,4);
UPDATE t1 SET b=-3 WHERE a=3; UPDATE t1 SET b=-3 WHERE a=3;
# Initiate a full purge, which should reset all DB_TRX_ID. # Initiate a full purge, which should reset all DB_TRX_ID.
SET GLOBAL innodb_fast_shutdown=0; --source include/wait_all_purged.inc
--source include/shutdown_mysqld.inc
FLUSH TABLE t1 FOR EXPORT;
# The following is based on innodb.table_flags: # The following is based on innodb.table_flags:
--perl --perl
use strict; use strict;
...@@ -54,6 +57,7 @@ for (my $offset= 0x65; $offset; ...@@ -54,6 +57,7 @@ for (my $offset= 0x65; $offset;
} }
close(FILE) || die "Unable to close $file\n"; close(FILE) || die "Unable to close $file\n";
EOF EOF
--source include/start_mysqld.inc UNLOCK TABLES;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency;
...@@ -2446,12 +2446,8 @@ DECLARE_THREAD(srv_master_thread)( ...@@ -2446,12 +2446,8 @@ DECLARE_THREAD(srv_master_thread)(
goto loop; goto loop;
} }
/** Check if purge should stop. /** @return whether purge should exit due to shutdown */
@param[in] n_purged pages purged in the last batch static bool srv_purge_should_exit()
@return whether purge should exit */
static
bool
srv_purge_should_exit(ulint n_purged)
{ {
ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE ut_ad(srv_shutdown_state == SRV_SHUTDOWN_NONE
|| srv_shutdown_state == SRV_SHUTDOWN_CLEANUP); || srv_shutdown_state == SRV_SHUTDOWN_CLEANUP);
...@@ -2463,12 +2459,7 @@ srv_purge_should_exit(ulint n_purged) ...@@ -2463,12 +2459,7 @@ srv_purge_should_exit(ulint n_purged)
return(true); return(true);
} }
/* Slow shutdown was requested. */ /* Slow shutdown was requested. */
if (n_purged) { return !trx_sys.any_active_transactions() && !trx_sys.history_size();
/* 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);
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -2643,9 +2634,9 @@ srv_do_purge(ulint* n_total_purged) ...@@ -2643,9 +2634,9 @@ srv_do_purge(ulint* n_total_purged)
*n_total_purged += n_pages_purged; *n_total_purged += n_pages_purged;
} while (!srv_purge_should_exit(n_pages_purged) } while (n_pages_purged > 0
&& n_pages_purged > 0 && purge_sys.state == PURGE_STATE_RUN
&& purge_sys.state == PURGE_STATE_RUN); && !srv_purge_should_exit());
return(rseg_history_len); return(rseg_history_len);
} }
...@@ -2776,14 +2767,14 @@ DECLARE_THREAD(srv_purge_coordinator_thread)( ...@@ -2776,14 +2767,14 @@ DECLARE_THREAD(srv_purge_coordinator_thread)(
ut_ad(!slot->suspended); ut_ad(!slot->suspended);
if (srv_purge_should_exit(n_total_purged)) { if (srv_purge_should_exit()) {
break; break;
} }
n_total_purged = 0; n_total_purged = 0;
rseg_history_len = srv_do_purge(&n_total_purged); 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 /* The task queue should always be empty, independent of fast
shutdown state. */ shutdown state. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment