Commit 463d8e33 authored by marko's avatar marko

Port r150 from branches/5.0: Port r19 from innodb-4.1/trunk:

Keep track on unflushed modifications to file spaces.  When there are tens
of thousands of file spaces, flushing all files in fil_flush_file_spaces()
would be very slow.  (Bug #15653)

fil_flush_file_spaces(): Only flush unflushed file spaces.

fil_space_t, fil_system_t: Add a list of unflushed spaces.
parent 553062fb
...@@ -181,6 +181,11 @@ struct fil_space_struct { ...@@ -181,6 +181,11 @@ struct fil_space_struct {
hash_node_t name_hash;/* hash chain the name_hash table */ hash_node_t name_hash;/* hash chain the name_hash table */
rw_lock_t latch; /* latch protecting the file space storage rw_lock_t latch; /* latch protecting the file space storage
allocation */ allocation */
UT_LIST_NODE_T(fil_space_t) unflushed_spaces;
/* list of spaces with at least one unflushed
file we have written to */
ibool is_in_unflushed_spaces; /* TRUE if this space is
currently in the list above */
UT_LIST_NODE_T(fil_space_t) space_list; UT_LIST_NODE_T(fil_space_t) space_list;
/* list of all spaces */ /* list of all spaces */
ibuf_data_t* ibuf_data; ibuf_data_t* ibuf_data;
...@@ -213,6 +218,12 @@ struct fil_system_struct { ...@@ -213,6 +218,12 @@ struct fil_system_struct {
not put to this list: they are opened not put to this list: they are opened
after the startup, and kept open until after the startup, and kept open until
shutdown */ shutdown */
UT_LIST_BASE_NODE_T(fil_space_t) unflushed_spaces;
/* base node for the list of those
tablespaces whose files contain
unflushed writes; those spaces have
at least one file node where
modification_counter > flush_counter */
ulint n_open; /* number of files currently open */ ulint n_open; /* number of files currently open */
ulint max_n_open; /* n_open is not allowed to exceed ulint max_n_open; /* n_open is not allowed to exceed
this */ this */
...@@ -389,6 +400,36 @@ fil_space_get_ibuf_data( ...@@ -389,6 +400,36 @@ fil_space_get_ibuf_data(
return(space->ibuf_data); return(space->ibuf_data);
} }
/**************************************************************************
Checks if all the file nodes in a space are flushed. The caller must hold
the fil_system mutex. */
static
ibool
fil_space_is_flushed(
/*=================*/
/* out: TRUE if all are flushed */
fil_space_t* space) /* in: space */
{
fil_node_t* node;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(fil_system->mutex)));
#endif /* UNIV_SYNC_DEBUG */
node = UT_LIST_GET_FIRST(space->chain);
while (node) {
if (node->modification_counter > node->flush_counter) {
return(FALSE);
}
node = UT_LIST_GET_NEXT(chain, node);
}
return(TRUE);
}
/*********************************************************************** /***********************************************************************
Appends a new file to the chain of files of a space. File must be closed. */ Appends a new file to the chain of files of a space. File must be closed. */
...@@ -841,6 +882,16 @@ fil_node_free( ...@@ -841,6 +882,16 @@ fil_node_free(
node->modification_counter = node->flush_counter; node->modification_counter = node->flush_counter;
if (space->is_in_unflushed_spaces
&& fil_space_is_flushed(space)) {
space->is_in_unflushed_spaces = FALSE;
UT_LIST_REMOVE(unflushed_spaces,
system->unflushed_spaces,
space);
}
fil_node_close_file(node, system); fil_node_close_file(node, system);
} }
...@@ -1004,6 +1055,8 @@ fil_space_create( ...@@ -1004,6 +1055,8 @@ fil_space_create(
HASH_INSERT(fil_space_t, name_hash, system->name_hash, HASH_INSERT(fil_space_t, name_hash, system->name_hash,
ut_fold_string(name), space); ut_fold_string(name), space);
space->is_in_unflushed_spaces = FALSE;
UT_LIST_ADD_LAST(space_list, system->space_list, space); UT_LIST_ADD_LAST(space_list, system->space_list, space);
mutex_exit(&(system->mutex)); mutex_exit(&(system->mutex));
...@@ -1099,6 +1152,13 @@ fil_space_free( ...@@ -1099,6 +1152,13 @@ fil_space_free(
HASH_DELETE(fil_space_t, name_hash, system->name_hash, HASH_DELETE(fil_space_t, name_hash, system->name_hash,
ut_fold_string(space->name), space); ut_fold_string(space->name), space);
if (space->is_in_unflushed_spaces) {
space->is_in_unflushed_spaces = FALSE;
UT_LIST_REMOVE(unflushed_spaces, system->unflushed_spaces,
space);
}
UT_LIST_REMOVE(space_list, system->space_list, space); UT_LIST_REMOVE(space_list, system->space_list, space);
ut_a(space->magic_n == FIL_SPACE_MAGIC_N); ut_a(space->magic_n == FIL_SPACE_MAGIC_N);
...@@ -1250,6 +1310,7 @@ fil_system_create( ...@@ -1250,6 +1310,7 @@ fil_system_create(
system->tablespace_version = 0; system->tablespace_version = 0;
UT_LIST_INIT(system->unflushed_spaces);
UT_LIST_INIT(system->space_list); UT_LIST_INIT(system->space_list);
return(system); return(system);
...@@ -3742,6 +3803,14 @@ fil_node_complete_io( ...@@ -3742,6 +3803,14 @@ fil_node_complete_io(
if (type == OS_FILE_WRITE) { if (type == OS_FILE_WRITE) {
system->modification_counter++; system->modification_counter++;
node->modification_counter = system->modification_counter; node->modification_counter = system->modification_counter;
if (!node->space->is_in_unflushed_spaces) {
node->space->is_in_unflushed_spaces = TRUE;
UT_LIST_ADD_FIRST(unflushed_spaces,
system->unflushed_spaces,
node->space);
}
} }
if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE if (node->n_pending == 0 && node->space->purpose == FIL_TABLESPACE
...@@ -4162,6 +4231,16 @@ fil_flush( ...@@ -4162,6 +4231,16 @@ fil_flush(
skip_flush: skip_flush:
if (node->flush_counter < old_mod_counter) { if (node->flush_counter < old_mod_counter) {
node->flush_counter = old_mod_counter; node->flush_counter = old_mod_counter;
if (space->is_in_unflushed_spaces
&& fil_space_is_flushed(space)) {
space->is_in_unflushed_spaces = FALSE;
UT_LIST_REMOVE(unflushed_spaces,
system->unflushed_spaces,
space);
}
} }
if (space->purpose == FIL_TABLESPACE) { if (space->purpose == FIL_TABLESPACE) {
...@@ -4193,7 +4272,7 @@ fil_flush_file_spaces( ...@@ -4193,7 +4272,7 @@ fil_flush_file_spaces(
mutex_enter(&(system->mutex)); mutex_enter(&(system->mutex));
space = UT_LIST_GET_FIRST(system->space_list); space = UT_LIST_GET_FIRST(system->unflushed_spaces);
while (space) { while (space) {
if (space->purpose == purpose && !space->is_being_deleted) { if (space->purpose == purpose && !space->is_being_deleted) {
...@@ -4209,7 +4288,7 @@ fil_flush_file_spaces( ...@@ -4209,7 +4288,7 @@ fil_flush_file_spaces(
space->n_pending_flushes--; space->n_pending_flushes--;
} }
space = UT_LIST_GET_NEXT(space_list, space); space = UT_LIST_GET_NEXT(unflushed_spaces, space);
} }
mutex_exit(&(system->mutex)); mutex_exit(&(system->mutex));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment