Skip to content

Commit 56f5599

Browse files
committed
MDEV-27610 Unnecessary wait in InnoDB crash recovery
In recv_sys_t::apply(), we were unnecessarily looking up pages in buf_pool.page_hash and potentially waiting for exclusive page latches. Before buf_page_get_low() would return an x-latched page, that page will have to be read and buf_page_read_complete() would have invoked recv_recover_page() to apply the log to the page. Therefore, it suffices to invoke recv_read_in_area() to trigger a transition from RECV_NOT_PROCESSED. recv_read_in_area(): Take the iterator as a parameter, and remove page_id lookups. Should the page already be in buf_pool.page_hash, buf_page_init_for_read() will return nullptr to buf_read_page_low() and buf_read_page_background(). recv_sys_t::apply(): Replace goto, remove dead code, and add assertions to guarantee that the iteration will make progress. Reviewed by: Vladislav Lesin
1 parent 216834b commit 56f5599

File tree

1 file changed

+33
-53
lines changed

1 file changed

+33
-53
lines changed

storage/innobase/log/log0recv.cc

Lines changed: 33 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2504,33 +2504,32 @@ void recv_recover_page(fil_space_t* space, buf_page_t* bpage)
25042504
ut_ad(mtr.has_committed());
25052505
}
25062506

2507-
/** Reads in pages which have hashed log records, from an area around a given
2508-
page number.
2509-
@param[in] page_id page id */
2510-
static void recv_read_in_area(page_id_t page_id)
2507+
/** Read pages for which log needs to be applied.
2508+
@param page_id first page identifier to read
2509+
@param i iterator to recv_sys.pages */
2510+
static void recv_read_in_area(page_id_t page_id, recv_sys_t::map::iterator i)
25112511
{
2512-
uint32_t page_nos[32];
2513-
page_id.set_page_no(ut_2pow_round(page_id.page_no(), 32U));
2514-
const uint32_t up_limit = page_id.page_no() + 32;
2515-
uint32_t* p = page_nos;
2516-
2517-
for (recv_sys_t::map::iterator i= recv_sys.pages.lower_bound(page_id);
2518-
i != recv_sys.pages.end()
2519-
&& i->first.space() == page_id.space()
2520-
&& i->first.page_no() < up_limit; i++) {
2521-
if (i->second.state == page_recv_t::RECV_NOT_PROCESSED
2522-
&& !buf_pool.page_hash_contains(i->first)) {
2523-
i->second.state = page_recv_t::RECV_BEING_READ;
2524-
*p++ = i->first.page_no();
2525-
}
2526-
}
2512+
uint32_t page_nos[32];
2513+
ut_ad(page_id == i->first);
2514+
page_id.set_page_no(ut_2pow_round(page_id.page_no(), 32U));
2515+
const page_id_t up_limit{page_id + 31};
2516+
uint32_t* p= page_nos;
25272517

2528-
if (p != page_nos) {
2529-
mutex_exit(&recv_sys.mutex);
2530-
buf_read_recv_pages(page_id.space(), page_nos,
2531-
ulint(p - page_nos));
2532-
mutex_enter(&recv_sys.mutex);
2533-
}
2518+
for (; i != recv_sys.pages.end() && i->first <= up_limit; i++)
2519+
{
2520+
if (i->second.state == page_recv_t::RECV_NOT_PROCESSED)
2521+
{
2522+
i->second.state= page_recv_t::RECV_BEING_READ;
2523+
*p++= i->first.page_no();
2524+
}
2525+
}
2526+
2527+
if (p != page_nos)
2528+
{
2529+
mutex_exit(&recv_sys.mutex);
2530+
buf_read_recv_pages(page_id.space(), page_nos, ulint(p - page_nos));
2531+
mutex_enter(&recv_sys.mutex);
2532+
}
25342533
}
25352534

25362535
/** Attempt to initialize a page based on redo log records.
@@ -2694,10 +2693,9 @@ void recv_sys_t::apply(bool last_batch)
26942693
for (map::iterator p= pages.begin(); p != pages.end(); )
26952694
{
26962695
const page_id_t page_id= p->first;
2697-
page_recv_t &recs= p->second;
2698-
ut_ad(!recs.log.empty());
2696+
ut_ad(!p->second.log.empty());
26992697

2700-
switch (recs.state) {
2698+
switch (p->second.state) {
27012699
case page_recv_t::RECV_BEING_READ:
27022700
case page_recv_t::RECV_BEING_PROCESSED:
27032701
p++;
@@ -2708,35 +2706,17 @@ void recv_sys_t::apply(bool last_batch)
27082706
mutex_exit(&mutex);
27092707
free_block= buf_LRU_get_free_block(false);
27102708
mutex_enter(&mutex);
2711-
next_page:
2712-
p= pages.lower_bound(page_id);
2713-
}
2714-
continue;
2715-
case page_recv_t::RECV_NOT_PROCESSED:
2716-
mtr.start();
2717-
mtr.set_log_mode(MTR_LOG_NO_REDO);
2718-
if (buf_block_t *block= buf_page_get_low(page_id, 0, RW_X_LATCH,
2719-
nullptr, BUF_GET_IF_IN_POOL,
2720-
__FILE__, __LINE__,
2721-
&mtr, nullptr, false))
2722-
{
2723-
buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
2724-
recv_recover_page(block, mtr, p);
2725-
ut_ad(mtr.has_committed());
2726-
}
2727-
else
2728-
{
2729-
mtr.commit();
2730-
recv_read_in_area(page_id);
27312709
break;
27322710
}
2733-
map::iterator r= p++;
2734-
r->second.log.clear();
2735-
pages.erase(r);
2711+
ut_ad(p == pages.end() || p->first > page_id);
27362712
continue;
2713+
case page_recv_t::RECV_NOT_PROCESSED:
2714+
recv_read_in_area(page_id, p);
27372715
}
2738-
2739-
goto next_page;
2716+
p= pages.lower_bound(page_id);
2717+
/* Ensure that progress will be made. */
2718+
ut_ad(p == pages.end() || p->first > page_id ||
2719+
p->second.state >= page_recv_t::RECV_BEING_READ);
27402720
}
27412721

27422722
buf_pool.free_block(free_block);

0 commit comments

Comments
 (0)