Skip to content

Commit afc9d00

Browse files
committed
MDEV-23991 dict_table_stats_lock() has unnecessarily long scope
Patch removes dict_index_t::stats_latch. Table/index statistics now protected with dict_sys->mutex. That way statistics computation can happen in parallel in several threads and dict_sys->mutex will be locked only for a short period of time. This patch is a joint work with Marko Mäkelä dict_index_t::lock: make mutable which allows to pass const pointer when only lock is touched in an object btr_height_get() btr_get_size(): make index argument const for better type safety btr_estimate_number_of_different_key_vals(): now returns computed values instead of setting fields in dict_index_t directly remove everything related to dict_index_t::stats_latch dict_stats_index_set_n_diff(): now returns computed values instead of setting fields in dict_index_t directly dict_stats_analyze_index(): now returns computed values instead of setting fields in dict_index_t directly Reviewed by: Marko Mäkelä
1 parent 42e1815 commit afc9d00

File tree

21 files changed

+289
-280
lines changed

21 files changed

+289
-280
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#
2+
# MDEV-23991 dict_table_stats_lock() has unnecessarily long scope
3+
#
4+
CREATE TABLE t1(a INT) ENGINE=INNODB STATS_PERSISTENT=1;
5+
SET DEBUG_SYNC='dict_stats_update_persistent SIGNAL stop WAIT_FOR go';
6+
ANALYZE TABLE t1;
7+
connect con1, localhost, root;
8+
SET DEBUG_SYNC='now WAIT_FOR stop';
9+
SELECT ENGINE,SUM(DATA_LENGTH+INDEX_LENGTH),COUNT(ENGINE),SUM(DATA_LENGTH),SUM(INDEX_LENGTH) FROM information_schema.TABLES WHERE ENGINE='InnoDB';
10+
ENGINE SUM(DATA_LENGTH+INDEX_LENGTH) COUNT(ENGINE) SUM(DATA_LENGTH) SUM(INDEX_LENGTH)
11+
InnoDB 49152 3 49152 0
12+
SET DEBUG_SYNC='now SIGNAL go';
13+
disconnect con1;
14+
connection default;
15+
Table Op Msg_type Msg_text
16+
test.t1 analyze status OK
17+
SET DEBUG_SYNC= 'RESET';
18+
DROP TABLE t1;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--source include/have_innodb.inc
2+
--source include/have_debug.inc
3+
--source include/have_debug_sync.inc
4+
--source include/count_sessions.inc
5+
6+
--echo #
7+
--echo # MDEV-23991 dict_table_stats_lock() has unnecessarily long scope
8+
--echo #
9+
CREATE TABLE t1(a INT) ENGINE=INNODB STATS_PERSISTENT=1;
10+
11+
SET DEBUG_SYNC='dict_stats_update_persistent SIGNAL stop WAIT_FOR go';
12+
--send ANALYZE TABLE t1
13+
14+
--connect(con1, localhost, root)
15+
SET DEBUG_SYNC='now WAIT_FOR stop';
16+
17+
SELECT ENGINE,SUM(DATA_LENGTH+INDEX_LENGTH),COUNT(ENGINE),SUM(DATA_LENGTH),SUM(INDEX_LENGTH) FROM information_schema.TABLES WHERE ENGINE='InnoDB';
18+
19+
SET DEBUG_SYNC='now SIGNAL go';
20+
--disconnect con1
21+
22+
--connection default
23+
--reap
24+
SET DEBUG_SYNC= 'RESET';
25+
DROP TABLE t1;
26+
27+
--source include/wait_until_count_sessions.inc

storage/innobase/btr/btr0btr.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ the index.
283283
ulint
284284
btr_height_get(
285285
/*===========*/
286-
dict_index_t* index,/*!< in: index tree */
286+
const dict_index_t* index,/*!< in: index tree */
287287
mtr_t* mtr)/*!< in/out: mini-transaction */
288288
{
289289
ulint height=0;
@@ -592,7 +592,7 @@ Gets the number of pages in a B-tree.
592592
ulint
593593
btr_get_size(
594594
/*=========*/
595-
dict_index_t* index,/*!< in: index */
595+
const dict_index_t* index,/*!< in: index */
596596
ulint flag,/*!< in: BTR_N_LEAF_PAGES or BTR_TOTAL_SIZE */
597597
mtr_t* mtr)/*!< in/out: mini-transaction where index
598598
is s-latched */

storage/innobase/btr/btr0cur.cc

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6133,21 +6133,19 @@ btr_record_not_null_field_in_rec(
61336133
}
61346134
}
61356135

6136-
/*******************************************************************//**
6137-
Estimates the number of different key values in a given index, for
6136+
/** Estimates the number of different key values in a given index, for
61386137
each n-column prefix of the index where 1 <= n <= dict_index_get_n_unique(index).
61396138
The estimates are stored in the array index->stat_n_diff_key_vals[] (indexed
61406139
0..n_uniq-1) and the number of pages that were sampled is saved in
6141-
index->stat_n_sample_sizes[].
6140+
result.n_sample_sizes[].
61426141
If innodb_stats_method is nulls_ignored, we also record the number of
61436142
non-null values for each prefix and stored the estimates in
6144-
array index->stat_n_non_null_key_vals.
6145-
@return true if the index is available and we get the estimated numbers,
6146-
false if the index is unavailable. */
6147-
bool
6148-
btr_estimate_number_of_different_key_vals(
6149-
/*======================================*/
6150-
dict_index_t* index)/*!< in: index */
6143+
array result.n_non_null_key_vals.
6144+
@param[in] index index
6145+
@return vector with statistics information
6146+
empty vector if the index is unavailable. */
6147+
std::vector<index_field_stats_t>
6148+
btr_estimate_number_of_different_key_vals(dict_index_t* index)
61516149
{
61526150
btr_cur_tcursor;
61536151
page_t* page;
@@ -6167,11 +6165,11 @@ btr_estimate_number_of_different_key_vals(
61676165
rec_offs* offsets_rec = NULL;
61686166
rec_offs* offsets_next_rec = NULL;
61696167

6168+
std::vector<index_field_stats_t> result;
6169+
61706170
/* For spatial index, there is no such stats can be
61716171
fetched. */
6172-
if (dict_index_is_spatial(index)) {
6173-
return(false);
6174-
}
6172+
ut_ad(!dict_index_is_spatial(index));
61756173

61766174
n_cols = dict_index_get_n_unique(index);
61776175

@@ -6280,7 +6278,7 @@ btr_estimate_number_of_different_key_vals(
62806278
mtr_commit(&mtr);
62816279
mem_heap_free(heap);
62826280

6283-
return(false);
6281+
return result;
62846282
}
62856283

62866284
/* Count the number of different key values for each prefix of
@@ -6386,8 +6384,12 @@ btr_estimate_number_of_different_key_vals(
63866384
also the pages used for external storage of fields (those pages are
63876385
included in index->stat_n_leaf_pages) */
63886386

6387+
result.reserve(n_cols);
6388+
63896389
for (j = 0; j < n_cols; j++) {
6390-
index->stat_n_diff_key_vals[j]
6390+
index_field_stats_t stat;
6391+
6392+
stat.n_diff_key_vals
63916393
= BTR_TABLE_STATS_FROM_SAMPLE(
63926394
n_diff[j], index, n_sample_pages,
63936395
total_external_size, not_empty_flag);
@@ -6408,25 +6410,23 @@ btr_estimate_number_of_different_key_vals(
64086410
add_on = n_sample_pages;
64096411
}
64106412

6411-
index->stat_n_diff_key_vals[j] += add_on;
6413+
stat.n_diff_key_vals += add_on;
64126414

6413-
index->stat_n_sample_sizes[j] = n_sample_pages;
6415+
stat.n_sample_sizes = n_sample_pages;
64146416

6415-
/* Update the stat_n_non_null_key_vals[] with our
6416-
sampled result. stat_n_non_null_key_vals[] is created
6417-
and initialized to zero in dict_index_add_to_cache(),
6418-
along with stat_n_diff_key_vals[] array */
64196417
if (n_not_null != NULL) {
6420-
index->stat_n_non_null_key_vals[j] =
6418+
stat.n_non_null_key_vals =
64216419
BTR_TABLE_STATS_FROM_SAMPLE(
64226420
n_not_null[j], index, n_sample_pages,
64236421
total_external_size, not_empty_flag);
64246422
}
6423+
6424+
result.push_back(stat);
64256425
}
64266426

64276427
mem_heap_free(heap);
64286428

6429-
return(true);
6429+
return result;
64306430
}
64316431

64326432
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/

storage/innobase/dict/dict0dict.cc

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -267,56 +267,6 @@ dict_mutex_exit_for_mysql(void)
267267
mutex_exit(&dict_sys->mutex);
268268
}
269269

270-
/** Lock the appropriate latch to protect a given table's statistics.
271-
@param[in] table table whose stats to lock
272-
@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
273-
void
274-
dict_table_stats_lock(
275-
dict_table_t* table,
276-
ulint latch_mode)
277-
{
278-
ut_ad(table != NULL);
279-
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
280-
281-
switch (latch_mode) {
282-
case RW_S_LATCH:
283-
rw_lock_s_lock(&table->stats_latch);
284-
break;
285-
case RW_X_LATCH:
286-
rw_lock_x_lock(&table->stats_latch);
287-
break;
288-
case RW_NO_LATCH:
289-
/* fall through */
290-
default:
291-
ut_error;
292-
}
293-
}
294-
295-
/** Unlock the latch that has been locked by dict_table_stats_lock().
296-
@param[in] table table whose stats to unlock
297-
@param[in] latch_mode RW_S_LATCH or RW_X_LATCH */
298-
void
299-
dict_table_stats_unlock(
300-
dict_table_t* table,
301-
ulint latch_mode)
302-
{
303-
ut_ad(table != NULL);
304-
ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
305-
306-
switch (latch_mode) {
307-
case RW_S_LATCH:
308-
rw_lock_s_unlock(&table->stats_latch);
309-
break;
310-
case RW_X_LATCH:
311-
rw_lock_x_unlock(&table->stats_latch);
312-
break;
313-
case RW_NO_LATCH:
314-
/* fall through */
315-
default:
316-
ut_error;
317-
}
318-
}
319-
320270
/**********************************************************************//**
321271
Try to drop any indexes after an aborted index creation.
322272
This can also be after a server kill during DROP INDEX. */

storage/innobase/dict/dict0mem.cc

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,7 @@ dict_mem_table_create(
125125
ulint n_cols,
126126
ulint n_v_cols,
127127
ulint flags,
128-
ulint flags2,
129-
boolinit_stats_latch)
128+
ulint flags2)
130129
{
131130
dict_table_t* table;
132131
mem_heap_t* heap;
@@ -182,12 +181,6 @@ dict_mem_table_create(
182181
new(&table->foreign_set) dict_foreign_set();
183182
new(&table->referenced_set) dict_foreign_set();
184183

185-
if (init_stats_latch) {
186-
rw_lock_create(dict_table_stats_key, &table->stats_latch,
187-
SYNC_INDEX_TREE);
188-
table->stats_latch_inited = true;
189-
}
190-
191184
return(table);
192185
}
193186

@@ -237,10 +230,6 @@ dict_mem_table_free(
237230
UT_DELETE(table->s_cols);
238231
}
239232

240-
if (table->stats_latch_inited) {
241-
rw_lock_free(&table->stats_latch);
242-
}
243-
244233
mem_heap_free(table->heap);
245234
}
246235

0 commit comments

Comments
 (0)