summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2022-01-20 16:30:18 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2022-01-21 14:15:18 +0530
commit28e166d6435741c46e0ea789657b739f78eb0425 (patch)
treeb290a6698ed3ae0609e1786b9ecd37f3369281e7
parenta0f711e928178b90523f62983ce0ee52d21a5824 (diff)
downloadmariadb-git-bb-10.5-MDEV-26784.tar.gz
MDEV-26784 [Warning] InnoDB: Difficult to find free blocks in the buffer poolbb-10.5-MDEV-26784
Problem: ======= InnoDB ran out of memory during recovery and it fails to flush the dirty LRU blocks. The reason is that buffer pool can ran out before the LRU list length reaches BUF_LRU_OLD_MIN_LEN(256) threshold. Fix: ==== During recovery, InnoDB should write out and evict all dirty blocks.
-rw-r--r--mysql-test/suite/innodb/r/recovery_memory.result12
-rw-r--r--mysql-test/suite/innodb/t/recovery_memory.opt1
-rw-r--r--mysql-test/suite/innodb/t/recovery_memory.test21
-rw-r--r--storage/innobase/buf/buf0flu.cc8
4 files changed, 39 insertions, 3 deletions
diff --git a/mysql-test/suite/innodb/r/recovery_memory.result b/mysql-test/suite/innodb/r/recovery_memory.result
new file mode 100644
index 00000000000..4fa31009130
--- /dev/null
+++ b/mysql-test/suite/innodb/r/recovery_memory.result
@@ -0,0 +1,12 @@
+CREATE TABLE t1(c TEXT, KEY(c(3072)))ENGINE=InnoDB;
+CREATE PROCEDURE dorepeat()
+LOOP
+INSERT INTO t1 VALUES ('abc');
+UPDATE t1 SET c='cba';
+END LOOP
+|
+connect con1,localhost,root,,,;
+CALL dorepeat();
+connection default;
+# restart: --innodb_buffer_pool_size=5242880
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/t/recovery_memory.opt b/mysql-test/suite/innodb/t/recovery_memory.opt
new file mode 100644
index 00000000000..7207fd27a42
--- /dev/null
+++ b/mysql-test/suite/innodb/t/recovery_memory.opt
@@ -0,0 +1 @@
+--innodb_buffer_pool_size=1073741824
diff --git a/mysql-test/suite/innodb/t/recovery_memory.test b/mysql-test/suite/innodb/t/recovery_memory.test
new file mode 100644
index 00000000000..d9afd52c499
--- /dev/null
+++ b/mysql-test/suite/innodb/t/recovery_memory.test
@@ -0,0 +1,21 @@
+--source include/have_innodb.inc
+--source include/big_test.inc
+CREATE TABLE t1(c TEXT, KEY(c(3072)))ENGINE=InnoDB;
+DELIMITER |;
+
+CREATE PROCEDURE dorepeat()
+ LOOP
+ INSERT INTO t1 VALUES ('abc');
+ UPDATE t1 SET c='cba';
+ END LOOP
+|
+
+DELIMITER ;|
+connect(con1,localhost,root,,,);
+send CALL dorepeat();
+connection default;
+sleep 10;
+let $shutdown_timeout=0;
+let $restart_parameters=--innodb_buffer_pool_size=5242880;
+--source include/restart_mysqld.inc
+DROP TABLE t1;
diff --git a/storage/innobase/buf/buf0flu.cc b/storage/innobase/buf/buf0flu.cc
index c14b274645d..ce8f8dc34c4 100644
--- a/storage/innobase/buf/buf0flu.cc
+++ b/storage/innobase/buf/buf0flu.cc
@@ -1288,9 +1288,11 @@ static void buf_flush_LRU_list_batch(ulint max, flush_counters_t *n)
static_assert(FIL_NULL > SRV_SPACE_ID_UPPER_BOUND, "consistency");
for (buf_page_t *bpage= UT_LIST_GET_LAST(buf_pool.LRU);
- bpage && n->flushed + n->evicted < max &&
- UT_LIST_GET_LEN(buf_pool.LRU) > BUF_LRU_MIN_LEN &&
- UT_LIST_GET_LEN(buf_pool.free) < free_limit; ++scanned)
+ bpage &&
+ ((UT_LIST_GET_LEN(buf_pool.LRU) > BUF_LRU_MIN_LEN &&
+ UT_LIST_GET_LEN(buf_pool.free) < free_limit &&
+ n->flushed + n->evicted < max) ||
+ recv_recovery_is_on()); ++scanned)
{
buf_page_t *prev= UT_LIST_GET_PREV(LRU, bpage);
const lsn_t oldest_modification= bpage->oldest_modification();