Commit 92cbe388 authored by Jan Lindström's avatar Jan Lindström

MDEV-13325: InnoDB assert dict_sys->size > 0 during ALTER TABLE

Problem was that dict_sys->size tries to maintain used memory
occupied by the data dictionary table and index objects.
However at least on table objects table->heap size can increase
between when table object is inserted to dict_sys and when
it is removed from dict_sys causing inconsistency on amount
of memory added to and removed from dict_sys->size variable.

Removed unnecessary dict_sys:size variable as it is really
used only for status output.

Introduced dict_sys_get_size function to calculate memory
occupied by the data dictionary table and index objects
that is then used on show engine innodb output.

dict_table_add_to_cache(),
dict_table_rename_in_cache(),
dict_table_remove_from_cache_low(),
dict_index_remove_from_cache_low(),
	Remove size calculation.

srv_printf_innodb_monitor(): Use dict_sys_get_size function to
get dictionary memory allocated.

xtradb_internal_hash_tables_fill_table(): Use dict_sys_get_size
function to get dictionary memory allocated.
parent 0ec147b6
...@@ -1365,9 +1365,6 @@ dict_table_add_to_cache( ...@@ -1365,9 +1365,6 @@ dict_table_add_to_cache(
dict_table_autoinc_restore(table); dict_table_autoinc_restore(table);
ut_ad(dict_lru_validate()); ut_ad(dict_lru_validate());
dict_sys->size += mem_heap_get_size(table->heap)
+ strlen(table->name) + 1;
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -1782,9 +1779,6 @@ dict_table_rename_in_cache( ...@@ -1782,9 +1779,6 @@ dict_table_rename_in_cache(
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
table); table);
dict_sys->size += strlen(new_name) - strlen(old_name);
ut_a(dict_sys->size > 0);
/* Update the table_name field in indexes */ /* Update the table_name field in indexes */
for (index = dict_table_get_first_index(table); for (index = dict_table_get_first_index(table);
index != NULL; index != NULL;
...@@ -2071,7 +2065,6 @@ dict_table_remove_from_cache_low( ...@@ -2071,7 +2065,6 @@ dict_table_remove_from_cache_low(
{ {
dict_foreign_t* foreign; dict_foreign_t* foreign;
dict_index_t* index; dict_index_t* index;
ulint size;
ut_ad(table); ut_ad(table);
ut_ad(dict_lru_validate()); ut_ad(dict_lru_validate());
...@@ -2151,12 +2144,6 @@ dict_table_remove_from_cache_low( ...@@ -2151,12 +2144,6 @@ dict_table_remove_from_cache_low(
trx_free_for_background(trx); trx_free_for_background(trx);
} }
size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
ut_ad(dict_sys->size >= size);
dict_sys->size -= size;
dict_mem_table_free(table); dict_mem_table_free(table);
} }
...@@ -2692,8 +2679,6 @@ dict_index_add_to_cache( ...@@ -2692,8 +2679,6 @@ dict_index_add_to_cache(
dict_index_is_ibuf(index) dict_index_is_ibuf(index)
? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE); ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
dict_sys->size += mem_heap_get_size(new_index->heap);
dict_mem_index_free(index); dict_mem_index_free(index);
return(DB_SUCCESS); return(DB_SUCCESS);
...@@ -2710,7 +2695,6 @@ dict_index_remove_from_cache_low( ...@@ -2710,7 +2695,6 @@ dict_index_remove_from_cache_low(
ibool lru_evict) /*!< in: TRUE if index being evicted ibool lru_evict) /*!< in: TRUE if index being evicted
to make room in the table LRU list */ to make room in the table LRU list */
{ {
ulint size;
ulint retries = 0; ulint retries = 0;
btr_search_t* info; btr_search_t* info;
...@@ -2778,12 +2762,6 @@ dict_index_remove_from_cache_low( ...@@ -2778,12 +2762,6 @@ dict_index_remove_from_cache_low(
/* Remove the index from the list of indexes of the table */ /* Remove the index from the list of indexes of the table */
UT_LIST_REMOVE(indexes, table->indexes, index); UT_LIST_REMOVE(indexes, table->indexes, index);
size = mem_heap_get_size(index->heap);
ut_ad(dict_sys->size >= size);
dict_sys->size -= size;
dict_mem_index_free(index); dict_mem_index_free(index);
} }
...@@ -7258,3 +7236,38 @@ dict_tf_to_row_format_string( ...@@ -7258,3 +7236,38 @@ dict_tf_to_row_format_string(
return(0); return(0);
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/** Calculate the used memory occupied by the data dictionary
table and index objects.
@return number of bytes occupied. */
UNIV_INTERN
ulint
dict_sys_get_size()
{
ulint size = 0;
ut_ad(dict_sys);
mutex_enter(&dict_sys->mutex);
for(ulint i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
dict_table_t* table;
for (table = static_cast<dict_table_t*>(HASH_GET_FIRST(dict_sys->table_hash,i));
table != NULL;
table = static_cast<dict_table_t*>(HASH_GET_NEXT(name_hash, table))) {
dict_index_t* index;
size += mem_heap_get_size(table->heap) + strlen(table->name) +1;
for(index = dict_table_get_first_index(table);
index != NULL;
index = dict_table_get_next_index(index)) {
size += mem_heap_get_size(index->heap);
}
}
}
mutex_exit(&dict_sys->mutex);
return (size);
}
...@@ -1614,9 +1614,6 @@ struct dict_sys_t{ ...@@ -1614,9 +1614,6 @@ struct dict_sys_t{
on name */ on name */
hash_table_t* table_id_hash; /*!< hash table of the tables, based hash_table_t* table_id_hash; /*!< hash table of the tables, based
on id */ on id */
ulint size; /*!< varying space in bytes occupied
by the data dictionary table and
index objects */
dict_table_t* sys_tables; /*!< SYS_TABLES table */ dict_table_t* sys_tables; /*!< SYS_TABLES table */
dict_table_t* sys_columns; /*!< SYS_COLUMNS table */ dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
dict_table_t* sys_indexes; /*!< SYS_INDEXES table */ dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
...@@ -1861,6 +1858,13 @@ dict_table_get_index_on_first_col( ...@@ -1861,6 +1858,13 @@ dict_table_get_index_on_first_col(
ulint col_index); /*!< in: position of column ulint col_index); /*!< in: position of column
in table */ in table */
/** Calculate the used memory occupied by the data dictionary
table and index objects.
@return number of bytes occupied. */
UNIV_INTERN
ulint
dict_sys_get_size();
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
#ifndef UNIV_NONINL #ifndef UNIV_NONINL
......
...@@ -1283,7 +1283,7 @@ srv_printf_innodb_monitor( ...@@ -1283,7 +1283,7 @@ srv_printf_innodb_monitor(
ut_total_allocated_memory, ut_total_allocated_memory,
mem_pool_get_reserved(mem_comm_pool)); mem_pool_get_reserved(mem_comm_pool));
fprintf(file, "Dictionary memory allocated " ULINTPF "\n", fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
dict_sys->size); dict_sys_get_size());
buf_print_io(file); buf_print_io(file);
......
...@@ -1374,9 +1374,6 @@ dict_table_add_to_cache( ...@@ -1374,9 +1374,6 @@ dict_table_add_to_cache(
dict_table_autoinc_restore(table); dict_table_autoinc_restore(table);
ut_ad(dict_lru_validate()); ut_ad(dict_lru_validate());
dict_sys->size += mem_heap_get_size(table->heap)
+ strlen(table->name) + 1;
} }
/**********************************************************************//** /**********************************************************************//**
...@@ -1791,9 +1788,6 @@ dict_table_rename_in_cache( ...@@ -1791,9 +1788,6 @@ dict_table_rename_in_cache(
HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold,
table); table);
dict_sys->size += strlen(new_name) - strlen(old_name);
ut_a(dict_sys->size > 0);
/* Update the table_name field in indexes */ /* Update the table_name field in indexes */
for (index = dict_table_get_first_index(table); for (index = dict_table_get_first_index(table);
index != NULL; index != NULL;
...@@ -2080,7 +2074,6 @@ dict_table_remove_from_cache_low( ...@@ -2080,7 +2074,6 @@ dict_table_remove_from_cache_low(
{ {
dict_foreign_t* foreign; dict_foreign_t* foreign;
dict_index_t* index; dict_index_t* index;
ulint size;
ut_ad(table); ut_ad(table);
ut_ad(dict_lru_validate()); ut_ad(dict_lru_validate());
...@@ -2160,12 +2153,6 @@ dict_table_remove_from_cache_low( ...@@ -2160,12 +2153,6 @@ dict_table_remove_from_cache_low(
trx_free_for_background(trx); trx_free_for_background(trx);
} }
size = mem_heap_get_size(table->heap) + strlen(table->name) + 1;
ut_ad(dict_sys->size >= size);
dict_sys->size -= size;
dict_mem_table_free(table); dict_mem_table_free(table);
} }
...@@ -2701,8 +2688,6 @@ dict_index_add_to_cache( ...@@ -2701,8 +2688,6 @@ dict_index_add_to_cache(
dict_index_is_ibuf(index) dict_index_is_ibuf(index)
? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE); ? SYNC_IBUF_INDEX_TREE : SYNC_INDEX_TREE);
dict_sys->size += mem_heap_get_size(new_index->heap);
dict_mem_index_free(index); dict_mem_index_free(index);
return(DB_SUCCESS); return(DB_SUCCESS);
...@@ -2719,7 +2704,6 @@ dict_index_remove_from_cache_low( ...@@ -2719,7 +2704,6 @@ dict_index_remove_from_cache_low(
ibool lru_evict) /*!< in: TRUE if index being evicted ibool lru_evict) /*!< in: TRUE if index being evicted
to make room in the table LRU list */ to make room in the table LRU list */
{ {
ulint size;
ulint retries = 0; ulint retries = 0;
btr_search_t* info; btr_search_t* info;
...@@ -2788,12 +2772,6 @@ dict_index_remove_from_cache_low( ...@@ -2788,12 +2772,6 @@ dict_index_remove_from_cache_low(
/* Remove the index from the list of indexes of the table */ /* Remove the index from the list of indexes of the table */
UT_LIST_REMOVE(indexes, table->indexes, index); UT_LIST_REMOVE(indexes, table->indexes, index);
size = mem_heap_get_size(index->heap);
ut_ad(dict_sys->size >= size);
dict_sys->size -= size;
dict_mem_index_free(index); dict_mem_index_free(index);
} }
...@@ -7296,3 +7274,38 @@ dict_tf_to_row_format_string( ...@@ -7296,3 +7274,38 @@ dict_tf_to_row_format_string(
return(0); return(0);
} }
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/** Calculate the used memory occupied by the data dictionary
table and index objects.
@return number of bytes occupied. */
UNIV_INTERN
ulint
dict_sys_get_size()
{
ulint size = 0;
ut_ad(dict_sys);
mutex_enter(&dict_sys->mutex);
for(ulint i = 0; i < hash_get_n_cells(dict_sys->table_hash); i++) {
dict_table_t* table;
for (table = static_cast<dict_table_t*>(HASH_GET_FIRST(dict_sys->table_hash,i));
table != NULL;
table = static_cast<dict_table_t*>(HASH_GET_NEXT(name_hash, table))) {
dict_index_t* index;
size += mem_heap_get_size(table->heap) + strlen(table->name) +1;
for(index = dict_table_get_first_index(table);
index != NULL;
index = dict_table_get_next_index(index)) {
size += mem_heap_get_size(index->heap);
}
}
}
mutex_exit(&dict_sys->mutex);
return (size);
}
...@@ -401,19 +401,20 @@ static int xtradb_internal_hash_tables_fill_table(THD* thd, TABLE_LIST* tables, ...@@ -401,19 +401,20 @@ static int xtradb_internal_hash_tables_fill_table(THD* thd, TABLE_LIST* tables,
if (dict_sys) if (dict_sys)
{ {
ulint dict_size = dict_sys_get_size();
OK(field_store_string(fields[INT_HASH_TABLES_NAME], OK(field_store_string(fields[INT_HASH_TABLES_NAME],
"Dictionary Cache")); "Dictionary Cache"));
OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL], OK(field_store_ulint(fields[INT_HASH_TABLES_TOTAL],
((dict_sys->table_hash->n_cells ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells + dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t) ) * sizeof(hash_cell_t)
+ dict_sys->size))); + dict_size)));
OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT], OK(field_store_ulint(fields[INT_HASH_TABLES_CONSTANT],
((dict_sys->table_hash->n_cells ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells + dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t)))); ) * sizeof(hash_cell_t))));
OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE], OK(field_store_ulint(fields[INT_HASH_TABLES_VARIABLE],
dict_sys->size)); dict_size));
OK(schema_table_store_record(thd, table)); OK(schema_table_store_record(thd, table));
} }
......
...@@ -1617,9 +1617,6 @@ struct dict_sys_t{ ...@@ -1617,9 +1617,6 @@ struct dict_sys_t{
on name */ on name */
hash_table_t* table_id_hash; /*!< hash table of the tables, based hash_table_t* table_id_hash; /*!< hash table of the tables, based
on id */ on id */
ulint size; /*!< varying space in bytes occupied
by the data dictionary table and
index objects */
dict_table_t* sys_tables; /*!< SYS_TABLES table */ dict_table_t* sys_tables; /*!< SYS_TABLES table */
dict_table_t* sys_columns; /*!< SYS_COLUMNS table */ dict_table_t* sys_columns; /*!< SYS_COLUMNS table */
dict_table_t* sys_indexes; /*!< SYS_INDEXES table */ dict_table_t* sys_indexes; /*!< SYS_INDEXES table */
...@@ -1863,6 +1860,13 @@ dict_table_get_index_on_first_col( ...@@ -1863,6 +1860,13 @@ dict_table_get_index_on_first_col(
ulint col_index); /*!< in: position of column ulint col_index); /*!< in: position of column
in table */ in table */
/** Calculate the used memory occupied by the data dictionary
table and index objects.
@return number of bytes occupied. */
UNIV_INTERN
ulint
dict_sys_get_size();
#endif /* !UNIV_HOTBACKUP */ #endif /* !UNIV_HOTBACKUP */
/************************************************************************* /*************************************************************************
set is_corrupt flag by space_id*/ set is_corrupt flag by space_id*/
......
...@@ -1520,6 +1520,8 @@ srv_printf_innodb_monitor( ...@@ -1520,6 +1520,8 @@ srv_printf_innodb_monitor(
recv_sys_subtotal = ((recv_sys && recv_sys->addr_hash) recv_sys_subtotal = ((recv_sys && recv_sys->addr_hash)
? mem_heap_get_size(recv_sys->heap) : 0); ? mem_heap_get_size(recv_sys->heap) : 0);
ulint dict_size = dict_sys ? dict_sys_get_size() : 0;
fprintf(file, fprintf(file,
"Internal hash tables (constant factor + variable factor)\n" "Internal hash tables (constant factor + variable factor)\n"
" Adaptive hash index %lu \t(%lu + " ULINTPF ")\n" " Adaptive hash index %lu \t(%lu + " ULINTPF ")\n"
...@@ -1538,11 +1540,11 @@ srv_printf_innodb_monitor( ...@@ -1538,11 +1540,11 @@ srv_printf_innodb_monitor(
(ulong) (dict_sys ? ((dict_sys->table_hash->n_cells (ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells + dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t) ) * sizeof(hash_cell_t)
+ dict_sys->size) : 0), + dict_size) : 0),
(ulong) (dict_sys ? ((dict_sys->table_hash->n_cells (ulong) (dict_sys ? ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells + dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t)) : 0), ) * sizeof(hash_cell_t)) : 0),
dict_sys ? (dict_sys->size) : 0, dict_size,
(ulong) (fil_system_hash_cells() * sizeof(hash_cell_t) (ulong) (fil_system_hash_cells() * sizeof(hash_cell_t)
+ fil_system_hash_nodes()), + fil_system_hash_nodes()),
...@@ -1563,7 +1565,7 @@ srv_printf_innodb_monitor( ...@@ -1563,7 +1565,7 @@ srv_printf_innodb_monitor(
fprintf(file, "Dictionary memory allocated " ULINTPF "\n", fprintf(file, "Dictionary memory allocated " ULINTPF "\n",
dict_sys ? dict_sys->size : 0); dict_sys ? dict_sys_get_size() : 0);
buf_print_io(file); buf_print_io(file);
...@@ -1719,7 +1721,7 @@ srv_export_innodb_status(void) ...@@ -1719,7 +1721,7 @@ srv_export_innodb_status(void)
mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells mem_dictionary = (dict_sys ? ((dict_sys->table_hash->n_cells
+ dict_sys->table_id_hash->n_cells + dict_sys->table_id_hash->n_cells
) * sizeof(hash_cell_t) ) * sizeof(hash_cell_t)
+ dict_sys->size) : 0); + dict_sys_get_size()) : 0);
mutex_enter(&srv_innodb_monitor_mutex); mutex_enter(&srv_innodb_monitor_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