Skip to content

Commit ed391b6

Browse files
author
Marko Makela
committed
Bug#19149177 Remove space_id lookups
Bug#16831138 69276: fil_system->mutex contention limits block read rate with fast storage (partial fix) The function calls fil_inc_pending_ops() and fil_decr_pending_ops() form a logical pair. If the first call succeeds, the fil_space_t object cannot be deleted until after the second call has been issued. So, we could safely cache the pointer here, and avoid looking up the tablespace again. We replace the two functions with fil_space_acquire() and fil_space_release(). We will also start using these functions in the following code: buf_load(): restoring a buffer pool dump fsp_get_available_space_in_free_extents(): used in ha_innobase::info() lock_rec_block_validate(): debug code rb#5919 approved by Yasufumi Kinoshita and Jimmy Yang
1 parent fda8d78 commit ed391b6

File tree

9 files changed

+138
-192
lines changed

9 files changed

+138
-192
lines changed

mysql-test/suite/innodb/t/innodb_buffer_pool_load.test

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ WHERE table_name LIKE '%ib_bp_test%';
2727

2828
# Here we end up with 16382 rows in the table
2929
-- disable_query_log
30+
call mtr.add_suppression("InnoDB: Trying to do an operation on a dropped tablespace");
3031
INSERT INTO ib_bp_test (b, c) VALUES (REPEAT('b', 64), REPEAT('c', 256));
3132
INSERT INTO ib_bp_test (b, c) VALUES (REPEAT('B', 64), REPEAT('C', 256));
3233
let $i=12;

storage/innobase/buf/buf0dump.cc

+19-9
Original file line numberDiff line numberDiff line change
@@ -540,31 +540,34 @@ buf_load()
540540
ulint last_check_time = 0;
541541
ulint last_activity_cnt = 0;
542542

543-
/* Avoid calling the expensive fil_space_get_page_size() for each
543+
/* Avoid calling the expensive fil_space_acquire() for each
544544
page within the same tablespace. dump[] is sorted by (space, page),
545545
so all pages from a given tablespace are consecutive. */
546546
ulint cur_space_id = BUF_DUMP_SPACE(dump[0]);
547-
bool found;
548-
page_size_t page_size(fil_space_get_page_size(
549-
cur_space_id, &found));
547+
fil_space_t* space = fil_space_acquire(cur_space_id);
548+
page_size_t page_size(space ? space->flags : 0);
550549

551550
for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
552551

553552
/* space_id for this iteration of the loop */
554553
const ulint this_space_id = BUF_DUMP_SPACE(dump[i]);
555554

556555
if (this_space_id != cur_space_id) {
557-
cur_space_id = this_space_id;
556+
if (space) {
557+
fil_space_release(space);
558+
}
558559

559-
const page_size_t cur_page_size(
560-
fil_space_get_page_size(cur_space_id, &found));
560+
cur_space_id = this_space_id;
561+
space = fil_space_acquire(cur_space_id);
561562

562-
if (found) {
563+
if (space) {
564+
const page_size_t cur_page_size(
565+
space->flags);
563566
page_size.copy_from(cur_page_size);
564567
}
565568
}
566569

567-
if (!found) {
570+
if (!space) {
568571
continue;
569572
}
570573

@@ -583,6 +586,9 @@ buf_load()
583586
}
584587

585588
if (buf_load_abort_flag) {
589+
if (space) {
590+
fil_space_release(space);
591+
}
586592
buf_load_abort_flag = FALSE;
587593
ut_free(dump);
588594
buf_load_status(
@@ -595,6 +601,10 @@ buf_load()
595601
&last_check_time, &last_activity_cnt, i);
596602
}
597603

604+
if (space) {
605+
fil_space_release(space);
606+
}
607+
598608
ut_free(dump);
599609

600610
ut_sprintf_timestamp(now);

storage/innobase/buf/buf0rea.cc

+39-31
Original file line numberDiff line numberDiff line change
@@ -278,22 +278,23 @@ buf_read_ahead_random(
278278
return(0);
279279
}
280280

281-
/* Remember the tablespace version before we ask te tablespace size
282-
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
283-
do not try to read outside the bounds of the tablespace! */
284-
285-
tablespace_version = fil_space_get_version(page_id.space());
286-
287281
low = (page_id.page_no() / buf_read_ahead_random_area)
288282
* buf_read_ahead_random_area;
289283

290284
high = (page_id.page_no() / buf_read_ahead_random_area + 1)
291285
* buf_read_ahead_random_area;
292286

293-
const ulint space_size = fil_space_get_size(page_id.space());
294-
295-
if (high > space_size) {
296-
high = space_size;
287+
/* Remember the tablespace version before we ask the tablespace size
288+
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
289+
do not try to read outside the bounds of the tablespace! */
290+
if (fil_space_t* space = fil_space_acquire(page_id.space())) {
291+
tablespace_version = space->tablespace_version;
292+
if (high > space->size) {
293+
high = space->size;
294+
}
295+
fil_space_release(space);
296+
} else {
297+
return(0);
297298
}
298299

299300
buf_pool_mutex_enter(buf_pool);
@@ -542,18 +543,24 @@ buf_read_ahead_linear(
542543
/* Remember the tablespace version before we ask te tablespace size
543544
below: if DISCARD + IMPORT changes the actual .ibd file meanwhile, we
544545
do not try to read outside the bounds of the tablespace! */
546+
ulint space_size;
545547

546-
tablespace_version = fil_space_get_version(page_id.space());
547-
548-
buf_pool_mutex_enter(buf_pool);
549-
550-
if (high > fil_space_get_size(page_id.space())) {
551-
buf_pool_mutex_exit(buf_pool);
552-
/* The area is not whole, return */
548+
if (fil_space_t* space = fil_space_acquire(page_id.space())) {
549+
tablespace_version = space->tablespace_version;
550+
space_size = space->size;
551+
fil_space_release(space);
553552

553+
if (high > space->size) {
554+
/* The area is not whole */
555+
return(0);
556+
}
557+
} else {
554558
return(0);
555559
}
556560

561+
562+
buf_pool_mutex_enter(buf_pool);
563+
557564
if (buf_pool->n_pend_reads
558565
> buf_pool->curr_size / BUF_READ_AHEAD_PEND_LIMIT) {
559566
buf_pool_mutex_exit(buf_pool);
@@ -677,7 +684,7 @@ buf_read_ahead_linear(
677684
return(0);
678685
}
679686

680-
if (high > fil_space_get_size(page_id.space())) {
687+
if (high > space_size) {
681688
/* The area is not whole, return */
682689

683690
return(0);
@@ -818,39 +825,40 @@ buf_read_ibuf_merge_pages(
818825
}
819826

820827
/** Issues read requests for pages which recovery wants to read in.
821-
@param[in] sync TRUE if the caller wants this function to wait
828+
@param[in] sync true if the caller wants this function to wait
822829
for the highest address page to get read in, before this function returns
823-
@param[in] space space id
830+
@param[in] space_id tablespace id
824831
@param[in] page_nos array of page numbers to read, with the
825832
highest page number the last in the array
826833
@param[in] n_stored number of page numbers in the array */
834+
827835
void
828836
buf_read_recv_pages(
829-
ibool sync,
830-
ulint space,
837+
bool sync,
838+
ulint space_id,
831839
const ulint* page_nos,
832840
ulint n_stored)
833841
{
834842
int64_t tablespace_version;
835843
ulint count;
836844
dberr_t err;
837845
ulint i;
838-
bool found;
839-
const page_size_t page_size(fil_space_get_page_size(space,
840-
&found));
841-
842-
if (!found) {
843-
/* It is a single table tablespace and the .ibd file is
844-
missing: do nothing */
846+
ulint space_flags;
845847

848+
if (fil_space_t* space = fil_space_acquire(space_id)) {
849+
tablespace_version = space->tablespace_version;
850+
space_flags = space->flags;
851+
fil_space_release(space);
852+
} else {
853+
/* The tablespace is missing: do nothing */
846854
return;
847855
}
848856

849-
tablespace_version = fil_space_get_version(space);
857+
const page_size_t page_size(space_flags);
850858

851859
for (i = 0; i < n_stored; i++) {
852860
buf_pool_t* buf_pool;
853-
const page_id_t cur_page_id(space, page_nos[i]);
861+
const page_id_t cur_page_id(space_id, page_nos[i]);
854862

855863
count = 0;
856864

storage/innobase/fil/fil0fil.cc

+37-53
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ Created 10/25/1995 Heikki Tuuri
5353
#else /* !UNIV_HOTBACKUP */
5454
# include "srv0srv.h"
5555
#endif /* !UNIV_HOTBACKUP */
56-
#include "fsp0file.h"
5756
#include "fsp0sysspace.h"
5857
#include "ut0new.h"
5958

@@ -1844,65 +1843,48 @@ fil_write_flushed_lsn(
18441843
return(err);
18451844
}
18461845

1847-
/*================ SINGLE-TABLE TABLESPACES ==========================*/
1848-
18491846
#ifndef UNIV_HOTBACKUP
1850-
/*******************************************************************//**
1851-
Increments the count of pending operation, if space is not being deleted
1852-
or truncated.
1853-
@return true if being deleted/truncated, and operations should be skipped */
1854-
bool
1855-
fil_inc_pending_ops(
1856-
/*================*/
1857-
ulint id) /*!< in: space id */
1847+
/** Acquire a tablespace when it could be dropped concurrently.
1848+
Used by background threads that do not necessarily hold proper locks
1849+
for concurrency control.
1850+
@param[in] id tablespace ID
1851+
@return the tablespace, or NULL if deleted or being deleted */
1852+
1853+
fil_space_t*
1854+
fil_space_acquire(
1855+
ulint id)
18581856
{
18591857
fil_space_t* space;
1860-
bool skip_inc_pending_ops = true;
18611858

18621859
mutex_enter(&fil_system->mutex);
18631860

18641861
space = fil_space_get_by_id(id);
18651862

18661863
if (space == NULL) {
1867-
18681864
ib::error() << "Trying to do an operation on a dropped"
18691865
" tablespace. Space ID: " << id;
1866+
} else if (space->stop_new_ops || space->is_being_truncated) {
1867+
space = NULL;
18701868
} else {
1871-
1872-
skip_inc_pending_ops = (space->stop_new_ops
1873-
|| space->is_being_truncated);
1874-
if (!skip_inc_pending_ops) {
1875-
space->n_pending_ops++;
1876-
}
1869+
space->n_pending_ops++;
18771870
}
18781871

18791872
mutex_exit(&fil_system->mutex);
18801873

1881-
return(skip_inc_pending_ops);
1874+
return(space);
18821875
}
18831876

1884-
/*******************************************************************//**
1885-
Decrements the count of pending operations. */
1877+
/** Release a tablespace acquired with fil_space_acquire().
1878+
@param[in,out] space tablespace to release */
1879+
18861880
void
1887-
fil_decr_pending_ops(
1888-
/*=================*/
1889-
ulint id) /*!< in: space id */
1881+
fil_space_release(
1882+
fil_space_t* space)
18901883
{
1891-
fil_space_t* space;
1892-
18931884
mutex_enter(&fil_system->mutex);
1894-
1895-
space = fil_space_get_by_id(id);
1896-
1897-
if (space == NULL) {
1898-
ib::error() << "Decrementing pending operation"
1899-
" of a dropped tablespace " << id;
1900-
}
1901-
1902-
if (space != NULL) {
1903-
space->n_pending_ops--;
1904-
}
1905-
1885+
ut_ad(space->magic_n == FIL_SPACE_MAGIC_N);
1886+
ut_ad(space->n_pending_ops > 0);
1887+
space->n_pending_ops--;
19061888
mutex_exit(&fil_system->mutex);
19071889
}
19081890
#endif /* !UNIV_HOTBACKUP */
@@ -2403,25 +2385,27 @@ enum fil_operation_t {
24032385
FIL_OPERATION_TRUNCATE /*!< truncate a single-table tablespace */
24042386
};
24052387

2406-
/*******************************************************************//**
2407-
Check for change buffer merges.
2408-
@return 0 if no merges else count + 1. */
2388+
/** Check for pending operations.
2389+
@param[in] space tablespace
2390+
@param[in] count number of attempts so far
2391+
@return 0 if no operations else count + 1. */
24092392
static
24102393
ulint
2411-
fil_ibuf_check_pending_ops(
2412-
/*=======================*/
2413-
fil_space_t* space, /*!< in/out: Tablespace to check */
2414-
ulint count) /*!< in: number of attempts so far */
2394+
fil_check_pending_ops(
2395+
fil_space_t* space,
2396+
ulint count)
24152397
{
24162398
ut_ad(mutex_own(&fil_system->mutex));
24172399

2418-
if (space != 0 && space->n_pending_ops != 0) {
2400+
const ulint n_pending_ops = space ? space->n_pending_ops : 0;
2401+
2402+
if (n_pending_ops) {
24192403

24202404
if (count > 5000) {
24212405
ib::warn() << "Trying to close/delete/truncate"
24222406
" tablespace '" << space->name
2423-
<< "' but there are " << space->n_pending_ops
2424-
<< " pending change buffer merges on it.";
2407+
<< "' but there are " << n_pending_ops
2408+
<< " pending operations on it.";
24252409
}
24262410

24272411
return(count + 1);
@@ -2506,14 +2490,14 @@ fil_check_pending_operations(
25062490
}
25072491
mutex_exit(&fil_system->mutex);
25082492

2509-
/* Check for pending change buffer merges. */
2493+
/* Check for pending operations. */
25102494

25112495
do {
25122496
mutex_enter(&fil_system->mutex);
25132497

25142498
sp = fil_space_get_by_id(id);
25152499

2516-
count = fil_ibuf_check_pending_ops(sp, count);
2500+
count = fil_check_pending_ops(sp, count);
25172501

25182502
mutex_exit(&fil_system->mutex);
25192503

@@ -6198,8 +6182,8 @@ fil_names_write(
61986182
while fil_check_pending_operations() is waiting for operations
61996183
to quiesce. This is not a problem, because
62006184
ibuf_merge_or_delete_for_page() would call
6201-
fil_inc_pending_ops() before mtr_start() and
6202-
fil_decr_pending_ops() after mtr_commit(). This is why
6185+
fil_space_acquire() before mtr_start() and
6186+
fil_space_release() after mtr_commit(). This is why
62036187
n_pending_ops should not be zero if stop_new_ops is set. */
62046188
ut_ad(!space->stop_new_ops
62056189
|| space->is_being_truncated /* TRUNCATE sets stop_new_ops */

0 commit comments

Comments
 (0)