summaryrefslogtreecommitdiff
path: root/storage/xtradb
diff options
context:
space:
mode:
authorJan Lindström <jan.lindstrom@mariadb.com>2015-12-15 09:30:13 +0200
committerJan Lindström <jan.lindstrom@mariadb.com>2015-12-15 09:35:22 +0200
commitb63bf7368b4881789bef931f90d4719b358cf507 (patch)
tree7542a8a4b0a7170e6664502004e141b9ecd3d92c /storage/xtradb
parentaf3c67056d3f9f7f348c612f9ce48e83c8a456d6 (diff)
downloadmariadb-git-b63bf7368b4881789bef931f90d4719b358cf507.tar.gz
MDEV-8923: port innodb_buffer_pool_dump_pct from MySQL
Backport pull request #125 from grooverdan/MDEV-8923_innodb_buffer_pool_dump_pct to 10.0 WL#6504 InnoDB buffer pool dump/load enchantments This patch consists of two parts: 1. Dump only the hottest N% of the buffer pool(s) 2. Prevent hogging the server duing BP load From MySQL - commit b409342c43ce2edb68807100a77001367c7e6b8e Add testcases for innodb_buffer_pool_dump_pct_basic. Part of the code authored by Daniel Black
Diffstat (limited to 'storage/xtradb')
-rw-r--r--storage/xtradb/buf/buf0dump.cc88
-rw-r--r--storage/xtradb/handler/ha_innodb.cc6
-rw-r--r--storage/xtradb/include/srv0srv.h2
-rw-r--r--storage/xtradb/srv/srv0srv.cc2
4 files changed, 95 insertions, 3 deletions
diff --git a/storage/xtradb/buf/buf0dump.cc b/storage/xtradb/buf/buf0dump.cc
index 090e8cac63b..2b3b506a457 100644
--- a/storage/xtradb/buf/buf0dump.cc
+++ b/storage/xtradb/buf/buf0dump.cc
@@ -230,6 +230,16 @@ buf_dump(
continue;
}
+ if (srv_buf_pool_dump_pct != 100) {
+ ut_ad(srv_buf_pool_dump_pct < 100);
+
+ n_pages = n_pages * srv_buf_pool_dump_pct / 100;
+
+ if (n_pages == 0) {
+ n_pages = 1;
+ }
+ }
+
dump = static_cast<buf_dump_t*>(
ut_malloc(n_pages * sizeof(*dump))) ;
@@ -244,9 +254,9 @@ buf_dump(
return;
}
- for (bpage = UT_LIST_GET_LAST(buf_pool->LRU), j = 0;
- bpage != NULL;
- bpage = UT_LIST_GET_PREV(LRU, bpage), j++) {
+ for (bpage = UT_LIST_GET_FIRST(buf_pool->LRU), j = 0;
+ bpage != NULL && j < n_pages;
+ bpage = UT_LIST_GET_NEXT(LRU, bpage), j++) {
ut_a(buf_page_in_file(bpage));
@@ -361,6 +371,72 @@ buf_dump_sort(
}
/*****************************************************************//**
+Artificially delay the buffer pool loading if necessary. The idea of
+this function is to prevent hogging the server with IO and slowing down
+too much normal client queries. */
+UNIV_INLINE
+void
+buf_load_throttle_if_needed(
+/*========================*/
+ ulint* last_check_time, /*!< in/out: miliseconds since epoch
+ of the last time we did check if
+ throttling is needed, we do the check
+ every srv_io_capacity IO ops. */
+ ulint* last_activity_count,
+ ulint n_io) /*!< in: number of IO ops done since
+ buffer pool load has started */
+{
+ if (n_io % srv_io_capacity < srv_io_capacity - 1) {
+ return;
+ }
+
+ if (*last_check_time == 0 || *last_activity_count == 0) {
+ *last_check_time = ut_time_ms();
+ *last_activity_count = srv_get_activity_count();
+ return;
+ }
+
+ /* srv_io_capacity IO operations have been performed by buffer pool
+ load since the last time we were here. */
+
+ /* If no other activity, then keep going without any delay. */
+ if (srv_get_activity_count() == *last_activity_count) {
+ return;
+ }
+
+ /* There has been other activity, throttle. */
+
+ ulint now = ut_time_ms();
+ ulint elapsed_time = now - *last_check_time;
+
+ /* Notice that elapsed_time is not the time for the last
+ srv_io_capacity IO operations performed by BP load. It is the
+ time elapsed since the last time we detected that there has been
+ other activity. This has a small and acceptable deficiency, e.g.:
+ 1. BP load runs and there is no other activity.
+ 2. Other activity occurs, we run N IO operations after that and
+ enter here (where 0 <= N < srv_io_capacity).
+ 3. last_check_time is very old and we do not sleep at this time, but
+ only update last_check_time and last_activity_count.
+ 4. We run srv_io_capacity more IO operations and call this function
+ again.
+ 5. There has been more other activity and thus we enter here.
+ 6. Now last_check_time is recent and we sleep if necessary to prevent
+ more than srv_io_capacity IO operations per second.
+ The deficiency is that we could have slept at 3., but for this we
+ would have to update last_check_time before the
+ "cur_activity_count == *last_activity_count" check and calling
+ ut_time_ms() that often may turn out to be too expensive. */
+
+ if (elapsed_time < 1000 /* 1 sec (1000 mili secs) */) {
+ os_thread_sleep((1000 - elapsed_time) * 1000 /* micro secs */);
+ }
+
+ *last_check_time = ut_time_ms();
+ *last_activity_count = srv_get_activity_count();
+}
+
+/*****************************************************************//**
Perform a buffer pool load from the file specified by
innodb_buffer_pool_filename. If any errors occur then the value of
innodb_buffer_pool_load_status will be set accordingly, see buf_load_status().
@@ -521,6 +597,9 @@ buf_load()
ut_free(dump_tmp);
+ ulint last_check_time = 0;
+ ulint last_activity_cnt = 0;
+
for (i = 0; i < dump_n && !SHUTTING_DOWN(); i++) {
buf_read_page_async(BUF_DUMP_SPACE(dump[i]),
@@ -544,6 +623,9 @@ buf_load()
"Buffer pool(s) load aborted on request");
return;
}
+
+ buf_load_throttle_if_needed(
+ &last_check_time, &last_activity_cnt, i);
}
ut_free(dump);
diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc
index 348e7107009..e30727b93d1 100644
--- a/storage/xtradb/handler/ha_innodb.cc
+++ b/storage/xtradb/handler/ha_innodb.cc
@@ -17840,6 +17840,11 @@ static MYSQL_SYSVAR_BOOL(buffer_pool_dump_at_shutdown, srv_buffer_pool_dump_at_s
"Dump the buffer pool into a file named @@innodb_buffer_pool_filename",
NULL, NULL, FALSE);
+static MYSQL_SYSVAR_ULONG(buffer_pool_dump_pct, srv_buf_pool_dump_pct,
+ PLUGIN_VAR_RQCMDARG,
+ "Dump only the hottest N% of each buffer pool, defaults to 100",
+ NULL, NULL, 100, 1, 100, 0);
+
#ifdef UNIV_DEBUG
static MYSQL_SYSVAR_STR(buffer_pool_evict, srv_buffer_pool_evict,
PLUGIN_VAR_RQCMDARG,
@@ -18382,6 +18387,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= {
MYSQL_SYSVAR(buffer_pool_filename),
MYSQL_SYSVAR(buffer_pool_dump_now),
MYSQL_SYSVAR(buffer_pool_dump_at_shutdown),
+ MYSQL_SYSVAR(buffer_pool_dump_pct),
#ifdef UNIV_DEBUG
MYSQL_SYSVAR(buffer_pool_evict),
#endif /* UNIV_DEBUG */
diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h
index 981bcd0797a..aabc9c7f434 100644
--- a/storage/xtradb/include/srv0srv.h
+++ b/storage/xtradb/include/srv0srv.h
@@ -335,6 +335,8 @@ extern ulong srv_flush_neighbors; /*!< whether or not to flush
neighbors of a block */
extern ulint srv_buf_pool_old_size; /*!< previously requested size */
extern ulint srv_buf_pool_curr_size; /*!< current size in bytes */
+extern ulong srv_buf_pool_dump_pct; /*!< dump that may % of each buffer
+ pool during BP dump */
extern ulint srv_mem_pool_size;
extern ulint srv_lock_table_size;
diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc
index c92aa0eaf2a..ffded97755e 100644
--- a/storage/xtradb/srv/srv0srv.cc
+++ b/storage/xtradb/srv/srv0srv.cc
@@ -260,6 +260,8 @@ UNIV_INTERN ulong srv_flush_neighbors = 1;
UNIV_INTERN ulint srv_buf_pool_old_size;
/* current size in kilobytes */
UNIV_INTERN ulint srv_buf_pool_curr_size = 0;
+/* dump that may % of each buffer pool during BP dump */
+UNIV_INTERN ulong srv_buf_pool_dump_pct;
/* size in bytes */
UNIV_INTERN ulint srv_mem_pool_size = ULINT_MAX;
UNIV_INTERN ulint srv_lock_table_size = ULINT_MAX;