diff options
Diffstat (limited to 'storage/xtradb/srv/srv0srv.c')
-rw-r--r-- | storage/xtradb/srv/srv0srv.c | 240 |
1 files changed, 161 insertions, 79 deletions
diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 6e210071746..6edfbaa7755 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -58,6 +58,8 @@ Created 10/8/1995 Heikki Tuuri *******************************************************/ /* Dummy comment */ +#include "m_string.h" /* for my_sys.h */ +#include "my_sys.h" /* DEBUG_SYNC_C */ #include "srv0srv.h" #include "ut0mem.h" @@ -181,7 +183,7 @@ UNIV_INTERN my_bool srv_track_changed_pages = TRUE; UNIV_INTERN ib_uint64_t srv_max_bitmap_file_size = 100 * 1024 * 1024; -UNIV_INTERN ulonglong srv_changed_pages_limit = 0; +UNIV_INTERN ulonglong srv_max_changed_pages = 0; /** When TRUE, fake change transcations take S rather than X row locks. When FALSE, row locks are not taken at all. */ @@ -312,58 +314,11 @@ UNIV_INTERN ulong srv_purge_batch_size = 20; /* the number of rollback segments to use */ UNIV_INTERN ulong srv_rollback_segments = TRX_SYS_N_RSEGS; -/* variable counts amount of data read in total (in bytes) */ -UNIV_INTERN ulint srv_data_read = 0; - /* Internal setting for "innodb_stats_method". Decides how InnoDB treats NULL value when collecting statistics. By default, it is set to SRV_STATS_NULLS_EQUAL(0), ie. all NULL value are treated equal */ ulong srv_innodb_stats_method = SRV_STATS_NULLS_EQUAL; -/* here we count the amount of data written in total (in bytes) */ -UNIV_INTERN ulint srv_data_written = 0; - -/* the number of the log write requests done */ -UNIV_INTERN ulint srv_log_write_requests = 0; - -/* the number of physical writes to the log performed */ -UNIV_INTERN ulint srv_log_writes = 0; - -/* amount of data written to the log files in bytes */ -UNIV_INTERN ulint srv_os_log_written = 0; - -/* amount of writes being done to the log files */ -UNIV_INTERN ulint srv_os_log_pending_writes = 0; - -/* we increase this counter, when there we don't have enough space in the -log buffer and have to flush it */ -UNIV_INTERN ulint srv_log_waits = 0; - -/* this variable counts the amount of times, when the doublewrite buffer -was flushed */ -UNIV_INTERN ulint srv_dblwr_writes = 0; - -/* here we store the number of pages that have been flushed to the -doublewrite buffer */ -UNIV_INTERN ulint srv_dblwr_pages_written = 0; - -/* in this variable we store the number of write requests issued */ -UNIV_INTERN ulint srv_buf_pool_write_requests = 0; - -/* here we store the number of times when we had to wait for a free page -in the buffer pool. It happens when the buffer pool is full and we need -to make a flush, in order to be able to read or create a page. */ -UNIV_INTERN ulint srv_buf_pool_wait_free = 0; - -/* variable to count the number of pages that were written from buffer -pool to the disk */ -UNIV_INTERN ulint srv_buf_pool_flushed = 0; -UNIV_INTERN ulint buf_lru_flush_page_count = 0; - -/** Number of buffer pool reads that led to the -reading of a disk page */ -UNIV_INTERN ulint srv_buf_pool_reads = 0; - /** Time in seconds between automatic buffer pool dumps */ UNIV_INTERN uint srv_auto_lru_dump = 0; @@ -406,6 +361,9 @@ UNIV_INTERN lint srv_conc_n_threads = 0; InnoDB */ UNIV_INTERN ulint srv_conc_n_waiting_threads = 0; +/* print all user-level transactions deadlocks to mysqld stderr */ +UNIV_INTERN my_bool srv_print_all_deadlocks = FALSE; + typedef struct srv_conc_slot_struct srv_conc_slot_t; struct srv_conc_slot_struct{ os_event_t event; /*!< event to wait */ @@ -451,6 +409,10 @@ UNIV_INTERN ulong srv_sys_stats_root_page = 0; #endif UNIV_INTERN ibool srv_use_doublewrite_buf = TRUE; +UNIV_INTERN ibool srv_use_atomic_writes = FALSE; +#ifdef HAVE_POSIX_FALLOCATE +UNIV_INTERN ibool srv_use_posix_fallocate = TRUE; +#endif UNIV_INTERN ibool srv_use_checksums = TRUE; UNIV_INTERN ibool srv_fast_checksum = FALSE; @@ -489,23 +451,83 @@ UNIV_INTERN ibool srv_print_log_io = FALSE; UNIV_INTERN ibool srv_print_latch_waits = FALSE; #endif /* UNIV_DEBUG */ -UNIV_INTERN ulint srv_n_rows_inserted = 0; -UNIV_INTERN ulint srv_n_rows_updated = 0; -UNIV_INTERN ulint srv_n_rows_deleted = 0; -UNIV_INTERN ulint srv_n_rows_read = 0; - static ulint srv_n_rows_inserted_old = 0; static ulint srv_n_rows_updated_old = 0; static ulint srv_n_rows_deleted_old = 0; static ulint srv_n_rows_read_old = 0; -UNIV_INTERN ulint srv_n_lock_deadlock_count = 0; -UNIV_INTERN ulint srv_n_lock_wait_count = 0; -UNIV_INTERN ulint srv_n_lock_wait_current_count = 0; -UNIV_INTERN ib_int64_t srv_n_lock_wait_time = 0; -UNIV_INTERN ulint srv_n_lock_max_wait_time = 0; +/* Ensure counters are on separate cache lines */ + +#define CACHE_LINE_SIZE 64 +#define CACHE_ALIGNED __attribute__ ((aligned (CACHE_LINE_SIZE))) + +UNIV_INTERN byte +counters_pad_start[CACHE_LINE_SIZE] __attribute__((unused)) = {0}; + +UNIV_INTERN ulint srv_n_rows_inserted CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_n_rows_updated CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_n_rows_deleted CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_n_rows_read CACHE_ALIGNED = 0; + +UNIV_INTERN ulint srv_n_lock_deadlock_count CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_n_lock_wait_count CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_n_lock_wait_current_count CACHE_ALIGNED = 0; +UNIV_INTERN ib_int64_t srv_n_lock_wait_time CACHE_ALIGNED = 0; +UNIV_INTERN ulint srv_n_lock_max_wait_time CACHE_ALIGNED = 0; -UNIV_INTERN ulint srv_truncated_status_writes = 0; +UNIV_INTERN ulint srv_truncated_status_writes CACHE_ALIGNED = 0; + +/* variable counts amount of data read in total (in bytes) */ +UNIV_INTERN ulint srv_data_read CACHE_ALIGNED = 0; + +/* here we count the amount of data written in total (in bytes) */ +UNIV_INTERN ulint srv_data_written CACHE_ALIGNED = 0; + +/* the number of the log write requests done */ +UNIV_INTERN ulint srv_log_write_requests CACHE_ALIGNED = 0; + +/* the number of physical writes to the log performed */ +UNIV_INTERN ulint srv_log_writes CACHE_ALIGNED = 0; + +/* amount of data written to the log files in bytes */ +UNIV_INTERN ulint srv_os_log_written CACHE_ALIGNED = 0; + +/* amount of writes being done to the log files */ +UNIV_INTERN ulint srv_os_log_pending_writes CACHE_ALIGNED = 0; + +/* we increase this counter, when there we don't have enough space in the +log buffer and have to flush it */ +UNIV_INTERN ulint srv_log_waits CACHE_ALIGNED = 0; + +/* this variable counts the amount of times, when the doublewrite buffer +was flushed */ +UNIV_INTERN ulint srv_dblwr_writes CACHE_ALIGNED = 0; + +/* here we store the number of pages that have been flushed to the +doublewrite buffer */ +UNIV_INTERN ulint srv_dblwr_pages_written CACHE_ALIGNED = 0; + +/* in this variable we store the number of write requests issued */ +UNIV_INTERN ulint srv_buf_pool_write_requests CACHE_ALIGNED = 0; + +/* here we store the number of times when we had to wait for a free page +in the buffer pool. It happens when the buffer pool is full and we need +to make a flush, in order to be able to read or create a page. */ +UNIV_INTERN ulint srv_buf_pool_wait_free CACHE_ALIGNED = 0; + +/** Number of buffer pool reads that led to the +reading of a disk page */ +UNIV_INTERN ulint srv_buf_pool_reads CACHE_ALIGNED = 0; + +/* variable to count the number of pages that were written from buffer +pool to the disk */ +UNIV_INTERN ulint srv_buf_pool_flushed CACHE_ALIGNED = 0; + +/* variable to count the number of LRU flushed pages */ +UNIV_INTERN ulint buf_lru_flush_page_count CACHE_ALIGNED = 0; + +UNIV_INTERN byte +counters_pad_end[CACHE_LINE_SIZE] __attribute__((unused)) = {0}; /* Set the following to 0 if you want InnoDB to write messages on @@ -1438,7 +1460,7 @@ retry: ut_ad(!sync_thread_levels_nonempty_trx(trx->has_search_latch)); #endif /* UNIV_SYNC_DEBUG */ - if (innobase_get_slow_log() && trx->take_stats) { + if (UNIV_UNLIKELY(trx->take_stats)) { ut_usectime(&sec, &ms); start_time = (ib_uint64_t)sec * 1000000 + ms; } else { @@ -1453,7 +1475,7 @@ retry: trx->op_info = ""; - if (innobase_get_slow_log() && trx->take_stats && start_time) { + if (UNIV_UNLIKELY(start_time != 0)) { ut_usectime(&sec, &ms); finish_time = (ib_uint64_t)sec * 1000000 + ms; trx->innodb_que_wait_timer += (ulint)(finish_time - start_time); @@ -1764,6 +1786,10 @@ srv_suspend_mysql_thread( trx = thr_get_trx(thr); + if (trx->mysql_thd != 0) { + DEBUG_SYNC_C("srv_suspend_mysql_thread_enter"); + } + os_event_set(srv_lock_timeout_thread_event); mutex_enter(&kernel_mutex); @@ -2193,6 +2219,8 @@ srv_printf_innodb_monitor( (long) srv_conc_n_threads, (ulong) srv_conc_n_waiting_threads); + mutex_enter(&kernel_mutex); + fprintf(file, "%lu read views open inside InnoDB\n", UT_LIST_GET_LEN(trx_sys->view_list)); @@ -2206,6 +2234,8 @@ srv_printf_innodb_monitor( } } + mutex_exit(&kernel_mutex); + n_reserved = fil_space_get_n_reserved_extents(0); if (n_reserved > 0) { fprintf(file, @@ -2290,16 +2320,18 @@ void srv_export_innodb_status(void) /*==========================*/ { - buf_pool_stat_t stat; - ulint LRU_len; - ulint free_len; - ulint flush_list_len; - ulint mem_adaptive_hash, mem_dictionary; - read_view_t* oldest_view; - ulint i; + buf_pool_stat_t stat; + buf_pools_list_size_t buf_pools_list_size; + ulint LRU_len; + ulint free_len; + ulint flush_list_len; + ulint mem_adaptive_hash, mem_dictionary; + read_view_t* oldest_view; + ulint i; buf_get_total_stat(&stat); buf_get_total_list_len(&LRU_len, &free_len, &flush_list_len); + buf_get_total_list_size_in_bytes(&buf_pools_list_size); if (btr_search_sys && btr_search_sys->hash_index[0]->heap) { mem_adaptive_hash = mem_heap_get_size(btr_search_sys->hash_index[0]->heap); @@ -2364,7 +2396,12 @@ srv_export_innodb_status(void) export_vars.innodb_buffer_pool_read_ahead_evicted = stat.n_ra_pages_evicted; export_vars.innodb_buffer_pool_pages_data = LRU_len; + export_vars.innodb_buffer_pool_bytes_data = + buf_pools_list_size.LRU_bytes + + buf_pools_list_size.unzip_LRU_bytes; export_vars.innodb_buffer_pool_pages_dirty = flush_list_len; + export_vars.innodb_buffer_pool_bytes_dirty = + buf_pools_list_size.flush_list_bytes; export_vars.innodb_buffer_pool_pages_free = free_len; export_vars.innodb_deadlocks = srv_n_lock_deadlock_count; #ifdef UNIV_DEBUG @@ -2497,6 +2534,23 @@ srv_export_innodb_status(void) export_vars.innodb_rows_deleted = srv_n_rows_deleted; export_vars.innodb_truncated_status_writes = srv_truncated_status_writes; +#ifdef UNIV_DEBUG + if (trx_sys->max_trx_id < purge_sys->done_trx_no) { + export_vars.innodb_purge_trx_id_age = 0; + } else { + export_vars.innodb_purge_trx_id_age = + trx_sys->max_trx_id - purge_sys->done_trx_no; + } + + if (!purge_sys->view + || trx_sys->max_trx_id < purge_sys->view->up_limit_id) { + export_vars.innodb_purge_view_trx_id_age = 0; + } else { + export_vars.innodb_purge_view_trx_id_age = + trx_sys->max_trx_id - purge_sys->view->up_limit_id; + } +#endif /* UNIV_DEBUG */ + mutex_exit(&srv_innodb_monitor_mutex); } @@ -3080,11 +3134,19 @@ srv_redo_log_follow_thread( os_event_reset(srv_checkpoint_completed_event); if (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE) { - log_online_follow_redo_log(); + if (!log_online_follow_redo_log()) { + /* TODO: sync with I_S log tracking status? */ + fprintf(stderr, + "InnoDB: Error: log tracking bitmap " + "write failed, stopping log tracking " + "thread!\n"); + break; + } } } while (srv_shutdown_state < SRV_SHUTDOWN_LAST_PHASE); + srv_track_changed_pages = FALSE; log_online_read_shutdown(); os_event_set(srv_redo_log_thread_finished_event); @@ -3329,6 +3391,26 @@ loop: for (i = 0; i < 10; i++) { ulint cur_time = ut_time_ms(); +#ifdef UNIV_DEBUG + if (btr_cur_limit_optimistic_insert_debug + && srv_n_purge_threads == 0) { + /* If btr_cur_limit_optimistic_insert_debug is enabled + and no purge_threads, purge opportunity is increased + by x100 (1purge/100msec), to speed up debug scripts + which should wait for purged. */ + next_itr_time -= 900; + + srv_main_thread_op_info = "master purging"; + + srv_master_do_purge(); + + if (srv_fast_shutdown && srv_shutdown_state > 0) { + + goto background_loop; + } + } +#endif /* UNIV_DEBUG */ + n_pages_flushed = 0; /* initialize */ /* ALTER TABLE in MySQL requires on Unix that the table handler @@ -3487,8 +3569,7 @@ loop: buf_pool = buf_pool_from_array(j); - /* The scanning flush_list is optimistic here */ - + buf_flush_list_mutex_enter(buf_pool); level = 0; n_blocks = 0; bpage = UT_LIST_GET_FIRST(buf_pool->flush_list); @@ -3502,6 +3583,7 @@ loop: bpage = UT_LIST_GET_NEXT(flush_list, bpage); n_blocks++; } + buf_flush_list_mutex_exit(buf_pool); if (level) { bpl += ((ib_uint64_t) n_blocks * n_blocks @@ -3567,30 +3649,25 @@ retry_flush_batch: /* prev_flush_info[j] should be the previous loop's */ for (j = 0; j < srv_buf_pool_instances; j++) { - lint blocks_num, new_blocks_num, flushed_blocks_num; - ibool found; + lint blocks_num, new_blocks_num = 0; + lint flushed_blocks_num; buf_pool = buf_pool_from_array(j); + buf_flush_list_mutex_enter(buf_pool); blocks_num = UT_LIST_GET_LEN(buf_pool->flush_list); bpage = UT_LIST_GET_FIRST(buf_pool->flush_list); - new_blocks_num = 0; - found = FALSE; while (bpage != NULL) { if (prev_flush_info[j].space == bpage->space && prev_flush_info[j].offset == bpage->offset && prev_flush_info[j].oldest_modification == bpage->oldest_modification) { - found = TRUE; break; } bpage = UT_LIST_GET_NEXT(flush_list, bpage); new_blocks_num++; } - if (!found) { - new_blocks_num = blocks_num; - } flushed_blocks_num = new_blocks_num + prev_flush_info[j].count - blocks_num; @@ -3605,7 +3682,9 @@ retry_flush_batch: prev_flush_info[j].space = bpage->space; prev_flush_info[j].offset = bpage->offset; prev_flush_info[j].oldest_modification = bpage->oldest_modification; + buf_flush_list_mutex_exit(buf_pool); } else { + buf_flush_list_mutex_exit(buf_pool); prev_flush_info[j].space = 0; prev_flush_info[j].offset = 0; prev_flush_info[j].oldest_modification = 0; @@ -3631,6 +3710,7 @@ retry_flush_batch: /* store previous first pages of the flush_list */ for (j = 0; j < srv_buf_pool_instances; j++) { buf_pool = buf_pool_from_array(j); + buf_flush_list_mutex_enter(buf_pool); bpage = UT_LIST_GET_FIRST(buf_pool->flush_list); @@ -3639,7 +3719,9 @@ retry_flush_batch: prev_flush_info[j].space = bpage->space; prev_flush_info[j].offset = bpage->offset; prev_flush_info[j].oldest_modification = bpage->oldest_modification; + buf_flush_list_mutex_exit(buf_pool); } else { + buf_flush_list_mutex_exit(buf_pool); prev_flush_info[j].space = 0; prev_flush_info[j].offset = 0; prev_flush_info[j].oldest_modification = 0; |