diff --git a/mysql-test/suite/group_replication/r/gr_check_stage_values_correctness.result b/mysql-test/suite/group_replication/r/gr_check_stage_values_correctness.result index d06a92e60024..c6f345073811 100644 --- a/mysql-test/suite/group_replication/r/gr_check_stage_values_correctness.result +++ b/mysql-test/suite/group_replication/r/gr_check_stage_values_correctness.result @@ -18,7 +18,8 @@ include/assert.inc [Group replication recovery thread is not present in threads include/stop_group_replication.inc include/assert.inc [No group replication entries are present in events_stages_current table.] -include/assert.inc [No group replication entries are present in threads table.] +include/assert.inc [2 group replication entries are present in threads table.] +include/assert.inc [THD_mysql_thread_handler* are present in threads table.] # 03. Create some data on server1. # Recovery channel will have some data on server2. diff --git a/mysql-test/suite/group_replication/r/gr_mysql_thread_queued_task_psi_memory.result b/mysql-test/suite/group_replication/r/gr_mysql_thread_queued_task_psi_memory.result index a8e048cbbee1..ac8fc8e42289 100644 --- a/mysql-test/suite/group_replication/r/gr_mysql_thread_queued_task_psi_memory.result +++ b/mysql-test/suite/group_replication/r/gr_mysql_thread_queued_task_psi_memory.result @@ -44,8 +44,11 @@ include/assert.inc ['There should be 1 entry corresponding to the mysql_thread_q ################################################################# # 4. Assert that the number of bytes allocated for -# mysql_thread_queued_task event must be 0. -include/assert.inc ['The sum of bytes allocated must be zero after stopping GR'] +# mysql_thread_queued_task event must be 0 when the plugin +# is uninstalled. +include/uninstall_group_replication_plugin.inc +include/assert.inc ['The sum of bytes allocated must be zero after uninstall GR'] +include/install_group_replication_plugin.inc ################################################################# # 5. Clean up diff --git a/mysql-test/suite/group_replication/r/gr_psi_keys_mysql.result b/mysql-test/suite/group_replication/r/gr_psi_keys_mysql.result index 50a1bf5c05a3..5d350ae20c1c 100644 --- a/mysql-test/suite/group_replication/r/gr_psi_keys_mysql.result +++ b/mysql-test/suite/group_replication/r/gr_psi_keys_mysql.result @@ -68,6 +68,8 @@ wait/synch/mutex/group_rpl/LOCK_mysql_thread_dispatcher_run YES YES singleton NU wait/synch/mutex/group_rpl/LOCK_connection_map YES YES singleton NULL 0 NULL wait/synch/mutex/group_rpl/LOCK_mysql_handler_thread_run YES YES singleton NULL 0 NULL wait/synch/mutex/group_rpl/LOCK_mysql_thread_handler_dispatcher_run YES YES singleton NULL 0 NULL +wait/synch/mutex/group_rpl/LOCK_mysql_handler_thread_read_only_mode_run YES YES singleton NULL 0 NULL +wait/synch/mutex/group_rpl/LOCK_mysql_thread_handler_read_only_mode_dispatcher_run YES YES singleton NULL 0 NULL wait/synch/rwlock/group_rpl/RWLOCK_certifier_stable_gtid_set YES YES singleton NULL 0 NULL wait/synch/rwlock/group_rpl/RWLOCK_channel_observation_list YES YES singleton NULL 0 NULL wait/synch/rwlock/group_rpl/RWLOCK_gcs_operations YES YES singleton NULL 0 NULL @@ -119,6 +121,8 @@ wait/synch/cond/group_rpl/COND_mysql_thread_run YES YES singleton NULL 0 NULL wait/synch/cond/group_rpl/COND_mysql_thread_dispatcher_run YES YES singleton NULL 0 NULL wait/synch/cond/group_rpl/COND_mysql_thread_handler_run YES YES singleton NULL 0 NULL wait/synch/cond/group_rpl/COND_mysql_thread_handler_dispatcher_run YES YES singleton NULL 0 NULL +wait/synch/cond/group_rpl/COND_mysql_thread_handler_read_only_mode_run YES YES singleton NULL 0 NULL +wait/synch/cond/group_rpl/COND_mysql_thread_handler_read_only_mode_dispatcher_run YES YES singleton NULL 0 NULL stage/group_rpl/Undergoing auto-rejoin procedure YES YES progress NULL 0 NULL stage/group_rpl/Multi-primary Switch: waiting for pending transactions to finish YES YES progress NULL 0 NULL stage/group_rpl/Multi-primary Switch: waiting on another member step completion YES YES progress NULL 0 NULL @@ -181,6 +185,7 @@ thread/group_rpl/THD_Gcs_xcom_engine::m_engine_thread BACKGROUND YES thread/group_rpl/THD_message_service_handler BACKGROUND YES thread/group_rpl/THD_mysql_thread BACKGROUND YES thread/group_rpl/THD_mysql_thread_handler BACKGROUND YES +thread/group_rpl/THD_mysql_thread_handler_read_only_mode BACKGROUND YES ############################################################ # 5. Test end. diff --git a/mysql-test/suite/group_replication/r/gr_psi_keys_xcom.result b/mysql-test/suite/group_replication/r/gr_psi_keys_xcom.result index 50a1bf5c05a3..5d350ae20c1c 100644 --- a/mysql-test/suite/group_replication/r/gr_psi_keys_xcom.result +++ b/mysql-test/suite/group_replication/r/gr_psi_keys_xcom.result @@ -68,6 +68,8 @@ wait/synch/mutex/group_rpl/LOCK_mysql_thread_dispatcher_run YES YES singleton NU wait/synch/mutex/group_rpl/LOCK_connection_map YES YES singleton NULL 0 NULL wait/synch/mutex/group_rpl/LOCK_mysql_handler_thread_run YES YES singleton NULL 0 NULL wait/synch/mutex/group_rpl/LOCK_mysql_thread_handler_dispatcher_run YES YES singleton NULL 0 NULL +wait/synch/mutex/group_rpl/LOCK_mysql_handler_thread_read_only_mode_run YES YES singleton NULL 0 NULL +wait/synch/mutex/group_rpl/LOCK_mysql_thread_handler_read_only_mode_dispatcher_run YES YES singleton NULL 0 NULL wait/synch/rwlock/group_rpl/RWLOCK_certifier_stable_gtid_set YES YES singleton NULL 0 NULL wait/synch/rwlock/group_rpl/RWLOCK_channel_observation_list YES YES singleton NULL 0 NULL wait/synch/rwlock/group_rpl/RWLOCK_gcs_operations YES YES singleton NULL 0 NULL @@ -119,6 +121,8 @@ wait/synch/cond/group_rpl/COND_mysql_thread_run YES YES singleton NULL 0 NULL wait/synch/cond/group_rpl/COND_mysql_thread_dispatcher_run YES YES singleton NULL 0 NULL wait/synch/cond/group_rpl/COND_mysql_thread_handler_run YES YES singleton NULL 0 NULL wait/synch/cond/group_rpl/COND_mysql_thread_handler_dispatcher_run YES YES singleton NULL 0 NULL +wait/synch/cond/group_rpl/COND_mysql_thread_handler_read_only_mode_run YES YES singleton NULL 0 NULL +wait/synch/cond/group_rpl/COND_mysql_thread_handler_read_only_mode_dispatcher_run YES YES singleton NULL 0 NULL stage/group_rpl/Undergoing auto-rejoin procedure YES YES progress NULL 0 NULL stage/group_rpl/Multi-primary Switch: waiting for pending transactions to finish YES YES progress NULL 0 NULL stage/group_rpl/Multi-primary Switch: waiting on another member step completion YES YES progress NULL 0 NULL @@ -181,6 +185,7 @@ thread/group_rpl/THD_Gcs_xcom_engine::m_engine_thread BACKGROUND YES thread/group_rpl/THD_message_service_handler BACKGROUND YES thread/group_rpl/THD_mysql_thread BACKGROUND YES thread/group_rpl/THD_mysql_thread_handler BACKGROUND YES +thread/group_rpl/THD_mysql_thread_handler_read_only_mode BACKGROUND YES ############################################################ # 5. Test end. diff --git a/mysql-test/suite/group_replication/t/gr_addmember_error_message.test b/mysql-test/suite/group_replication/t/gr_addmember_error_message.test index 2db1b99c8feb..3299ac1b193d 100644 --- a/mysql-test/suite/group_replication/t/gr_addmember_error_message.test +++ b/mysql-test/suite/group_replication/t/gr_addmember_error_message.test @@ -43,7 +43,7 @@ --let $assert_file = $MYSQLTEST_VARDIR/tmp/gr_add_member_error_message.2.err --let $assert_only_after= Plugin 'group_replication' is starting --let $assert_select = \[System\] \[MY-011565\] \[Repl\] Plugin group_replication reported: 'Setting super_read_only=ON\.' ---let $assert_count = 1 +--let $assert_count = 2 --let $assert_text = Found message informing that `super_read_only` is ON. --source include/assert_grep.inc diff --git a/mysql-test/suite/group_replication/t/gr_check_stage_values_correctness.test b/mysql-test/suite/group_replication/t/gr_check_stage_values_correctness.test index ec530188e7cf..f95636168459 100644 --- a/mysql-test/suite/group_replication/t/gr_check_stage_values_correctness.test +++ b/mysql-test/suite/group_replication/t/gr_check_stage_values_correctness.test @@ -57,8 +57,11 @@ CREATE TABLE test.t1 (a INT PRIMARY KEY); --let $assert_cond= [SELECT COUNT(*) FROM performance_schema.events_stages_current WHERE event_name LIKE "%/group_rpl/%"] = 0 --source include/assert.inc ---let $assert_text= No group replication entries are present in threads table. ---let $assert_cond= [SELECT COUNT(*) FROM performance_schema.threads WHERE name LIKE "%/group_rpl/%"] = 0 +--let $assert_text= 2 group replication entries are present in threads table. +--let $assert_cond= [SELECT COUNT(*) FROM performance_schema.threads WHERE name LIKE "%/group_rpl/%"] = 2 +--source include/assert.inc +--let $assert_text= THD_mysql_thread_handler* are present in threads table. +--let $assert_cond= [SELECT COUNT(*) FROM performance_schema.threads WHERE name LIKE "%/group_rpl/THD_mysql_thread%"] = 2 --source include/assert.inc --echo diff --git a/mysql-test/suite/group_replication/t/gr_consistent_reads_before_switch_group_mode.test b/mysql-test/suite/group_replication/t/gr_consistent_reads_before_switch_group_mode.test index a0ad3e7eff6f..d9aefe518865 100644 --- a/mysql-test/suite/group_replication/t/gr_consistent_reads_before_switch_group_mode.test +++ b/mysql-test/suite/group_replication/t/gr_consistent_reads_before_switch_group_mode.test @@ -93,7 +93,7 @@ SET @@SESSION.group_replication_consistency= 'BEFORE'; --let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE user='root' AND state='executing' AND info LIKE 'SELECT group_replication_switch_to_single_primary_mode(%' --source include/wait_condition.inc ---let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist WHERE user='mysql.session' AND state='Waiting for global read lock' AND info='PLUGIN: SET GLOBAL super_read_only= 1' +--let $wait_condition=SELECT COUNT(*)=1 FROM performance_schema.threads WHERE NAME = 'thread/group_rpl/THD_mysql_thread_handler_read_only_mode' AND PROCESSLIST_STATE = 'Waiting for global read lock' --source include/wait_condition.inc diff --git a/mysql-test/suite/group_replication/t/gr_lock_tables_unblock.test b/mysql-test/suite/group_replication/t/gr_lock_tables_unblock.test index 84070650c229..6fd59ca245b0 100644 --- a/mysql-test/suite/group_replication/t/gr_lock_tables_unblock.test +++ b/mysql-test/suite/group_replication/t/gr_lock_tables_unblock.test @@ -47,7 +47,7 @@ LOCK TABLE t1 WRITE; --echo # super_read_only mode. --let $rpl_connection_name= server_1_1 --source include/rpl_connection.inc ---let $wait_condition=SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for global read lock' and Info = 'PLUGIN: SET GLOBAL super_read_only= 1' +--let $wait_condition=SELECT COUNT(*)=1 FROM performance_schema.threads WHERE NAME = 'thread/group_rpl/THD_mysql_thread_handler_read_only_mode' AND PROCESSLIST_STATE = 'Waiting for global read lock' --source include/wait_condition.inc --connection server_1 diff --git a/mysql-test/suite/group_replication/t/gr_mysql_thread_queued_task_psi_memory.test b/mysql-test/suite/group_replication/t/gr_mysql_thread_queued_task_psi_memory.test index d3b0e2cd2b3c..0b51224e5be9 100644 --- a/mysql-test/suite/group_replication/t/gr_mysql_thread_queued_task_psi_memory.test +++ b/mysql-test/suite/group_replication/t/gr_mysql_thread_queued_task_psi_memory.test @@ -16,12 +16,14 @@ # 3. Verify that the entries corresponding to the instrumented # mysql_thread_queued_task remain in the tables after stopping GR. # 4. Assert that the number of bytes allocated for -# mysql_thread_queued_task event must be 0. +# mysql_thread_queued_task event must be 0 when the plugin +# is uninstalled. # 5. Clean up ############################################################################### --source include/have_debug_sync.inc --source include/have_group_replication_plugin.inc +--source include/force_restart.inc --let $rpl_skip_group_replication_start= 1 --let $rpl_group_replication_single_primary_mode=1 --source include/group_replication.inc @@ -99,10 +101,13 @@ SELECT EVENT_NAME FROM performance_schema.memory_summary_global_by_event_name WH --echo --echo ################################################################# --echo # 4. Assert that the number of bytes allocated for ---echo # mysql_thread_queued_task event must be 0. ---let $assert_text= 'The sum of bytes allocated must be zero after stopping GR' +--echo # mysql_thread_queued_task event must be 0 when the plugin +--echo # is uninstalled. +--source include/uninstall_group_replication_plugin.inc +--let $assert_text= 'The sum of bytes allocated must be zero after uninstall GR' --let $assert_cond= CURRENT_NUMBER_OF_BYTES_USED = 0 FROM performance_schema.memory_summary_global_by_event_name WHERE EVENT_NAME LIKE "memory/group_rpl/mysql_thread_queued_task" --source include/assert.inc +--source include/install_group_replication_plugin.inc --echo --echo ################################################################# diff --git a/mysql-test/suite/group_replication/t/gr_recovery_clone_activation_threshold.test b/mysql-test/suite/group_replication/t/gr_recovery_clone_activation_threshold.test index e4a8b9d31175..20585687aef2 100644 --- a/mysql-test/suite/group_replication/t/gr_recovery_clone_activation_threshold.test +++ b/mysql-test/suite/group_replication/t/gr_recovery_clone_activation_threshold.test @@ -60,7 +60,9 @@ SET SESSION sql_log_bin = 0; call mtr.add_suppression("Plugin group_replication reported.*"); SET SESSION sql_log_bin = 1; ---let $group_replication_start_member_state= RECOVERING +# Clone plugin is not installed, as such the member will error +# during recovery. +--let $group_replication_start_member_state= ERROR --source include/start_group_replication.inc # Assert that recovery using clone is logged to the server error log. diff --git a/mysql-test/suite/group_replication/t/gr_stop_procedure_hang.test b/mysql-test/suite/group_replication/t/gr_stop_procedure_hang.test index 0d34dba2cf7b..a3302539fbfa 100644 --- a/mysql-test/suite/group_replication/t/gr_stop_procedure_hang.test +++ b/mysql-test/suite/group_replication/t/gr_stop_procedure_hang.test @@ -71,7 +71,7 @@ SET @@GLOBAL.DEBUG='d,group_replication_before_commit_hook_wait'; --let $rpl_connection_name= server_1_1 --source include/rpl_connection.inc ---let $wait_condition=SELECT COUNT(*)=1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE State = 'Waiting for global read lock' +--let $wait_condition=SELECT COUNT(*)=1 FROM performance_schema.threads WHERE NAME = 'thread/group_rpl/THD_mysql_thread_handler_read_only_mode' AND PROCESSLIST_STATE = 'Waiting for global read lock' --source include/wait_condition.inc SET DEBUG_SYNC='now SIGNAL continue_commit'; diff --git a/mysql-test/suite/x/r/notices_gr_join_leave.result b/mysql-test/suite/x/r/notices_gr_join_leave.result index 4daea777cf31..c92802473ea6 100644 --- a/mysql-test/suite/x/r/notices_gr_join_leave.result +++ b/mysql-test/suite/x/r/notices_gr_join_leave.result @@ -115,6 +115,8 @@ RUN STOP GROUP_REPLICATION RUN SET GLOBAL read_only= FALSE RUN DROP TABLE test.tab1 RUN RESET MASTER +[ASSERT view_change on 'verify_1' connection] +[ASSERT state_change on 'verify_1' connection] [connection server_2] RUN DROP TABLE test.tab1 RUN RESET MASTER @@ -253,6 +255,8 @@ RUN STOP GROUP_REPLICATION RUN SET GLOBAL read_only= FALSE RUN DROP TABLE test.tab1 RUN RESET MASTER +[ASSERT no notices on 'verify_1' connection] +[ASSERT no notices on 'verify_1' connection] [connection server_2] RUN DROP TABLE test.tab1 RUN RESET MASTER diff --git a/mysql-test/suite/x/t/notices_gr_join_leave.test b/mysql-test/suite/x/t/notices_gr_join_leave.test index 7dddaf3a8ba6..7ac80855ab75 100644 --- a/mysql-test/suite/x/t/notices_gr_join_leave.test +++ b/mysql-test/suite/x/t/notices_gr_join_leave.test @@ -173,6 +173,8 @@ noquery_result; DROP TABLE test.tab1; RESET MASTER; query_result; +callmacro %ASSERT_NOTICES% view_changed verify_1; +callmacro %ASSERT_NOTICES% state_changed verify_1; callmacro Setsession server_2; noquery_result; diff --git a/plugin/group_replication/CMakeLists.txt b/plugin/group_replication/CMakeLists.txt index 2c288e609e18..958d5f5c1ddc 100644 --- a/plugin/group_replication/CMakeLists.txt +++ b/plugin/group_replication/CMakeLists.txt @@ -67,7 +67,6 @@ SET(GROUP_REPLICATION_SOURCES src/plugin_handlers/member_actions_handler.cc src/plugin_handlers/member_actions_handler_configuration.cc src/plugin_handlers/offline_mode_handler.cc - src/plugin_handlers/persistent_variables_handler.cc src/plugin_handlers/primary_election_invocation_handler.cc src/plugin_handlers/primary_election_primary_process.cc src/plugin_handlers/primary_election_secondary_process.cc @@ -97,11 +96,13 @@ SET(GROUP_REPLICATION_SOURCES src/recovery_channel_state_observer.cc src/recovery_state_transfer.cc src/replication_threads_api.cc - src/services/get_system_variable/get_system_variable.cc src/services/message_service/message_service.cc src/services/notification/notification.cc src/services/status_service/status_service.cc + src/services/system_variable/get_system_variable.cc + src/services/system_variable/set_system_variable.cc src/services/registry.cc + src/services/server_services_references.cc src/sql_service/sql_command_test.cc src/sql_service/sql_resultset.cc src/sql_service/sql_service_command.cc diff --git a/plugin/group_replication/include/delayed_plugin_initialization.h b/plugin/group_replication/include/delayed_plugin_initialization.h index b54fe9f21b09..91bfb8137947 100644 --- a/plugin/group_replication/include/delayed_plugin_initialization.h +++ b/plugin/group_replication/include/delayed_plugin_initialization.h @@ -23,7 +23,7 @@ #ifndef DELAYED_PLUGIN_INITIALIZATION_INCLUDE #define DELAYED_PLUGIN_INITIALIZATION_INCLUDE -#include "plugin/group_replication/include/plugin_handlers/read_mode_handler.h" +#include "plugin/group_replication/include/plugin_utils.h" class Delayed_initialization_thread { public: diff --git a/plugin/group_replication/include/leave_group_on_failure.h b/plugin/group_replication/include/leave_group_on_failure.h index dead33d272a3..0030304411b8 100644 --- a/plugin/group_replication/include/leave_group_on_failure.h +++ b/plugin/group_replication/include/leave_group_on_failure.h @@ -25,8 +25,8 @@ #include +#include "my_inttypes.h" #include "plugin/group_replication/include/services/notification/notification.h" -#include "plugin/group_replication/include/sql_service/sql_service_command.h" /** Structure that holds the actions taken by the plugin when the @@ -57,10 +57,6 @@ struct leave_group_on_failure { Actions performed. @param[in] error_to_log Error logged into error log. - @param[in] session_isolation - Session creation requirements: use current thread, - use thread but initialize it or create it in a - dedicated thread. @param[in] caller_notification_context If defined the member state change notification will update this notification context and the @@ -73,7 +69,6 @@ struct leave_group_on_failure { that function is called. */ static void leave(const mask &actions, longlong error_to_log, - enum_plugin_con_isolation session_isolation, Notification_context *caller_notification_context, const char *exit_state_action_abort_log_message); }; diff --git a/plugin/group_replication/include/plugin.h b/plugin/group_replication/include/plugin.h index b2c0f5597ac3..730fbdf502c4 100644 --- a/plugin/group_replication/include/plugin.h +++ b/plugin/group_replication/include/plugin.h @@ -49,6 +49,7 @@ #include "plugin/group_replication/include/recovery.h" #include "plugin/group_replication/include/services/message_service/message_service.h" #include "plugin/group_replication/include/services/registry.h" +#include "plugin/group_replication/include/services/server_services_references.h" #include "plugin/group_replication/libmysqlgcs/include/mysql/gcs/gcs_interface.h" // Forward declarations @@ -116,7 +117,6 @@ struct gr_modules { MESSAGE_SERVICE_HANDLER, BINLOG_DUMP_THREAD_KILL, MEMBER_ACTIONS_HANDLER, - MYSQL_THREAD_HANDLER, NUM_MODULES }; using mask = std::bitset; @@ -173,6 +173,8 @@ extern Autorejoin_thread *autorejoin_module; extern Message_service_handler *message_service_handler; extern Member_actions_handler *member_actions_handler; extern Mysql_thread *mysql_thread_handler; +extern Mysql_thread *mysql_thread_handler_read_only_mode; +extern Server_services_references *server_services_references_module; // Auxiliary Functionality extern Plugin_gcs_events_handler *events_handler; @@ -230,6 +232,7 @@ bool get_plugin_is_stopping(); bool get_wait_on_engine_initialization(); void enable_server_shutdown_status(); bool get_server_shutdown_status(); +void mysql_thread_handler_finalize(); void set_plugin_is_setting_read_mode(bool value); bool get_plugin_is_setting_read_mode(); const char *get_group_name_var(); diff --git a/plugin/group_replication/include/plugin_handlers/offline_mode_handler.h b/plugin/group_replication/include/plugin_handlers/offline_mode_handler.h index 0bb0ed889f42..9ba9dbeb717e 100644 --- a/plugin/group_replication/include/plugin_handlers/offline_mode_handler.h +++ b/plugin/group_replication/include/plugin_handlers/offline_mode_handler.h @@ -23,16 +23,10 @@ #ifndef OFFLINE_MODE_HANDLER_INCLUDE #define OFFLINE_MODE_HANDLER_INCLUDE -#include "plugin/group_replication/include/sql_service/sql_service_command.h" - /** This method creates a server session and connects to the server to enable the offline mode - - @param session_isolation session creation requirements: use current thread, - use thread but initialize it or create it in a - dedicated thread */ -void enable_server_offline_mode(enum_plugin_con_isolation session_isolation); +void enable_server_offline_mode(); #endif /* OFFLINE_MODE_HANDLER_INCLUDE */ diff --git a/plugin/group_replication/include/plugin_handlers/persistent_variables_handler.h b/plugin/group_replication/include/plugin_handlers/persistent_variables_handler.h deleted file mode 100644 index 28ace425a3a4..000000000000 --- a/plugin/group_replication/include/plugin_handlers/persistent_variables_handler.h +++ /dev/null @@ -1,42 +0,0 @@ -/* Copyright (c) 2018, 2022, Oracle and/or its affiliates. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License, version 2.0, - as published by the Free Software Foundation. - - This program is also distributed with certain software (including - but not limited to OpenSSL) that is licensed under separate terms, - as designated in a particular file or component or in included license - documentation. The authors of MySQL hereby grant you an additional - permission to link the program and your derivative works with the - separately licensed software that they have included with MySQL. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License, version 2.0, for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#ifndef PERSISTENT_VARIABLES_HANDLER_INCLUDED -#define PERSISTENT_VARIABLES_HANDLER_INCLUDED - -#include "plugin/group_replication/include/sql_service/sql_service_command.h" - -/** - Persist a variable in the configuration but do not set the value - @param name the name of the query - @param value the value to set in the variable - @param command_interface the interface to the session API - - @note use this method when there is already an open server connection - - @returns 0 in case of success, or the error value from the query -*/ -long set_persist_only_variable( - std::string &name, std::string &value, - Sql_service_command_interface *command_interface); - -#endif /* PERSISTENT_VARIABLES_HANDLER_INCLUDED */ diff --git a/plugin/group_replication/include/plugin_handlers/primary_election_secondary_process.h b/plugin/group_replication/include/plugin_handlers/primary_election_secondary_process.h index 3c0cce484b2d..b77a16a4a9be 100644 --- a/plugin/group_replication/include/plugin_handlers/primary_election_secondary_process.h +++ b/plugin/group_replication/include/plugin_handlers/primary_election_secondary_process.h @@ -85,12 +85,6 @@ class Primary_election_secondary_process : public Group_event_observer { void set_stop_wait_timeout(ulong timeout); private: - enum enum_election_read_mode_status { - SECONDARY_ELECTION_READ_MODE_NOT_SET = 0, // Read only mode not set - SECONDARY_ELECTION_READ_MODE_BEING_SET = 1, // Read only mode being set - SECONDARY_ELECTION_READ_MODE_IS_SET = 2, // Read only mode is set - }; - // The listeners for group events int after_view_change(const std::vector &joining, @@ -113,12 +107,6 @@ class Primary_election_secondary_process : public Group_event_observer { */ bool enable_read_mode_on_server(); - /** - Kills the current read mode query that might be stuck - @return false in case of success, or true otherwise - */ - bool kill_read_mode_query(); - /** Signal that the read mode is ready on this member @returns false in case of success, or true otherwise @@ -138,10 +126,6 @@ class Primary_election_secondary_process : public Group_event_observer { bool group_in_read_mode; /** Process is waiting on read mode - stage related var*/ bool is_waiting_on_read_mode_group; - /** The session id that is set the read mode*/ - unsigned long read_mode_session_id; - /** What is the status on the read only mode enabling query */ - enum_election_read_mode_status is_read_mode_set; /** The election invocation context */ enum_primary_election_mode election_mode; diff --git a/plugin/group_replication/include/plugin_handlers/read_mode_handler.h b/plugin/group_replication/include/plugin_handlers/read_mode_handler.h index 4ba43b58255e..4de900794214 100644 --- a/plugin/group_replication/include/plugin_handlers/read_mode_handler.h +++ b/plugin/group_replication/include/plugin_handlers/read_mode_handler.h @@ -23,66 +23,27 @@ #ifndef READ_MODE_HANDLER_INCLUDE #define READ_MODE_HANDLER_INCLUDE -#include "my_inttypes.h" -#include "plugin/group_replication/include/sql_service/sql_service_command.h" - -/** - This method creates a server session and connects to the server - to enable the read mode - - @param session_isolation session creation requirements: use current thread, - use thread but initialize it or create it in a - dedicated thread - - @return the operation status - @retval 0 OK - @retval !=0 Error -*/ -int enable_server_read_mode(enum_plugin_con_isolation session_isolation); - -/** - This method creates a server session and connects to the server - to disable the read mode - - @param session_isolation session creation requirements: use current thread, - use thread but initialize it or create it in a - dedicated thread - - @return the operation status - @retval 0 OK - @retval !=0 Error -*/ -int disable_server_read_mode(enum_plugin_con_isolation session_isolation); - /** Enable the super read only mode in the server. - @param sql_service_command Command interface given to execute the command - @return the operation status @retval 0 OK @retval !=0 Error */ -long enable_super_read_only_mode( - Sql_service_command_interface *sql_service_command); +int enable_server_read_mode(); /** Disable the read only mode in the server. - @param sql_service_command Command interface given to execute the command - @return the operation status @retval 0 OK @retval !=0 Error */ -long disable_super_read_only_mode( - Sql_service_command_interface *sql_service_command); +int disable_server_read_mode(); /** Get read mode status from server. - @param sql_service_command Command interface given to execute the - command @param read_only_enabled Update with value of read only mode @param super_read_only_enabled Update with value of super read only mode @@ -90,15 +51,11 @@ long disable_super_read_only_mode( @retval 0 OK @retval !=0 Error */ -long get_read_mode_state(Sql_service_command_interface *sql_service_command, - bool *read_only_enabled, - bool *super_read_only_enabled); +int get_read_mode_state(bool *read_only_enabled, bool *super_read_only_enabled); /** Set read mode status from server. - @param sql_service_command Command interface given to execute the - command @param read_only_enabled Value to set on read only mode @param super_read_only_enabled Value to set on super read only mode @@ -106,7 +63,6 @@ long get_read_mode_state(Sql_service_command_interface *sql_service_command, @retval 0 OK @retval !=0 Error */ -long set_read_mode_state(Sql_service_command_interface *sql_service_command, - bool read_only_enabled, bool super_read_only_enabled); +int set_read_mode_state(bool read_only_enabled, bool super_read_only_enabled); #endif /* READ_MODE_HANDLER_INCLUDE */ diff --git a/plugin/group_replication/include/plugin_handlers/remote_clone_handler.h b/plugin/group_replication/include/plugin_handlers/remote_clone_handler.h index 19a2d669e926..f4d07e17cf55 100644 --- a/plugin/group_replication/include/plugin_handlers/remote_clone_handler.h +++ b/plugin/group_replication/include/plugin_handlers/remote_clone_handler.h @@ -202,12 +202,9 @@ class Remote_clone_handler : public Group_event_observer { /** In error fall back to recovery or error out - @param[in] sql_command_interface the server connection @param[in] critical_error the error prevent distributed recovery */ - int fallback_to_recovery_or_leave( - Sql_service_command_interface *sql_command_interface, - bool critical_error = false); + int fallback_to_recovery_or_leave(bool critical_error = false); /** Executes the query to change the allowed donor list for clone diff --git a/plugin/group_replication/include/plugin_psi.h b/plugin/group_replication/include/plugin_psi.h index fb020626ec0d..54b6ad898e41 100644 --- a/plugin/group_replication/include/plugin_psi.h +++ b/plugin/group_replication/include/plugin_psi.h @@ -130,7 +130,9 @@ extern PSI_mutex_key key_GR_LOCK_applier_module_run, key_GR_LOCK_mysql_thread_dispatcher_run, key_GR_LOCK_connection_map, key_GR_LOCK_mysql_thread_handler_run, - key_GR_LOCK_mysql_thread_handler_dispatcher_run; + key_GR_LOCK_mysql_thread_handler_dispatcher_run, + key_GR_LOCK_mysql_thread_handler_read_only_mode_run, + key_GR_LOCK_mysql_thread_handler_read_only_mode_dispatcher_run; extern PSI_cond_key key_GR_COND_applier_module_run, key_GR_COND_applier_module_suspend, @@ -169,7 +171,9 @@ extern PSI_cond_key key_GR_COND_applier_module_run, key_GR_COND_mysql_thread_run, key_GR_COND_mysql_thread_dispatcher_run, key_GR_COND_mysql_thread_handler_run, - key_GR_COND_mysql_thread_handler_dispatcher_run; + key_GR_COND_mysql_thread_handler_dispatcher_run, + key_GR_COND_mysql_thread_handler_read_only_mode_run, + key_GR_COND_mysql_thread_handler_read_only_mode_dispatcher_run; extern PSI_thread_key key_GR_THD_applier_module_receiver, key_GR_THD_autorejoin, @@ -185,7 +189,8 @@ extern PSI_thread_key key_GR_THD_applier_module_receiver, key_GR_THD_recovery, key_GR_THD_message_service_handler, key_GR_THD_mysql_thread, - key_GR_THD_mysql_thread_handler; + key_GR_THD_mysql_thread_handler, + key_GR_THD_mysql_thread_handler_read_only_mode; extern PSI_rwlock_key key_GR_RWLOCK_cert_stable_gtid_set, key_GR_RWLOCK_channel_observation_list, diff --git a/plugin/group_replication/include/plugin_utils.h b/plugin/group_replication/include/plugin_utils.h index 11fb7294bb39..62da359dd8fc 100644 --- a/plugin/group_replication/include/plugin_utils.h +++ b/plugin/group_replication/include/plugin_utils.h @@ -361,14 +361,21 @@ class Abortable_synchronized_queue : public Synchronized_queue { /** Remove all elements, abort current and future waits on retrieving elements from queue. + + @param delete_elements When true, apart from emptying the queue, it also + delete each element. + When false, the delete (memory release) responsibility + belongs to the `push()` caller. */ - void abort() { + void abort(bool delete_elements) { mysql_mutex_lock(&this->lock); while (this->queue.size()) { T elem; elem = this->queue.front(); this->queue.pop(); - delete elem; + if (delete_elements) { + delete elem; + } } m_abort = true; mysql_cond_broadcast(&this->cond); diff --git a/plugin/group_replication/include/services/server_services_references.h b/plugin/group_replication/include/services/server_services_references.h new file mode 100644 index 000000000000..503d187a00e6 --- /dev/null +++ b/plugin/group_replication/include/services/server_services_references.h @@ -0,0 +1,107 @@ +/* Copyright (c) 2022, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef GR_SERVER_SERVICES_REFERENCES +#define GR_SERVER_SERVICES_REFERENCES + +#include +#include +#include +#include +#include + +/** + @class Server_services_references + + This class holds the references to server services that + Group Replication acquires on plugin install. + server services are the ones implemented on + `sql/server_component` folder. +*/ +class Server_services_references { + public: + Server_services_references() = default; + + virtual ~Server_services_references(); + + /** + Deleted copy ctor. + */ + Server_services_references(const Server_services_references &) = delete; + + /** + Deleted move ctor. + */ + Server_services_references(const Server_services_references &&) = delete; + + /** + Deleted assignment operator. + */ + Server_services_references &operator=(const Server_services_references &) = + delete; + + /** + Deleted move operator. + */ + Server_services_references &operator=(const Server_services_references &&) = + delete; + + /** + Acquire the server services. + + @return Operation status + @retval false Successful + @retval true Error + */ + bool initialize(); + + /** + Release the server services. + + @return Operation status + @retval false Successful + @retval true Error + */ + bool finalize(); + + /* clang-format off */ + SERVICE_TYPE(registry) *registry_service{nullptr}; + SERVICE_TYPE(mysql_charset) *mysql_charset_service{nullptr}; + SERVICE_TYPE(mysql_string_factory) *mysql_string_factory_service{nullptr}; + SERVICE_TYPE(mysql_string_charset_converter) *mysql_string_charset_converter_service{nullptr}; + SERVICE_TYPE(mysql_system_variable_update_string) *mysql_system_variable_update_string_service{nullptr}; + SERVICE_TYPE(mysql_system_variable_update_integer) *mysql_system_variable_update_integer_service{nullptr}; + SERVICE_TYPE(component_sys_variable_register) *component_sys_variable_register_service{nullptr}; + /* clang-format on */ + + private: + /* clang-format off */ + my_h_service m_mysql_charset_handle{nullptr}; + my_h_service m_mysql_string_factory_handle{nullptr}; + my_h_service m_mysql_string_charset_converter_handle{nullptr}; + my_h_service m_mysql_system_variable_update_string_handle{nullptr}; + my_h_service m_mysql_system_variable_update_integer_handle{nullptr}; + my_h_service m_component_sys_variable_register_handle{nullptr}; + /* clang-format on */ +}; + +#endif // GR_SERVER_SERVICES_REFERENCES diff --git a/plugin/group_replication/include/services/get_system_variable/get_system_variable.h b/plugin/group_replication/include/services/system_variable/get_system_variable.h similarity index 72% rename from plugin/group_replication/include/services/get_system_variable/get_system_variable.h rename to plugin/group_replication/include/services/system_variable/get_system_variable.h index 15dca9b6918e..f0a42855bf8f 100644 --- a/plugin/group_replication/include/services/get_system_variable/get_system_variable.h +++ b/plugin/group_replication/include/services/system_variable/get_system_variable.h @@ -23,14 +23,17 @@ #ifndef GR_GET_SYSTEM_VARIABLE #define GR_GET_SYSTEM_VARIABLE -#include -#include #include #include "plugin/group_replication/include/thread/mysql_thread.h" class Get_system_variable_parameters : public Mysql_thread_body_parameters { public: - enum System_variable_service { VAR_GTID_EXECUTED, VAR_GTID_PURGED }; + enum System_variable_service { + VAR_GTID_EXECUTED, + VAR_GTID_PURGED, + VAR_READ_ONLY, + VAR_SUPER_READ_ONLY + }; Get_system_variable_parameters(System_variable_service service) : m_result(""), m_service(service), m_error(1){}; @@ -70,9 +73,9 @@ class Get_system_variable_parameters : public Mysql_thread_body_parameters { class Get_system_variable : Mysql_thread_body { public: - Get_system_variable(); + Get_system_variable() = default; - virtual ~Get_system_variable(); + virtual ~Get_system_variable() = default; /** Method to return the server gtid_executed by executing the get_variables @@ -84,7 +87,7 @@ class Get_system_variable : Mysql_thread_body { @retval 0 OK @retval !=0 Error */ - int get_server_gtid_executed(std::string >id_executed); + int get_global_gtid_executed(std::string >id_executed); /** Method to return the server gtid_purged by executing the get_variables @@ -96,7 +99,31 @@ class Get_system_variable : Mysql_thread_body { @retval 0 OK @retval !=0 Error */ - int get_server_gtid_purged(std::string >id_purged); + int get_global_gtid_purged(std::string >id_purged); + + /** + Method to return the global value of read_only by executing + the get_variables component service. + + @param [out] value The variable where the value will be set + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int get_global_read_only(bool &value); + + /** + Method to return the global value of super_read_only by executing + the get_variables component service. + + @param [out] value The variable where the value will be set + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int get_global_super_read_only(bool &value); /** Method that will be run on mysql_thread. @@ -107,19 +134,30 @@ class Get_system_variable : Mysql_thread_body { void run(Mysql_thread_body_parameters *parameters); private: + /** + Method to convert a string into a boolean. + + @param [in] value The value as string. + + @return the value as boolean + @retval true string value is "ON" + @retval false otherwise + */ + bool string_to_bool(const std::string &value); + /** Method to return the server system variable specified on variable. @param [in] variable The system variable name to be retrieved @param [out] value The string where the result will be set + @param [in] value_max_length The maximum string value length @return the error value returned @retval 0 OK @retval !=0 Error */ - int internal_get_system_variable(std::string variable, std::string &value); - - my_h_service component_sys_variable_register_service_handler{nullptr}; + int internal_get_system_variable(std::string variable, std::string &value, + size_t value_max_length); }; #endif // GR_GET_SYSTEM_VARIABLE diff --git a/plugin/group_replication/include/services/system_variable/set_system_variable.h b/plugin/group_replication/include/services/system_variable/set_system_variable.h new file mode 100644 index 000000000000..f67b6cbe7bcc --- /dev/null +++ b/plugin/group_replication/include/services/system_variable/set_system_variable.h @@ -0,0 +1,175 @@ +/* Copyright (c) 2022, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#ifndef GR_SET_SYSTEM_VARIABLE +#define GR_SET_SYSTEM_VARIABLE + +#include +#include "plugin/group_replication/include/thread/mysql_thread.h" + +class Set_system_variable_parameters : public Mysql_thread_body_parameters { + public: + enum System_variable { + VAR_READ_ONLY, + VAR_SUPER_READ_ONLY, + VAR_OFFLINE_MODE, + VAR_GROUP_REPLICATION_SINGLE_PRIMARY_MODE, + VAR_GROUP_REPLICATION_ENFORCE_UPDATE_EVERYWHERE_CHECKS + }; + + /** + Set_system_variable_parameters constructor. + + @param [in] variable The system variable to be set + @param [in] value The value to be set + @param [in] type GLOBAL or PERSIST_ONLY + */ + Set_system_variable_parameters(System_variable variable, + const std::string &value, + const std::string &type) + : m_value(value), m_type(type), m_variable(variable), m_error(1){}; + virtual ~Set_system_variable_parameters(){}; + + /** + Get value for class private member error. + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int get_error(); + + /** + Set value for class private member error. + + @param [in] error Set value of error + */ + void set_error(int error); + + /** + Get value for class private member variable. + + @return System defined to run + */ + Set_system_variable_parameters::System_variable get_variable(); + + // to avoid multiple copies on get and set methods we define it as public + const std::string m_value{""}; + const std::string m_type{""}; + + private: + System_variable m_variable{System_variable::VAR_READ_ONLY}; + int m_error{1}; +}; + +class Set_system_variable : Mysql_thread_body { + public: + Set_system_variable() = default; + + virtual ~Set_system_variable() = default; + + /** + Method to set the global value of read_only. + + @param [in] value The value to be set + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int set_global_read_only(bool value); + + /** + Method to set the global value of super_read_only. + + @param [in] value The value to be set + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int set_global_super_read_only(bool value); + + /** + Method to set the global value of offline_mode. + + @param [in] value The value to be set + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int set_global_offline_mode(bool value); + + /** + Method to only persist the value of + group_replication_single_primary_mode. + + @param [in] value The value to be persisted + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int set_persist_only_group_replication_single_primary_mode(bool value); + + /** + Method to only persist the value of + group_replication_enforce_update_everywhere_checks + + @param [in] value The value to be persisted + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int set_persist_only_group_replication_enforce_update_everywhere_checks( + bool value); + + /** + Method that will be run on mysql_thread. + + @param [in, out] parameters Values used by method to get service variable. + + */ + void run(Mysql_thread_body_parameters *parameters); + + private: + /** + Method to set the server system variable specified on variable. + + @param [in] variable The system variable name to be set + @param [in] value The value to be set + @param [in] type GLOBAL or PERSIST_ONLY + @param [in] lock_wait_timeout Lock wait timeout in seconds + + @return the error value returned + @retval 0 OK + @retval !=0 Error + */ + int internal_set_system_variable(const std::string &variable, + const std::string &value, + const std::string &type, + unsigned long long lock_wait_timeout); +}; + +#endif // GR_SET_SYSTEM_VARIABLE diff --git a/plugin/group_replication/include/sql_service/sql_service_command.h b/plugin/group_replication/include/sql_service/sql_service_command.h index f60105175acf..bf75bdcfbb51 100644 --- a/plugin/group_replication/include/sql_service/sql_service_command.h +++ b/plugin/group_replication/include/sql_service/sql_service_command.h @@ -42,71 +42,6 @@ enum enum_plugin_con_isolation { class Sql_service_commands { public: - /** - Internal method to set the super read only mode. - - @param sql_interface the server session interface for query execution - @param arg a generic argument to give the method info or get a result - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long internal_set_super_read_only(Sql_service_interface *sql_interface, - void *arg = nullptr); - - /** - Internal method to reset the super read only mode. - - @param sql_interface the server session interface for query execution - @param arg a generic argument to give the method info or get a result - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long internal_reset_super_read_only(Sql_service_interface *sql_interface, - void *arg = nullptr); - - /** - Internal method to reset the super read only mode. - - @param sql_interface the server session interface for query execution - @param arg a generic argument to give the method info or get a result - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long internal_reset_read_only(Sql_service_interface *sql_interface, - void *arg = nullptr); - - /** - Internal method to get the super read only mode. - - @param sql_interface the server session interface for query execution - @param arg a generic argument to give the method info or get a result - - @retval -1 Error reading the value - @retval 0 Not in super read mode - @retval 1 In read super mode - */ - long internal_get_server_super_read_only(Sql_service_interface *sql_interface, - void *arg = nullptr); - - /** - Internal method to get the super read only mode. - - @param sql_interface the server session interface for query execution - @param arg a generic argument to give the method info or get a result - - @retval -1 Error reading the value - @retval 0 Not in super read mode - @retval 1 In read super mode - */ - long internal_get_server_read_only(Sql_service_interface *sql_interface, - void *arg = nullptr); - /** Method to wait for the server gtid_executed to match the given GTID string @@ -136,17 +71,6 @@ class Sql_service_commands { long internal_kill_session(Sql_service_interface *sql_interface, void *session_id = nullptr); - /** - Method to set a variable using SET PERSIST_ONLY - @param sql_interface the server session interface for query execution - @param variable_args arg void pointer, should be pair - @return the error value returned - @retval 0 OK - @retval !=0 Error - */ - long internal_set_persist_only_variable(Sql_service_interface *sql_interface, - void *variable_args = nullptr); - /** Method to remotely clone a server @@ -185,19 +109,6 @@ class Sql_service_commands { */ long internal_execute_conditional_query(Sql_service_interface *sql_interface, void *variable_args = nullptr); - - /** - Internal method to set the offline mode. - - @param sql_interface the server session interface for query execution - @param arg a generic argument to give the method info or get a result - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long internal_set_offline_mode(Sql_service_interface *sql_interface, - void *arg = nullptr); }; struct st_session_method { @@ -384,35 +295,6 @@ class Sql_service_command_interface { */ bool is_session_valid(); - /** - Method to set the super_read_only variable "ON". - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long set_super_read_only(); - - /** - Method to reset the super_read_only mode back to "OFF" on the - server. - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long reset_super_read_only(); - - /** - Method to reset the read_only mode back to "OFF" on the - server. - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long reset_read_only(); - /** Method to wait for the server gtid_executed to match the given GTID string @@ -427,34 +309,6 @@ class Sql_service_command_interface { long wait_for_server_gtid_executed(std::string >id_executed, int timeout = 0); - /** - Method to get the value of the super_read_only variable on the server. - - @retval -1 Error reading the value - @retval 0 Not in super read mode - @retval 1 In read super mode - */ - long get_server_super_read_only(); - - /** - Method to get the value of the read_only variable on the server. - - @retval -1 Error reading the value - @retval 0 Not in super read mode - @retval 1 In read super mode - */ - long get_server_read_only(); - - /** - Method to set a variable using SET PERSIST_ONLY - @param variable the variable name - @param value the value for the variable - @return the error value returned - @retval 0 OK - @retval !=0 Error - */ - long set_persist_only_variable(std::string &variable, std::string &value); - /** Method to remotely clone a server @@ -521,15 +375,6 @@ class Sql_service_command_interface { long execute_conditional_query(std::string &query, bool *result, std::string &error); - /** - Method to set the offline_mode variable "ON". - - @return error code during execution of the sql query. - @retval 0 - success - @retval >0 - failure - */ - long set_offline_mode(); - private: enum_plugin_con_isolation connection_thread_isolation; diff --git a/plugin/group_replication/include/thread/mysql_thread.h b/plugin/group_replication/include/thread/mysql_thread.h index 664c527486a5..a15310ef20f1 100644 --- a/plugin/group_replication/include/thread/mysql_thread.h +++ b/plugin/group_replication/include/thread/mysql_thread.h @@ -23,6 +23,7 @@ #ifndef MYSQL_THREAD_INCLUDE #define MYSQL_THREAD_INCLUDE +#include #include "plugin/group_replication/include/plugin_psi.h" #include "plugin/group_replication/include/plugin_server_include.h" #include "plugin/group_replication/include/plugin_utils.h" @@ -182,10 +183,20 @@ class Mysql_thread_task { */ void execute(); + /** + Check if the task did finish. + + @return did the task finish? + @retval false No + @retval true Yes + */ + bool is_finished(); + private: // cannot be deleted, represent class where method will run Mysql_thread_body *m_body{nullptr}; Mysql_thread_body_parameters *m_parameters{nullptr}; + std::atomic m_finished{false}; }; /** @@ -249,11 +260,10 @@ class Mysql_thread { mysql_mutex_t m_run_lock; mysql_cond_t m_run_cond; thread_state m_state; - bool m_aborted{false}; + std::atomic m_aborted{false}; mysql_mutex_t m_dispatcher_lock; mysql_cond_t m_dispatcher_cond; - bool m_trigger_run_complete{false}; Abortable_synchronized_queue *m_trigger_queue{nullptr}; }; diff --git a/plugin/group_replication/src/applier.cc b/plugin/group_replication/src/applier.cc index 3ee553484a7b..0947cefca705 100644 --- a/plugin/group_replication/src/applier.cc +++ b/plugin/group_replication/src/applier.cc @@ -585,9 +585,9 @@ int Applier_module::applier_thread_handle() { */ leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, gcs_module->belongs_to_group()); - leave_group_on_failure::leave( - leave_actions, ER_GRP_RPL_APPLIER_EXECUTION_FATAL_ERROR, - PSESSION_USE_THREAD, nullptr, exit_state_action_abort_log_message); + leave_group_on_failure::leave(leave_actions, + ER_GRP_RPL_APPLIER_EXECUTION_FATAL_ERROR, + nullptr, exit_state_action_abort_log_message); } // Even on error cases, send a stop signal to all handlers that could be diff --git a/plugin/group_replication/src/autorejoin.cc b/plugin/group_replication/src/autorejoin.cc index 0c75b21ab314..d4d600b268a8 100644 --- a/plugin/group_replication/src/autorejoin.cc +++ b/plugin/group_replication/src/autorejoin.cc @@ -218,7 +218,7 @@ void Autorejoin_thread::execute_rejoin_process() { LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_FINISHED_AUTO_REJOIN, num_attempts - 1UL, m_attempts, " not"); - enable_server_read_mode(PSESSION_INIT_THREAD); + enable_server_read_mode(); /* Only abort() if the auto-rejoin thread wasn't explicitly stopped, i.e. if someone called Autorejoin_thread::abort(), because that implies an @@ -235,7 +235,7 @@ void Autorejoin_thread::execute_rejoin_process() { break; } case EXIT_STATE_ACTION_OFFLINE_MODE: - enable_server_offline_mode(PSESSION_INIT_THREAD); + enable_server_offline_mode(); break; } } diff --git a/plugin/group_replication/src/certifier.cc b/plugin/group_replication/src/certifier.cc index 055b1afe8fb5..3ef0760adcff 100644 --- a/plugin/group_replication/src/certifier.cc +++ b/plugin/group_replication/src/certifier.cc @@ -31,7 +31,7 @@ #include "plugin/group_replication/include/certifier.h" #include "plugin/group_replication/include/observer_trans.h" #include "plugin/group_replication/include/plugin.h" -#include "plugin/group_replication/include/services/get_system_variable/get_system_variable.h" +#include "plugin/group_replication/include/services/system_variable/get_system_variable.h" const std::string Certifier::GTID_EXTRACTED_NAME = "gtid_extracted"; const std::string Certifier::CERTIFICATION_INFO_ERROR_NAME = @@ -414,7 +414,7 @@ int Certifier::initialize_server_gtid_set(bool get_server_gtid_retrieved) { get_system_variable = new Get_system_variable(); - error = get_system_variable->get_server_gtid_executed(gtid_executed); + error = get_system_variable->get_global_gtid_executed(gtid_executed); DBUG_EXECUTE_IF("gr_server_gtid_executed_extraction_error", error = 1;); if (error) { LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_ERROR_FETCHING_GTID_EXECUTED_SET); diff --git a/plugin/group_replication/src/gcs_event_handlers.cc b/plugin/group_replication/src/gcs_event_handlers.cc index 60e756877555..545413243a5f 100644 --- a/plugin/group_replication/src/gcs_event_handlers.cc +++ b/plugin/group_replication/src/gcs_event_handlers.cc @@ -46,7 +46,7 @@ #include "plugin/group_replication/include/plugin_messages/sync_before_execution_message.h" #include "plugin/group_replication/include/plugin_messages/transaction_prepared_message.h" #include "plugin/group_replication/include/plugin_messages/transaction_with_guarantee_message.h" -#include "plugin/group_replication/include/services/get_system_variable/get_system_variable.h" +#include "plugin/group_replication/include/services/system_variable/get_system_variable.h" using std::vector; @@ -777,7 +777,7 @@ bool Plugin_gcs_events_handler::was_member_expelled_from_group( leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); leave_actions.set(leave_group_on_failure::HANDLE_AUTO_REJOIN, true); leave_group_on_failure::leave(leave_actions, ER_GRP_RPL_MEMBER_EXPELLED, - PSESSION_INIT_THREAD, &m_notification_ctx, + &m_notification_ctx, exit_state_action_abort_log_message); } @@ -921,7 +921,7 @@ void Plugin_gcs_events_handler::handle_joining_members(const Gcs_view &new_view, /** Set the read mode if not set during start (auto-start) */ - if (enable_server_read_mode(PSESSION_DEDICATED_THREAD)) { + if (enable_server_read_mode()) { /* The notification will be triggered in the top level handle function that calls this one. In this case, the on_view_changed handle. @@ -929,9 +929,9 @@ void Plugin_gcs_events_handler::handle_joining_members(const Gcs_view &new_view, leave_group_on_failure::mask leave_actions; leave_actions.set(leave_group_on_failure::SKIP_SET_READ_ONLY, true); leave_actions.set(leave_group_on_failure::SKIP_LEAVE_VIEW_WAIT, true); - leave_group_on_failure::leave( - leave_actions, ER_GRP_RPL_SUPER_READ_ONLY_ACTIVATE_ERROR, - PSESSION_DEDICATED_THREAD, &m_notification_ctx, ""); + leave_group_on_failure::leave(leave_actions, + ER_GRP_RPL_SUPER_READ_ONLY_ACTIVATE_ERROR, + &m_notification_ctx, ""); set_plugin_is_setting_read_mode(false); return; @@ -1038,8 +1038,7 @@ void Plugin_gcs_events_handler::handle_joining_members(const Gcs_view &new_view, */ leave_group_on_failure::mask leave_actions; leave_actions.set(leave_group_on_failure::SKIP_LEAVE_VIEW_WAIT, true); - leave_group_on_failure::leave(leave_actions, 0, PSESSION_DEDICATED_THREAD, - &m_notification_ctx, ""); + leave_group_on_failure::leave(leave_actions, 0, &m_notification_ctx, ""); return; } } @@ -1322,13 +1321,13 @@ Gcs_message_data *Plugin_gcs_events_handler::get_exchangeable_data() const { Get_system_variable *get_system_variable = new Get_system_variable(); - if (get_system_variable->get_server_gtid_executed(server_executed_gtids)) { + if (get_system_variable->get_global_gtid_executed(server_executed_gtids)) { /* purecov: begin inspected */ LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_GTID_EXECUTED_EXTRACT_ERROR); goto sending; /* purecov: inspected */ } - if (get_system_variable->get_server_gtid_purged(server_purged_gtids)) { + if (get_system_variable->get_global_gtid_purged(server_purged_gtids)) { /* purecov: begin inspected */ LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_GTID_PURGED_EXTRACT_ERROR); goto sending; @@ -1868,7 +1867,7 @@ void Plugin_gcs_events_handler::disable_read_mode_for_compatible_members( * version. */ if (!local_member_info->in_primary_mode() && *joiner_compatibility_status == COMPATIBLE) { - if (disable_server_read_mode(PSESSION_DEDICATED_THREAD)) { + if (disable_server_read_mode()) { LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_DISABLE_SRV_READ_MODE_RESTRICTED); } diff --git a/plugin/group_replication/src/group_actions/group_action_coordinator.cc b/plugin/group_replication/src/group_actions/group_action_coordinator.cc index 67b693f97fc5..e1e418e80b55 100644 --- a/plugin/group_replication/src/group_actions/group_action_coordinator.cc +++ b/plugin/group_replication/src/group_actions/group_action_coordinator.cc @@ -924,8 +924,7 @@ int Group_action_coordinator::execute_group_action_handler() { leave_actions.set(leave_group_on_failure::STOP_APPLIER, true); leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); leave_group_on_failure::leave( - leave_actions, ER_GRP_RPL_CONFIGURATION_ACTION_KILLED_ERROR, - PSESSION_INIT_THREAD, nullptr, + leave_actions, ER_GRP_RPL_CONFIGURATION_ACTION_KILLED_ERROR, nullptr, exit_state_action_abort_log_message.c_str()); awake_coordinator_on_error(current_executing_action, is_sender, true); diff --git a/plugin/group_replication/src/group_actions/multi_primary_migration_action.cc b/plugin/group_replication/src/group_actions/multi_primary_migration_action.cc index 7b462021f3da..6be99ac79241 100644 --- a/plugin/group_replication/src/group_actions/multi_primary_migration_action.cc +++ b/plugin/group_replication/src/group_actions/multi_primary_migration_action.cc @@ -21,11 +21,11 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "plugin/group_replication/include/group_actions/multi_primary_migration_action.h" -#include #include "plugin/group_replication/include/mysql_version_gcs_protocol_map.h" #include "plugin/group_replication/include/plugin.h" #include "plugin/group_replication/include/plugin_handlers/consensus_leaders_handler.h" #include "plugin/group_replication/include/plugin_handlers/server_ongoing_transactions_handler.h" +#include "plugin/group_replication/include/services/system_variable/set_system_variable.h" bool send_multi_primary_action_message(Plugin_gcs_message *message) { enum_gcs_error msg_error = gcs_module->send_message(*message); @@ -202,7 +202,7 @@ Multi_primary_migration_action::execute_action( local_member_info->get_member_version(), group_member_mgr->get_group_lowest_online_version()) == READ_COMPATIBLE) { - if (enable_server_read_mode(PSESSION_USE_THREAD)) { + if (enable_server_read_mode()) { /* purecov: begin inspected */ LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_ENABLE_READ_ONLY_FAILED); /* purecov: end */ @@ -341,31 +341,23 @@ int Multi_primary_migration_action::before_message_handling( } bool Multi_primary_migration_action::persist_variable_values() { - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - long error = 0; - std::string var_name, var_value; - - if ((error = sql_command_interface->establish_session_connection( - PSESSION_USE_THREAD, GROUPREPL_USER, get_plugin_pointer()))) - goto end; /* purecov: inspected */ - - var_name.assign("group_replication_single_primary_mode"); - var_value.assign("OFF"); + int error = 0; + Set_system_variable set_system_variable; - if ((error = set_persist_only_variable(var_name, var_value, - sql_command_interface))) + if ((error = set_system_variable + .set_persist_only_group_replication_single_primary_mode( + false))) { goto end; /* purecov: inspected */ + } - var_name.assign("group_replication_enforce_update_everywhere_checks"); - var_value.assign("ON"); - - if ((error = set_persist_only_variable(var_name, var_value, - sql_command_interface))) + if ((error = + set_system_variable + .set_persist_only_group_replication_enforce_update_everywhere_checks( + true))) { goto end; /* purecov: inspected */ + } end: - delete sql_command_interface; if (error) { execution_message_area.set_warning_message( "It was not possible to persist the configuration values for this " diff --git a/plugin/group_replication/src/group_actions/primary_election_action.cc b/plugin/group_replication/src/group_actions/primary_election_action.cc index 1ca8eec4177d..b7c61f4ad6d9 100644 --- a/plugin/group_replication/src/group_actions/primary_election_action.cc +++ b/plugin/group_replication/src/group_actions/primary_election_action.cc @@ -21,10 +21,10 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "plugin/group_replication/include/group_actions/primary_election_action.h" -#include #include "plugin/group_replication/include/plugin.h" #include "plugin/group_replication/include/plugin_handlers/server_ongoing_transactions_handler.h" #include "plugin/group_replication/include/plugin_messages/group_action_message.h" +#include "plugin/group_replication/include/services/system_variable/set_system_variable.h" #include "template_utils.h" Primary_election_action::Primary_election_action() @@ -723,32 +723,23 @@ int Primary_election_action::before_message_handling( } bool Primary_election_action::persist_variable_values() { - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - long error = 0; - std::string var_name, var_value; - - if ((error = sql_command_interface->establish_session_connection( - PSESSION_USE_THREAD, GROUPREPL_USER, get_plugin_pointer()))) - goto end; /* purecov: inspected */ - - var_name.assign("group_replication_enforce_update_everywhere_checks"); - var_value.assign("OFF"); + int error = 0; + Set_system_variable set_system_variable; - if ((error = set_persist_only_variable(var_name, var_value, - sql_command_interface))) + if ((error = + set_system_variable + .set_persist_only_group_replication_enforce_update_everywhere_checks( + false))) { goto end; /* purecov: inspected */ + } - var_name.assign("group_replication_single_primary_mode"); - var_value.assign("ON"); - - if ((error = set_persist_only_variable(var_name, var_value, - sql_command_interface))) - + if ((error = + set_system_variable + .set_persist_only_group_replication_single_primary_mode(true))) { goto end; /* purecov: inspected */ + } end: - delete sql_command_interface; if (error) { execution_message_area.set_warning_message( "It was not possible to persist the configuration values for this " diff --git a/plugin/group_replication/src/leave_group_on_failure.cc b/plugin/group_replication/src/leave_group_on_failure.cc index d446c3bb05d9..ea00a657fd69 100644 --- a/plugin/group_replication/src/leave_group_on_failure.cc +++ b/plugin/group_replication/src/leave_group_on_failure.cc @@ -33,7 +33,6 @@ void leave_group_on_failure::leave( const leave_group_on_failure::mask &actions, longlong error_to_log, - enum_plugin_con_isolation session_isolation, Notification_context *caller_notification_context, const char *exit_state_action_abort_log_message) { DBUG_TRACE; @@ -176,7 +175,7 @@ void leave_group_on_failure::leave( if (!actions[leave_group_on_failure::SKIP_SET_READ_ONLY]) { LogPluginErr(ERROR_LEVEL, ER_GRP_RPL_SERVER_SET_TO_READ_ONLY_DUE_TO_ERRORS); - enable_server_read_mode(session_isolation); + enable_server_read_mode(); } /* @@ -187,7 +186,7 @@ void leave_group_on_failure::leave( if (actions[leave_group_on_failure::HANDLE_EXIT_STATE_ACTION] && !start_auto_rejoin) { if (get_exit_state_action_var() == EXIT_STATE_ACTION_OFFLINE_MODE) { - enable_server_offline_mode(session_isolation); + enable_server_offline_mode(); } } diff --git a/plugin/group_replication/src/observer_server_state.cc b/plugin/group_replication/src/observer_server_state.cc index 144a88edf9cf..250b65a1504a 100644 --- a/plugin/group_replication/src/observer_server_state.cc +++ b/plugin/group_replication/src/observer_server_state.cc @@ -56,6 +56,11 @@ int group_replication_after_dd_upgrade(Server_state_param *) { return 0; } int group_replication_after_server_shutdown(Server_state_param *) { enable_server_shutdown_status(); plugin_group_replication_stop(); + /* + Terminate mysql_thread session when client connections are closed, + otherwise server will block waiting for them to terminate. + */ + mysql_thread_handler_finalize(); return 0; } diff --git a/plugin/group_replication/src/observer_trans.cc b/plugin/group_replication/src/observer_trans.cc index f154973f3835..b6c2c5fbf66e 100644 --- a/plugin/group_replication/src/observer_trans.cc +++ b/plugin/group_replication/src/observer_trans.cc @@ -38,9 +38,10 @@ #include "plugin/group_replication/include/plugin_messages/transaction_message.h" #include "plugin/group_replication/include/plugin_messages/transaction_with_guarantee_message.h" #include "plugin/group_replication/include/plugin_observers/group_transaction_observation_manager.h" + +#ifndef NDEBUG #include "plugin/group_replication/include/sql_service/sql_command_test.h" -#include "plugin/group_replication/include/sql_service/sql_service_command.h" -#include "plugin/group_replication/include/sql_service/sql_service_interface.h" +#endif /* Buffer to read the write_set value as a string. diff --git a/plugin/group_replication/src/plugin.cc b/plugin/group_replication/src/plugin.cc index 6dc07a19fa80..67ab7523c563 100644 --- a/plugin/group_replication/src/plugin.cc +++ b/plugin/group_replication/src/plugin.cc @@ -126,6 +126,15 @@ Advertised_recovery_endpoints *advertised_recovery_endpoints = nullptr; Member_actions_handler *member_actions_handler = nullptr; /** Handle tasks on mysql_thread */ Mysql_thread *mysql_thread_handler = nullptr; +/** + Dedicated mysql_thread to enable `read_only` and `super_read_only` + since these are blocking operations. + If we did use `mysql_thread_handler` that would block all other + other operations until read modes operations complete. +*/ +Mysql_thread *mysql_thread_handler_read_only_mode = nullptr; +/** Module with the acquired server services on plugin install */ +Server_services_references *server_services_references_module = nullptr; Plugin_gcs_events_handler *events_handler = nullptr; Plugin_gcs_view_modification_notifier *view_change_notifier = nullptr; @@ -678,8 +687,17 @@ int initialize_plugin_and_join( bool read_only_mode = false, super_read_only_mode = false; bool write_set_limits_set = false; - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); + /* + Despite START GROUP_REPLICATION do not depend on the SQL API, + other operations, like distributed recovery through clone, do + depend, as such we do validate early that SQL API is operational. + */ + Sql_service_command_interface sql_command_interface; + if (sql_command_interface.establish_session_connection( + sql_api_isolation, GROUPREPL_USER, lv.plugin_info_ptr)) { + error = 1; + goto err; + } /** We redo the check for the group name here when starting on boot as only @@ -708,15 +726,7 @@ int initialize_plugin_and_join( // GCS interface. if ((error = gcs_module->initialize())) goto err; /* purecov: inspected */ - // Setup SQL service interface. - if (sql_command_interface->establish_session_connection( - sql_api_isolation, GROUPREPL_USER, lv.plugin_info_ptr)) { - error = 1; /* purecov: inspected */ - goto err; /* purecov: inspected */ - } - - get_read_mode_state(sql_command_interface, &read_only_mode, - &super_read_only_mode); + get_read_mode_state(&read_only_mode, &super_read_only_mode); /* At this point in the code, set the super_read_only mode here on the @@ -725,7 +735,7 @@ int initialize_plugin_and_join( deadlock issues. */ if (!lv.plugin_is_auto_starting_on_install) { - if (enable_super_read_only_mode(sql_command_interface)) { + if (enable_server_read_mode()) { /* purecov: begin inspected */ error = 1; LogPluginErr(ERROR_LEVEL, @@ -844,8 +854,7 @@ int initialize_plugin_and_join( if (!lv.server_shutdown_status && server_engine_initialized() && enabled_super_read_only) { - set_read_mode_state(sql_command_interface, read_only_mode, - super_read_only_mode); + set_read_mode_state(read_only_mode, super_read_only_mode); } assert(transactions_latch->empty()); @@ -858,7 +867,6 @@ int initialize_plugin_and_join( } } - delete sql_command_interface; lv.plugin_is_auto_starting_on_install = false; return error; @@ -1257,7 +1265,7 @@ int plugin_group_replication_stop(char **error_message) { // Enable super_read_only. if (!lv.server_shutdown_status && !lv.plugin_is_being_uninstalled && server_engine_initialized()) { - if (enable_server_read_mode(PSESSION_DEDICATED_THREAD)) { + if (enable_server_read_mode()) { /* purecov: begin inspected */ LogPluginErr(ERROR_LEVEL, ER_GRP_RPL_FAILED_TO_ENABLE_READ_ONLY_MODE_ON_SHUTDOWN); @@ -1300,20 +1308,6 @@ int initialize_plugin_modules(gr_modules::mask modules_to_init) { DBUG_EXECUTE_IF("group_replication_rejoin_long_retry", { lv.rejoin_timeout = 60ULL; };); - /* - Mysql thread handler. - */ - if (modules_to_init[gr_modules::MYSQL_THREAD_HANDLER]) { - mysql_thread_handler = new Mysql_thread( - key_GR_THD_mysql_thread_handler, key_GR_LOCK_mysql_thread_handler_run, - key_GR_COND_mysql_thread_handler_run, - key_GR_LOCK_mysql_thread_handler_dispatcher_run, - key_GR_COND_mysql_thread_handler_dispatcher_run); - if (mysql_thread_handler->initialize()) { - return GROUP_REPLICATION_CONFIGURATION_ERROR; - } - } - /* Registry module. */ @@ -1669,17 +1663,6 @@ int terminate_plugin_modules(gr_modules::mask modules_to_terminate, } } - /* - Mysql thread handler. - */ - if (modules_to_terminate[gr_modules::MYSQL_THREAD_HANDLER]) { - if (nullptr != mysql_thread_handler) { - mysql_thread_handler->terminate(); - delete mysql_thread_handler; - mysql_thread_handler = nullptr; - } - } - return error; } @@ -1700,7 +1683,6 @@ bool attempt_rejoin() { modules_mask.set(gr_modules::GCS_EVENTS_HANDLER, true); modules_mask.set(gr_modules::REMOTE_CLONE_HANDLER, true); modules_mask.set(gr_modules::MEMBER_ACTIONS_HANDLER, true); - modules_mask.set(gr_modules::MYSQL_THREAD_HANDLER, true); modules_mask.set(gr_modules::MESSAGE_SERVICE_HANDLER, true); modules_mask.set(gr_modules::BINLOG_DUMP_THREAD_KILL, true); modules_mask.set(gr_modules::RECOVERY_MODULE, true); @@ -1874,6 +1856,66 @@ bool attempt_rejoin() { return ret; } +void mysql_thread_handler_finalize() { + if (nullptr != mysql_thread_handler_read_only_mode) { + mysql_thread_handler_read_only_mode->terminate(); + delete mysql_thread_handler_read_only_mode; + mysql_thread_handler_read_only_mode = nullptr; + } + + if (nullptr != mysql_thread_handler) { + mysql_thread_handler->terminate(); + delete mysql_thread_handler; + mysql_thread_handler = nullptr; + } +} + +bool mysql_thread_handler_initialize() { + mysql_thread_handler = new Mysql_thread( + key_GR_THD_mysql_thread_handler, key_GR_LOCK_mysql_thread_handler_run, + key_GR_COND_mysql_thread_handler_run, + key_GR_LOCK_mysql_thread_handler_dispatcher_run, + key_GR_COND_mysql_thread_handler_dispatcher_run); + bool error = mysql_thread_handler->initialize(); + + mysql_thread_handler_read_only_mode = new Mysql_thread( + key_GR_THD_mysql_thread_handler_read_only_mode, + key_GR_LOCK_mysql_thread_handler_read_only_mode_run, + key_GR_COND_mysql_thread_handler_read_only_mode_run, + key_GR_LOCK_mysql_thread_handler_read_only_mode_dispatcher_run, + key_GR_COND_mysql_thread_handler_read_only_mode_dispatcher_run); + error |= mysql_thread_handler_read_only_mode->initialize(); + + if (error) { + LogPluginErr( + ERROR_LEVEL, ER_GRP_RPL_ERROR_MSG, + "Failed to initialize Group Replication mysql thread handlers."); + mysql_thread_handler_finalize(); + } + + return error; +} + +void server_services_references_finalize() { + if (nullptr != server_services_references_module) { + server_services_references_module->finalize(); + delete server_services_references_module; + server_services_references_module = nullptr; + } +} + +bool server_services_references_initialize() { + server_services_references_module = new Server_services_references(); + bool error = server_services_references_module->initialize(); + if (error) { + LogPluginErr(ERROR_LEVEL, ER_GRP_RPL_ERROR_MSG, + "Failed to acquire the required server services."); + server_services_references_finalize(); + } + + return error; +} + int plugin_group_replication_init(MYSQL_PLUGIN plugin_info) { // Initialize plugin local variables. lv.init(); @@ -1894,6 +1936,13 @@ int plugin_group_replication_init(MYSQL_PLUGIN plugin_info) { reinterpret_cast( h_mysql_runtime_error_service); + /* + Acquire required server services once at plugin install. + */ + if (server_services_references_initialize()) { + return 1; + } + // Register all PSI keys at the time plugin init #ifdef HAVE_PSI_INTERFACE register_all_group_replication_psi_keys(); @@ -1987,6 +2036,16 @@ int plugin_group_replication_init(MYSQL_PLUGIN plugin_info) { consensus_leaders_handler = new Consensus_leaders_handler{*group_events_observation_manager}; + /* + We do query super_read_only value while Group Replication is stopped, + on example is the `group_replication_enable_member_action` UDF, as such, + we need to initialize the mysql_thread used on `Get_system_variable` + on plugin install. + */ + if (mysql_thread_handler_initialize()) { + return 1; + } + bool const error = register_udfs(); if (error) return 1; @@ -2144,6 +2203,7 @@ int plugin_group_replication_deinit(void *p) { unregister_udfs(); sql_service_interface_deinit(); + mysql_thread_handler_finalize(); delete member_actions_handler; member_actions_handler = nullptr; @@ -2170,6 +2230,8 @@ int plugin_group_replication_deinit(void *p) { lv.plugin_info_ptr = nullptr; + server_services_references_finalize(); + // Deinitialize runtime error service. my_h_service h_mysql_runtime_error_service = reinterpret_cast(mysql_runtime_error_service); diff --git a/plugin/group_replication/src/plugin_handlers/group_partition_handling.cc b/plugin/group_replication/src/plugin_handlers/group_partition_handling.cc index 40ab9dbb7252..536b6c08ccec 100644 --- a/plugin/group_replication/src/plugin_handlers/group_partition_handling.cc +++ b/plugin/group_replication/src/plugin_handlers/group_partition_handling.cc @@ -224,8 +224,8 @@ int Group_partition_handling::partition_thread_handler() { leave_actions.set(leave_group_on_failure::STOP_APPLIER, true); leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); leave_actions.set(leave_group_on_failure::HANDLE_AUTO_REJOIN, true); - leave_group_on_failure::leave(leave_actions, 0, PSESSION_INIT_THREAD, - nullptr, exit_state_action_abort_log_message); + leave_group_on_failure::leave(leave_actions, 0, nullptr, + exit_state_action_abort_log_message); } mysql_mutex_lock(&run_lock); diff --git a/plugin/group_replication/src/plugin_handlers/member_actions_handler.cc b/plugin/group_replication/src/plugin_handlers/member_actions_handler.cc index eecf8e49f2a7..a15d218cec3d 100644 --- a/plugin/group_replication/src/plugin_handlers/member_actions_handler.cc +++ b/plugin/group_replication/src/plugin_handlers/member_actions_handler.cc @@ -354,7 +354,7 @@ void Member_actions_handler::run(Mysql_thread_body_parameters *parameters) { leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); leave_group_on_failure::leave( - leave_actions, 0, PSESSION_USE_THREAD, nullptr, + leave_actions, 0, nullptr, "Please check previous messages in the error log."); } } @@ -372,7 +372,7 @@ int Member_actions_handler::run_internal_action( if (action.name() == "mysql_disable_super_read_only_if_primary") { if (im_the_primary) { - error = disable_server_read_mode(PSESSION_USE_THREAD); + error = disable_server_read_mode(); DBUG_EXECUTE_IF( "group_replication_force_error_on_mysql_disable_super_read_only_if_" diff --git a/plugin/group_replication/src/plugin_handlers/offline_mode_handler.cc b/plugin/group_replication/src/plugin_handlers/offline_mode_handler.cc index c3c14c110260..f3ee0476be19 100644 --- a/plugin/group_replication/src/plugin_handlers/offline_mode_handler.cc +++ b/plugin/group_replication/src/plugin_handlers/offline_mode_handler.cc @@ -22,22 +22,16 @@ #include "plugin/group_replication/include/plugin_handlers/offline_mode_handler.h" -#include - #include "my_dbug.h" -#include "mysql/components/services/log_builtins.h" #include "plugin/group_replication/include/plugin.h" #include "plugin/group_replication/include/plugin_utils.h" +#include "plugin/group_replication/include/services/system_variable/set_system_variable.h" -void enable_server_offline_mode(enum_plugin_con_isolation session_isolation) { +void enable_server_offline_mode() { DBUG_TRACE; - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - int error = sql_command_interface->establish_session_connection( - session_isolation, GROUPREPL_USER, get_plugin_pointer()) || - sql_command_interface->set_offline_mode(); - delete sql_command_interface; + Set_system_variable set_system_variable; + int error = set_system_variable.set_global_offline_mode(true); if (error) { /* purecov: begin inspected */ diff --git a/plugin/group_replication/src/plugin_handlers/persistent_variables_handler.cc b/plugin/group_replication/src/plugin_handlers/persistent_variables_handler.cc deleted file mode 100644 index 4b4c035d7de0..000000000000 --- a/plugin/group_replication/src/plugin_handlers/persistent_variables_handler.cc +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2018, 2022, Oracle and/or its affiliates. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License, version 2.0, - as published by the Free Software Foundation. - - This program is also distributed with certain software (including - but not limited to OpenSSL) that is licensed under separate terms, - as designated in a particular file or component or in included license - documentation. The authors of MySQL hereby grant you an additional - permission to link the program and your derivative works with the - separately licensed software that they have included with MySQL. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License, version 2.0, for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "plugin/group_replication/include/plugin_handlers/persistent_variables_handler.h" -#include "plugin/group_replication/include/plugin.h" -#include "plugin/group_replication/include/plugin_constants.h" - -long set_persist_only_variable( - std::string &name, std::string &value, - Sql_service_command_interface *command_interface) { - DBUG_TRACE; - long error = 0; - - DBUG_EXECUTE_IF("group_replication_var_persist_error", { return 1; }); - - assert(command_interface != nullptr); - - error = command_interface->set_persist_only_variable(name, value); - - return error; -} \ No newline at end of file diff --git a/plugin/group_replication/src/plugin_handlers/primary_election_invocation_handler.cc b/plugin/group_replication/src/plugin_handlers/primary_election_invocation_handler.cc index 6025cc80722f..da16423ab82d 100644 --- a/plugin/group_replication/src/plugin_handlers/primary_election_invocation_handler.cc +++ b/plugin/group_replication/src/plugin_handlers/primary_election_invocation_handler.cc @@ -24,7 +24,7 @@ #include "plugin/group_replication/include/plugin.h" #include "plugin/group_replication/include/plugin_handlers/member_actions_handler.h" #include "plugin/group_replication/include/plugin_handlers/primary_election_utils.h" -#include "plugin/group_replication/include/services/get_system_variable/get_system_variable.h" +#include "plugin/group_replication/include/services/system_variable/get_system_variable.h" Primary_election_handler::Primary_election_handler( ulong components_stop_timeout) @@ -137,7 +137,7 @@ int Primary_election_handler::execute_primary_election( enum_primary_election_primary_change_status:: PRIMARY_DID_NOT_CHANGE_NO_CANDIDATE, mode, PRIMARY_ELECTION_NO_CANDIDATES_ERROR); - if (enable_server_read_mode(PSESSION_DEDICATED_THREAD)) { + if (enable_server_read_mode()) { LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_ENABLE_READ_ONLY_FAILED); /* purecov: inspected */ } @@ -224,7 +224,7 @@ void Primary_election_handler::print_gtid_info_in_log() { std::string server_executed_gtids; Get_system_variable *get_system_variable = new Get_system_variable(); - if (get_system_variable->get_server_gtid_executed(server_executed_gtids)) { + if (get_system_variable->get_global_gtid_executed(server_executed_gtids)) { /* purecov: begin inspected */ LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_GTID_EXECUTED_EXTRACT_ERROR); goto err; @@ -303,7 +303,7 @@ int Primary_election_handler::legacy_primary_election( member_actions_handler->trigger_actions( Member_actions::AFTER_PRIMARY_ELECTION); } else { - if (enable_server_read_mode(PSESSION_DEDICATED_THREAD)) { + if (enable_server_read_mode()) { LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_ENABLE_READ_ONLY_FAILED); /* purecov: inspected */ } diff --git a/plugin/group_replication/src/plugin_handlers/primary_election_primary_process.cc b/plugin/group_replication/src/plugin_handlers/primary_election_primary_process.cc index 785e4d65cde0..1ee91c30e676 100644 --- a/plugin/group_replication/src/plugin_handlers/primary_election_primary_process.cc +++ b/plugin/group_replication/src/plugin_handlers/primary_election_primary_process.cc @@ -240,7 +240,7 @@ int Primary_election_primary_process::primary_election_process_handler() { primary changes we do enabled `super_read_only` on all members and then run the member actions on the new primary. */ - if (enable_server_read_mode(PSESSION_USE_THREAD)) { + if (enable_server_read_mode()) { /* purecov: begin inspected */ LogPluginErr(WARNING_LEVEL, ER_GRP_RPL_ENABLE_READ_ONLY_FAILED); /* purecov: end */ diff --git a/plugin/group_replication/src/plugin_handlers/primary_election_secondary_process.cc b/plugin/group_replication/src/plugin_handlers/primary_election_secondary_process.cc index bca367c3266c..eb171d4e2648 100644 --- a/plugin/group_replication/src/plugin_handlers/primary_election_secondary_process.cc +++ b/plugin/group_replication/src/plugin_handlers/primary_election_secondary_process.cc @@ -39,8 +39,6 @@ Primary_election_secondary_process::Primary_election_secondary_process() primary_ready(false), group_in_read_mode(false), is_waiting_on_read_mode_group(false), - read_mode_session_id(0), - is_read_mode_set(SECONDARY_ELECTION_READ_MODE_NOT_SET), number_of_know_members(0) { mysql_mutex_init(key_GR_LOCK_primary_election_secondary_process_run, &election_lock, MY_MUTEX_INIT_FAST); @@ -77,8 +75,6 @@ int Primary_election_secondary_process::launch_secondary_election_process( group_in_read_mode = false; is_waiting_on_read_mode_group = false; election_process_aborted = false; - read_mode_session_id = 0; - is_read_mode_set = SECONDARY_ELECTION_READ_MODE_NOT_SET; known_members_addresses.clear(); for (Group_member_info *member : *group_members_info) { @@ -271,26 +267,9 @@ bool Primary_election_secondary_process::enable_read_mode_on_server() { remote_clone_handler->lock_gr_clone_read_mode_lock(); if (!plugin_is_group_replication_cloning()) { - mysql_mutex_lock(&election_lock); - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - error = sql_command_interface->establish_session_connection( - PSESSION_USE_THREAD, GROUPREPL_USER, get_plugin_pointer()); - if (!error) { - read_mode_session_id = - sql_command_interface->get_sql_service_interface()->get_session_id(); - is_read_mode_set = SECONDARY_ELECTION_READ_MODE_BEING_SET; - } - mysql_mutex_unlock(&election_lock); - if (!error && !election_process_aborted) { - error = enable_super_read_only_mode(sql_command_interface); + error = enable_server_read_mode(); } - - mysql_mutex_lock(&election_lock); - delete sql_command_interface; - is_read_mode_set = SECONDARY_ELECTION_READ_MODE_IS_SET; - mysql_mutex_unlock(&election_lock); } remote_clone_handler->unlock_gr_clone_read_mode_lock(); @@ -298,30 +277,6 @@ bool Primary_election_secondary_process::enable_read_mode_on_server() { return error != 0; } -bool Primary_election_secondary_process::kill_read_mode_query() { - int error = 0; - - mysql_mutex_assert_owner(&election_lock); - - if (is_read_mode_set == SECONDARY_ELECTION_READ_MODE_BEING_SET) { - assert(read_mode_session_id != 0); - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - error = sql_command_interface->establish_session_connection( - PSESSION_DEDICATED_THREAD, GROUPREPL_USER, get_plugin_pointer()); - if (!error) { - error = sql_command_interface->kill_session(read_mode_session_id); - // If the thread is no longer there don't report an warning - if (ER_NO_SUCH_THREAD == error) { - error = 0; /* purecov: inspected */ - } - } - delete sql_command_interface; - } - - return error != 0; -} - bool Primary_election_secondary_process::signal_read_mode_ready() { Single_primary_message single_primary_message( Single_primary_message::SINGLE_PRIMARY_READ_MODE_SET); @@ -463,13 +418,6 @@ int Primary_election_secondary_process::terminate_election_process(bool wait) { // Awake up possible stuck conditions mysql_cond_broadcast(&election_cond); - if (kill_read_mode_query()) { - abort_plugin_process( - "In the primary election process it was not possible to kill a " - "previous query trying to enable the server read " - "mode."); /* purecov: inspected */ - } - if (wait) { while (election_process_thd_state.is_thread_alive()) { DBUG_PRINT("sleep", ("Waiting for the Primary election secondary process " diff --git a/plugin/group_replication/src/plugin_handlers/primary_election_utils.cc b/plugin/group_replication/src/plugin_handlers/primary_election_utils.cc index 3be2f7341cd5..313cebf2157c 100644 --- a/plugin/group_replication/src/plugin_handlers/primary_election_utils.cc +++ b/plugin/group_replication/src/plugin_handlers/primary_election_utils.cc @@ -88,6 +88,6 @@ void kill_transactions_and_leave_on_election_error(std::string &err_msg) { leave_group_on_failure::mask leave_actions; leave_actions.set(leave_group_on_failure::STOP_APPLIER, true); leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); - leave_group_on_failure::leave(leave_actions, 0, PSESSION_INIT_THREAD, nullptr, + leave_group_on_failure::leave(leave_actions, 0, nullptr, exit_state_action_abort_log_message.c_str()); } diff --git a/plugin/group_replication/src/plugin_handlers/read_mode_handler.cc b/plugin/group_replication/src/plugin_handlers/read_mode_handler.cc index 4f03d83a9283..48619abab615 100644 --- a/plugin/group_replication/src/plugin_handlers/read_mode_handler.cc +++ b/plugin/group_replication/src/plugin_handlers/read_mode_handler.cc @@ -22,96 +22,56 @@ #include "plugin/group_replication/include/plugin_handlers/read_mode_handler.h" -#include - #include "my_dbug.h" -#include "mysql/components/services/log_builtins.h" #include "plugin/group_replication/include/plugin.h" #include "plugin/group_replication/include/plugin_utils.h" +#include "plugin/group_replication/include/services/system_variable/get_system_variable.h" +#include "plugin/group_replication/include/services/system_variable/set_system_variable.h" -long enable_super_read_only_mode( - Sql_service_command_interface *command_interface) { +int enable_server_read_mode() { DBUG_TRACE; - long error = 0; - -#ifndef NDEBUG - DBUG_EXECUTE_IF("group_replication_skip_read_mode", { return 0; }); - DBUG_EXECUTE_IF("group_replication_read_mode_error", { return 1; }); -#endif - - assert(command_interface != nullptr); + int error = 0; // Extract server values for super read mode - longlong server_super_read_only_query = - command_interface->get_server_super_read_only(); - - error = server_super_read_only_query == -1; + bool super_read_only_value = false; + Get_system_variable get_system_variable; + get_system_variable.get_global_super_read_only(super_read_only_value); // Setting the super_read_only mode on the server. - if (!error) { - if (!server_super_read_only_query) - error = command_interface->set_super_read_only(); - } else { - LogPluginErr( - ERROR_LEVEL, - ER_GRP_RPL_READ_UNABLE_FOR_SUPER_READ_ONLY); /* purecov: inspected */ + if (!super_read_only_value) { + Set_system_variable set_system_variable; + error = set_system_variable.set_global_super_read_only(true); } + LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_SUPER_READ_ON); return error; } -long disable_super_read_only_mode( - Sql_service_command_interface *command_interface) { +int disable_server_read_mode() { DBUG_TRACE; - long error = 0; - - assert(command_interface != nullptr); - error = command_interface->reset_read_only(); + Set_system_variable set_system_variable; + int error = set_system_variable.set_global_read_only(false); + LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_SUPER_READ_OFF); return error; } -int enable_server_read_mode(enum_plugin_con_isolation session_isolation) { - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - int error = sql_command_interface->establish_session_connection( - session_isolation, GROUPREPL_USER, get_plugin_pointer()) || - enable_super_read_only_mode(sql_command_interface); - delete sql_command_interface; - return error; -} - -int disable_server_read_mode(enum_plugin_con_isolation session_isolation) { - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - int error = sql_command_interface->establish_session_connection( - session_isolation, GROUPREPL_USER, get_plugin_pointer()) || - disable_super_read_only_mode(sql_command_interface); - delete sql_command_interface; - return error; -} - -long get_read_mode_state(Sql_service_command_interface *sql_command_interface, - bool *read_only_enabled, - bool *super_read_only_enabled) { +int get_read_mode_state(bool *read_only_enabled, + bool *super_read_only_enabled) { DBUG_TRACE; + int error = 0; + bool read_only_value = false; + bool super_read_only_value = false; + Get_system_variable get_system_variable; - long error = 0; - - assert(sql_command_interface != nullptr); - - // Extract server values for the read mode - longlong server_read_only_query = - sql_command_interface->get_server_read_only(); - longlong server_super_read_only_query = - sql_command_interface->get_server_super_read_only(); - - error = server_read_only_query == -1 || server_super_read_only_query == -1; + error |= get_system_variable.get_global_read_only(read_only_value); + error |= + get_system_variable.get_global_super_read_only(super_read_only_value); if (!error) { - *read_only_enabled = (bool)server_read_only_query; - *super_read_only_enabled = (bool)server_super_read_only_query; + *read_only_enabled = read_only_value; + *super_read_only_enabled = super_read_only_value; } else { LogPluginErr( ERROR_LEVEL, @@ -122,19 +82,20 @@ long get_read_mode_state(Sql_service_command_interface *sql_command_interface, return error; } -long set_read_mode_state(Sql_service_command_interface *sql_service_command, - bool read_only_enabled, bool super_read_only_enabled) { +int set_read_mode_state(bool read_only_enabled, bool super_read_only_enabled) { DBUG_TRACE; - - long error = 0; - - if (!read_only_enabled) - error |= sql_service_command->reset_read_only(); - else if (!super_read_only_enabled) - error |= sql_service_command->reset_super_read_only(); + int error = 0; + Set_system_variable set_system_variable; + + if (!read_only_enabled) { + error |= set_system_variable.set_global_read_only(false); + LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_SUPER_READ_OFF); + } else if (!super_read_only_enabled) { + error |= set_system_variable.set_global_super_read_only(false); + LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_SUPER_READ_OFF); + } if (error) { - // Do not throw an error as the user can reset the read mode LogPluginErr( ERROR_LEVEL, ER_GRP_RPL_UNABLE_TO_RESET_SERVER_READ_MODE); /* purecov: inspected */ diff --git a/plugin/group_replication/src/plugin_handlers/remote_clone_handler.cc b/plugin/group_replication/src/plugin_handlers/remote_clone_handler.cc index 943be1ea94ee..22e4ac03fa1f 100644 --- a/plugin/group_replication/src/plugin_handlers/remote_clone_handler.cc +++ b/plugin/group_replication/src/plugin_handlers/remote_clone_handler.cc @@ -398,8 +398,7 @@ int Remote_clone_handler::set_clone_ssl_options( return error; } -int Remote_clone_handler::fallback_to_recovery_or_leave( - Sql_service_command_interface *sql_command_interface, bool critical_error) { +int Remote_clone_handler::fallback_to_recovery_or_leave(bool critical_error) { // Do nothing if the server is shutting down. // The stop process will leave the group if (get_server_shutdown_status()) return 0; @@ -413,8 +412,7 @@ int Remote_clone_handler::fallback_to_recovery_or_leave( return 1; } // If it failed to (re)connect to the server or the set read only query - if (!sql_command_interface->is_session_valid() || - sql_command_interface->set_super_read_only()) { + if (enable_server_read_mode()) { abort_plugin_process( "Cannot re-enable the super read only after clone failure."); return 1; @@ -446,9 +444,9 @@ int Remote_clone_handler::fallback_to_recovery_or_leave( leave_group_on_failure::mask leave_actions; leave_actions.set(leave_group_on_failure::SKIP_SET_READ_ONLY, true); leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); - leave_group_on_failure::leave( - leave_actions, ER_GRP_RPL_RECOVERY_STRAT_NO_FALLBACK, - PSESSION_INIT_THREAD, nullptr, exit_state_action_abort_log_message); + leave_group_on_failure::leave(leave_actions, + ER_GRP_RPL_RECOVERY_STRAT_NO_FALLBACK, + nullptr, exit_state_action_abort_log_message); return 1; } } @@ -723,7 +721,7 @@ void Remote_clone_handler::gr_clone_debug_point() { /* The clone operation does not work with read mode so we have to disable it * here */ - if (sql_command_interface->reset_read_only()) { + if (disable_server_read_mode()) { /* purecov: begin inspected */ LogPluginErr(ERROR_LEVEL, ER_GRP_RPL_CLONE_PROCESS_PREPARE_ERROR, "Could not disable the server read only mode for cloning."); @@ -876,7 +874,7 @@ void Remote_clone_handler::gr_clone_debug_point() { declare_plugin_cloning(false); if (error && !m_being_terminated) { - fallback_to_recovery_or_leave(sql_command_interface, critical_error); + fallback_to_recovery_or_leave(critical_error); } delete sql_command_interface; diff --git a/plugin/group_replication/src/plugin_psi.cc b/plugin/group_replication/src/plugin_psi.cc index 148639816c89..83b6766c299d 100644 --- a/plugin/group_replication/src/plugin_psi.cc +++ b/plugin/group_replication/src/plugin_psi.cc @@ -85,7 +85,9 @@ PSI_mutex_key key_GR_LOCK_applier_module_run, key_GR_LOCK_mysql_thread_dispatcher_run, key_GR_LOCK_connection_map, key_GR_LOCK_mysql_thread_handler_run, - key_GR_LOCK_mysql_thread_handler_dispatcher_run; + key_GR_LOCK_mysql_thread_handler_dispatcher_run, + key_GR_LOCK_mysql_thread_handler_read_only_mode_run, + key_GR_LOCK_mysql_thread_handler_read_only_mode_dispatcher_run; PSI_cond_key key_GR_COND_applier_module_run, key_GR_COND_applier_module_suspend, @@ -124,7 +126,10 @@ PSI_cond_key key_GR_COND_applier_module_run, key_GR_COND_mysql_thread_run, key_GR_COND_mysql_thread_dispatcher_run, key_GR_COND_mysql_thread_handler_run, - key_GR_COND_mysql_thread_handler_dispatcher_run; + key_GR_COND_mysql_thread_handler_dispatcher_run, + key_GR_COND_mysql_thread_handler_read_only_mode_run, + key_GR_COND_mysql_thread_handler_read_only_mode_dispatcher_run; + PSI_thread_key key_GR_THD_applier_module_receiver, key_GR_THD_autorejoin, @@ -140,7 +145,8 @@ PSI_thread_key key_GR_THD_applier_module_receiver, key_GR_THD_recovery, key_GR_THD_message_service_handler, key_GR_THD_mysql_thread, - key_GR_THD_mysql_thread_handler; + key_GR_THD_mysql_thread_handler, + key_GR_THD_mysql_thread_handler_read_only_mode; PSI_rwlock_key key_GR_RWLOCK_cert_stable_gtid_set, key_GR_RWLOCK_channel_observation_list, @@ -382,7 +388,13 @@ static PSI_mutex_info all_group_replication_psi_mutex_keys[] = { PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME}, {&key_GR_LOCK_mysql_thread_handler_dispatcher_run, "LOCK_mysql_thread_handler_dispatcher_run", PSI_FLAG_SINGLETON, 0, - PSI_DOCUMENT_ME}}; + PSI_DOCUMENT_ME}, + {&key_GR_LOCK_mysql_thread_handler_read_only_mode_run, + "LOCK_mysql_handler_thread_read_only_mode_run", PSI_FLAG_SINGLETON, 0, + PSI_DOCUMENT_ME}, + {&key_GR_LOCK_mysql_thread_handler_read_only_mode_dispatcher_run, + "LOCK_mysql_thread_handler_read_only_mode_dispatcher_run", + PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME}}; static PSI_cond_info all_group_replication_psi_condition_keys[] = { {&key_GR_COND_applier_module_run, "COND_applier_module_run", @@ -473,7 +485,13 @@ static PSI_cond_info all_group_replication_psi_condition_keys[] = { PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME}, {&key_GR_COND_mysql_thread_handler_dispatcher_run, "COND_mysql_thread_handler_dispatcher_run", PSI_FLAG_SINGLETON, 0, - PSI_DOCUMENT_ME}}; + PSI_DOCUMENT_ME}, + {&key_GR_COND_mysql_thread_handler_read_only_mode_run, + "COND_mysql_thread_handler_read_only_mode_run", PSI_FLAG_SINGLETON, 0, + PSI_DOCUMENT_ME}, + {&key_GR_COND_mysql_thread_handler_read_only_mode_dispatcher_run, + "COND_mysql_thread_handler_read_only_mode_dispatcher_run", + PSI_FLAG_SINGLETON, 0, PSI_DOCUMENT_ME}}; static PSI_thread_info all_group_replication_psi_thread_keys[] = { {&key_GR_THD_applier_module_receiver, "THD_applier_module_receiver", @@ -510,6 +528,9 @@ static PSI_thread_info all_group_replication_psi_thread_keys[] = { {&key_GR_THD_mysql_thread, "THD_mysql_thread", "gr_mysql", PSI_FLAG_SINGLETON | PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME}, {&key_GR_THD_mysql_thread_handler, "THD_mysql_thread_handler", "gr_handler", + PSI_FLAG_SINGLETON | PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME}, + {&key_GR_THD_mysql_thread_handler_read_only_mode, + "THD_mysql_thread_handler_read_only_mode", "gr_handler_rom", PSI_FLAG_SINGLETON | PSI_FLAG_THREAD_SYSTEM, 0, PSI_DOCUMENT_ME}}; static PSI_rwlock_info all_group_replication_psi_rwlock_keys[] = { diff --git a/plugin/group_replication/src/recovery.cc b/plugin/group_replication/src/recovery.cc index fe8e2aba7601..16870290d444 100644 --- a/plugin/group_replication/src/recovery.cc +++ b/plugin/group_replication/src/recovery.cc @@ -163,8 +163,7 @@ void Recovery_module::leave_group_on_recovery_failure() { leave_group_on_failure::mask leave_actions; leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); leave_group_on_failure::leave(leave_actions, ER_GRP_RPL_FATAL_REC_PROCESS, - PSESSION_USE_THREAD, nullptr, - exit_state_action_abort_log_message); + nullptr, exit_state_action_abort_log_message); } /* diff --git a/plugin/group_replication/src/services/message_service/message_service.cc b/plugin/group_replication/src/services/message_service/message_service.cc index c1b22d72442b..fff917ba4a45 100644 --- a/plugin/group_replication/src/services/message_service/message_service.cc +++ b/plugin/group_replication/src/services/message_service/message_service.cc @@ -203,8 +203,8 @@ void Message_service_handler::dispatcher() { leave_actions.set(leave_group_on_failure::STOP_APPLIER, true); leave_actions.set(leave_group_on_failure::HANDLE_EXIT_STATE_ACTION, true); leave_group_on_failure::leave( - leave_actions, ER_GRP_RPL_MESSAGE_SERVICE_FATAL_ERROR, - PSESSION_USE_THREAD, nullptr, exit_state_action_abort_log_message); + leave_actions, ER_GRP_RPL_MESSAGE_SERVICE_FATAL_ERROR, nullptr, + exit_state_action_abort_log_message); } delete service_message; @@ -237,7 +237,7 @@ int Message_service_handler::terminate() { mysql_mutex_lock(&m_message_service_run_lock); m_aborted = true; - m_incoming->abort(); + m_incoming->abort(true); while (m_message_service_thd_state.is_thread_alive()) { struct timespec abstime; diff --git a/plugin/group_replication/src/services/notification/impl/gms_listener_test.cc b/plugin/group_replication/src/services/notification/impl/gms_listener_test.cc index 70f0b4b1a358..62c154fe8f39 100644 --- a/plugin/group_replication/src/services/notification/impl/gms_listener_test.cc +++ b/plugin/group_replication/src/services/notification/impl/gms_listener_test.cc @@ -54,6 +54,7 @@ bool log_notification_to_test_table(std::string msg) { Sql_resultset rset; ulong srv_err = 0; bool was_read_only = false; + bool read_only_mode = false, super_read_only_mode = false; Sql_service_command_interface *sql_cmd = new Sql_service_command_interface(); Sql_service_interface *sql_intf = nullptr; enum_plugin_con_isolation trx_iso = @@ -84,7 +85,8 @@ bool log_notification_to_test_table(std::string msg) { goto end; /* purecov: inspected */ } - if (sql_cmd->get_server_super_read_only()) { + get_read_mode_state(&read_only_mode, &super_read_only_mode); + if (super_read_only_mode) { /* When joining the group the server is in super_read_only. Unset this temporarily. diff --git a/plugin/group_replication/src/services/server_services_references.cc b/plugin/group_replication/src/services/server_services_references.cc new file mode 100644 index 000000000000..1352523f95db --- /dev/null +++ b/plugin/group_replication/src/services/server_services_references.cc @@ -0,0 +1,146 @@ +/* Copyright (c) 2022, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "plugin/group_replication/include/services/server_services_references.h" + +Server_services_references::~Server_services_references() { finalize(); } + +bool Server_services_references::initialize() { + bool error = false; + + registry_service = mysql_plugin_registry_acquire(); + if (nullptr == registry_service) { + error = true; + goto end; + } + + if (registry_service->acquire("mysql_charset", &m_mysql_charset_handle)) { + error = true; + goto end; + } + mysql_charset_service = + reinterpret_cast(m_mysql_charset_handle); + + if (registry_service->acquire("mysql_string_factory", + &m_mysql_string_factory_handle)) { + error = true; + goto end; + } + mysql_string_factory_service = + reinterpret_cast( + m_mysql_string_factory_handle); + + if (registry_service->acquire("mysql_string_charset_converter", + &m_mysql_string_charset_converter_handle)) { + error = true; + goto end; + } + mysql_string_charset_converter_service = + reinterpret_cast( + m_mysql_string_charset_converter_handle); + + if (registry_service->acquire( + "mysql_system_variable_update_string", + &m_mysql_system_variable_update_string_handle)) { + error = true; + goto end; + } + mysql_system_variable_update_string_service = + reinterpret_cast( + m_mysql_system_variable_update_string_handle); + + if (registry_service->acquire( + "mysql_system_variable_update_integer", + &m_mysql_system_variable_update_integer_handle)) { + error = true; + goto end; + } + mysql_system_variable_update_integer_service = + reinterpret_cast( + m_mysql_system_variable_update_integer_handle); + + if (registry_service->acquire("component_sys_variable_register", + &m_component_sys_variable_register_handle)) { + error = true; + goto end; + } + component_sys_variable_register_service = + reinterpret_cast( + m_component_sys_variable_register_handle); + +end: + if (error) { + finalize(); + } + + return error; +} + +bool Server_services_references::finalize() { + int error = 0; + + component_sys_variable_register_service = nullptr; + if (nullptr != m_component_sys_variable_register_handle) { + error |= + registry_service->release(m_component_sys_variable_register_handle); + m_component_sys_variable_register_handle = nullptr; + } + + mysql_system_variable_update_integer_service = nullptr; + if (nullptr != m_mysql_system_variable_update_integer_handle) { + error |= registry_service->release( + m_mysql_system_variable_update_integer_handle); + m_mysql_system_variable_update_integer_handle = nullptr; + } + + mysql_system_variable_update_string_service = nullptr; + if (nullptr != m_mysql_system_variable_update_string_handle) { + error |= + registry_service->release(m_mysql_system_variable_update_string_handle); + m_mysql_system_variable_update_string_handle = nullptr; + } + + mysql_string_charset_converter_service = nullptr; + if (nullptr != m_mysql_string_charset_converter_handle) { + error |= registry_service->release(m_mysql_string_charset_converter_handle); + m_mysql_string_charset_converter_handle = nullptr; + } + + mysql_string_factory_service = nullptr; + if (nullptr != m_mysql_string_factory_handle) { + error |= registry_service->release(m_mysql_string_factory_handle); + m_mysql_string_factory_handle = nullptr; + } + + mysql_charset_service = nullptr; + if (nullptr != m_mysql_charset_handle) { + error |= registry_service->release(m_mysql_charset_handle); + m_mysql_charset_handle = nullptr; + } + + if (nullptr != registry_service) { + error |= mysql_plugin_registry_release(registry_service); + registry_service = nullptr; + } + + return (0 != error); +} diff --git a/plugin/group_replication/src/services/get_system_variable/get_system_variable.cc b/plugin/group_replication/src/services/system_variable/get_system_variable.cc similarity index 52% rename from plugin/group_replication/src/services/get_system_variable/get_system_variable.cc rename to plugin/group_replication/src/services/system_variable/get_system_variable.cc index 03360989b34f..faaa3927540b 100644 --- a/plugin/group_replication/src/services/get_system_variable/get_system_variable.cc +++ b/plugin/group_replication/src/services/system_variable/get_system_variable.cc @@ -20,13 +20,12 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "plugin/group_replication/include/services/get_system_variable/get_system_variable.h" +#include "plugin/group_replication/include/services/system_variable/get_system_variable.h" #include "plugin/group_replication/include/plugin.h" -#include "sql/sql_class.h" - // safeguard due unknown gtid_executed or gtid_purged length -#define GTID_VALUES_FETCH_BUFFER_SIZE 500000 +constexpr size_t GTID_VALUES_FETCH_BUFFER_SIZE{500000}; +constexpr size_t BOOL_VALUES_FETCH_BUFFER_SIZE{4}; int Get_system_variable_parameters::get_error() { return m_error; } @@ -37,20 +36,7 @@ Get_system_variable_parameters::get_service() { return m_service; } -Get_system_variable::Get_system_variable() { - get_plugin_registry()->acquire( - "component_sys_variable_register", - &component_sys_variable_register_service_handler); -} - -Get_system_variable::~Get_system_variable() { - if (component_sys_variable_register_service_handler != nullptr) { - get_plugin_registry()->release( - component_sys_variable_register_service_handler); - } -} - -int Get_system_variable::get_server_gtid_executed(std::string >id_executed) { +int Get_system_variable::get_global_gtid_executed(std::string >id_executed) { int error = 1; if (nullptr == mysql_thread_handler) { @@ -72,7 +58,7 @@ int Get_system_variable::get_server_gtid_executed(std::string >id_executed) { return error; } -int Get_system_variable::get_server_gtid_purged(std::string >id_purged) { +int Get_system_variable::get_global_gtid_purged(std::string >id_purged) { int error = 1; if (nullptr == mysql_thread_handler) { @@ -94,17 +80,81 @@ int Get_system_variable::get_server_gtid_purged(std::string >id_purged) { return error; } +int Get_system_variable::get_global_read_only(bool &value) { + int error = 1; + + if (nullptr == mysql_thread_handler_read_only_mode) { + return 1; + } + + Get_system_variable_parameters *parameter = + new Get_system_variable_parameters( + Get_system_variable_parameters::VAR_READ_ONLY); + Mysql_thread_task *task = new Mysql_thread_task(this, parameter); + error = mysql_thread_handler_read_only_mode->trigger(task); + error |= parameter->get_error(); + + if (!error) { + value = string_to_bool(parameter->m_result); + } + + delete task; + return error; +} + +int Get_system_variable::get_global_super_read_only(bool &value) { + int error = 1; + + if (nullptr == mysql_thread_handler_read_only_mode) { + return 1; + } + + Get_system_variable_parameters *parameter = + new Get_system_variable_parameters( + Get_system_variable_parameters::VAR_SUPER_READ_ONLY); + Mysql_thread_task *task = new Mysql_thread_task(this, parameter); + error = mysql_thread_handler_read_only_mode->trigger(task); + error |= parameter->get_error(); + + if (!error) { + value = string_to_bool(parameter->m_result); + } + + delete task; + return error; +} + +bool Get_system_variable::string_to_bool(const std::string &value) { + if (value == "ON") { + return true; + } + assert(value == "OFF"); + return false; +} + void Get_system_variable::run(Mysql_thread_body_parameters *parameters) { Get_system_variable_parameters *param = (Get_system_variable_parameters *)parameters; switch (param->get_service()) { case Get_system_variable_parameters::VAR_GTID_EXECUTED: param->set_error(internal_get_system_variable( - std::string("gtid_executed"), param->m_result)); + std::string("gtid_executed"), param->m_result, + GTID_VALUES_FETCH_BUFFER_SIZE)); break; case Get_system_variable_parameters::VAR_GTID_PURGED: - param->set_error(internal_get_system_variable(std::string("gtid_purged"), - param->m_result)); + param->set_error(internal_get_system_variable( + std::string("gtid_purged"), param->m_result, + GTID_VALUES_FETCH_BUFFER_SIZE)); + break; + case Get_system_variable_parameters::VAR_READ_ONLY: + param->set_error(internal_get_system_variable( + std::string("read_only"), param->m_result, + BOOL_VALUES_FETCH_BUFFER_SIZE)); + break; + case Get_system_variable_parameters::VAR_SUPER_READ_ONLY: + param->set_error(internal_get_system_variable( + std::string("super_read_only"), param->m_result, + BOOL_VALUES_FETCH_BUFFER_SIZE)); break; default: param->set_error(1); @@ -112,32 +162,28 @@ void Get_system_variable::run(Mysql_thread_body_parameters *parameters) { } int Get_system_variable::internal_get_system_variable(std::string variable, - std::string &value) { - SERVICE_TYPE(component_sys_variable_register) - *component_sys_variable_register_service{nullptr}; + std::string &value, + size_t value_max_length) { char *var_value = nullptr; - size_t var_len = GTID_VALUES_FETCH_BUFFER_SIZE; - bool error = false; + size_t var_len = value_max_length; + int error = false; - if (nullptr == component_sys_variable_register_service_handler) { - error = true; /* purecov: inspected */ - goto end; /* purecov: inspected */ + if (nullptr == server_services_references_module + ->component_sys_variable_register_service) { + error = 1; /* purecov: inspected */ + goto end; /* purecov: inspected */ } - component_sys_variable_register_service = - reinterpret_cast( - component_sys_variable_register_service_handler); - if ((var_value = new (std::nothrow) char[var_len + 1]) == nullptr) { - error = true; /* purecov: inspected */ - goto end; /* purecov: inspected */ + error = 1; /* purecov: inspected */ + goto end; /* purecov: inspected */ } - if (component_sys_variable_register_service->get_variable( - "mysql_server", variable.c_str(), - reinterpret_cast(&var_value), &var_len)) { - error = true; /* purecov: inspected */ - goto end; /* purecov: inspected */ + if (server_services_references_module->component_sys_variable_register_service + ->get_variable("mysql_server", variable.c_str(), + reinterpret_cast(&var_value), &var_len)) { + error = 1; /* purecov: inspected */ + goto end; /* purecov: inspected */ } value.assign(var_value, var_len); diff --git a/plugin/group_replication/src/services/system_variable/set_system_variable.cc b/plugin/group_replication/src/services/system_variable/set_system_variable.cc new file mode 100644 index 000000000000..7c8e14a07851 --- /dev/null +++ b/plugin/group_replication/src/services/system_variable/set_system_variable.cc @@ -0,0 +1,327 @@ +/* Copyright (c) 2022, Oracle and/or its affiliates. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2.0, + as published by the Free Software Foundation. + + This program is also distributed with certain software (including + but not limited to OpenSSL) that is licensed under separate terms, + as designated in a particular file or component or in included license + documentation. The authors of MySQL hereby grant you an additional + permission to link the program and your derivative works with the + separately licensed software that they have included with MySQL. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License, version 2.0, for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ + +#include "plugin/group_replication/include/services/system_variable/set_system_variable.h" +#include "plugin/group_replication/include/plugin.h" + +constexpr unsigned long long WAIT_LOCK_TIMEOUT{5}; +constexpr unsigned long long READ_ONLY_WAIT_LOCK_TIMEOUT{120}; + +int Set_system_variable_parameters::get_error() { return m_error; } + +void Set_system_variable_parameters::set_error(int error) { m_error = error; } + +Set_system_variable_parameters::System_variable +Set_system_variable_parameters::get_variable() { + return m_variable; +} + +int Set_system_variable::set_global_read_only(bool value) { + int error = 1; + + if (nullptr == mysql_thread_handler_read_only_mode) { + return 1; + } + + std::string parameter_value{"ON"}; + if (!value) { + parameter_value.assign("OFF"); + } + + Set_system_variable_parameters *parameter = + new Set_system_variable_parameters( + Set_system_variable_parameters::VAR_READ_ONLY, parameter_value, + "GLOBAL"); + Mysql_thread_task *task = new Mysql_thread_task(this, parameter); + /* + Since enable `read_only` and `super_read_only` are blocking + operations, we use the dedicated `mysql_thread_handler_read_only_mode` + to this operation. + If we did use `mysql_thread_handler` that would block all other + other operations until read modes operations complete. + */ + error = mysql_thread_handler_read_only_mode->trigger(task); + error |= parameter->get_error(); + + delete task; + return error; +} + +int Set_system_variable::set_global_super_read_only(bool value) { + int error = 1; + + if (nullptr == mysql_thread_handler_read_only_mode) { + return 1; + } + + std::string parameter_value{"ON"}; + if (!value) { + parameter_value.assign("OFF"); + } + + Set_system_variable_parameters *parameter = + new Set_system_variable_parameters( + Set_system_variable_parameters::VAR_SUPER_READ_ONLY, parameter_value, + "GLOBAL"); + Mysql_thread_task *task = new Mysql_thread_task(this, parameter); + /* + Since enable `read_only` and `super_read_only` are blocking + operations, we use the dedicated `mysql_thread_handler_read_only_mode` + to this operation. + If we did use `mysql_thread_handler` that would block all other + other operations until read modes operations complete. + */ + error = mysql_thread_handler_read_only_mode->trigger(task); + error |= parameter->get_error(); + + delete task; + return error; +} + +int Set_system_variable::set_global_offline_mode(bool value) { + int error = 1; + + if (nullptr == mysql_thread_handler) { + return 1; + } + + std::string parameter_value{"ON"}; + if (!value) { + parameter_value.assign("OFF"); + } + + Set_system_variable_parameters *parameter = + new Set_system_variable_parameters( + Set_system_variable_parameters::VAR_OFFLINE_MODE, parameter_value, + "GLOBAL"); + Mysql_thread_task *task = new Mysql_thread_task(this, parameter); + error = mysql_thread_handler->trigger(task); + error |= parameter->get_error(); + + delete task; + return error; +} + +int Set_system_variable::set_persist_only_group_replication_single_primary_mode( + bool value) { + int error = 1; + + if (nullptr == mysql_thread_handler) { + return 1; + } + + std::string parameter_value{"ON"}; + if (!value) { + parameter_value.assign("OFF"); + } + + Set_system_variable_parameters *parameter = + new Set_system_variable_parameters( + Set_system_variable_parameters:: + VAR_GROUP_REPLICATION_SINGLE_PRIMARY_MODE, + parameter_value, "PERSIST_ONLY"); + Mysql_thread_task *task = new Mysql_thread_task(this, parameter); + error = mysql_thread_handler->trigger(task); + error |= parameter->get_error(); + + delete task; + return error; +} + +int Set_system_variable:: + set_persist_only_group_replication_enforce_update_everywhere_checks( + bool value) { + int error = 1; + + if (nullptr == mysql_thread_handler) { + return 1; + } + + std::string parameter_value{"ON"}; + if (!value) { + parameter_value.assign("OFF"); + } + + Set_system_variable_parameters *parameter = + new Set_system_variable_parameters( + Set_system_variable_parameters:: + VAR_GROUP_REPLICATION_ENFORCE_UPDATE_EVERYWHERE_CHECKS, + parameter_value, "PERSIST_ONLY"); + Mysql_thread_task *task = new Mysql_thread_task(this, parameter); + error = mysql_thread_handler->trigger(task); + error |= parameter->get_error(); + + delete task; + return error; +} + +void Set_system_variable::run(Mysql_thread_body_parameters *parameters) { + Set_system_variable_parameters *param = + (Set_system_variable_parameters *)parameters; + switch (param->get_variable()) { + case Set_system_variable_parameters::VAR_READ_ONLY: + param->set_error(internal_set_system_variable( + std::string("read_only"), param->m_value, param->m_type, + READ_ONLY_WAIT_LOCK_TIMEOUT)); + break; + case Set_system_variable_parameters::VAR_SUPER_READ_ONLY: +#ifndef NDEBUG + DBUG_EXECUTE_IF("group_replication_skip_read_mode", { + if (param->m_value == "ON") { + param->set_error(0); + return; + } + }); + DBUG_EXECUTE_IF("group_replication_read_mode_error", { + if (param->m_value == "ON") { + param->set_error(1); + return; + } + }); +#endif + param->set_error(internal_set_system_variable( + std::string("super_read_only"), param->m_value, param->m_type, + READ_ONLY_WAIT_LOCK_TIMEOUT)); + break; + case Set_system_variable_parameters::VAR_OFFLINE_MODE: + param->set_error(internal_set_system_variable( + std::string("offline_mode"), param->m_value, param->m_type, + WAIT_LOCK_TIMEOUT)); + break; + case Set_system_variable_parameters:: + VAR_GROUP_REPLICATION_SINGLE_PRIMARY_MODE: + param->set_error(internal_set_system_variable( + std::string("group_replication_single_primary_mode"), param->m_value, + param->m_type, WAIT_LOCK_TIMEOUT)); + break; + case Set_system_variable_parameters:: + VAR_GROUP_REPLICATION_ENFORCE_UPDATE_EVERYWHERE_CHECKS: + param->set_error(internal_set_system_variable( + std::string("group_replication_enforce_update_everywhere_checks"), + param->m_value, param->m_type, WAIT_LOCK_TIMEOUT)); + break; + default: + param->set_error(1); + } +} + +int Set_system_variable::internal_set_system_variable( + const std::string &variable, const std::string &value, + const std::string &type, unsigned long long lock_wait_timeout) { + int error = 0; + CHARSET_INFO_h charset_utf8{nullptr}; + my_h_string variable_name{nullptr}; + my_h_string variable_value{nullptr}; + const std::string lock_wait_timeout_name{"lock_wait_timeout"}; + my_h_string lock_wait_timeout_variable_name{nullptr}; + +#ifndef NDEBUG + DBUG_EXECUTE_IF("group_replication_var_persist_error", { + if (type == "PERSIST_ONLY") { + return 1; + } + }); +#endif + + if (nullptr == server_services_references_module->mysql_charset_service || + nullptr == + server_services_references_module->mysql_string_factory_service || + nullptr == server_services_references_module + ->mysql_string_charset_converter_service || + nullptr == server_services_references_module + ->mysql_system_variable_update_integer_service || + nullptr == server_services_references_module + ->mysql_system_variable_update_string_service) { + error = 1; + goto end; + } + + if (server_services_references_module->mysql_string_factory_service->create( + &lock_wait_timeout_variable_name)) { + error = 1; + goto end; + } + if (server_services_references_module->mysql_string_factory_service->create( + &variable_name)) { + error = 1; + goto end; + } + if (server_services_references_module->mysql_string_factory_service->create( + &variable_value)) { + error = 1; + goto end; + } + + charset_utf8 = + server_services_references_module->mysql_charset_service->get_utf8mb4(); + if (server_services_references_module->mysql_string_charset_converter_service + ->convert_from_buffer( + lock_wait_timeout_variable_name, lock_wait_timeout_name.c_str(), + lock_wait_timeout_name.length(), charset_utf8)) { + error = 1; + goto end; + } + if (server_services_references_module->mysql_string_charset_converter_service + ->convert_from_buffer(variable_name, variable.c_str(), + variable.length(), charset_utf8)) { + error = 1; + goto end; + } + if (server_services_references_module->mysql_string_charset_converter_service + ->convert_from_buffer(variable_value, value.c_str(), value.length(), + charset_utf8)) { + error = 1; + goto end; + } + + if (server_services_references_module + ->mysql_system_variable_update_integer_service->set_unsigned( + current_thd, "SESSION", nullptr, lock_wait_timeout_variable_name, + lock_wait_timeout)) { + error = 1; + goto end; + } + + if (server_services_references_module + ->mysql_system_variable_update_string_service->set( + current_thd, type.c_str(), nullptr, variable_name, + variable_value)) { + error = 1; + goto end; + } + +end: + if (nullptr != lock_wait_timeout_variable_name) { + server_services_references_module->mysql_string_factory_service->destroy( + lock_wait_timeout_variable_name); + } + if (nullptr != variable_name) { + server_services_references_module->mysql_string_factory_service->destroy( + variable_name); + } + if (nullptr != variable_value) { + server_services_references_module->mysql_string_factory_service->destroy( + variable_value); + } + + return error; +} diff --git a/plugin/group_replication/src/sql_service/sql_service_command.cc b/plugin/group_replication/src/sql_service/sql_service_command.cc index 870ce78d54a0..ee58d0e6353f 100644 --- a/plugin/group_replication/src/sql_service/sql_service_command.cc +++ b/plugin/group_replication/src/sql_service/sql_service_command.cc @@ -128,128 +128,6 @@ int Sql_service_command_interface::set_interface_user(const char *user) { return m_server_interface->set_session_user(user); } -long Sql_service_command_interface::set_super_read_only() { - DBUG_TRACE; - long error = 0; - - if (connection_thread_isolation != PSESSION_DEDICATED_THREAD) { - error = - sql_service_commands.internal_set_super_read_only(m_server_interface); - } else { - m_plugin_session_thread->queue_new_method_for_application( - &Sql_service_commands::internal_set_super_read_only); - error = m_plugin_session_thread->wait_for_method_execution(); - } - - return error; -} - -long Sql_service_commands::internal_set_super_read_only( - Sql_service_interface *sql_interface, void *) { - DBUG_TRACE; - - // These debug branches are repeated here due to THD support variations on - // invocation - DBUG_EXECUTE_IF("group_replication_read_mode_error", { return 1; }); - DBUG_EXECUTE_IF("group_replication_skip_read_mode", { return 0; }); - - assert(sql_interface != nullptr); - - Sql_resultset rset; - long srv_err = sql_interface->execute_query("SET GLOBAL super_read_only= 1;"); - LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_SUPER_READ_ON); -#ifndef NDEBUG - if (srv_err == 0) { - long err; - err = - sql_interface->execute_query("SELECT @@GLOBAL.super_read_only", &rset); - - assert(err || (!err && rset.get_rows() > 0 && rset.getLong(0) == 1)); - } -#endif - - return srv_err; -} - -long Sql_service_command_interface::reset_super_read_only() { - DBUG_TRACE; - long error = 0; - - if (connection_thread_isolation != PSESSION_DEDICATED_THREAD) { - error = - sql_service_commands.internal_reset_super_read_only(m_server_interface); - } else { - m_plugin_session_thread->queue_new_method_for_application( - &Sql_service_commands::internal_reset_super_read_only); - error = m_plugin_session_thread->wait_for_method_execution(); - } - - return error; -} - -long Sql_service_commands::internal_reset_super_read_only( - Sql_service_interface *sql_interface, void *) { - DBUG_TRACE; - - assert(sql_interface != nullptr); - - Sql_resultset rset; - - const char *query = "SET GLOBAL super_read_only= 0"; - long srv_err = sql_interface->execute_query(query); - LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_SUPER_READ_OFF); -#ifndef NDEBUG - if (srv_err == 0) { - long err; - query = "SELECT @@GLOBAL.super_read_only"; - err = sql_interface->execute_query(query, &rset); - - assert(!err && rset.get_rows() > 0 && rset.getLong(0) == 0); - } -#endif - return srv_err; -} - -long Sql_service_command_interface::reset_read_only() { - DBUG_TRACE; - long error = 0; - - if (connection_thread_isolation != PSESSION_DEDICATED_THREAD) { - error = sql_service_commands.internal_reset_read_only(m_server_interface); - } else { - m_plugin_session_thread->queue_new_method_for_application( - &Sql_service_commands::internal_reset_read_only); - error = m_plugin_session_thread->wait_for_method_execution(); - } - - return error; -} - -long Sql_service_commands::internal_reset_read_only( - Sql_service_interface *sql_interface, void *) { - DBUG_TRACE; - - assert(sql_interface != nullptr); - - Sql_resultset rset; - - const char *query = "SET GLOBAL read_only= 0"; - long srv_err = sql_interface->execute_query(query); - LogPluginErr(SYSTEM_LEVEL, ER_GRP_RPL_SUPER_READ_OFF); - -#ifndef NDEBUG - if (srv_err == 0) { - long err; - query = "SELECT @@GLOBAL.read_only"; - err = sql_interface->execute_query(query, &rset); - - assert(!err && rset.get_rows() > 0 && rset.getLong(0) == 0); - } -#endif - - return srv_err; -} - long Sql_service_commands::internal_kill_session( Sql_service_interface *sql_interface, void *session_id) { DBUG_TRACE; @@ -291,73 +169,6 @@ long Sql_service_command_interface::kill_session(unsigned long session_id) { return error; } -long Sql_service_command_interface::get_server_super_read_only() { - DBUG_TRACE; - long error = 0; - - if (connection_thread_isolation != PSESSION_DEDICATED_THREAD) { - error = sql_service_commands.internal_get_server_super_read_only( - m_server_interface); - } else { - m_plugin_session_thread->queue_new_method_for_application( - &Sql_service_commands::internal_get_server_super_read_only); - error = m_plugin_session_thread->wait_for_method_execution(); - } - - return error; -} - -long Sql_service_commands::internal_get_server_super_read_only( - Sql_service_interface *sql_interface, void *) { - DBUG_TRACE; - - assert(sql_interface != nullptr); - - Sql_resultset rset; - long server_super_read_only = -1; - - long srv_error = - sql_interface->execute_query("SELECT @@GLOBAL.super_read_only", &rset); - if (srv_error == 0 && rset.get_rows() > 0) { - server_super_read_only = rset.getLong(0); - } - - return server_super_read_only; -} - -long Sql_service_command_interface::get_server_read_only() { - DBUG_TRACE; - long error = 0; - - if (connection_thread_isolation != PSESSION_DEDICATED_THREAD) { - error = - sql_service_commands.internal_get_server_read_only(m_server_interface); - } else { - m_plugin_session_thread->queue_new_method_for_application( - &Sql_service_commands::internal_get_server_read_only); - error = m_plugin_session_thread->wait_for_method_execution(); - } - - return error; -} - -long Sql_service_commands::internal_get_server_read_only( - Sql_service_interface *sql_interface, void *) { - DBUG_TRACE; - - assert(sql_interface != nullptr); - - Sql_resultset rset; - longlong server_read_only = -1; - long srv_error = - sql_interface->execute_query("SELECT @@GLOBAL.read_only", &rset); - if (srv_error == 0 && rset.get_rows()) { - server_read_only = rset.getLong(0); - } - - return server_read_only; -} - long Sql_service_command_interface::wait_for_server_gtid_executed( std::string >id_executed, int timeout) { DBUG_TRACE; @@ -407,53 +218,6 @@ long Sql_service_commands::internal_wait_for_server_gtid_executed( return 0; } -long Sql_service_commands::internal_set_persist_only_variable( - Sql_service_interface *sql_interface, void *var_args) { - DBUG_TRACE; - - std::pair *variable_args = - (std::pair *)var_args; - - assert(sql_interface != nullptr); - - std::string query = "SET PERSIST_ONLY "; - query.append(variable_args->first); - query.append(" = "); - query.append(variable_args->second); - - long srv_err = sql_interface->execute_query(query); - if (srv_err) { - /* purecov: begin inspected */ - LogPluginErr(ERROR_LEVEL, ER_GRP_RPL_INTERNAL_QUERY, query.c_str(), - srv_err); - return 1; - /* purecov: end */ - } - return 0; - - return 0; -} - -long Sql_service_command_interface::set_persist_only_variable( - std::string &variable, std::string &value) { - DBUG_TRACE; - long error = 0; - - std::pair variable_args(variable, value); - - if (connection_thread_isolation != PSESSION_DEDICATED_THREAD) { - error = sql_service_commands.internal_set_persist_only_variable( - m_server_interface, (void *)&variable_args); - } else { - m_plugin_session_thread->set_return_pointer((void *)&variable_args); - m_plugin_session_thread->queue_new_method_for_application( - &Sql_service_commands::internal_set_persist_only_variable); - error = m_plugin_session_thread->wait_for_method_execution(); - } - - return error; -} - long Sql_service_command_interface::clone_server( std::string &host, std::string &port, std::string &user, std::string &pass, bool use_ssl, std::string &error_msg) { @@ -667,30 +431,6 @@ long Sql_service_commands::internal_execute_conditional_query( return 0; } -long Sql_service_command_interface::set_offline_mode() { - DBUG_TRACE; - long error = 0; - - if (connection_thread_isolation != PSESSION_DEDICATED_THREAD) { - error = sql_service_commands.internal_set_offline_mode(m_server_interface); - } else { - m_plugin_session_thread->queue_new_method_for_application( - &Sql_service_commands::internal_set_offline_mode); - error = m_plugin_session_thread->wait_for_method_execution(); - } - - return error; -} - -long Sql_service_commands::internal_set_offline_mode( - Sql_service_interface *sql_interface, void *) { - DBUG_TRACE; - - long srv_err = sql_interface->execute_query("SET GLOBAL offline_mode= 1;"); - - return srv_err; -} - Session_plugin_thread::Session_plugin_thread( Sql_service_commands *command_interface) : command_interface(command_interface), diff --git a/plugin/group_replication/src/thread/mysql_thread.cc b/plugin/group_replication/src/thread/mysql_thread.cc index 9d6199ddebef..73c21e15adb9 100644 --- a/plugin/group_replication/src/thread/mysql_thread.cc +++ b/plugin/group_replication/src/thread/mysql_thread.cc @@ -23,6 +23,7 @@ #include "plugin/group_replication/include/thread/mysql_thread.h" #include "my_dbug.h" #include "mysql/components/services/log_builtins.h" +#include "plugin/group_replication/include/plugin_constants.h" #include "plugin/group_replication/include/plugin_psi.h" #include "sql/sql_class.h" @@ -32,7 +33,12 @@ static void *launch_thread(void *arg) { return nullptr; } -void Mysql_thread_task::execute() { m_body->run(m_parameters); } +void Mysql_thread_task::execute() { + m_body->run(m_parameters); + m_finished = true; +} + +bool Mysql_thread_task::is_finished() { return m_finished; } Mysql_thread::Mysql_thread(PSI_thread_key thread_key, PSI_mutex_key run_mutex_key, @@ -45,8 +51,7 @@ Mysql_thread::Mysql_thread(PSI_thread_key thread_key, m_dispatcher_mutex_key(dispatcher_mutex_key), m_dispatcher_cond_key(dispatcher_cond_key), m_state(), - m_aborted(false), - m_trigger_run_complete(false) { + m_aborted(false) { mysql_mutex_init(m_mutex_key, &m_run_lock, MY_MUTEX_INIT_FAST); mysql_cond_init(m_cond_key, &m_run_cond); mysql_mutex_init(m_dispatcher_mutex_key, &m_dispatcher_lock, @@ -67,7 +72,6 @@ Mysql_thread::~Mysql_thread() { /* purecov: begin inspected */ Mysql_thread_task *task = nullptr; m_trigger_queue->pop(&task); - delete task; /* purecov: end */ } } @@ -87,13 +91,27 @@ bool Mysql_thread::initialize() { m_aborted = false; - if ((mysql_thread_create(m_thread_key, &m_pthd, get_connection_attrib(), - launch_thread, (void *)this))) { + /* + Ensure that the thread is joinable so that we can wait until it + is terminated on the `terminate()` method. + */ + my_thread_attr_t thread_attr; + my_thread_attr_init(&thread_attr); + my_thread_attr_setdetachstate(&thread_attr, MY_THREAD_CREATE_JOINABLE); +#ifndef _WIN32 + pthread_attr_setscope(&thread_attr, PTHREAD_SCOPE_SYSTEM); +#endif + + bool error = mysql_thread_create(m_thread_key, &m_pthd, &thread_attr, + launch_thread, (void *)this); + my_thread_attr_destroy(&thread_attr); + if (error) { /* purecov: begin inspected */ mysql_mutex_unlock(&m_run_lock); return true; /* purecov: end */ } + m_state.set_created(); while (m_state.is_alive_not_running()) { @@ -119,7 +137,11 @@ bool Mysql_thread::terminate() { } m_aborted = true; - m_trigger_queue->abort(); + /* + The memory of each queue element is released by the + Mysql_thread::trigger() caller. + */ + m_trigger_queue->abort(false); while (m_state.is_thread_alive()) { DBUG_PRINT("sleep", ("Waiting for Mysql_thread to stop")); @@ -129,10 +151,8 @@ bool Mysql_thread::terminate() { } mysql_mutex_unlock(&m_run_lock); - mysql_mutex_lock(&m_dispatcher_lock); - m_trigger_run_complete = true; - mysql_cond_broadcast(&m_dispatcher_cond); - mysql_mutex_unlock(&m_dispatcher_lock); + /* Wait until the thread is terminated. */ + my_thread_join(&m_pthd, nullptr); return false; } @@ -146,8 +166,9 @@ void Mysql_thread::dispatcher() { thd->set_new_thread_id(); thd->thread_stack = (char *)&thd; thd->store_globals(); + thd->security_context()->assign_user(STRING_WITH_LEN(GROUPREPL_USER)); // Needed to start replication threads - thd->security_context()->skip_grants(); + thd->security_context()->skip_grants("", ""); global_thd_manager_add_thd(thd); m_thd = thd; @@ -161,18 +182,26 @@ void Mysql_thread::dispatcher() { break; } - DBUG_EXECUTE_IF("group_replication_mysql_thread_dispatcher_before_pop", { - Mysql_thread_task *t = nullptr; - m_trigger_queue->front(&t); - const char act[] = - "now signal " - "signal.group_replication_mysql_thread_dispatcher_before_pop_" - "reached " - "wait_for " - "signal.group_replication_mysql_thread_dispatcher_before_pop_" - "continue"; - assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act))); - }); +#ifndef NDEBUG + /* + Restrict the debug sync point to the mysql_thread used for + member actions. + */ + if (m_thread_key == key_GR_THD_mysql_thread) { + DBUG_EXECUTE_IF("group_replication_mysql_thread_dispatcher_before_pop", { + Mysql_thread_task *t = nullptr; + m_trigger_queue->front(&t); + const char act[] = + "now signal " + "signal.group_replication_mysql_thread_dispatcher_before_pop_" + "reached " + "wait_for " + "signal.group_replication_mysql_thread_dispatcher_before_pop_" + "continue"; + assert(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act))); + }); + } +#endif Mysql_thread_task *task = nullptr; if (m_trigger_queue->pop(&task)) { @@ -182,18 +211,20 @@ void Mysql_thread::dispatcher() { task->execute(); mysql_mutex_lock(&m_dispatcher_lock); - m_trigger_run_complete = true; mysql_cond_broadcast(&m_dispatcher_cond); mysql_mutex_unlock(&m_dispatcher_lock); } mysql_mutex_lock(&m_run_lock); m_aborted = true; - m_trigger_queue->abort(); + /* + The memory of each queue element is released by the + Mysql_thread::trigger() caller. + */ + m_trigger_queue->abort(false); mysql_mutex_unlock(&m_run_lock); mysql_mutex_lock(&m_dispatcher_lock); - m_trigger_run_complete = true; mysql_cond_broadcast(&m_dispatcher_cond); mysql_mutex_unlock(&m_dispatcher_lock); @@ -222,8 +253,7 @@ bool Mysql_thread::trigger(Mysql_thread_task *task) { /* purecov: end */ } - m_trigger_run_complete = false; - while (!m_trigger_run_complete) { + while (!m_aborted && !task->is_finished()) { DBUG_PRINT("sleep", ("Waiting for Mysql_thread to complete a trigger run")); struct timespec abstime; set_timespec(&abstime, 1); diff --git a/plugin/group_replication/src/udf/udf_utils.cc b/plugin/group_replication/src/udf/udf_utils.cc index ce36b256e6ca..c5828b1619a8 100644 --- a/plugin/group_replication/src/udf/udf_utils.cc +++ b/plugin/group_replication/src/udf/udf_utils.cc @@ -106,14 +106,7 @@ void log_privilege_status_result(privilege_result const &privilege, std::pair check_super_read_only_is_disabled() { bool read_only_mode = false, super_read_only_mode = false; - - Sql_service_command_interface *sql_command_interface = - new Sql_service_command_interface(); - bool error = sql_command_interface->establish_session_connection( - PSESSION_USE_THREAD, GROUPREPL_USER, get_plugin_pointer()) || - get_read_mode_state(sql_command_interface, &read_only_mode, - &super_read_only_mode); - delete sql_command_interface; + bool error = get_read_mode_state(&read_only_mode, &super_read_only_mode); if (error) { /* purecov: begin inspected */ diff --git a/share/messages_to_error_log.txt b/share/messages_to_error_log.txt index 8791b9c6bcd7..734f589a1b18 100644 --- a/share/messages_to_error_log.txt +++ b/share/messages_to_error_log.txt @@ -4937,7 +4937,7 @@ ER_GRP_RPL_UNABLE_TO_ENSURE_EXECUTION_REC ER_GRP_RPL_WHILE_SENDING_MSG_REC eng "Error while sending message in the group replication incremental recovery process." -ER_GRP_RPL_READ_UNABLE_FOR_SUPER_READ_ONLY +OBSOLETE_ER_GRP_RPL_READ_UNABLE_FOR_SUPER_READ_ONLY eng "Unable to read the server value for the super_read_only variable." ER_GRP_RPL_READ_UNABLE_FOR_READ_ONLY_SUPER_READ_ONLY diff --git a/sql/server_component/mysql_system_variable_update_imp.cc b/sql/server_component/mysql_system_variable_update_imp.cc index 9f03d7c1e657..7959ba8471b0 100644 --- a/sql/server_component/mysql_system_variable_update_imp.cc +++ b/sql/server_component/mysql_system_variable_update_imp.cc @@ -92,20 +92,26 @@ static enum_var_type sysvar_type(const char *type_name) { the temporary THD, if we create one. @param var_type: Reference to output variable type enumeration (avoids parsing type multiple times). + @param override_thd_lock_wait_timeout: Reference to output variable, override + the value of thd lock_wait_timeout @retval FALSE: Success @retval TRUE: Failure, error set */ static bool prepare_thread_and_validate( MYSQL_THD thd_handle, const char *variable_type, my_h_string variable_name, THD *&thd, std::unique_ptr &thd_auto, - enum_var_type &var_type) { + enum_var_type &var_type, bool &override_thd_lock_wait_timeout) { var_type = sysvar_type(variable_type); if (var_type == OPT_DEFAULT) var_type = OPT_GLOBAL; /* Use either the THD provided or create a temporary one */ - if (thd_handle) + if (thd_handle) { + /* + If a THD is being reused, we will use its lock_wait_timeout value. + */ + override_thd_lock_wait_timeout = false; thd = static_cast(thd_handle); - else { + } else { /* A session variable update for a temporary THD has no effect and is not supported. */ if (var_type == OPT_SESSION) { @@ -113,6 +119,10 @@ static bool prepare_thread_and_validate( LogErr(ERROR_LEVEL, ER_TMP_SESSION_FOR_VAR, name->c_ptr_safe()); return true; } + /* + lock_wait_timeout value will be override on a temporary THD. + */ + override_thd_lock_wait_timeout = true; thd_auto.reset(new Storing_auto_THD()); thd = thd_auto->get_THD(); } @@ -131,15 +141,18 @@ static bool prepare_thread_and_validate( @param variable_value: Pointer to Item object storing the value of the correct type (matching the type stored in system variable). If NULL, then the system variable default will be set. + @param override_thd_lock_wait_timeout: override the value of thd + lock_wait_timeout @retval FALSE: Success @retval TRUE: Failure, error set */ -static bool common_system_variable_update_set(THD *thd, enum_var_type var_type, - my_h_string variable_base, - my_h_string variable_name, - Item *variable_value) { +static bool common_system_variable_update_set( + THD *thd, enum_var_type var_type, my_h_string variable_base, + my_h_string variable_name, Item *variable_value, + bool override_thd_lock_wait_timeout) { bool result{false}; constexpr ulong timeout{5}; // temporary lock wait timeout, in seconds + std::unique_ptr lock_wait_timeout; String *base = reinterpret_cast(variable_base); String *name = reinterpret_cast(variable_name); @@ -157,7 +170,9 @@ static bool common_system_variable_update_set(THD *thd, enum_var_type var_type, locks during the update. Should that happen, we don't want to be holding LOCK_system_variables_hash. */ - Lock_wait_timeout lock_wait_timeout(thd, timeout); + if (override_thd_lock_wait_timeout) { + lock_wait_timeout.reset(new Lock_wait_timeout(thd, timeout)); + } System_variable_tracker var_tracker = System_variable_tracker::make_tracker(prefix, suffix); @@ -211,15 +226,19 @@ DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_string, enum_var_type var_type; if (variable_value == nullptr) return true; + + bool override_thd_lock_wait_timeout = true; if (prepare_thread_and_validate(hthd, variable_type, variable_name, thd, - thd_auto, var_type)) + thd_auto, var_type, + override_thd_lock_wait_timeout)) return true; String *value = reinterpret_cast(variable_value); Item *value_str = new (thd->mem_root) Item_string(value->c_ptr_safe(), value->length(), value->charset()); return common_system_variable_update_set(thd, var_type, variable_base, - variable_name, value_str); + variable_name, value_str, + override_thd_lock_wait_timeout); } catch (...) { mysql_components_handle_std_exception(__func__); } @@ -260,14 +279,17 @@ DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_signed, std::unique_ptr thd_auto; enum_var_type var_type; + bool override_thd_lock_wait_timeout = true; if (prepare_thread_and_validate(hthd, variable_type, variable_name, thd, - thd_auto, var_type)) + thd_auto, var_type, + override_thd_lock_wait_timeout)) return true; Item *value_num = new (thd->mem_root) Item_int(variable_value); return common_system_variable_update_set(thd, var_type, variable_base, - variable_name, value_num); + variable_name, value_num, + override_thd_lock_wait_timeout); } catch (...) { mysql_components_handle_std_exception(__func__); } @@ -301,14 +323,17 @@ DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_unsigned, std::unique_ptr thd_auto; enum_var_type var_type; + bool override_thd_lock_wait_timeout = true; if (prepare_thread_and_validate(hthd, variable_type, variable_name, thd, - thd_auto, var_type)) + thd_auto, var_type, + override_thd_lock_wait_timeout)) return true; Item *value_num = new (thd->mem_root) Item_uint(variable_value); return common_system_variable_update_set(thd, var_type, variable_base, - variable_name, value_num); + variable_name, value_num, + override_thd_lock_wait_timeout); } catch (...) { mysql_components_handle_std_exception(__func__); } @@ -340,12 +365,15 @@ DEFINE_BOOL_METHOD(mysql_system_variable_update_imp::set_default, std::unique_ptr thd_auto; enum_var_type var_type; + bool override_thd_lock_wait_timeout = true; if (prepare_thread_and_validate(hthd, variable_type, variable_name, thd, - thd_auto, var_type)) + thd_auto, var_type, + override_thd_lock_wait_timeout)) return true; return common_system_variable_update_set(thd, var_type, variable_base, - variable_name, nullptr); + variable_name, nullptr, + override_thd_lock_wait_timeout); } catch (...) { mysql_components_handle_std_exception(__func__); }