From 361017e5cef1a1f08d294b541a013dc487c8a658 Mon Sep 17 00:00:00 2001 From: Satya Bodapati Date: Mon, 11 Feb 2019 12:44:23 -0800 Subject: [PATCH] FB8-52: Slowing down transaction log init (#931) (#931) Summary: JIRA: https://jira.percona.com/browse/FB8-52 Reference Patch: https://github.com/facebook/mysql-5.6/commit/80ca845 Reference Patch: https://github.com/facebook/mysql-5.6/commit/0fb428b Patch introduces new variable 'innodb_txlog_init_rate' to limit the IO rate of InnoDB redo log file initialization. Pull Request resolved: https://github.com/facebook/mysql-5.6/pull/931 Reviewed By: lloyd Differential Revision: D13789095 Pulled By: lth --- .../r/innodb_txlog_init_rate_basic.result | 25 +++++++++++++++++++ .../t/innodb_txlog_init_rate_basic.test | 22 ++++++++++++++++ storage/innobase/handler/ha_innodb.cc | 8 ++++++ storage/innobase/include/os0file.h | 10 +++++--- storage/innobase/os/os0file.cc | 20 ++++++++++++--- 5 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 mysql-test/suite/sys_vars/r/innodb_txlog_init_rate_basic.result create mode 100644 mysql-test/suite/sys_vars/t/innodb_txlog_init_rate_basic.test diff --git a/mysql-test/suite/sys_vars/r/innodb_txlog_init_rate_basic.result b/mysql-test/suite/sys_vars/r/innodb_txlog_init_rate_basic.result new file mode 100644 index 000000000000..2540be0d368e --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_txlog_init_rate_basic.result @@ -0,0 +1,25 @@ +SET @orig_txlog_init_rate = @@global.innodb_txlog_init_rate; +SELECT @orig_txlog_init_rate; +@orig_txlog_init_rate +134217728 +SET GLOBAL innodb_txlog_init_rate = 500*1024*1024; +SELECT @@global.innodb_txlog_init_rate; +@@global.innodb_txlog_init_rate +524288000 +SET GLOBAL innodb_txlog_init_rate = 0; +SELECT @@global.innodb_txlog_init_rate; +@@global.innodb_txlog_init_rate +0 +SET GLOBAL innodb_txlog_init_rate = -1; +Warnings: +Warning 1292 Truncated incorrect innodb_txlog_init_rate value: '-1' +SELECT @@global.innodb_txlog_init_rate; +@@global.innodb_txlog_init_rate +0 +SET GLOBAL innodb_txlog_init_rate = 12345; +Warnings: +Warning 1292 Truncated incorrect innodb_txlog_init_rate value: '12345' +SELECT @@global.innodb_txlog_init_rate; +@@global.innodb_txlog_init_rate +0 +SET GLOBAL innodb_txlog_init_rate = @orig_txlog_init_rate; diff --git a/mysql-test/suite/sys_vars/t/innodb_txlog_init_rate_basic.test b/mysql-test/suite/sys_vars/t/innodb_txlog_init_rate_basic.test new file mode 100644 index 000000000000..649e9398f2e5 --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_txlog_init_rate_basic.test @@ -0,0 +1,22 @@ +SET @orig_txlog_init_rate = @@global.innodb_txlog_init_rate; + +SELECT @orig_txlog_init_rate; + +# 500MB/s +SET GLOBAL innodb_txlog_init_rate = 500*1024*1024; +SELECT @@global.innodb_txlog_init_rate; + +# min value +SET GLOBAL innodb_txlog_init_rate = 0; +SELECT @@global.innodb_txlog_init_rate; + +# invalid value +# too small +SET GLOBAL innodb_txlog_init_rate = -1; +SELECT @@global.innodb_txlog_init_rate; + +# not bound to page size +SET GLOBAL innodb_txlog_init_rate = 12345; +SELECT @@global.innodb_txlog_init_rate; + +SET GLOBAL innodb_txlog_init_rate = @orig_txlog_init_rate; diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 826eed0760cd..9147cb8dbcd7 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -22815,6 +22815,13 @@ static MYSQL_SYSVAR_ULONGLONG( "entire file at once before closing it.", nullptr, nullptr, 0, 0, ~0ULL, UNIV_PAGE_SIZE); +static MYSQL_SYSVAR_ULONGLONG( + txlog_init_rate, os_txlog_init_rate, PLUGIN_VAR_OPCMDARG, + "The value of this variable determines how fast (in bytes/s) InnoDB " + "initializes the transaction log when creating a new file" + "Setting this value to 0 means no limit. Default is 128MB", + nullptr, nullptr, 1ULL << 27, 0ULL, ULONG_MAX, 1ULL << 20); + static MYSQL_SYSVAR_ULONG(thread_concurrency, srv_thread_concurrency, PLUGIN_VAR_RQCMDARG, "Helps in performance tuning in heavily concurrent " @@ -23353,6 +23360,7 @@ static SYS_VAR *innobase_system_variables[] = { MYSQL_SYSVAR(spin_wait_delay), MYSQL_SYSVAR(spin_wait_pause_multiplier), MYSQL_SYSVAR(fsync_threshold), + MYSQL_SYSVAR(txlog_init_rate), MYSQL_SYSVAR(table_locks), MYSQL_SYSVAR(thread_concurrency), MYSQL_SYSVAR(adaptive_max_sleep_delay), diff --git a/storage/innobase/include/os0file.h b/storage/innobase/include/os0file.h index a3c01c29450c..ce2a77be5986 100644 --- a/storage/innobase/include/os0file.h +++ b/storage/innobase/include/os0file.h @@ -79,6 +79,10 @@ extern std::atomic os_n_pending_writes; /* Flush after each os_fsync_threshold bytes */ extern unsigned long long os_fsync_threshold; +/** This is used to limit the IO write rate during +initalization of redo log. Unit is bytes/second */ +extern unsigned long long os_txlog_init_rate; + /** File offset in bytes */ typedef uint64_t os_offset_t; @@ -654,7 +658,6 @@ enum class AIO_mode : size_t { extern ulint os_n_file_reads; extern ulint os_n_file_writes; extern ulint os_n_fsyncs; - /* File types for directory entry data type */ enum os_file_type_t { @@ -1435,7 +1438,7 @@ zeros otherwise. @return true if success */ [[nodiscard]] bool os_file_set_size_fast(const char *name, pfs_os_file_t file, os_offset_t offset, os_offset_t size, - bool flush); + bool flush, bool throttle = false); /** Write the specified number of zeros to a file from specific offset. @param[in] name name of the file or path as a null-terminated @@ -1444,10 +1447,11 @@ zeros otherwise. @param[in] offset file offset @param[in] size file size @param[in] flush flush file content to disk +@param[in] throttle throttle the initialization IO write rate @return true if success */ [[nodiscard]] bool os_file_set_size(const char *name, pfs_os_file_t file, os_offset_t offset, os_offset_t size, - bool flush); + bool flush, bool throttle = false); /** Truncates a file at its current position. @param[in,out] file file to be truncated diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index ea68fe7ef886..c8e29a64c6ca 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -103,6 +103,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA /* Flush after each os_fsync_threshold bytes */ unsigned long long os_fsync_threshold = 0; +/* Redo log initialization rate (128MB) */ +unsigned long long os_txlog_init_rate = 1ULL << 27; + /** Insert buffer segment id */ static const ulint IO_IBUF_SEGMENT = 0; @@ -5580,7 +5583,8 @@ void os_file_set_nocache(int fd [[maybe_unused]], } bool os_file_set_size_fast(const char *name, pfs_os_file_t pfs_file, - os_offset_t offset, os_offset_t size, bool flush) { + os_offset_t offset, os_offset_t size, bool flush, + bool throttle) { #if !defined(NO_FALLOCATE) && defined(UNIV_LINUX) && \ defined(HAVE_FALLOC_FL_ZERO_RANGE) ut_a(size >= offset); @@ -5608,11 +5612,11 @@ bool os_file_set_size_fast(const char *name, pfs_os_file_t pfs_file, } #endif /* !NO_FALLOCATE && UNIV_LINUX && HAVE_FALLOC_FL_ZERO_RANGE */ - return os_file_set_size(name, pfs_file, offset, size, flush); + return os_file_set_size(name, pfs_file, offset, size, flush, throttle); } bool os_file_set_size(const char *name, pfs_os_file_t file, os_offset_t offset, - os_offset_t size, bool flush) { + os_offset_t size, bool flush, bool throttle) { /* Write up to FSP_EXTENT_SIZE bytes at a time. */ ulint buf_size = 0; @@ -5635,6 +5639,7 @@ bool os_file_set_size(const char *name, pfs_os_file_t file, os_offset_t offset, /* Count to check and print progress of file write for file_size > 100 MB. */ uint percentage_count = 10; + ulonglong start_time = my_timer_now(); while (current_size < size) { ulint n_bytes; @@ -5654,6 +5659,15 @@ bool os_file_set_size(const char *name, pfs_os_file_t file, os_offset_t offset, return (false); } + if (os_txlog_init_rate > 0 && throttle) { + /* check write rate on every chunk (1MB) we write */ + while ((double)(current_size + n_bytes) > + os_txlog_init_rate * + my_timer_to_seconds(my_timer_since(start_time))) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + } + /* Flush after each os_fsync_threhold bytes */ if (flush && os_fsync_threshold != 0) { if ((current_size + n_bytes) / os_fsync_threshold !=