Skip to content

Commit 5027338

Browse files
author
Jan Lindström
committed
(Inadequate background LRU flushing for write workloads with InnoDB compression). If InnoDB compression is used and the workload has writes, the following situation is possible. The LRU flusher issues an LRU flush request for an instance. buf_do_LRU_batch decides to perform unzip_LRU eviction and this eviction might fully satisfy the request. Then buf_flush_LRU_tail checks the number of flushed pages in the last iteration, finds it to be zero, and wrongly decides not to flush that instance anymore. Fixed by maintaining unzip_LRU eviction counter in struct flush_counter_t variables, and checking it in buf_flush_LRU_tail when deciding whether to stop flushing the current instance. Added test cases for new configuration files to get mysql-test-run suite sys_vars to pass. Fix some small errors.
1 parent f761835 commit 5027338

12 files changed

+184
-12
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
select @@global.innodb_mtflush_threads;
2+
@@global.innodb_mtflush_threads
3+
8
4+
select @@session.innodb_mtflush_threads;
5+
ERROR HY000: Variable 'innodb_mtflush_threads' is a GLOBAL variable
6+
show global variables like 'innodb_mtflush_threads';
7+
Variable_name Value
8+
innodb_mtflush_threads 8
9+
show session variables like 'innodb_mtflush_threads';
10+
Variable_name Value
11+
innodb_mtflush_threads 8
12+
select * from information_schema.global_variables where variable_name='innodb_mtflush_threads';
13+
VARIABLE_NAME VARIABLE_VALUE
14+
INNODB_MTFLUSH_THREADS 8
15+
select * from information_schema.session_variables where variable_name='innodb_mtflush_threads';
16+
VARIABLE_NAME VARIABLE_VALUE
17+
INNODB_MTFLUSH_THREADS 8
18+
set global innodb_mtflush_threads=1;
19+
ERROR HY000: Variable 'innodb_mtflush_threads' is a read only variable
20+
set session innodb_mtflush_threads=1;
21+
ERROR HY000: Variable 'innodb_mtflush_threads' is a read only variable
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
select @@global.innodb_use_fallocate;
2+
@@global.innodb_use_fallocate
3+
0
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
select @@global.innodb_use_mtflush;
2+
@@global.innodb_use_mtflush
3+
0
4+
select @@session.innodb_use_mtflush;
5+
ERROR HY000: Variable 'innodb_use_mtflush' is a GLOBAL variable
6+
show global variables like 'innodb_use_mtflush';
7+
Variable_name Value
8+
innodb_use_mtflush OFF
9+
show session variables like 'innodb_use_mtflush';
10+
Variable_name Value
11+
innodb_use_mtflush OFF
12+
select * from information_schema.global_variables where variable_name='innodb_use_mtflush';
13+
VARIABLE_NAME VARIABLE_VALUE
14+
INNODB_USE_MTFLUSH OFF
15+
select * from information_schema.session_variables where variable_name='innodb_use_mtflush';
16+
VARIABLE_NAME VARIABLE_VALUE
17+
INNODB_USE_MTFLUSH OFF
18+
set global innodb_use_mtflush=1;
19+
ERROR HY000: Variable 'innodb_use_mtflush' is a read only variable
20+
set session innodb_use_mtflush=1;
21+
ERROR HY000: Variable 'innodb_use_mtflush' is a read only variable
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
SET @start_use_trim = @@global.innodb_use_trim;
2+
SELECT @start_use_trim;
3+
@start_use_trim
4+
0
5+
SELECT COUNT(@@GLOBAL.innodb_use_trim);
6+
COUNT(@@GLOBAL.innodb_use_trim)
7+
1
8+
1 Expected
9+
SET @@GLOBAL.innodb_use_trim=1;
10+
SELECT COUNT(@@GLOBAL.innodb_use_trim);
11+
COUNT(@@GLOBAL.innodb_use_trim)
12+
1
13+
1 Expected
14+
SELECT IF(@@GLOBAL.innodb_use_trim, 'ON', 'OFF') = VARIABLE_VALUE
15+
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
16+
WHERE VARIABLE_NAME='innodb_use_trim';
17+
IF(@@GLOBAL.innodb_use_trim, 'ON', 'OFF') = VARIABLE_VALUE
18+
1
19+
1 Expected
20+
SELECT COUNT(@@GLOBAL.innodb_use_trim);
21+
COUNT(@@GLOBAL.innodb_use_trim)
22+
1
23+
1 Expected
24+
SELECT COUNT(VARIABLE_VALUE)
25+
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
26+
WHERE VARIABLE_NAME='innodb_use_trim';
27+
COUNT(VARIABLE_VALUE)
28+
1
29+
1 Expected
30+
SET @@global.innodb_use_trim = @start_use_trim;
31+
SELECT @@global.innodb_use_trim;
32+
@@global.innodb_use_trim
33+
0
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--source include/have_innodb.inc
2+
# bool readonly
3+
4+
#
5+
# show values;
6+
#
7+
select @@global.innodb_mtflush_threads;
8+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
9+
select @@session.innodb_mtflush_threads;
10+
show global variables like 'innodb_mtflush_threads';
11+
show session variables like 'innodb_mtflush_threads';
12+
select * from information_schema.global_variables where variable_name='innodb_mtflush_threads';
13+
select * from information_schema.session_variables where variable_name='innodb_mtflush_threads';
14+
15+
#
16+
# show that it's read-only
17+
#
18+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
19+
set global innodb_mtflush_threads=1;
20+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
21+
set session innodb_mtflush_threads=1;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
--source include/have_innodb.inc
2+
# bool readonly
3+
# not on all compilations
4+
select @@global.innodb_use_fallocate;
5+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--source include/have_innodb.inc
2+
# bool readonly
3+
4+
#
5+
# show values;
6+
#
7+
select @@global.innodb_use_mtflush;
8+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
9+
select @@session.innodb_use_mtflush;
10+
show global variables like 'innodb_use_mtflush';
11+
show session variables like 'innodb_use_mtflush';
12+
select * from information_schema.global_variables where variable_name='innodb_use_mtflush';
13+
select * from information_schema.session_variables where variable_name='innodb_use_mtflush';
14+
15+
#
16+
# show that it's read-only
17+
#
18+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
19+
set global innodb_use_mtflush=1;
20+
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
21+
set session innodb_use_mtflush=1;
22+
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
--source include/have_innodb.inc
2+
3+
SET @start_use_trim = @@global.innodb_use_trim;
4+
SELECT @start_use_trim;
5+
6+
SELECT COUNT(@@GLOBAL.innodb_use_trim);
7+
--echo 1 Expected
8+
9+
####################################################################
10+
# Check if Value can set #
11+
####################################################################
12+
13+
SET @@GLOBAL.innodb_use_trim=1;
14+
15+
SELECT COUNT(@@GLOBAL.innodb_use_trim);
16+
--echo 1 Expected
17+
18+
#################################################################
19+
# Check if the value in GLOBAL Table matches value in variable #
20+
#################################################################
21+
22+
SELECT IF(@@GLOBAL.innodb_use_trim, 'ON', 'OFF') = VARIABLE_VALUE
23+
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
24+
WHERE VARIABLE_NAME='innodb_use_trim';
25+
--echo 1 Expected
26+
27+
SELECT COUNT(@@GLOBAL.innodb_use_trim);
28+
--echo 1 Expected
29+
30+
SELECT COUNT(VARIABLE_VALUE)
31+
FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES
32+
WHERE VARIABLE_NAME='innodb_use_trim';
33+
--echo 1 Expected
34+
35+
SET @@global.innodb_use_trim = @start_use_trim;
36+
SELECT @@global.innodb_use_trim;

storage/innobase/handler/ha_innodb.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16801,7 +16801,7 @@ static MYSQL_SYSVAR_BOOL(use_lz4, srv_use_lz4,
1680116801
#endif /* HAVE_LZ4 */
1680216802

1680316803
static MYSQL_SYSVAR_LONG(mtflush_threads, srv_mtflush_threads,
16804-
PLUGIN_VAR_RQCMDARG,
16804+
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1680516805
"Number of multi-threaded flush threads",
1680616806
NULL, NULL,
1680716807
MTFLUSH_DEFAULT_WORKER, /* Default setting */
@@ -16810,7 +16810,7 @@ static MYSQL_SYSVAR_LONG(mtflush_threads, srv_mtflush_threads,
1681016810
0);
1681116811

1681216812
static MYSQL_SYSVAR_BOOL(use_mtflush, srv_use_mtflush,
16813-
PLUGIN_VAR_OPCMDARG ,
16813+
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1681416814
"Use multi-threaded flush. Default FALSE.",
1681516815
NULL, NULL, FALSE);
1681616816

storage/xtradb/buf/buf0flu.cc

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1549,6 +1549,7 @@ buf_flush_LRU_list_batch(
15491549

15501550
n->flushed = 0;
15511551
n->evicted = 0;
1552+
n->unzip_LRU_evicted = 0;
15521553

15531554
ut_ad(mutex_own(&buf_pool->LRU_list_mutex));
15541555

@@ -1660,21 +1661,22 @@ buf_do_LRU_batch(
16601661
flush_counters_t* n) /*!< out: flushed/evicted page
16611662
counts */
16621663
{
1663-
ulint count = 0;
1664-
16651664
if (buf_LRU_evict_from_unzip_LRU(buf_pool)) {
1666-
count += buf_free_from_unzip_LRU_list_batch(buf_pool, max);
1665+
n->unzip_LRU_evicted
1666+
+= buf_free_from_unzip_LRU_list_batch(buf_pool, max);
1667+
} else {
1668+
n->unzip_LRU_evicted = 0;
16671669
}
16681670

1669-
if (max > count) {
1670-
buf_flush_LRU_list_batch(buf_pool, max - count, limited_scan,
1671-
n);
1671+
if (max > n->unzip_LRU_evicted) {
1672+
buf_flush_LRU_list_batch(buf_pool, max - n->unzip_LRU_evicted,
1673+
limited_scan, n);
16721674
} else {
16731675
n->evicted = 0;
16741676
n->flushed = 0;
16751677
}
16761678

1677-
n->flushed += count;
1679+
n->evicted += n->unzip_LRU_evicted;
16781680
}
16791681

16801682
/*******************************************************************//**
@@ -2306,9 +2308,15 @@ buf_flush_LRU_tail(void)
23062308

23072309
requested_pages[i] += lru_chunk_size;
23082310

2311+
/* If we failed to flush or evict this
2312+
instance, do not bother anymore. But take into
2313+
account that we might have zero flushed pages
2314+
because the flushing request was fully
2315+
satisfied by unzip_LRU evictions. */
23092316
if (requested_pages[i] >= scan_depth[i]
23102317
|| !(srv_cleaner_eviction_factor
2311-
? n.evicted : n.flushed)) {
2318+
? n.evicted
2319+
: (n.flushed + n.unzip_LRU_evicted))) {
23122320

23132321
active_instance[i] = false;
23142322
remaining_instances--;

0 commit comments

Comments
 (0)