diff options
author | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2018-01-23 18:04:34 +0200 |
---|---|---|
committer | Vicențiu Ciorbaru <vicentiu@mariadb.org> | 2018-01-23 18:04:34 +0200 |
commit | cd33250d2acf65361ee2ead625c626bfd2f51046 (patch) | |
tree | 99a17eed2623f31a1c2b9373cf82fce3e762cca4 /storage | |
parent | b4606367d7ba82652a346320d458c25c391847ea (diff) | |
download | mariadb-git-cd33250d2acf65361ee2ead625c626bfd2f51046.tar.gz |
5.6.38-83.0
Diffstat (limited to 'storage')
34 files changed, 604 insertions, 99 deletions
diff --git a/storage/xtradb/btr/btr0pcur.cc b/storage/xtradb/btr/btr0pcur.cc index 28a60de6ba2..2965cbcaf9e 100644 --- a/storage/xtradb/btr/btr0pcur.cc +++ b/storage/xtradb/btr/btr0pcur.cc @@ -33,6 +33,40 @@ Created 2/23/1996 Heikki Tuuri #include "rem0cmp.h" #include "trx0trx.h" #include "srv0srv.h" + +/** Updates fragmentation statistics for a single page transition. +@param[in] page the current page being processed +@param[in] page_no page number to move to (next_page_no + if forward_direction is true, + prev_page_no otherwise. +@param[in] forward_direction move direction: true means moving + forward, false - backward. */ +static +void +btr_update_scan_stats(const page_t* page, ulint page_no, bool forward_direction) +{ + fragmentation_stats_t stats; + memset(&stats, 0, sizeof(stats)); + ulint extracted_page_no = page_get_page_no(page); + ulint delta = forward_direction ? + page_no - extracted_page_no : + extracted_page_no - page_no; + + if (delta == 1) { + ++stats.scan_pages_contiguous; + } else { + ++stats.scan_pages_disjointed; + } + stats.scan_pages_total_seek_distance += + extracted_page_no > page_no ? + extracted_page_no - page_no : + page_no - extracted_page_no; + + stats.scan_data_size += page_get_data_size(page); + stats.scan_deleted_recs_size += + page_header_get_field(page, PAGE_GARBAGE); + thd_add_fragmentation_stats(current_thd, &stats); +} /**************************************************************//** Allocates memory for a persistent cursor object and initializes the cursor. @return own: persistent cursor */ @@ -426,6 +460,8 @@ btr_pcur_move_to_next_page( ut_ad(next_page_no != FIL_NULL); + btr_update_scan_stats(page, next_page_no, true /* forward */); + next_block = btr_block_get(space, zip_size, next_page_no, cursor->latch_mode, btr_pcur_get_btr_cur(cursor)->index, mtr); @@ -509,6 +545,10 @@ btr_pcur_move_backward_from_page( prev_page_no = btr_page_get_prev(page, mtr); + if (prev_page_no != FIL_NULL) { + btr_update_scan_stats(page, prev_page_no, false /* backward */); + } + if (prev_page_no == FIL_NULL) { } else if (btr_pcur_is_before_first_on_page(cursor)) { diff --git a/storage/xtradb/buf/buf0rea.cc b/storage/xtradb/buf/buf0rea.cc index c28df72df92..2e935c52a59 100644 --- a/storage/xtradb/buf/buf0rea.cc +++ b/storage/xtradb/buf/buf0rea.cc @@ -123,7 +123,12 @@ buf_read_page_low( use to stop dangling page reads from a tablespace which we have DISCARDed + IMPORTed back */ ulint offset, /*!< in: page number */ - trx_t* trx) + trx_t* trx, + bool should_buffer) /*!< in: whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ { buf_page_t* bpage; ulint wake_later; @@ -229,14 +234,15 @@ not_to_recover: *err = _fil_io(OS_FILE_READ | wake_later | ignore_nonexistent_pages, sync, space, zip_size, offset, 0, zip_size, - bpage->zip.data, bpage, trx); + bpage->zip.data, bpage, trx, should_buffer); } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); *err = _fil_io(OS_FILE_READ | wake_later | ignore_nonexistent_pages, sync, space, 0, offset, 0, UNIV_PAGE_SIZE, - ((buf_block_t*) bpage)->frame, bpage, trx); + ((buf_block_t*) bpage)->frame, bpage, trx, + should_buffer); } if (sync) { @@ -395,7 +401,7 @@ read_ahead: &err, false, ibuf_mode | OS_AIO_SIMULATED_WAKE_LATER, space, zip_size, FALSE, - tablespace_version, i, trx); + tablespace_version, i, trx, false); if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -459,7 +465,7 @@ buf_read_page( count = buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space, zip_size, FALSE, - tablespace_version, offset, trx); + tablespace_version, offset, trx, false); srv_stats.buf_pool_reads.add(count); if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); @@ -507,7 +513,7 @@ buf_read_page_async( | OS_AIO_SIMULATED_WAKE_LATER | BUF_READ_IGNORE_NONEXISTENT_PAGES, space, zip_size, FALSE, - tablespace_version, offset, NULL); + tablespace_version, offset, NULL, false); srv_stats.buf_pool_reads.add(count); /* We do not increment number of I/O operations used for LRU policy @@ -775,7 +781,8 @@ buf_read_ahead_linear( count += buf_read_page_low( &err, false, ibuf_mode, - space, zip_size, FALSE, tablespace_version, i, trx); + space, zip_size, FALSE, tablespace_version, + i, trx, true); if (err == DB_TABLESPACE_DELETED) { ut_print_timestamp(stderr); fprintf(stderr, @@ -788,6 +795,7 @@ buf_read_ahead_linear( } } } + os_aio_dispatch_read_array_submit(); /* In simulated aio we wake the aio handler threads only after queuing all aio requests, in native aio the following call does @@ -865,7 +873,7 @@ buf_read_ibuf_merge_pages( buf_read_page_low(&err, sync && (i + 1 == n_stored), BUF_READ_ANY_PAGE, space_ids[i], zip_size, TRUE, space_versions[i], - page_nos[i], NULL); + page_nos[i], NULL, false); if (UNIV_UNLIKELY(err == DB_TABLESPACE_DELETED)) { tablespace_deleted: @@ -1005,12 +1013,13 @@ not_to_recover: if ((i + 1 == n_stored) && sync) { buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space, zip_size, TRUE, tablespace_version, - page_nos[i], NULL); + page_nos[i], NULL, false); } else { buf_read_page_low(&err, false, BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER, space, zip_size, TRUE, - tablespace_version, page_nos[i], NULL); + tablespace_version, page_nos[i], + NULL, false); } } diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc index 975c8a50803..bc8fbe6ece4 100644 --- a/storage/xtradb/dict/dict0stats_bg.cc +++ b/storage/xtradb/dict/dict0stats_bg.cc @@ -195,7 +195,7 @@ dict_stats_wait_bg_to_stop_using_table( unlocking/locking the data dict */ { while (!dict_stats_stop_bg(table)) { - DICT_STATS_BG_YIELD(trx); + DICT_BG_YIELD(trx); } } diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index d701bddebfc..081c518afec 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -5253,7 +5253,7 @@ retry: success = os_aio(OS_FILE_WRITE, OS_AIO_SYNC, node->name, node->handle, buf, offset, page_size * n_pages, - NULL, NULL, space_id, NULL); + NULL, NULL, space_id, NULL, false); #endif /* UNIV_HOTBACKUP */ if (success) { os_has_said_disk_full = FALSE; @@ -5630,7 +5630,12 @@ _fil_io( appropriately aligned */ void* message, /*!< in: message for aio handler if non-sync aio used, else ignored */ - trx_t* trx) + trx_t* trx, + bool should_buffer) /*!< in: whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ { ulint mode; fil_space_t* space; @@ -5848,7 +5853,7 @@ _fil_io( /* Queue the aio request */ ret = os_aio(type, mode | wake_later, node->name, node->handle, buf, - offset, len, node, message, space_id, trx); + offset, len, node, message, space_id, trx, should_buffer); #else /* In mysqlbackup do normal i/o, not aio */ diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index a0f0fab5566..a29e046eb84 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -25,6 +25,7 @@ Full Text Search interface #include "row0mysql.h" #include "row0upd.h" #include "dict0types.h" +#include "dict0stats_bg.h" #include "row0sel.h" #include "fts0fts.h" @@ -867,18 +868,37 @@ fts_drop_index( err = fts_drop_index_tables(trx, index); - fts_free(table); - + for(;;) { + bool retry = false; + if (index->index_fts_syncing) { + retry = true; + } + if (!retry){ + fts_free(table); + break; + } + DICT_BG_YIELD(trx); + } return(err); } - current_doc_id = table->fts->cache->next_doc_id; - first_doc_id = table->fts->cache->first_doc_id; - fts_cache_clear(table->fts->cache); - fts_cache_destroy(table->fts->cache); - table->fts->cache = fts_cache_create(table); - table->fts->cache->next_doc_id = current_doc_id; - table->fts->cache->first_doc_id = first_doc_id; + for(;;) { + bool retry = false; + if (index->index_fts_syncing) { + retry = true; + } + if (!retry){ + current_doc_id = table->fts->cache->next_doc_id; + first_doc_id = table->fts->cache->first_doc_id; + fts_cache_clear(table->fts->cache); + fts_cache_destroy(table->fts->cache); + table->fts->cache = fts_cache_create(table); + table->fts->cache->next_doc_id = current_doc_id; + table->fts->cache->first_doc_id = first_doc_id; + break; + } + DICT_BG_YIELD(trx); + } } else { fts_cache_t* cache = table->fts->cache; fts_index_cache_t* index_cache; @@ -888,9 +908,17 @@ fts_drop_index( index_cache = fts_find_index_cache(cache, index); if (index_cache != NULL) { - if (index_cache->words) { - fts_words_free(index_cache->words); - rbt_free(index_cache->words); + for(;;) { + bool retry = false; + if (index->index_fts_syncing) { + retry = true; + } + if (!retry && index_cache->words) { + fts_words_free(index_cache->words); + rbt_free(index_cache->words); + break; + } + DICT_BG_YIELD(trx); } ib_vector_remove(cache->indexes, *(void**) index_cache); @@ -4611,10 +4639,16 @@ begin_sync: index_cache = static_cast<fts_index_cache_t*>( ib_vector_get(cache->indexes, i)); - if (index_cache->index->to_be_dropped) { + if (index_cache->index->to_be_dropped + || index_cache->index->table->to_be_dropped) { continue; } + index_cache->index->index_fts_syncing = true; + DBUG_EXECUTE_IF("fts_instrument_sync_sleep_drop_waits", + os_thread_sleep(10000000); + ); + error = fts_sync_index(sync, index_cache); if (error != DB_SUCCESS && !sync->interrupted) { @@ -4647,11 +4681,33 @@ begin_sync: end_sync: if (error == DB_SUCCESS && !sync->interrupted) { error = fts_sync_commit(sync); + if (error == DB_SUCCESS) { + for (i = 0; i < ib_vector_size(cache->indexes); ++i) { + fts_index_cache_t* index_cache; + index_cache = static_cast<fts_index_cache_t*>( + ib_vector_get(cache->indexes, i)); + if (index_cache->index->index_fts_syncing) { + index_cache->index->index_fts_syncing + = false; + } + } + } } else { fts_sync_rollback(sync); } rw_lock_x_lock(&cache->lock); + /* Clear fts syncing flags of any indexes incase sync is + interrupeted */ + for (i = 0; i < ib_vector_size(cache->indexes); ++i) { + fts_index_cache_t* index_cache; + index_cache = static_cast<fts_index_cache_t*>( + ib_vector_get(cache->indexes, i)); + if (index_cache->index->index_fts_syncing == true) { + index_cache->index->index_fts_syncing = false; + } + } + sync->interrupted = false; sync->in_progress = false; os_event_set(sync->event); diff --git a/storage/xtradb/fts/fts0opt.cc b/storage/xtradb/fts/fts0opt.cc index 19098dc00ef..0a9728abe1d 100644 --- a/storage/xtradb/fts/fts0opt.cc +++ b/storage/xtradb/fts/fts0opt.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -2970,13 +2970,6 @@ fts_optimize_sync_table( { dict_table_t* table = NULL; - /* Prevent DROP INDEX etc. from running when we are syncing - cache in background. */ - if (!rw_lock_s_lock_nowait(&dict_operation_lock, __FILE__, __LINE__)) { - /* Exit when fail to get dict operation lock. */ - return; - } - table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL); if (table) { @@ -2986,8 +2979,6 @@ fts_optimize_sync_table( dict_table_close(table, FALSE, FALSE); } - - rw_lock_s_unlock(&dict_operation_lock); } /**********************************************************************//** diff --git a/storage/xtradb/fts/fts0que.cc b/storage/xtradb/fts/fts0que.cc index d926d9b0675..84f616b7800 100644 --- a/storage/xtradb/fts/fts0que.cc +++ b/storage/xtradb/fts/fts0que.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -3652,6 +3652,11 @@ fts_query_free( fts_doc_ids_free(query->deleted); } + if (query->intersection) { + fts_query_free_doc_ids(query, query->intersection); + query->intersection = NULL; + } + if (query->doc_ids) { fts_query_free_doc_ids(query, query->doc_ids); } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 5926ef77794..7b695fd4c5a 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1000,6 +1000,24 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG}, {"secondary_index_triggered_cluster_reads_avoided", (char*) &export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG}, + {"buffered_aio_submitted", + (char*) &export_vars.innodb_buffered_aio_submitted, SHOW_LONG}, + + {"scan_pages_contiguous", + (char*) &export_vars.innodb_fragmentation_stats.scan_pages_contiguous, + SHOW_LONG}, + {"scan_pages_disjointed", + (char*) &export_vars.innodb_fragmentation_stats.scan_pages_disjointed, + SHOW_LONG}, + {"scan_pages_total_seek_distance", + (char*) &export_vars.innodb_fragmentation_stats.scan_pages_total_seek_distance, + SHOW_LONG}, + {"scan_data_size", + (char*) &export_vars.innodb_fragmentation_stats.scan_data_size, + SHOW_LONG}, + {"scan_deleted_recs_size", + (char*) &export_vars.innodb_fragmentation_stats.scan_deleted_recs_size, + SHOW_LONG}, {NullS, NullS, SHOW_LONG} }; @@ -2847,7 +2865,7 @@ ha_innobase::ha_innobase( HA_BINLOG_ROW_CAPABLE | HA_CAN_GEOMETRY | HA_PARTIAL_COLUMN_READ | HA_TABLE_SCAN_ON_INDEX | HA_CAN_FULLTEXT | - HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT), + HA_CAN_FULLTEXT_EXT | HA_CAN_EXPORT | HA_ONLINE_ANALYZE), start_of_scan(0), num_write_row(0) {} @@ -7608,7 +7626,8 @@ ha_innobase::innobase_lock_autoinc(void) break; } } - /* Fall through to old style locking. */ + // fallthrough + // to old style locking. case AUTOINC_OLD_STYLE_LOCKING: DBUG_EXECUTE_IF("die_if_autoinc_old_lock_style_used", @@ -10312,7 +10331,8 @@ create_options_are_invalid( case ROW_TYPE_DYNAMIC: CHECK_ERROR_ROW_TYPE_NEEDS_FILE_PER_TABLE(use_tablespace); CHECK_ERROR_ROW_TYPE_NEEDS_GT_ANTELOPE; - /* fall through since dynamic also shuns KBS */ + // fallthrough + // since dynamic also shuns KBS case ROW_TYPE_COMPACT: case ROW_TYPE_REDUNDANT: if (kbs_specified) { @@ -10700,7 +10720,8 @@ index_bad: break; } zip_allowed = FALSE; - /* fall through to set row_format = COMPACT */ + // fallthrough + // to set row_format = COMPACT case ROW_TYPE_NOT_USED: case ROW_TYPE_FIXED: case ROW_TYPE_PAGE: @@ -10709,9 +10730,11 @@ index_bad: thd, Sql_condition::WARN_LEVEL_WARN, ER_ILLEGAL_HA_CREATE_OPTION, "InnoDB: assuming ROW_FORMAT=COMPACT."); + // fallthrough case ROW_TYPE_DEFAULT: /* If we fell through, set row format to Compact. */ row_format = ROW_TYPE_COMPACT; + // fallthrough case ROW_TYPE_COMPACT: break; } @@ -17537,7 +17560,7 @@ buffer_pool_load_now( const void* save) /*!< in: immediate result from check function */ { - if (*(my_bool*) save) { + if (*(my_bool*) save && !srv_read_only_mode) { buf_load_start(); } } @@ -18649,6 +18672,13 @@ static MYSQL_SYSVAR_BOOL(print_all_deadlocks, srv_print_all_deadlocks, "Print all deadlocks to MySQL error log (off by default)", NULL, NULL, FALSE); +static MYSQL_SYSVAR_BOOL( + print_lock_wait_timeout_info, + srv_print_lock_wait_timeout_info, + PLUGIN_VAR_OPCMDARG, + "Print lock wait timeout info to MySQL error log (off by default)", + NULL, NULL, FALSE); + static MYSQL_SYSVAR_ULONG(compression_failure_threshold_pct, zip_failure_threshold_pct, PLUGIN_VAR_OPCMDARG, "If the compression failure rate of a table is greater than this number" @@ -18921,6 +18951,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(foreground_preflush), MYSQL_SYSVAR(empty_free_list_algorithm), MYSQL_SYSVAR(print_all_deadlocks), + MYSQL_SYSVAR(print_lock_wait_timeout_info), MYSQL_SYSVAR(cmp_per_index_enabled), MYSQL_SYSVAR(undo_logs), MYSQL_SYSVAR(rollback_segments), diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index d6576fe27d5..7e155c99b9d 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -5652,7 +5652,47 @@ ha_innobase::commit_inplace_alter_table( break; } - DICT_STATS_BG_YIELD(trx); + DICT_BG_YIELD(trx); + } + + /* Make a concurrent Drop fts Index to wait until sync of that + fts index is happening in the background */ + for (;;) { + bool retry = false; + + for (inplace_alter_handler_ctx** pctx = ctx_array; + *pctx; pctx++) { + int count =0; + ha_innobase_inplace_ctx* ctx + = static_cast<ha_innobase_inplace_ctx*>(*pctx); + DBUG_ASSERT(new_clustered == ctx->need_rebuild()); + + if (dict_fts_index_syncing(ctx->old_table)) { + count++; + if (count == 100) { + fprintf(stderr, + "Drop index waiting for background sync" + "to finish\n"); + } + retry = true; + } + + if (new_clustered && dict_fts_index_syncing(ctx->new_table)) { + count++; + if (count == 100) { + fprintf(stderr, + "Drop index waiting for background sync" + "to finish\n"); + } + retry = true; + } + } + + if (!retry) { + break; + } + + DICT_BG_YIELD(trx); } /* Apply the changes to the data dictionary tables, for all @@ -5968,8 +6008,13 @@ foreign_fail: ut_d(dict_table_check_for_dup_indexes( ctx->new_table, CHECK_ABORTED_OK)); - ut_a(fts_check_cached_index(ctx->new_table)); +#ifdef UNIV_DEBUG + if (!(ctx->new_table->fts != NULL + && ctx->new_table->fts->cache->sync->in_progress)) { + ut_a(fts_check_cached_index(ctx->new_table)); + } +#endif if (new_clustered) { /* Since the table has been rebuilt, we remove all persistent statistics corresponding to the diff --git a/storage/xtradb/include/data0type.ic b/storage/xtradb/include/data0type.ic index 29dc480a19c..552d62eef00 100644 --- a/storage/xtradb/include/data0type.ic +++ b/storage/xtradb/include/data0type.ic @@ -575,7 +575,8 @@ dtype_get_fixed_size_low( #else /* !UNIV_HOTBACKUP */ return(len); #endif /* !UNIV_HOTBACKUP */ - /* fall through for variable-length charsets */ + // fallthrough + // for variable-length charsets case DATA_VARCHAR: case DATA_BINARY: case DATA_DECIMAL: diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic index 32bc4f376d9..72020715bef 100644 --- a/storage/xtradb/include/dict0dict.ic +++ b/storage/xtradb/include/dict0dict.ic @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -910,6 +910,27 @@ dict_table_x_lock_indexes( } /*********************************************************************//** +Returns true if the particular FTS index in the table is still syncing +in the background, false otherwise. +@param [in] table Table containing FTS index +@return True if sync of fts index is still going in the background */ +UNIV_INLINE +bool +dict_fts_index_syncing( + dict_table_t* table) +{ + dict_index_t* index; + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + if (index->index_fts_syncing) { + return(true); + } + } + return(false); +} +/*********************************************************************//** Release the exclusive locks on all index tree. */ UNIV_INLINE void diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index a64cb71370e..b6d2ab9fad1 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. This program is free software; you can redistribute it and/or modify it under @@ -617,6 +617,8 @@ struct dict_index_t{ dict_sys->mutex. Other changes are protected by index->lock. */ dict_field_t* fields; /*!< array of field descriptions */ + bool index_fts_syncing;/*!< Whether the fts index is + still syncing in the background */ #ifndef UNIV_HOTBACKUP UT_LIST_NODE_T(dict_index_t) indexes;/*!< list of indexes of the table */ diff --git a/storage/xtradb/include/dict0stats_bg.h b/storage/xtradb/include/dict0stats_bg.h index 82cd2b468b9..bf77cd125fb 100644 --- a/storage/xtradb/include/dict0stats_bg.h +++ b/storage/xtradb/include/dict0stats_bg.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -59,7 +59,7 @@ dict_stats_recalc_pool_del( /** Yield the data dictionary latch when waiting for the background thread to stop accessing a table. @param trx transaction holding the data dictionary locks */ -#define DICT_STATS_BG_YIELD(trx) do { \ +#define DICT_BG_YIELD(trx) do { \ row_mysql_unlock_data_dictionary(trx); \ os_thread_sleep(250000); \ row_mysql_lock_data_dictionary(trx); \ diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 78222b3122a..a9593cc4dec 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -597,7 +597,7 @@ fil_create_new_single_table_tablespace( ulint size) /*!< in: the initial size of the tablespace file in pages, must be >= FIL_IBD_FILE_INITIAL_SIZE */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); + MY_ATTRIBUTE((nonnull(2), warn_unused_result)); #ifndef UNIV_HOTBACKUP /********************************************************************//** Tries to open a single-table tablespace and optionally checks the space id is @@ -751,8 +751,10 @@ fil_space_get_n_reserved_extents( Reads or writes data. This operation is asynchronous (aio). @return DB_SUCCESS, or DB_TABLESPACE_DELETED if we are trying to do i/o on a tablespace which does not exist */ -#define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message) \ - _fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, NULL) +#define fil_io(type, sync, space_id, zip_size, block_offset, \ + byte_offset, len, buf, message) \ + _fil_io(type, sync, space_id, zip_size, block_offset, \ + byte_offset, len, buf, message, NULL, false) UNIV_INTERN dberr_t @@ -783,7 +785,9 @@ _fil_io( appropriately aligned */ void* message, /*!< in: message for aio handler if non-sync aio used, else ignored */ - trx_t* trx) + trx_t* trx, + bool should_buffer) /*!< in: whether to buffer an aio request. + Only used by aio read ahead*/ MY_ATTRIBUTE((nonnull(8))); /**********************************************************************//** Waits for an aio operation to complete. This function is used to write the diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h index 5c3e7d07fd9..2d05c827545 100644 --- a/storage/xtradb/include/log0online.h +++ b/storage/xtradb/include/log0online.h @@ -129,7 +129,11 @@ log_online_bitmap_iterator_next( /** Struct for single bitmap file information */ struct log_online_bitmap_file_struct { - char name[FN_REFLEN]; /*!< Name with full path */ + /** Name with full path + 61 is a nice magic constant for the extra space needed for the sprintf + template in the cc file + */ + char name[FN_REFLEN+61]; pfs_os_file_t file; /*!< Handle to opened file */ ib_uint64_t size; /*!< Size of the file */ os_offset_t offset; /*!< Offset of the next read, diff --git a/storage/xtradb/include/mach0data.ic b/storage/xtradb/include/mach0data.ic index 27b9f62b552..10fc6fe119b 100644 --- a/storage/xtradb/include/mach0data.ic +++ b/storage/xtradb/include/mach0data.ic @@ -792,13 +792,13 @@ mach_swap_byte_order( dest += len; switch (len & 0x7) { - case 0: *--dest = *from++; - case 7: *--dest = *from++; - case 6: *--dest = *from++; - case 5: *--dest = *from++; - case 4: *--dest = *from++; - case 3: *--dest = *from++; - case 2: *--dest = *from++; + case 0: *--dest = *from++; // fallthrough + case 7: *--dest = *from++; // fallthrough + case 6: *--dest = *from++; // fallthrough + case 5: *--dest = *from++; // fallthrough + case 4: *--dest = *from++; // fallthrough + case 3: *--dest = *from++; // fallthrough + case 2: *--dest = *from++; // fallthrough case 1: *--dest = *from; } } diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h index 4dab704ad50..f7531d99f38 100644 --- a/storage/xtradb/include/os0file.h +++ b/storage/xtradb/include/os0file.h @@ -371,9 +371,9 @@ The wrapper functions have the prefix of "innodb_". */ pfs_os_file_close_no_error_handling_func(file, __FILE__, __LINE__) # define os_aio(type, mode, name, file, buf, offset, \ - n, message1, message2, space_id, trx) \ + n, message1, message2, space_id, trx, should_buffer) \ pfs_os_aio_func(type, mode, name, file, buf, offset, \ - n, message1, message2, space_id, trx, \ + n, message1, message2, space_id, trx, should_buffer, \ __FILE__, __LINE__) # define os_file_read_pfs(file, buf, offset, n) \ @@ -443,9 +443,9 @@ to original un-instrumented file I/O APIs */ os_file_close_no_error_handling_func(file) # define os_aio(type, mode, name, file, buf, offset, n, message1, \ - message2, space_id, trx) \ + message2, space_id, trx, should_buffer) \ os_aio_func(type, mode, name, file, buf, offset, n, \ - message1, message2, space_id, trx) + message1, message2, space_id, trx, should_buffer) # define os_file_read_pfs(file, buf, offset, n) \ os_file_read_func(file, buf, offset, n, NULL) @@ -975,6 +975,12 @@ pfs_os_aio_func( OS_AIO_SYNC */ ulint space_id, trx_t* trx, + bool should_buffer, + /*!< in: Whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ const char* src_file,/*!< in: file name where func invoked */ ulint src_line);/*!< in: line where the func invoked */ /*******************************************************************//** @@ -1389,7 +1395,13 @@ os_aio_func( aio operation); ignored if mode is OS_AIO_SYNC */ ulint space_id, - trx_t* trx); + trx_t* trx, + bool should_buffer); + /*!< in: Whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ /************************************************************************//** Wakes up all async i/o threads so that they know to exit themselves in shutdown. */ @@ -1558,6 +1570,11 @@ os_aio_linux_handle( ulint* space_id); #endif /* LINUX_NATIVE_AIO */ +/** Submit buffered AIO requests on the given segment to the kernel. */ +UNIV_INTERN +void +os_aio_dispatch_read_array_submit(); + #ifndef UNIV_NONINL #include "os0file.ic" #endif diff --git a/storage/xtradb/include/os0file.ic b/storage/xtradb/include/os0file.ic index c82a2559fed..98474a33c7e 100644 --- a/storage/xtradb/include/os0file.ic +++ b/storage/xtradb/include/os0file.ic @@ -246,6 +246,9 @@ pfs_os_aio_func( OS_AIO_SYNC */ ulint space_id, trx_t* trx, + bool should_buffer, + /*!< in: whether to buffer an aio request. + Only used by aio read ahead*/ const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { @@ -261,7 +264,8 @@ pfs_os_aio_func( src_file, src_line); result = os_aio_func(type, mode, name, file, buf, offset, - n, message1, message2, space_id, trx); + n, message1, message2, space_id, trx, + should_buffer); register_pfs_file_io_end(locker, n); diff --git a/storage/xtradb/include/page0zip.ic b/storage/xtradb/include/page0zip.ic index 6c7d8cd32c7..61e6f37c612 100644 --- a/storage/xtradb/include/page0zip.ic +++ b/storage/xtradb/include/page0zip.ic @@ -172,7 +172,7 @@ page_zip_rec_needs_ext( ignored if zip_size == 0 */ ulint zip_size) /*!< in: compressed page size in bytes, or 0 */ { - ut_ad(rec_size > comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES); + ut_ad(rec_size > (comp ? REC_N_NEW_EXTRA_BYTES : REC_N_OLD_EXTRA_BYTES)); ut_ad(ut_is_2pow(zip_size)); ut_ad(comp || !zip_size); diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 0fb563f539c..248083db10f 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -52,6 +52,8 @@ Created 10/10/1995 Heikki Tuuri #include "buf0checksum.h" #include "ut0counter.h" +#include <sql_class.h> + /* Global counters used inside InnoDB. */ struct srv_stats_t { typedef ib_counter_t<lsn_t, 1, single_indexer_t> lsn_ctr_1_t; @@ -129,6 +131,9 @@ struct srv_stats_t { ulint_ctr_1_t lock_deadlock_count; ulint_ctr_1_t n_lock_max_wait_time; + + /** Number of buffered aio requests submitted */ + ulint_ctr_64_t n_aio_submitted; }; extern const char* srv_main_thread_op_info; @@ -586,6 +591,9 @@ extern ulong srv_sync_array_size; /* print all user-level transactions deadlocks to mysqld stderr */ extern my_bool srv_print_all_deadlocks; +/* print lock wait timeout info to mysqld stderr */ +extern my_bool srv_print_lock_wait_timeout_info; + extern my_bool srv_cmp_per_index_enabled; /** Number of times secondary index lookup triggered cluster lookup */ @@ -1100,6 +1108,11 @@ struct export_var_t{ ulint innodb_sec_rec_cluster_reads; /*!< srv_sec_rec_cluster_reads */ ulint innodb_sec_rec_cluster_reads_avoided; /*!< srv_sec_rec_cluster_reads_avoided */ + + ulint innodb_buffered_aio_submitted; + + fragmentation_stats_t innodb_fragmentation_stats;/*!< Fragmentation + statistics */ }; /** Thread slot in the thread table. */ diff --git a/storage/xtradb/include/trx0rec.h b/storage/xtradb/include/trx0rec.h index 359937e3583..c7820480fe0 100644 --- a/storage/xtradb/include/trx0rec.h +++ b/storage/xtradb/include/trx0rec.h @@ -233,7 +233,7 @@ trx_undo_report_row_operation( inserted undo log record, 0 if BTR_NO_UNDO_LOG flag was specified */ - MY_ATTRIBUTE((nonnull(3,4,10), warn_unused_result)); + MY_ATTRIBUTE((nonnull(4,10), warn_unused_result)); /******************************************************************//** Copies an undo record to heap. This function can be called if we know that the undo log record exists. diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 639faca0fe3..ce2de004dd4 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -47,7 +47,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_BUGFIX MYSQL_VERSION_PATCH #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 82.2 +#define PERCONA_INNODB_VERSION 83.0 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ diff --git a/storage/xtradb/include/ut0rnd.ic b/storage/xtradb/include/ut0rnd.ic index 024c59e553b..5351c8d9d5a 100644 --- a/storage/xtradb/include/ut0rnd.ic +++ b/storage/xtradb/include/ut0rnd.ic @@ -236,17 +236,17 @@ ut_fold_binary( switch (len & 0x7) { case 7: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); // fallthrough case 6: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); // fallthrough case 5: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); // fallthrough case 4: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); // fallthrough case 3: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); // fallthrough case 2: - fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); + fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); // fallthrough case 1: fold = ut_fold_ulint_pair(fold, (ulint)(*str++)); } diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index e2e7c4207a1..277fc000502 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -32,6 +32,20 @@ Created 25/5/2010 Sunny Bains #include "srv0start.h" #include "ha_prototypes.h" #include "lock0priv.h" +#include "lock0iter.h" + +#include <sstream> + +extern "C" +LEX_STRING* thd_query_string(MYSQL_THD thd); + +struct blocking_trx_info { + uint64_t trx_id; + uint32_t thread_id; + int64_t query_id; +}; + +static const size_t MAX_BLOCKING_TRX_IN_REPORT = 10; /*********************************************************************//** Print the contents of the lock_sys_t::waiting_threads array. */ @@ -184,6 +198,46 @@ lock_wait_table_reserve_slot( return(NULL); } +/** Print lock wait timeout info to stderr. It's supposed this function +is executed in trx's THD thread as it calls some non-thread-safe +functions to get some info from THD. +@param[in] trx requested trx +@param[in] blocking blocking info array +@param[in] blocking_count blocking info array size */ +void +print_lock_wait_timeout( + const trx_t &trx, + blocking_trx_info *blocking, + size_t blocking_count) +{ + std::ostringstream outs; + + outs << "Lock wait timeout info:\n"; + outs << "Requested thread id: " << + thd_get_thread_id(trx.mysql_thd) << + "\n"; + outs << "Requested trx id: " << trx.id << "\n"; + outs << "Requested query: " << + thd_query_string(trx.mysql_thd)->str << "\n"; + + outs << "Total blocking transactions count: " << + blocking_count << + "\n"; + + for (size_t i = 0; i < blocking_count; ++i) { + outs << "Blocking transaction number: " << (i + 1) << "\n"; + outs << "Blocking thread id: " << + blocking[i].thread_id << + "\n"; + outs << "Blocking query id: " << + blocking[i].query_id << + "\n"; + outs << "Blocking trx id: " << blocking[i].trx_id << "\n"; + } + ut_print_timestamp(stderr); + fprintf(stderr, " %s", outs.str().c_str()); +} + /***************************************************************//** Puts a user OS thread to wait for a lock to be released. If an error occurs during the wait trx->error_state associated with thr is @@ -207,6 +261,8 @@ lock_wait_suspend_thread( ulint sec; ulint ms; ulong lock_wait_timeout; + blocking_trx_info blocking[MAX_BLOCKING_TRX_IN_REPORT]; + size_t blocking_count = 0; trx = thr_get_trx(thr); @@ -272,6 +328,27 @@ lock_wait_suspend_thread( if (const lock_t* wait_lock = trx->lock.wait_lock) { lock_type = lock_get_type_low(wait_lock); + if (srv_print_lock_wait_timeout_info) { + lock_queue_iterator_t iter; + const lock_t* curr_lock; + lock_queue_iterator_reset(&iter, wait_lock, ULINT_UNDEFINED); + for (curr_lock = lock_queue_iterator_get_prev(&iter); + curr_lock != NULL; + curr_lock = lock_queue_iterator_get_prev(&iter)) { + if (lock_has_to_wait(trx->lock.wait_lock, curr_lock)) { + blocking[blocking_count].trx_id = lock_get_trx_id(curr_lock); + blocking[blocking_count].thread_id = + curr_lock->trx->mysql_thd ? + thd_get_thread_id(curr_lock->trx->mysql_thd) : 0; + blocking[blocking_count].query_id = + curr_lock->trx->mysql_thd ? + thd_get_query_id(curr_lock->trx->mysql_thd) : 0; + /* Only limited number of blocking transaction infos is implemented*/ + if ((++blocking_count) >= MAX_BLOCKING_TRX_IN_REPORT) + break; + } + } + } } lock_mutex_exit(); @@ -377,6 +454,8 @@ lock_wait_suspend_thread( && wait_time > (double) lock_wait_timeout) { trx->error_state = DB_LOCK_WAIT_TIMEOUT; + if (srv_print_lock_wait_timeout_info) + print_lock_wait_timeout(*trx, blocking, blocking_count); MONITOR_INC(MONITOR_TIMEOUT); } diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 99762c00a08..9e9e3a4c284 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -489,7 +489,7 @@ log_online_make_bitmap_name( /*=========================*/ lsn_t start_lsn) /*!< in: the start LSN name part */ { - ut_snprintf(log_bmp_sys->out.name, FN_REFLEN, bmp_file_name_template, + ut_snprintf(log_bmp_sys->out.name, sizeof(log_bmp_sys->out.name), bmp_file_name_template, log_bmp_sys->bmp_file_home, bmp_file_name_stem, log_bmp_sys->out_seq_num, start_lsn); } diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 9b2a2746976..966eb31e260 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -247,6 +247,16 @@ struct os_aio_array_t{ There is one such event for each possible pending IO. The size of the array is equal to n_slots. */ + struct iocb** pending; + /* Array to buffer the not-submitted aio + requests. The array length is n_slots. + It is divided into n_segments segments. + pending requests on each segment are buffered + separately.*/ + ulint* count; + /* Array of length n_segments. Each element + counts the number of not-submitted aio + request on that segment.*/ #endif /* LINUX_NATIV_AIO */ }; @@ -4084,6 +4094,13 @@ os_aio_array_create( memset(io_event, 0x0, sizeof(*io_event) * n); array->aio_events = io_event; + array->pending = static_cast<struct iocb**>( + ut_malloc(n * sizeof(struct iocb*))); + memset(array->pending, 0x0, sizeof(struct iocb*) * n); + array->count = static_cast<ulint*>( + ut_malloc(n_segments * sizeof(ulint))); + memset(array->count, 0x0, sizeof(ulint) * n_segments); + skip_native_aio: #endif /* LINUX_NATIVE_AIO */ for (ulint i = 0; i < n; i++) { @@ -4140,6 +4157,16 @@ os_aio_array_free( if (srv_use_native_aio) { ut_free(array->aio_events); ut_free(array->aio_ctx); + +#ifdef UNIV_DEBUG + for (size_t idx = 0; idx < array->n_slots; ++idx) + ut_ad(array->pending[idx] == NULL); + for (size_t idx = 0; idx < array->n_segments; ++idx) + ut_ad(array->count[idx] == 0); +#endif + + ut_free(array->pending); + ut_free(array->count); } #endif /* LINUX_NATIVE_AIO */ @@ -4769,6 +4796,83 @@ readahead requests. */ #endif /* __WIN__ */ } +/** Submit buffered AIO requests on the given segment to the kernel +(low level function). +@param acquire_mutex specifies whether to lock array mutex +*/ +static +void +os_aio_dispatch_read_array_submit_low(bool acquire_mutex MY_ATTRIBUTE((unused))) +{ + if (!srv_use_native_aio) { + return; + } +#if defined(LINUX_NATIVE_AIO) + os_aio_array_t* array = os_aio_read_array; + ulint total_submitted = 0; + if (acquire_mutex) + os_mutex_enter(array->mutex); + /* Submit aio requests buffered on all segments. */ + for (ulint i = 0; i < array->n_segments; i++) { + const int count = array->count[i]; + int offset = 0; + while (offset != count) { + struct iocb** const iocb_array = array->pending + + i * array->n_slots / array->n_segments + + offset; + const int partial_count = count - offset; + /* io_submit() returns number of successfully queued + requests or (-errno). + It returns 0 only if the number of iocb blocks passed + is also 0. */ + const int submitted = io_submit(array->aio_ctx[i], + partial_count, iocb_array); + + /* This assertion prevents infinite loop in both + debug and release modes. */ + ut_a(submitted != 0); + + if (submitted < 0) { + /* Terminating with fatal error */ + const char* errmsg = + strerror(-submitted); + ib_logf(IB_LOG_LEVEL_FATAL, + "Trying to sumbit %d aio requests, " + "io_submit() set errno to %d: %s", + partial_count, -submitted, + errmsg ? errmsg : "<unknown>"); + } + ut_ad(submitted <= partial_count); + if (submitted < partial_count) + { + ib_logf(IB_LOG_LEVEL_WARN, + "Trying to sumbit %d aio requests, " + "io_submit() submitted only %d", + partial_count, submitted); + } + offset += submitted; + } + total_submitted += count; + } + /* Reset the aio request buffer. */ + memset(array->pending, 0x0, sizeof(struct iocb*) * array->n_slots); + memset(array->count, 0x0, sizeof(ulint) * array->n_segments); + + if (acquire_mutex) + os_mutex_exit(array->mutex); + + srv_stats.n_aio_submitted.add(total_submitted); +#endif +} + +/** Submit buffered AIO requests on the given segment to the kernel. */ +UNIV_INTERN +void +os_aio_dispatch_read_array_submit() +{ + os_aio_dispatch_read_array_submit_low(true); +} + #if defined(LINUX_NATIVE_AIO) /*******************************************************************//** Dispatch an AIO request to the kernel. @@ -4778,10 +4882,11 @@ ibool os_aio_linux_dispatch( /*==================*/ os_aio_array_t* array, /*!< in: io request array. */ - os_aio_slot_t* slot) /*!< in: an already reserved slot. */ + os_aio_slot_t* slot, /*!< in: an already reserved slot. */ + bool should_buffer) /*!< in: should buffer the request + rather than submit. */ { int ret; - ulint io_ctx_index; struct iocb* iocb; ut_ad(slot != NULL); @@ -4793,9 +4898,31 @@ os_aio_linux_dispatch( The iocb struct is directly in the slot. The io_context is one per segment. */ + ulint slots_per_segment = array->n_slots / array->n_segments; iocb = &slot->control; - io_ctx_index = (slot->pos * array->n_segments) / array->n_slots; + ulint io_ctx_index = slot->pos / slots_per_segment; + if (should_buffer) { + ut_ad(array == os_aio_read_array); + os_mutex_enter(array->mutex); + /* There are array->n_slots elements in array->pending, + which is divided into array->n_segments area of equal size. + The iocb of each segment are buffered in its corresponding area + in the pending array consecutively as they come. + array->count[i] records the number of buffered aio requests + in the ith segment.*/ + ulint& count = array->count[io_ctx_index]; + ut_ad(count != slots_per_segment); + ulint n = io_ctx_index * slots_per_segment + count; + array->pending[n] = iocb; + ++count; + if (count == slots_per_segment) { + os_aio_dispatch_read_array_submit_low(false); + } + os_mutex_exit(array->mutex); + return(TRUE); + } + /* Submit the given request. */ ret = io_submit(array->aio_ctx[io_ctx_index], 1, &iocb); #if defined(UNIV_AIO_DEBUG) @@ -4855,7 +4982,13 @@ os_aio_func( aio operation); ignored if mode is OS_AIO_SYNC */ ulint space_id, - trx_t* trx) + trx_t* trx, + bool should_buffer) + /*!< in: Whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ { os_aio_array_t* array; os_aio_slot_t* slot; @@ -4965,7 +5098,8 @@ try_again: ret = ReadFile(file.m_file, buf, (DWORD) n, &len, &(slot->control)); #elif defined(LINUX_NATIVE_AIO) - if (!os_aio_linux_dispatch(array, slot)) { + if (!os_aio_linux_dispatch(array, slot, + should_buffer)) { goto err_exit; } #endif /* WIN_ASYNC_IO */ @@ -4984,7 +5118,7 @@ try_again: ret = WriteFile(file.m_file, buf, (DWORD) n, &len, &(slot->control)); #elif defined(LINUX_NATIVE_AIO) - if (!os_aio_linux_dispatch(array, slot)) { + if (!os_aio_linux_dispatch(array, slot, false)) { goto err_exit; } #endif /* WIN_ASYNC_IO */ diff --git a/storage/xtradb/page/page0page.cc b/storage/xtradb/page/page0page.cc index 48c4b53aaa4..a340c04913a 100644 --- a/storage/xtradb/page/page0page.cc +++ b/storage/xtradb/page/page0page.cc @@ -2832,7 +2832,7 @@ page_warn_strict_checksum( ulint space_id, ulint page_no) { - srv_checksum_algorithm_t curr_algo_nonstrict; + srv_checksum_algorithm_t curr_algo_nonstrict = srv_checksum_algorithm_t(); switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_CRC32; diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index 11c4333577e..ac26c318cb2 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -2025,6 +2025,7 @@ PageConverter::update_page( case FIL_PAGE_TYPE_XDES: err = set_current_xdes( buf_block_get_page_no(block), get_frame(block)); + // fallthrough case FIL_PAGE_INODE: case FIL_PAGE_TYPE_TRX_SYS: case FIL_PAGE_IBUF_FREE_LIST: diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 4596e2fb951..4fa2ed5cf56 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/row/row0log.cc @@ -1872,6 +1872,7 @@ row_log_table_apply_update( When applying the subsequent ROW_T_DELETE, no matching record will be found. */ + return(DB_SUCCESS); case DB_SUCCESS: ut_ad(row != NULL); break; diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 15a386f7660..9d1fcfc0393 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -57,6 +57,7 @@ Created 9/17/2000 Heikki Tuuri #include "log0log.h" #include "btr0sea.h" #include "fil0fil.h" +#include "srv0srv.h" #include "ibuf0ibuf.h" #include "fts0fts.h" #include "fts0types.h" @@ -4448,6 +4449,16 @@ row_drop_table_for_mysql( ut_ad(!table->fts->add_wq); ut_ad(lock_trx_has_sys_table_locks(trx) == 0); + for (;;) { + bool retry = false; + if (dict_fts_index_syncing(table)) { + retry = true; + } + if (!retry) { + break; + } + DICT_BG_YIELD(trx); + } row_mysql_unlock_data_dictionary(trx); fts_optimize_remove_table(table); row_mysql_lock_data_dictionary(trx); @@ -5892,7 +5903,8 @@ loop: fputs(" InnoDB: Warning: CHECK TABLE on ", stderr); dict_index_name_print(stderr, prebuilt->trx, index); fprintf(stderr, " returned %lu\n", ret); - /* fall through (this error is ignored by CHECK TABLE) */ + // fallthrough + // (this error is ignored by CHECK TABLE) case DB_END_OF_INDEX: func_exit: mem_free(buf); diff --git a/storage/xtradb/row/row0purge.cc b/storage/xtradb/row/row0purge.cc index 35b3520749b..45a8ae4102c 100644 --- a/storage/xtradb/row/row0purge.cc +++ b/storage/xtradb/row/row0purge.cc @@ -488,8 +488,8 @@ row_purge_remove_sec_if_poss_leaf( success = false; } } - /* fall through (the index entry is still needed, - or the deletion succeeded) */ + // fallthrough + // (the index entry is still needed, or the deletion succeeded) case ROW_NOT_DELETED_REF: /* The index entry is still needed. */ case ROW_BUFFERED: diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index 5866021cffa..060c12e7e2e 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -2993,8 +2993,8 @@ row_sel_store_mysql_rec( const ulint* offsets, bool clust_templ_for_sec) { - ulint i; - std::vector<ulint> template_col; + ulint i; + std::vector<const dict_col_t*> template_col; ut_ad(rec_clust || index == prebuilt->index); ut_ad(!rec_clust || dict_index_is_clust(index)); @@ -3008,13 +3008,24 @@ row_sel_store_mysql_rec( mem_heap_empty(prebuilt->compress_heap); if (clust_templ_for_sec) { - /* Store all clustered index field of + /* Store all clustered index column of secondary index record. */ for (i = 0; i < dict_index_get_n_fields( prebuilt->index); i++) { ulint sec_field = dict_index_get_nth_field_pos( index, prebuilt->index, i); - template_col.push_back(sec_field); + + if (sec_field == ULINT_UNDEFINED) { + template_col.push_back(NULL); + continue; + } + + const dict_field_t* field = + dict_index_get_nth_field(index, sec_field); + const dict_col_t* col = + dict_field_get_col(field); + + template_col.push_back(col); } } @@ -3034,9 +3045,13 @@ row_sel_store_mysql_rec( == 0 || templ->rec_field_is_prefix); if (clust_templ_for_sec) { - std::vector<ulint>::iterator it; + std::vector<const dict_col_t*>::iterator it; + const dict_field_t* field = + dict_index_get_nth_field(index, field_no); + const dict_col_t* col = dict_field_get_col( + field); it = std::find(template_col.begin(), - template_col.end(), field_no); + template_col.end(), col); if (it == template_col.end()) { continue; @@ -4393,6 +4408,10 @@ rec_loop: if (page_rec_is_supremum(rec)) { + DBUG_EXECUTE_IF("compare_end_range", + if (end_loop < 100) { + end_loop = 100; + }); /** Compare the last record of the page with end range passed to InnoDB when there is no ICP and number of loops in row_search_for_mysql for rows found but not @@ -4433,7 +4452,7 @@ rec_loop: /** In case of prebuilt->fetch, set the error in prebuilt->end_range. */ - if (prebuilt->n_fetch_cached > 0) { + if (next_buf != NULL) { prebuilt->end_range = true; } diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index 2153440886c..e0e3f995bae 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -428,6 +428,10 @@ UNIV_INTERN ulong srv_force_recovery_crash; UNIV_INTERN my_bool srv_print_all_deadlocks = FALSE; +/** Print lock wait timeout info to mysqld stderr */ + +my_bool srv_print_lock_wait_timeout_info = FALSE; + /** Enable INFORMATION_SCHEMA.innodb_cmp_per_index */ UNIV_INTERN my_bool srv_cmp_per_index_enabled = FALSE; @@ -1908,6 +1912,12 @@ srv_export_innodb_status(void) export_vars.innodb_sec_rec_cluster_reads_avoided = srv_sec_rec_cluster_reads_avoided; + export_vars.innodb_buffered_aio_submitted = + srv_stats.n_aio_submitted; + + thd_get_fragmentation_stats(current_thd, + &export_vars.innodb_fragmentation_stats); + mutex_exit(&srv_innodb_monitor_mutex); } diff --git a/storage/xtradb/sync/sync0sync.cc b/storage/xtradb/sync/sync0sync.cc index b795100972c..7d0314c1ef6 100644 --- a/storage/xtradb/sync/sync0sync.cc +++ b/storage/xtradb/sync/sync0sync.cc @@ -1230,6 +1230,7 @@ sync_thread_add_level( upgrading in innobase_start_or_create_for_mysql(). */ break; } + // fallthrough case SYNC_MEM_POOL: case SYNC_MEM_HASH: case SYNC_RECV: @@ -1293,8 +1294,8 @@ sync_thread_add_level( } ut_ad(found_current); - /* fallthrough */ } + // fallthrough case SYNC_BUF_FLUSH_LIST: case SYNC_BUF_LRU_LIST: case SYNC_BUF_FREE_LIST: |