summaryrefslogtreecommitdiff
path: root/storage/innobase/fil
diff options
context:
space:
mode:
authorSunny Bains <Sunny.Bains@Oracle.Com>2010-08-20 17:49:43 +1000
committerSunny Bains <Sunny.Bains@Oracle.Com>2010-08-20 17:49:43 +1000
commit81da9b3d72a6d971f686613129679661524e2dd4 (patch)
tree547d4703d2293d11a22e2f1360b8afe0db57ba2d /storage/innobase/fil
parent3daf6d3d73168971dfba30f7a248a6a48fca5691 (diff)
downloadmariadb-git-81da9b3d72a6d971f686613129679661524e2dd4.tar.gz
Fix Bug #54538 - use of exclusive innodb dictionary lock limits performance.
This patch doesn't get rid of the need to acquire the dict_sys->mutex but reduces the need to keep the mutex locked for the duration of the query to fsp_get_available_space_in_free_extents() from ha_innobase::info(). rb://390.
Diffstat (limited to 'storage/innobase/fil')
-rw-r--r--storage/innobase/fil/fil0fil.c104
1 files changed, 87 insertions, 17 deletions
diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c
index 3810fefd3cb..6ca8381ebdf 100644
--- a/storage/innobase/fil/fil0fil.c
+++ b/storage/innobase/fil/fil0fil.c
@@ -966,6 +966,8 @@ try_again:
HASH_SEARCH(name_hash, system->name_hash, ut_fold_string(name), space,
0 == strcmp(name, space->name));
if (space != NULL) {
+ ibool success;
+
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Warning: trying to init to the"
@@ -1002,9 +1004,10 @@ try_again:
namesake_id = space->id;
- mutex_exit(&(system->mutex));
+ success = fil_space_free(namesake_id, FALSE);
+ ut_a(success);
- fil_space_free(namesake_id);
+ mutex_exit(&(system->mutex));
goto try_again;
}
@@ -1128,6 +1131,33 @@ fil_assign_new_space_id(void)
}
/***********************************************************************
+Check if the space id exists in the cache, complain to stderr if the
+space id cannot be found. */
+static
+fil_space_t*
+fil_space_search(
+/*=============*/
+ /* out: file space instance*/
+ ulint id) /* in: space id */
+{
+ fil_space_t* space;
+
+ ut_ad(mutex_own(&fil_system->mutex));
+
+ HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
+
+ if (space == NULL) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB: Error: trying to remove tablespace %lu"
+ " from the cache but\n"
+ "InnoDB: it is not there.\n", (ulong) id);
+ }
+
+ return(space);
+}
+
+/***********************************************************************
Frees a space object from the tablespace memory cache. Closes the files in
the chain but does not delete them. There must not be any pending i/o's or
flushes on the files. */
@@ -1135,27 +1165,21 @@ flushes on the files. */
ibool
fil_space_free(
/*===========*/
- /* out: TRUE if success */
- ulint id) /* in: space id */
+ /* out: TRUE if success */
+ ulint id, /* in: space id */
+ ibool x_latched) /* in: TRUE if caller has space->latch
+ in X mode */
{
fil_system_t* system = fil_system;
fil_space_t* space;
fil_space_t* namespace;
fil_node_t* fil_node;
- mutex_enter(&(system->mutex));
+ ut_ad(mutex_own(&fil_system->mutex));
- HASH_SEARCH(hash, system->spaces, id, space, space->id == id);
-
- if (!space) {
- ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: trying to remove tablespace %lu"
- " from the cache but\n"
- "InnoDB: it is not there.\n", (ulong) id);
-
- mutex_exit(&(system->mutex));
+ space = fil_space_search(id);
+ if (space == NULL) {
return(FALSE);
}
@@ -1191,7 +1215,9 @@ fil_space_free(
ut_a(0 == UT_LIST_GET_LEN(space->chain));
- mutex_exit(&(system->mutex));
+ if (x_latched) {
+ rw_lock_x_unlock(&space->latch);
+ }
rw_lock_free(&(space->latch));
@@ -2048,6 +2074,19 @@ try_again:
path = mem_strdup(space->name);
mutex_exit(&(system->mutex));
+
+ /* Important: We rely on the data dictionary mutex to ensure
+ that a race is not possible here. It should serialize the tablespace
+ drop/free. We acquire an X latch only to avoid a race condition
+ when accessing the tablespace instance via:
+
+ fsp_get_available_space_in_free_extents().
+
+ There our main motivation is to reduce the contention on the
+ dictionary mutex and not correctness. */
+
+ rw_lock_x_lock(&space->latch);
+
#ifndef UNIV_HOTBACKUP
/* Invalidate in the buffer pool all pages belonging to the
tablespace. Since we have set space->is_being_deleted = TRUE, readahead
@@ -2060,7 +2099,11 @@ try_again:
#endif
/* printf("Deleting tablespace %s id %lu\n", space->name, id); */
- success = fil_space_free(id);
+ mutex_enter(&system->mutex);
+
+ success = fil_space_free(id, TRUE);
+
+ mutex_exit(&system->mutex);
if (success) {
success = os_file_delete(path);
@@ -2068,6 +2111,8 @@ try_again:
if (!success) {
success = os_file_delete_if_exists(path);
}
+ } else {
+ rw_lock_x_unlock(&space->latch);
}
if (success) {
@@ -4569,3 +4614,28 @@ fil_page_get_type(
return(mach_read_from_2(page + FIL_PAGE_TYPE));
}
+
+/***********************************************************************
+Returns TRUE if a single-table tablespace is being deleted. */
+
+ibool
+fil_tablespace_is_being_deleted(
+/*============================*/
+ /* out: TRUE if space is being deleted */
+ ulint id) /* in: space id */
+{
+ fil_space_t* space;
+ ibool is_being_deleted;
+
+ mutex_enter(&fil_system->mutex);
+
+ HASH_SEARCH(hash, fil_system->spaces, id, space, space->id == id);
+
+ ut_a(space != NULL);
+
+ is_being_deleted = space->is_being_deleted;
+
+ mutex_exit(&fil_system->mutex);
+
+ return(is_being_deleted);
+}