From 90827b89e9f81df1843d96b45c38bb39391cb7ac Mon Sep 17 00:00:00 2001 From: Yoshinori Matsunobu Date: Mon, 23 Jul 2018 08:19:02 -0700 Subject: [PATCH] Introducing a dedicated thread for handling manual compactions in MyRocks Upstream commit ID : fb-mysql-5.6.35/566b7f095eb1d62a6379c33c911f36d7434898e7 PS-5217 : Merge fb-prod201803 Summary: SET GLOBAL rocksdb_compact_cf='cf_name' is a command to trigger a manual compaction. Manual compaction may take a long time, depending on target column family size. Prior to this diff, when running manual compaction with SET GLOBAL, clean mysqld shutdown was blocked until the manual compaction finished. This was because shutdown path had no way to terminate a user thread calling CompactRange. This diff changes how to handle manual compactions. Changes are as follows. - Introducing a dedicated MyRocks thread to handle manual compactions (via SET GLOBAL rocksdb_compact_cf). Inside RocksDB, only one manual compaction can be running at a time so concurrency does not change. - Adding a system variable (rocksdb_max_manual_compactions), a debug system variable, and a session variable (rocksdb_manual_compaction_threads), and a few status variables to track manual compaction progress. With this diff, normal shutdown no longer waits for manual compaction to finish. Also, you can change the number of manual compaction threads based on each compaction. For example, you can increase compaction threads to 16 for large CFs, and uses 1 thread for small CFs. A user thread calling SET GLOBAL rocksdb_compact_cf checks the manual compaction thread activities, as well as its own thd state. If its manual compaction finishes, or its own thd is killed, the user thread proceeds. As a result, mysqld normal shutdown is no longer blocked by long running manual compactions. Manual compaction thread does not persist any state. This diff does not change OPTIMIZE TABLE behavior. It will be covered by future diffs. Reviewed By: lth Differential Revision: D8874346 fbshipit-source-id: 396f787ff78 Percona Server: - Fixed issue with debug delay variable where code depended on specific expected behavior of my_sleep w.r.t. shutdown is different in PS 5.7. - Moved testing into its own eplicit test file and fixed test to use proper mtr idioms. - Slightly touched up commit comment formatting. --- ...debug_manual_compaction_delay_basic.result | 46 +++ ...sdb_manual_compaction_threads_basic.result | 93 ++++++ ...ocksdb_max_manual_compactions_basic.result | 57 ++++ ...b_debug_manual_compaction_delay_basic.test | 16 + ...cksdb_manual_compaction_threads_basic.test | 17 + .../rocksdb_max_manual_compactions_basic.test | 17 + .../r/non_blocking_manual_compaction.result | 18 ++ mysql-test/suite/rocksdb/r/rocksdb.result | 9 + .../non_blocking_manual_compaction-master.opt | 2 + .../t/non_blocking_manual_compaction.test | 48 +++ storage/rocksdb/ha_rocksdb.cc | 295 ++++++++++++++++-- storage/rocksdb/ha_rocksdb.h | 5 + storage/rocksdb/rdb_psi.cc | 17 +- storage/rocksdb/rdb_psi.h | 10 +- storage/rocksdb/rdb_threads.h | 27 ++ 15 files changed, 640 insertions(+), 37 deletions(-) create mode 100644 mysql-test/suite/rocksdb.sys_vars/r/rocksdb_debug_manual_compaction_delay_basic.result create mode 100644 mysql-test/suite/rocksdb.sys_vars/r/rocksdb_manual_compaction_threads_basic.result create mode 100644 mysql-test/suite/rocksdb.sys_vars/r/rocksdb_max_manual_compactions_basic.result create mode 100644 mysql-test/suite/rocksdb.sys_vars/t/rocksdb_debug_manual_compaction_delay_basic.test create mode 100644 mysql-test/suite/rocksdb.sys_vars/t/rocksdb_manual_compaction_threads_basic.test create mode 100644 mysql-test/suite/rocksdb.sys_vars/t/rocksdb_max_manual_compactions_basic.test create mode 100644 mysql-test/suite/rocksdb/r/non_blocking_manual_compaction.result create mode 100644 mysql-test/suite/rocksdb/t/non_blocking_manual_compaction-master.opt create mode 100644 mysql-test/suite/rocksdb/t/non_blocking_manual_compaction.test diff --git a/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_debug_manual_compaction_delay_basic.result b/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_debug_manual_compaction_delay_basic.result new file mode 100644 index 000000000000..6c5db01533bf --- /dev/null +++ b/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_debug_manual_compaction_delay_basic.result @@ -0,0 +1,46 @@ +CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO valid_values VALUES(2400); +INSERT INTO valid_values VALUES(100000); +CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO invalid_values VALUES('\'aaa\''); +SET @start_global_value = @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY; +SELECT @start_global_value; +@start_global_value +0 +'# Setting to valid values in global scope#' +"Trying to set variable @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY to 2400" +SET @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY = 2400; +SELECT @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY; +@@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY +2400 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY = DEFAULT; +SELECT @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY; +@@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY +0 +"Trying to set variable @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY to 100000" +SET @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY = 100000; +SELECT @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY; +@@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY +100000 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY = DEFAULT; +SELECT @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY; +@@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY +0 +"Trying to set variable @@session.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY to 444. It should fail because it is not session." +SET @@session.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY = 444; +ERROR HY000: Variable 'rocksdb_debug_manual_compaction_delay' is a GLOBAL variable and should be set with SET GLOBAL +'# Testing with invalid values in global scope #' +"Trying to set variable @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY to 'aaa'" +SET @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY = 'aaa'; +Got one of the listed errors +SELECT @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY; +@@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY +0 +SET @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY = @start_global_value; +SELECT @@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY; +@@global.ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY +0 +DROP TABLE valid_values; +DROP TABLE invalid_values; diff --git a/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_manual_compaction_threads_basic.result b/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_manual_compaction_threads_basic.result new file mode 100644 index 000000000000..3d599e1768ed --- /dev/null +++ b/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_manual_compaction_threads_basic.result @@ -0,0 +1,93 @@ +CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO valid_values VALUES(0); +INSERT INTO valid_values VALUES(1); +INSERT INTO valid_values VALUES(99); +CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO invalid_values VALUES('\'aaa\''); +SET @start_global_value = @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +SELECT @start_global_value; +@start_global_value +0 +SET @start_session_value = @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +SELECT @start_session_value; +@start_session_value +0 +'# Setting to valid values in global scope#' +"Trying to set variable @@global.ROCKSDB_MANUAL_COMPACTION_THREADS to 0" +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = 0; +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = DEFAULT; +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +"Trying to set variable @@global.ROCKSDB_MANUAL_COMPACTION_THREADS to 1" +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = 1; +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +1 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = DEFAULT; +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +"Trying to set variable @@global.ROCKSDB_MANUAL_COMPACTION_THREADS to 99" +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = 99; +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +99 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = DEFAULT; +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +'# Setting to valid values in session scope#' +"Trying to set variable @@session.ROCKSDB_MANUAL_COMPACTION_THREADS to 0" +SET @@session.ROCKSDB_MANUAL_COMPACTION_THREADS = 0; +SELECT @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@session.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +"Setting the session scope variable back to default" +SET @@session.ROCKSDB_MANUAL_COMPACTION_THREADS = DEFAULT; +SELECT @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@session.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +"Trying to set variable @@session.ROCKSDB_MANUAL_COMPACTION_THREADS to 1" +SET @@session.ROCKSDB_MANUAL_COMPACTION_THREADS = 1; +SELECT @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@session.ROCKSDB_MANUAL_COMPACTION_THREADS +1 +"Setting the session scope variable back to default" +SET @@session.ROCKSDB_MANUAL_COMPACTION_THREADS = DEFAULT; +SELECT @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@session.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +"Trying to set variable @@session.ROCKSDB_MANUAL_COMPACTION_THREADS to 99" +SET @@session.ROCKSDB_MANUAL_COMPACTION_THREADS = 99; +SELECT @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@session.ROCKSDB_MANUAL_COMPACTION_THREADS +99 +"Setting the session scope variable back to default" +SET @@session.ROCKSDB_MANUAL_COMPACTION_THREADS = DEFAULT; +SELECT @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@session.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +'# Testing with invalid values in global scope #' +"Trying to set variable @@global.ROCKSDB_MANUAL_COMPACTION_THREADS to 'aaa'" +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = 'aaa'; +Got one of the listed errors +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +SET @@global.ROCKSDB_MANUAL_COMPACTION_THREADS = @start_global_value; +SELECT @@global.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@global.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +SET @@session.ROCKSDB_MANUAL_COMPACTION_THREADS = @start_session_value; +SELECT @@session.ROCKSDB_MANUAL_COMPACTION_THREADS; +@@session.ROCKSDB_MANUAL_COMPACTION_THREADS +0 +DROP TABLE valid_values; +DROP TABLE invalid_values; diff --git a/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_max_manual_compactions_basic.result b/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_max_manual_compactions_basic.result new file mode 100644 index 000000000000..815506ccac8c --- /dev/null +++ b/mysql-test/suite/rocksdb.sys_vars/r/rocksdb_max_manual_compactions_basic.result @@ -0,0 +1,57 @@ +CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO valid_values VALUES(1); +INSERT INTO valid_values VALUES(1024); +INSERT INTO valid_values VALUES(512*1024*1024); +CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO invalid_values VALUES('\'aaa\''); +SET @start_global_value = @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +SELECT @start_global_value; +@start_global_value +10 +'# Setting to valid values in global scope#' +"Trying to set variable @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS to 1" +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = 1; +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +1 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = DEFAULT; +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +10 +"Trying to set variable @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS to 1024" +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = 1024; +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +1024 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = DEFAULT; +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +10 +"Trying to set variable @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS to 536870912" +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = 536870912; +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +536870912 +"Setting the global scope variable back to default" +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = DEFAULT; +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +10 +"Trying to set variable @@session.ROCKSDB_MAX_MANUAL_COMPACTIONS to 444. It should fail because it is not session." +SET @@session.ROCKSDB_MAX_MANUAL_COMPACTIONS = 444; +ERROR HY000: Variable 'rocksdb_max_manual_compactions' is a GLOBAL variable and should be set with SET GLOBAL +'# Testing with invalid values in global scope #' +"Trying to set variable @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS to 'aaa'" +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = 'aaa'; +Got one of the listed errors +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +10 +SET @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS = @start_global_value; +SELECT @@global.ROCKSDB_MAX_MANUAL_COMPACTIONS; +@@global.ROCKSDB_MAX_MANUAL_COMPACTIONS +10 +DROP TABLE valid_values; +DROP TABLE invalid_values; diff --git a/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_debug_manual_compaction_delay_basic.test b/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_debug_manual_compaction_delay_basic.test new file mode 100644 index 000000000000..518c284c0cf8 --- /dev/null +++ b/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_debug_manual_compaction_delay_basic.test @@ -0,0 +1,16 @@ +--source include/have_rocksdb.inc + +CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO valid_values VALUES(2400); +INSERT INTO valid_values VALUES(100000); + +CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO invalid_values VALUES('\'aaa\''); + +--let $sys_var=ROCKSDB_DEBUG_MANUAL_COMPACTION_DELAY +--let $read_only=0 +--let $session=0 +--source ../include/rocksdb_sys_var.inc + +DROP TABLE valid_values; +DROP TABLE invalid_values; diff --git a/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_manual_compaction_threads_basic.test b/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_manual_compaction_threads_basic.test new file mode 100644 index 000000000000..4f166a9ca8ed --- /dev/null +++ b/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_manual_compaction_threads_basic.test @@ -0,0 +1,17 @@ +--source include/have_rocksdb.inc + +CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO valid_values VALUES(0); +INSERT INTO valid_values VALUES(1); +INSERT INTO valid_values VALUES(99); + +CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO invalid_values VALUES('\'aaa\''); + +--let $sys_var=ROCKSDB_MANUAL_COMPACTION_THREADS +--let $read_only=0 +--let $session=1 +--source ../include/rocksdb_sys_var.inc + +DROP TABLE valid_values; +DROP TABLE invalid_values; diff --git a/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_max_manual_compactions_basic.test b/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_max_manual_compactions_basic.test new file mode 100644 index 000000000000..1c66316858b8 --- /dev/null +++ b/mysql-test/suite/rocksdb.sys_vars/t/rocksdb_max_manual_compactions_basic.test @@ -0,0 +1,17 @@ +--source include/have_rocksdb.inc + +CREATE TABLE valid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO valid_values VALUES(1); +INSERT INTO valid_values VALUES(1024); +INSERT INTO valid_values VALUES(512*1024*1024); + +CREATE TABLE invalid_values (value varchar(255)) ENGINE=myisam; +INSERT INTO invalid_values VALUES('\'aaa\''); + +--let $sys_var=ROCKSDB_MAX_MANUAL_COMPACTIONS +--let $read_only=0 +--let $session=0 +--source ../include/rocksdb_sys_var.inc + +DROP TABLE valid_values; +DROP TABLE invalid_values; diff --git a/mysql-test/suite/rocksdb/r/non_blocking_manual_compaction.result b/mysql-test/suite/rocksdb/r/non_blocking_manual_compaction.result new file mode 100644 index 000000000000..00392a13606d --- /dev/null +++ b/mysql-test/suite/rocksdb/r/non_blocking_manual_compaction.result @@ -0,0 +1,18 @@ +CREATE TABLE t1 ( +a int not null, +b int not null, +primary key (a,b) comment 'cf1', +key (b) comment 'rev:cf2' +) ENGINE=ROCKSDB; +DELETE FROM t1; +SET GLOBAL rocksdb_max_manual_compactions = 2; +SET GLOBAL rocksdb_debug_manual_compaction_delay = 3600; +SET GLOBAL rocksdb_compact_cf='cf1'; +SET GLOBAL rocksdb_compact_cf='rev:cf2'; +Timeout in wait_condition.inc for select variable_value > 1 from performance_schema.global_status where variable_name='rocksdb_manual_compactions_running' +SET GLOBAL rocksdb_compact_cf='cf1'; +ERROR HY000: Internal error: Can't schedule more manual compactions. Increase rocksdb_max_manual_compactions or stop issuing more manual compactions. +SET GLOBAL rocksdb_compact_cf='rev:cf2'; +ERROR HY000: Internal error: Can't schedule more manual compactions. Increase rocksdb_max_manual_compactions or stop issuing more manual compactions. +DROP TABLE t1; +# restart diff --git a/mysql-test/suite/rocksdb/r/rocksdb.result b/mysql-test/suite/rocksdb/r/rocksdb.result index ce1c374b13b8..3fb62f3de101 100644 --- a/mysql-test/suite/rocksdb/r/rocksdb.result +++ b/mysql-test/suite/rocksdb/r/rocksdb.result @@ -922,6 +922,7 @@ rocksdb_datadir ./.rocksdb rocksdb_db_write_buffer_size 0 rocksdb_deadlock_detect OFF rocksdb_deadlock_detect_depth 50 +rocksdb_debug_manual_compaction_delay 0 rocksdb_debug_optimizer_no_zero_cardinality ON rocksdb_debug_ttl_ignore_pk OFF rocksdb_debug_ttl_read_filter_ts 0 @@ -954,11 +955,13 @@ rocksdb_lock_scanned_rows OFF rocksdb_lock_wait_timeout 1 rocksdb_log_file_time_to_roll 0 rocksdb_manifest_preallocation_size 4194304 +rocksdb_manual_compaction_threads 0 rocksdb_manual_wal_flush ON rocksdb_max_background_jobs 2 rocksdb_max_latest_deadlocks 5 rocksdb_max_log_file_size 0 rocksdb_max_manifest_file_size 1073741824 +rocksdb_max_manual_compactions 10 rocksdb_max_row_locks 1048576 rocksdb_max_subcompactions 1 rocksdb_max_total_wal_size 2147483648 @@ -1568,6 +1571,8 @@ rocksdb_get_hit_l1 # rocksdb_get_hit_l2_and_up # rocksdb_get_updates_since_calls # rocksdb_iter_bytes_read # +rocksdb_manual_compactions_processed # +rocksdb_manual_compactions_running # rocksdb_memtable_hit # rocksdb_memtable_miss # rocksdb_no_file_closes # @@ -1676,6 +1681,8 @@ rocksdb_get_hit_l1 rocksdb_get_hit_l2_and_up rocksdb_get_updates_since_calls rocksdb_iter_bytes_read +rocksdb_manual_compactions_processed +rocksdb_manual_compactions_running rocksdb_memtable_hit rocksdb_memtable_miss rocksdb_no_file_closes @@ -1786,6 +1793,8 @@ rocksdb_get_hit_l1 rocksdb_get_hit_l2_and_up rocksdb_get_updates_since_calls rocksdb_iter_bytes_read +rocksdb_manual_compactions_processed +rocksdb_manual_compactions_running rocksdb_memtable_hit rocksdb_memtable_miss rocksdb_no_file_closes diff --git a/mysql-test/suite/rocksdb/t/non_blocking_manual_compaction-master.opt b/mysql-test/suite/rocksdb/t/non_blocking_manual_compaction-master.opt new file mode 100644 index 000000000000..3016407cd346 --- /dev/null +++ b/mysql-test/suite/rocksdb/t/non_blocking_manual_compaction-master.opt @@ -0,0 +1,2 @@ +--loose-rocksdb_max_subcompactions=1 +--loose-rocksdb_default_cf_options=write_buffer_size=512k;target_file_size_base=512k;level0_file_num_compaction_trigger=2;level0_slowdown_writes_trigger=-1;level0_stop_writes_trigger=1000;max_bytes_for_level_base=1m diff --git a/mysql-test/suite/rocksdb/t/non_blocking_manual_compaction.test b/mysql-test/suite/rocksdb/t/non_blocking_manual_compaction.test new file mode 100644 index 000000000000..35420e1e75f3 --- /dev/null +++ b/mysql-test/suite/rocksdb/t/non_blocking_manual_compaction.test @@ -0,0 +1,48 @@ +--source include/have_rocksdb.inc +--source include/count_sessions.inc + +CREATE TABLE t1 ( + a int not null, + b int not null, + primary key (a,b) comment 'cf1', + key (b) comment 'rev:cf2' +) ENGINE=ROCKSDB; + +# Populate tables +let $max = 1000; +let $table = t1; +--source suite/rocksdb/include/drop_table_repopulate_table.inc + +# Run manual compaction, then restarting mysqld +# and confirming it is not blocked. +SET GLOBAL rocksdb_max_manual_compactions = 2; +SET GLOBAL rocksdb_debug_manual_compaction_delay = 3600; +connect (con1, localhost, root,,); +connect (con2, localhost, root,,); +connect (con3, localhost, root,,); +connection con1; +send SET GLOBAL rocksdb_compact_cf='cf1'; +connection con2; +send SET GLOBAL rocksdb_compact_cf='rev:cf2'; +connection default; +let $wait_condition = select count(*) = 2 from information_schema.processlist where info like 'SET GLOBAL rocksdb_compact_cf%'; +--source include/wait_condition.inc + +let $wait_condition = select variable_value > 1 from performance_schema.global_status where variable_name='rocksdb_manual_compactions_running'; +--source include/wait_condition.inc + +connection con3; +--error ER_INTERNAL_ERROR +SET GLOBAL rocksdb_compact_cf='cf1'; +--error ER_INTERNAL_ERROR +SET GLOBAL rocksdb_compact_cf='rev:cf2'; + +connection default; +disconnect con1; +disconnect con2; +disconnect con3; + +DROP TABLE t1; + +--source include/restart_mysqld.inc +--source include/wait_until_count_sessions.inc diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 813af926e634..68a9476d1edd 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -115,11 +115,15 @@ static handler *rocksdb_create_handler(my_core::handlerton *hton, bool partitioned, my_core::MEM_ROOT *mem_root); -static rocksdb::CompactRangeOptions getCompactRangeOptions() { +static rocksdb::CompactRangeOptions +getCompactRangeOptions(int concurrency = 0) { rocksdb::CompactRangeOptions compact_range_options; compact_range_options.bottommost_level_compaction = rocksdb::BottommostLevelCompaction::kForce; compact_range_options.exclusive_manual_compaction = false; + if (concurrency > 0) { + compact_range_options.max_subcompactions = concurrency; + } return compact_range_options; } @@ -154,6 +158,8 @@ Rdb_hton_init_state hton_init_state; static Rdb_background_thread rdb_bg_thread; +static Rdb_manual_compaction_thread rdb_mc_thread; + // List of table names (using regex) that are exceptions to the strict // collation check requirement. Regex *rdb_collation_exceptions; @@ -167,31 +173,6 @@ static void rocksdb_flush_all_memtables() { } } -static void rocksdb_compact_column_family_stub(THD *const thd, - struct SYS_VAR *const var, - void *const var_ptr, - const void *const save) {} - -static int rocksdb_compact_column_family(THD *const thd, - struct SYS_VAR *const var, - void *const var_ptr, - struct st_mysql_value *const value) { - char buff[STRING_BUFFER_USUAL_SIZE]; - int len = sizeof(buff); - - DBUG_ASSERT(value != nullptr); - - if (const char *const cf = value->val_str(value, buff, &len)) { - auto cfh = cf_manager.get_cf(cf); - if (cfh != nullptr && rdb != nullptr) { - LogPluginErrMsg(INFORMATION_LEVEL, 0, - "RocksDB: Manual compaction of column family: %s\n", cf); - rdb->CompactRange(getCompactRangeOptions(), cfh, nullptr, nullptr); - } - } - return HA_EXIT_SUCCESS; -} - /////////////////////////////////////////////////////////// // Hash map: table name => open table handler /////////////////////////////////////////////////////////// @@ -304,7 +285,7 @@ static int rocksdb_force_flush_memtable_and_lzero_now( DBUG_ASSERT(metadata.levels[0].level == 0); std::vector file_names; - for (auto &file : metadata.levels[0].files) { + for (const auto &file : metadata.levels[0].files) { file_names.emplace_back(file.db_path + file.name); } @@ -494,11 +475,15 @@ static uint64_t rocksdb_write_policy = static bool rocksdb_error_on_suboptimal_collation = false; static uint32_t rocksdb_stats_recalc_rate = 0; static bool rocksdb_no_create_column_family = false; +static uint32_t rocksdb_debug_manual_compaction_delay = 0; +static uint32_t rocksdb_max_manual_compactions = 0; std::atomic rocksdb_row_lock_deadlocks(0); std::atomic rocksdb_row_lock_wait_timeouts(0); std::atomic rocksdb_snapshot_conflict_errors(0); std::atomic rocksdb_wal_group_syncs(0); +std::atomic rocksdb_manual_compactions_processed(0); +std::atomic rocksdb_manual_compactions_running(0); static std::unique_ptr rdb_init_rocksdb_db_options(void) { auto o = std::unique_ptr(new rocksdb::DBOptions()); @@ -615,6 +600,14 @@ static int rocksdb_validate_flush_log_at_trx_commit( *static_cast(var_ptr) = static_cast(new_value); return HA_EXIT_SUCCESS; } +static void rocksdb_compact_column_family_stub( + THD *const thd, struct st_mysql_sys_var *const var, void *const var_ptr, + const void *const save) {} + +static int rocksdb_compact_column_family(THD *const thd, + struct st_mysql_sys_var *const var, + void *const var_ptr, + struct st_mysql_value *const value); static const char *index_type_names[] = {"kBinarySearch", "kHashSearch", NullS}; @@ -755,6 +748,12 @@ static MYSQL_THDVAR_ULONGLONG( /* min (0ms) */ RDB_MIN_MERGE_TMP_FILE_REMOVAL_DELAY, /* max */ SIZE_T_MAX, 1); +static MYSQL_THDVAR_INT( + manual_compaction_threads, PLUGIN_VAR_RQCMDARG, + "How many rocksdb threads to run for manual compactions", nullptr, nullptr, + /* default rocksdb.dboption max_subcompactions */ 0, + /* min */ 0, /* max */ 128, 0); + static MYSQL_SYSVAR_BOOL( create_if_missing, *static_cast(&rocksdb_db_options->create_if_missing), @@ -1354,6 +1353,18 @@ static MYSQL_SYSVAR_BOOL( "on PK TTL data. This variable is a no-op in non-debug builds.", nullptr, nullptr, false); +static MYSQL_SYSVAR_UINT( + max_manual_compactions, rocksdb_max_manual_compactions, PLUGIN_VAR_RQCMDARG, + "Maximum number of pending + ongoing number of manual compactions.", + nullptr, nullptr, /* default */ 10, /* min */ 0, /* max */ UINT_MAX, 0); + +static MYSQL_SYSVAR_UINT( + debug_manual_compaction_delay, rocksdb_debug_manual_compaction_delay, + PLUGIN_VAR_RQCMDARG, + "For debugging purposes only. Sleeping specified seconds " + "for simulating long running compactions.", + nullptr, nullptr, 0, /* min */ 0, /* max */ UINT_MAX, 0); + static MYSQL_SYSVAR_BOOL( reset_stats, rocksdb_reset_stats, PLUGIN_VAR_RQCMDARG, "Reset the RocksDB internal statistics without restarting the DB.", nullptr, @@ -1677,6 +1688,9 @@ static struct SYS_VAR *rocksdb_system_variables[] = { MYSQL_SYSVAR(error_on_suboptimal_collation), MYSQL_SYSVAR(no_create_column_family), MYSQL_SYSVAR(stats_recalc_rate), + MYSQL_SYSVAR(debug_manual_compaction_delay), + MYSQL_SYSVAR(max_manual_compactions), + MYSQL_SYSVAR(manual_compaction_threads), nullptr}; static rocksdb::WriteOptions @@ -1691,6 +1705,50 @@ rdb_get_rocksdb_write_options(my_core::THD *const thd) { return opt; } +static int rocksdb_compact_column_family(THD *const thd, + struct st_mysql_sys_var *const var, + void *const var_ptr, + struct st_mysql_value *const value) { + char buff[STRING_BUFFER_USUAL_SIZE]; + int len = sizeof(buff); + + DBUG_ASSERT(value != nullptr); + + if (const char *const cf = value->val_str(value, buff, &len)) { + auto cfh = cf_manager.get_cf(cf); + if (cfh != nullptr && rdb != nullptr) { + int mc_id = rdb_mc_thread.request_manual_compaction( + cfh, nullptr, nullptr, THDVAR(thd, manual_compaction_threads)); + if (mc_id == -1) { + my_error(ER_INTERNAL_ERROR, MYF(0), + "Can't schedule more manual compactions. " + "Increase rocksdb_max_manual_compactions or stop issuing " + "more manual compactions."); + return HA_EXIT_FAILURE; + } else if (mc_id < 0) { + return HA_EXIT_FAILURE; + } + // NO_LINT_DEBUG + sql_print_information("RocksDB: Manual compaction of column family: %s\n", + cf); + // Checking thd state every short cycle (100ms). This is for allowing to + // exiting this function without waiting for CompactRange to finish. + do { + my_sleep(100000); + } while (!thd->killed && + !rdb_mc_thread.is_manual_compaction_finished(mc_id)); + + if (thd->killed) { + // This cancels if requested compaction state is INITED. + // TODO(yoshinorim): Cancel running compaction as well once + // it is supported in RocksDB. + rdb_mc_thread.clear_manual_compaction_request(mc_id, true); + } + } + } + return HA_EXIT_SUCCESS; +} + /* Drop index thread's control */ @@ -3919,9 +3977,11 @@ static int rocksdb_init_func(void *const p) { rdb_bg_thread.init(rdb_signal_bg_psi_mutex_key, rdb_signal_bg_psi_cond_key); rdb_drop_idx_thread.init(rdb_signal_drop_idx_psi_mutex_key, rdb_signal_drop_idx_psi_cond_key); + rdb_mc_thread.init(rdb_signal_mc_psi_mutex_key, rdb_signal_mc_psi_cond_key); #else rdb_bg_thread.init(); rdb_drop_idx_thread.init(); + rdb_mc_thread.init(); #endif mysql_mutex_init(rdb_collation_data_mutex_key, &rdb_collation_data_mutex, MY_MUTEX_INIT_FAST); @@ -4295,6 +4355,20 @@ static int rocksdb_init_func(void *const p) { DBUG_RETURN(HA_EXIT_FAILURE); } + err = rdb_mc_thread.create_thread(MANUAL_COMPACTION_THREAD_NAME +#ifdef HAVE_PSI_INTERFACE + , + rdb_mc_psi_thread_key +#endif + ); + if (err != 0) { + // NO_LINT_DEBUG + sql_print_error( + "RocksDB: Couldn't start the manual compaction thread: (errno=%d)", + err); + DBUG_RETURN(HA_EXIT_FAILURE); + } + rdb_set_collation_exception_list(rocksdb_strict_collation_exceptions); if (rocksdb_pause_background_work) { @@ -4367,6 +4441,16 @@ static int rocksdb_done_func(void *const p) { "Couldn't stop the index thread: (errno=%d)", err); } + // signal the manual compaction thread to stop + rdb_mc_thread.signal(true); + // Wait for the manual compaction thread to finish. + err = rdb_mc_thread.join(); + if (err != 0) { + // NO_LINT_DEBUG + sql_print_error( + "RocksDB: Couldn't stop the manual compaction thread: (errno=%d)", err); + } + if (rdb_open_tables.m_hash.size()) { // Looks like we are getting unloaded and yet we have some open tables // left behind. @@ -11977,6 +12061,10 @@ static SHOW_VAR rocksdb_status_vars[] = { &rocksdb_snapshot_conflict_errors, SHOW_LONGLONG), DEF_STATUS_VAR_PTR("wal_group_syncs", &rocksdb_wal_group_syncs, SHOW_LONGLONG), + DEF_STATUS_VAR_PTR("manual_compactions_processed", + &rocksdb_manual_compactions_processed, SHOW_LONGLONG), + DEF_STATUS_VAR_PTR("manual_compactions_running", + &rocksdb_manual_compactions_running, SHOW_LONGLONG), DEF_STATUS_VAR_PTR("number_sst_entry_put", &rocksdb_num_sst_entry_put, SHOW_LONGLONG), DEF_STATUS_VAR_PTR("number_sst_entry_delete", &rocksdb_num_sst_entry_delete, @@ -12097,6 +12185,159 @@ void Rdb_background_thread::run() { ddl_manager.persist_stats(); } +/* + A background thread to handle manual compactions, + except for dropping indexes/tables. Every second, it checks + pending manual compactions, and it calls CompactRange if there is. +*/ +void Rdb_manual_compaction_thread::run() { + mysql_mutex_init(0, &m_mc_mutex, MY_MUTEX_INIT_FAST); + RDB_MUTEX_LOCK_CHECK(m_signal_mutex); + for (;;) { + if (m_stop) { + break; + } + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += 1; + + const auto ret MY_ATTRIBUTE((__unused__)) = + mysql_cond_timedwait(&m_signal_cond, &m_signal_mutex, &ts); + if (m_stop) { + break; + } + // make sure, no program error is returned + DBUG_ASSERT(ret == 0 || ret == ETIMEDOUT); + RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); + + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + // Grab the first item and proceed, if not empty. + if (m_requests.empty()) { + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + RDB_MUTEX_LOCK_CHECK(m_signal_mutex); + continue; + } + Manual_compaction_request &mcr = m_requests.begin()->second; + DBUG_ASSERT(mcr.cf != nullptr); + DBUG_ASSERT(mcr.state == Manual_compaction_request::INITED); + mcr.state = Manual_compaction_request::RUNNING; + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + + DBUG_ASSERT(mcr.state == Manual_compaction_request::RUNNING); + // NO_LINT_DEBUG + sql_print_information("Manual Compaction id %d cf %s started.", mcr.mc_id, + mcr.cf->GetName().c_str()); + rocksdb_manual_compactions_running++; + if (rocksdb_debug_manual_compaction_delay > 0) { + // In Facebook MySQL 5.6.35, my_sleep breaks the sleep when the server + // gets a shutdown signal and this code depended on that behavior. + // In 5.7, for whatever reason, this is not the case. my_sleep will + // continue to sleep until the sleep time has elapsed. For the purpose + // of this variable and the accompanying test case, we need to break this + // down into a loop that sleeps and checks to see if the thread was + // signalled with the stop flag. It is ugly, but without having DBUG_SYNC + // available in background threads, it is good enough for the test. + for (uint32_t sleeps = 0; sleeps < rocksdb_debug_manual_compaction_delay; + sleeps++) { + RDB_MUTEX_LOCK_CHECK(m_signal_mutex); + const bool local_stop = m_stop; + RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); + if (local_stop) + break; + my_sleep(1000000); + } + } + // CompactRange may take a very long time. On clean shutdown, + // it is cancelled by CancelAllBackgroundWork, then status is + // set to shutdownInProgress. + const rocksdb::Status s = rdb->CompactRange( + getCompactRangeOptions(mcr.concurrency), mcr.cf, mcr.start, mcr.limit); + rocksdb_manual_compactions_running--; + if (s.ok()) { + // NO_LINT_DEBUG + sql_print_information("Manual Compaction id %d cf %s ended.", mcr.mc_id, + mcr.cf->GetName().c_str()); + } else { + // NO_LINT_DEBUG + sql_print_information("Manual Compaction id %d cf %s aborted. %s", + mcr.mc_id, mcr.cf->GetName().c_str(), s.getState()); + if (!s.IsShutdownInProgress()) { + rdb_handle_io_error(s, RDB_IO_ERROR_BG_THREAD); + } else { + DBUG_ASSERT(m_requests.size() == 1); + } + } + rocksdb_manual_compactions_processed++; + clear_manual_compaction_request(mcr.mc_id, false); + RDB_MUTEX_LOCK_CHECK(m_signal_mutex); + } + clear_all_manual_compaction_requests(); + DBUG_ASSERT(m_requests.empty()); + RDB_MUTEX_UNLOCK_CHECK(m_signal_mutex); + mysql_mutex_destroy(&m_mc_mutex); +} + +void Rdb_manual_compaction_thread::clear_all_manual_compaction_requests() { + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + m_requests.clear(); + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); +} + +void Rdb_manual_compaction_thread::clear_manual_compaction_request( + int mc_id, bool init_only) { + bool erase = true; + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + auto it = m_requests.find(mc_id); + if (it != m_requests.end()) { + if (init_only) { + Manual_compaction_request mcr = it->second; + if (mcr.state != Manual_compaction_request::INITED) { + erase = false; + } + } + if (erase) { + m_requests.erase(it); + } + } else { + // Current code path guarantees that erasing by the same mc_id happens + // at most once. INITED state may be erased by a thread that requested + // the compaction. RUNNING state is erased by mc thread only. + DBUG_ASSERT(0); + } + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); +} + +int Rdb_manual_compaction_thread::request_manual_compaction( + rocksdb::ColumnFamilyHandle *cf, rocksdb::Slice *start, + rocksdb::Slice *limit, int concurrency) { + int mc_id = -1; + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + if (m_requests.size() >= rocksdb_max_manual_compactions) { + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + return mc_id; + } + Manual_compaction_request mcr; + mc_id = mcr.mc_id = ++m_latest_mc_id; + mcr.state = Manual_compaction_request::INITED; + mcr.cf = cf; + mcr.start = start; + mcr.limit = limit; + mcr.concurrency = concurrency; + m_requests.insert(std::make_pair(mcr.mc_id, mcr)); + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + return mc_id; +} + +bool Rdb_manual_compaction_thread::is_manual_compaction_finished(int mc_id) { + bool finished = false; + RDB_MUTEX_LOCK_CHECK(m_mc_mutex); + if (m_requests.count(mc_id) == 0) { + finished = true; + } + RDB_MUTEX_UNLOCK_CHECK(m_mc_mutex); + return finished; +} + bool ha_rocksdb::check_bloom_and_set_bounds( THD *thd, const Rdb_key_def &kd, const rocksdb::Slice &eq_cond, const bool use_all_keys, size_t bound_len, uchar *const lower_bound, diff --git a/storage/rocksdb/ha_rocksdb.h b/storage/rocksdb/ha_rocksdb.h index 3a5535624be5..b039e7443768 100644 --- a/storage/rocksdb/ha_rocksdb.h +++ b/storage/rocksdb/ha_rocksdb.h @@ -150,6 +150,11 @@ const char *const BG_THREAD_NAME = "myrocks-bg"; */ const char *const INDEX_THREAD_NAME = "myrocks-index"; +/* + Name for the manual compaction thread. +*/ +static const char constexpr MANUAL_COMPACTION_THREAD_NAME[] = "myrocks-mc"; + /* Separator between partition name and the qualifier. Sample usage: diff --git a/storage/rocksdb/rdb_psi.cc b/storage/rocksdb/rdb_psi.cc index da9d72326e99..315b20525bf1 100644 --- a/storage/rocksdb/rdb_psi.cc +++ b/storage/rocksdb/rdb_psi.cc @@ -35,17 +35,19 @@ my_core::PSI_stage_info stage_waiting_on_row_lock(0, "Waiting for row lock", 0, my_core::PSI_stage_info *all_rocksdb_stages[] = {&stage_waiting_on_row_lock}; my_core::PSI_thread_key rdb_background_psi_thread_key, - rdb_drop_idx_psi_thread_key; + rdb_drop_idx_psi_thread_key, rdb_mc_psi_thread_key; my_core::PSI_thread_info all_rocksdb_threads[] = { {&rdb_background_psi_thread_key, "background", PSI_FLAG_SINGLETON}, {&rdb_drop_idx_psi_thread_key, "drop index", PSI_FLAG_SINGLETON}, + {&rdb_mc_psi_thread_key, "manual compaction", PSI_FLAG_SINGLETON}, }; my_core::PSI_mutex_key rdb_psi_open_tbls_mutex_key, rdb_signal_bg_psi_mutex_key, - rdb_signal_drop_idx_psi_mutex_key, rdb_collation_data_mutex_key, - rdb_mem_cmp_space_mutex_key, key_mutex_tx_list, rdb_sysvars_psi_mutex_key, - rdb_cfm_mutex_key, rdb_sst_commit_key, rdb_block_cache_resize_mutex_key; + rdb_signal_drop_idx_psi_mutex_key, rdb_signal_mc_psi_mutex_key, + rdb_collation_data_mutex_key, rdb_mem_cmp_space_mutex_key, + key_mutex_tx_list, rdb_sysvars_psi_mutex_key, rdb_cfm_mutex_key, + rdb_sst_commit_key, rdb_block_cache_resize_mutex_key; my_core::PSI_mutex_info all_rocksdb_mutexes[] = { {&rdb_psi_open_tbls_mutex_key, "open tables", PSI_FLAG_SINGLETON}, @@ -53,6 +55,9 @@ my_core::PSI_mutex_info all_rocksdb_mutexes[] = { {&rdb_signal_drop_idx_psi_mutex_key, "signal drop index", PSI_FLAG_SINGLETON}, {&rdb_collation_data_mutex_key, "collation data init", PSI_FLAG_SINGLETON}, + {&rdb_signal_mc_psi_mutex_key, "signal manual compaction", + PSI_FLAG_SINGLETON}, + {&rdb_collation_data_mutex_key, "collation data init", PSI_FLAG_SINGLETON}, {&rdb_mem_cmp_space_mutex_key, "collation space char data init", PSI_FLAG_SINGLETON}, {&key_mutex_tx_list, "tx_list", PSI_FLAG_SINGLETON}, @@ -76,12 +81,14 @@ my_core::PSI_rwlock_info all_rocksdb_rwlocks[] = { }; my_core::PSI_cond_key rdb_signal_bg_psi_cond_key, - rdb_signal_drop_idx_psi_cond_key; + rdb_signal_drop_idx_psi_cond_key, rdb_signal_mc_psi_cond_key; my_core::PSI_cond_info all_rocksdb_conds[] = { {&rdb_signal_bg_psi_cond_key, "cond signal background", PSI_FLAG_SINGLETON}, {&rdb_signal_drop_idx_psi_cond_key, "cond signal drop index", PSI_FLAG_SINGLETON}, + {&rdb_signal_mc_psi_cond_key, "cond signal manual compaction", + PSI_FLAG_SINGLETON}, }; my_core::PSI_memory_key rdb_datadic_memory_key, rdb_open_tables_memory_key, diff --git a/storage/rocksdb/rdb_psi.h b/storage/rocksdb/rdb_psi.h index cab4bee14d93..5f64763a0d5c 100644 --- a/storage/rocksdb/rdb_psi.h +++ b/storage/rocksdb/rdb_psi.h @@ -38,19 +38,19 @@ extern my_core::PSI_stage_info stage_waiting_on_row_lock; #ifdef HAVE_PSI_INTERFACE extern my_core::PSI_thread_key rdb_background_psi_thread_key, - rdb_drop_idx_psi_thread_key; + rdb_drop_idx_psi_thread_key, rdb_mc_psi_thread_key; extern my_core::PSI_mutex_key rdb_psi_open_tbls_mutex_key, rdb_signal_bg_psi_mutex_key, rdb_signal_drop_idx_psi_mutex_key, - rdb_collation_data_mutex_key, rdb_mem_cmp_space_mutex_key, - key_mutex_tx_list, rdb_sysvars_psi_mutex_key, rdb_cfm_mutex_key, - rdb_sst_commit_key, rdb_block_cache_resize_mutex_key; + rdb_signal_mc_psi_mutex_key, rdb_collation_data_mutex_key, + rdb_mem_cmp_space_mutex_key, key_mutex_tx_list, rdb_sysvars_psi_mutex_key, + rdb_cfm_mutex_key, rdb_sst_commit_key, rdb_block_cache_resize_mutex_key; extern my_core::PSI_rwlock_key key_rwlock_collation_exception_list, key_rwlock_read_free_rpl_tables, key_rwlock_skip_unique_check_tables; extern my_core::PSI_cond_key rdb_signal_bg_psi_cond_key, - rdb_signal_drop_idx_psi_cond_key; + rdb_signal_drop_idx_psi_cond_key, rdb_signal_mc_psi_cond_key; extern my_core::PSI_memory_key rdb_datadic_memory_key, rdb_open_tables_memory_key, rdb_handler_memory_key; diff --git a/storage/rocksdb/rdb_threads.h b/storage/rocksdb/rdb_threads.h index d8b03f7d72cf..c2d8bc0e8647 100644 --- a/storage/rocksdb/rdb_threads.h +++ b/storage/rocksdb/rdb_threads.h @@ -18,6 +18,7 @@ /* C++ standard header files */ #include +#include #include /* MySQL includes */ @@ -27,6 +28,7 @@ /* MyRocks header files */ #include "./rdb_utils.h" +#include "rocksdb/db.h" namespace myrocks { @@ -101,6 +103,31 @@ class Rdb_background_thread : public Rdb_thread { } }; +class Rdb_manual_compaction_thread : public Rdb_thread { + private: + struct Manual_compaction_request { + int mc_id; + enum mc_state { INITED = 0, RUNNING } state; + rocksdb::ColumnFamilyHandle *cf; + rocksdb::Slice *start; + rocksdb::Slice *limit; + int concurrency = 0; + }; + + int m_latest_mc_id; + mysql_mutex_t m_mc_mutex; + std::map m_requests; + + public: + virtual void run() override; + int request_manual_compaction(rocksdb::ColumnFamilyHandle *cf, + rocksdb::Slice *start, rocksdb::Slice *limit, + int concurrency = 0); + bool is_manual_compaction_finished(int mc_id); + void clear_manual_compaction_request(int mc_id, bool init_only = false); + void clear_all_manual_compaction_requests(); +}; + /* Drop index thread control */