diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2022-01-20 16:30:18 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2022-01-21 14:15:18 +0530 |
commit | 28e166d6435741c46e0ea789657b739f78eb0425 (patch) | |
tree | b290a6698ed3ae0609e1786b9ecd37f3369281e7 | |
parent | a0f711e928178b90523f62983ce0ee52d21a5824 (diff) | |
download | mariadb-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.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/recovery_memory.opt | 1 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/recovery_memory.test | 21 | ||||
-rw-r--r-- | storage/innobase/buf/buf0flu.cc | 8 |
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(); |