diff options
author | Monty <monty@mariadb.org> | 2017-10-25 11:07:44 +0300 |
---|---|---|
committer | Monty <monty@mariadb.org> | 2017-12-18 13:43:36 +0200 |
commit | 2e53b96a0aa9dcb18d8bbe12e5bc7e0aba208540 (patch) | |
tree | 112b522a5ae3a3132266052e38edcdac0a919e1a | |
parent | 77030649fb1f492b6dd9351a7d4b36e1aeb29f4d (diff) | |
download | mariadb-git-2e53b96a0aa9dcb18d8bbe12e5bc7e0aba208540.tar.gz |
Moved semisync from a plugin to normal server
Part of MDEV-13073 AliSQL Optimize performance of semisync
Did the following renames to match other similar variables
key_ss_mutex_LOCK_binlog_ > key_LOCK_bing
key_ss_cond_COND_binlog_send_ -> key_COND_binlog_send
COND_binlog_send_ -> COND_binlog_send
LOCK_binlog_ -> LOCK_binlog
debian/mariadb-server-10.2.install does not install semisync libs.
38 files changed, 860 insertions, 1189 deletions
diff --git a/debian/mariadb-server-10.3.install b/debian/mariadb-server-10.3.install index 23f8046baaf..604179c7dca 100644 --- a/debian/mariadb-server-10.3.install +++ b/debian/mariadb-server-10.3.install @@ -52,8 +52,6 @@ usr/lib/mysql/plugin/locales.so usr/lib/mysql/plugin/metadata_lock_info.so usr/lib/mysql/plugin/query_cache_info.so usr/lib/mysql/plugin/query_response_time.so -usr/lib/mysql/plugin/semisync_master.so -usr/lib/mysql/plugin/semisync_slave.so usr/lib/mysql/plugin/server_audit.so usr/lib/mysql/plugin/simple_password_check.so usr/lib/mysql/plugin/sql_errlog.so diff --git a/mysql-test/extra/rpl_tests/rpl_semi_sync.inc b/mysql-test/extra/rpl_tests/rpl_semi_sync.inc index 12053c54f4e..ed56e405e27 100644 --- a/mysql-test/extra/rpl_tests/rpl_semi_sync.inc +++ b/mysql-test/extra/rpl_tests/rpl_semi_sync.inc @@ -4,7 +4,6 @@ # Please check all dependent tests after modifying it # -source include/have_semisync.inc; source include/not_embedded.inc; source include/have_innodb.inc; source include/master-slave.inc; diff --git a/mysql-test/include/have_semisync.inc b/mysql-test/include/have_semisync.inc deleted file mode 100644 index 243fad83717..00000000000 --- a/mysql-test/include/have_semisync.inc +++ /dev/null @@ -1,4 +0,0 @@ -if (`select count(*) < 2 from information_schema.plugins where plugin_name like 'rpl_semi_sync_%'`) -{ - --skip Test requires semisync plugins -} diff --git a/mysql-test/include/have_semisync.opt b/mysql-test/include/have_semisync.opt deleted file mode 100644 index 19e29c7e4de..00000000000 --- a/mysql-test/include/have_semisync.opt +++ /dev/null @@ -1,4 +0,0 @@ ---plugin-load-add=$SEMISYNC_MASTER_SO ---plugin-load-add=$SEMISYNC_SLAVE_SO ---loose-rpl-semi-sync-master ---loose-rpl-semi-sync-slave diff --git a/mysql-test/include/install_semisync.inc b/mysql-test/include/install_semisync.inc deleted file mode 100644 index 9cc6df2072a..00000000000 --- a/mysql-test/include/install_semisync.inc +++ /dev/null @@ -1,39 +0,0 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# ---let $include_filename= install_semisync.inc ---source include/begin_include_file.inc - ---source include/not_embedded.inc ---source include/have_semisync_plugin.inc - ---connection master - ---disable_query_log ---let $value = query_get_value(show variables like 'rpl_semi_sync_master_enabled', Value, 1) -if ($value == No such row) -{ - SET sql_log_bin = 0; - install plugin rpl_semi_sync_master soname 'semisync_master'; - SET GLOBAL rpl_semi_sync_master_enabled = 1; - SET sql_log_bin = 1; -} ---enable_query_log - ---connection slave ---source include/stop_slave_io.inc - ---disable_query_log ---let $value= query_get_value(show variables like 'rpl_semi_sync_slave_enabled', Value, 1) -if ($value == No such row) -{ - SET sql_log_bin = 0; - install plugin rpl_semi_sync_slave soname 'semisync_slave'; - SET GLOBAL rpl_semi_sync_slave_enabled = 1; - SET sql_log_bin = 1; -} -START SLAVE IO_THREAD; ---source include/wait_for_slave_io_to_start.inc ---enable_query_log - ---source include/end_include_file.inc diff --git a/mysql-test/include/uninstall_semisync.inc b/mysql-test/include/uninstall_semisync.inc deleted file mode 100644 index 0a4c55fa4f2..00000000000 --- a/mysql-test/include/uninstall_semisync.inc +++ /dev/null @@ -1,29 +0,0 @@ -# -# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -# ---let $include_filename= uninstall_semisync.inc ---source include/begin_include_file.inc - ---disable_query_log ---connection slave ---source include/stop_slave_io.inc - -# Uninstall rpl_semi_sync_slave first ---disable_warnings -UNINSTALL PLUGIN rpl_semi_sync_slave; - ---connection master -# After BUG#17638477 fix, uninstallation of rpl_semi_sync_master -# is not allowed when there are semi sync slaves. Hence kill -# all dump threads before uninstalling it. -SET GLOBAL rpl_semi_sync_master_enabled = OFF; ---source include/stop_dump_threads.inc -UNINSTALL PLUGIN rpl_semi_sync_master; ---enable_warnings - ---connection slave -START SLAVE IO_THREAD; ---source include/wait_for_slave_io_to_start.inc ---enable_query_log - ---source include/end_include_file.inc diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index f76957fdcba..032c64b8040 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -998,6 +998,27 @@ The following options may be given as the first argument: --rowid-merge-buff-size=# The size of the buffers used [NOT] IN evaluation via partial matching + --rpl-semi-sync-master-enabled + Enable semi-synchronous replication master (disabled by + default). + --rpl-semi-sync-master-timeout=# + The timeout value (in ms) for semi-synchronous + replication in the master + --rpl-semi-sync-master-trace-level=# + The tracing level for semi-sync replication. + --rpl-semi-sync-master-wait-no-slave + Wait until timeout when no semi-synchronous replication + slave available (enabled by default). + (Defaults to on; use --skip-rpl-semi-sync-master-wait-no-slave to disable.) + --rpl-semi-sync-master-wait-point=name + Should transaction wait for semi-sync ack after having + synced binlog, or after having committed in storage + engine.. One of: AFTER_SYNC, AFTER_COMMIT + --rpl-semi-sync-slave-enabled + Enable semi-synchronous replication slave (disabled by + default). + --rpl-semi-sync-slave-trace-level=# + The tracing level for semi-sync replication. --safe-mode Skip some optimize stages (for testing). Deprecated. --safe-user-create Don't allow new user creation by the user who has no write privileges to the mysql.user table. @@ -1569,6 +1590,13 @@ report-password (No default value) report-port 0 report-user (No default value) rowid-merge-buff-size 8388608 +rpl-semi-sync-master-enabled FALSE +rpl-semi-sync-master-timeout 10000 +rpl-semi-sync-master-trace-level 32 +rpl-semi-sync-master-wait-no-slave TRUE +rpl-semi-sync-master-wait-point AFTER_COMMIT +rpl-semi-sync-slave-enabled FALSE +rpl-semi-sync-slave-trace-level 32 safe-user-create FALSE secure-auth TRUE secure-file-priv (No default value) diff --git a/mysql-test/suite/perfschema/r/dml_setup_instruments.result b/mysql-test/suite/perfschema/r/dml_setup_instruments.result index 83510e5827e..940839b105f 100644 --- a/mysql-test/suite/perfschema/r/dml_setup_instruments.result +++ b/mysql-test/suite/perfschema/r/dml_setup_instruments.result @@ -13,7 +13,7 @@ wait/synch/mutex/sql/HA_DATA_PARTITION::LOCK_auto_inc YES YES wait/synch/mutex/sql/LOCK_active_mi YES YES wait/synch/mutex/sql/LOCK_after_binlog_sync YES YES wait/synch/mutex/sql/LOCK_audit_mask YES YES -wait/synch/mutex/sql/LOCK_binlog_state YES YES +wait/synch/mutex/sql/LOCK_binlog YES YES select * from performance_schema.setup_instruments where name like 'Wait/Synch/Rwlock/sql/%' and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock') @@ -36,6 +36,7 @@ where name like 'Wait/Synch/Cond/sql/%' 'wait/synch/cond/sql/DEBUG_SYNC::cond') order by name limit 10; NAME ENABLED TIMED +wait/synch/cond/sql/COND_binlog_send YES YES wait/synch/cond/sql/COND_flush_thread_cache YES YES wait/synch/cond/sql/COND_group_commit_orderer YES YES wait/synch/cond/sql/COND_gtid_ignore_duplicates YES YES @@ -45,7 +46,6 @@ wait/synch/cond/sql/COND_prepare_ordered YES YES wait/synch/cond/sql/COND_queue_state YES YES wait/synch/cond/sql/COND_rpl_thread YES YES wait/synch/cond/sql/COND_rpl_thread_pool YES YES -wait/synch/cond/sql/COND_rpl_thread_queue YES YES select * from performance_schema.setup_instruments where name='Wait'; select * from performance_schema.setup_instruments diff --git a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result b/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result deleted file mode 100644 index 68ad4877927..00000000000 --- a/mysql-test/suite/rpl/r/rpl_semi_sync_uninstall_plugin.result +++ /dev/null @@ -1,73 +0,0 @@ -include/master-slave.inc -[connection master] -call mtr.add_suppression("Read semi-sync reply network error"); -call mtr.add_suppression("Timeout waiting for reply of binlog"); -INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master'; -connection slave; -INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave'; -UNINSTALL PLUGIN rpl_semi_sync_slave; -connection master; -UNINSTALL PLUGIN rpl_semi_sync_master; -CREATE TABLE t1(i int); -INSERT INTO t1 values (1); -DROP TABLE t1; -connection slave; -include/install_semisync.inc -connection master; -connection slave; -connection slave; -show global status like "Slave%_running"; -Variable_name Value -Slave_running ON -Slaves_running 1 -UNINSTALL PLUGIN rpl_semi_sync_slave; -Warnings: -Warning 1620 Plugin is busy and will be uninstalled on shutdown -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; -plugin_name plugin_status -rpl_semi_sync_slave DELETED -connection master; -show global status like "Slave%_connect%"; -Variable_name Value -Slave_connections 2 -Slaves_connected 1 -UNINSTALL PLUGIN rpl_semi_sync_master; -Warnings: -Warning 1620 Plugin is busy and will be uninstalled on shutdown -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; -plugin_name plugin_status -rpl_semi_sync_master DELETED -CREATE TABLE t1(i int); -INSERT INTO t1 values (2); -DROP TABLE t1; -connection slave; -show status like "Rpl_semi_sync_slave_status"; -Variable_name Value -Rpl_semi_sync_slave_status ON -connection master; -show status like "Rpl_semi_sync_master_status"; -Variable_name Value -Rpl_semi_sync_master_status ON -show status like "Rpl_semi_sync_master_clients"; -Variable_name Value -Rpl_semi_sync_master_clients 1 -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; -plugin_name plugin_status -rpl_semi_sync_master DELETED -connection slave; -include/stop_slave.inc -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; -plugin_name plugin_status -connection master; -create table t2 (a int); -drop table t2; -connection slave; -include/start_slave.inc -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; -plugin_name plugin_status -connection master; -CREATE TABLE t1(i int); -INSERT INTO t1 values (3); -DROP TABLE t1; -connection slave; -include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_mdev359.test b/mysql-test/suite/rpl/t/rpl_mdev359.test index 3026c6d363e..5b02ecd72c0 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev359.test +++ b/mysql-test/suite/rpl/t/rpl_mdev359.test @@ -1,4 +1,3 @@ ---source include/have_semisync.inc --source include/not_embedded.inc --source include/have_debug_sync.inc --source include/have_binlog_format_mixed_or_statement.inc diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test index b8f3c8130be..d7685413a07 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_event.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_event.test @@ -1,4 +1,3 @@ -source include/have_semisync.inc; source include/not_embedded.inc; source include/have_innodb.inc; source include/master-slave.inc; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test b/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test deleted file mode 100644 index 360706922ea..00000000000 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_uninstall_plugin.test +++ /dev/null @@ -1,132 +0,0 @@ -############################################################################### -# Bug#17638477 UNINSTALL AND INSTALL SEMI-SYNC PLUGIN CAUSES SLAVES TO BREAK -# Problem: Uninstallation of Semi sync plugin should be blocked when it is -# in use. -# Test case: Uninstallation of semi sync should be allowed -# On Master: -# 1) When there is no dump thread -# 2) When there are no semi sync slaves (i.e., async replication). -# On Slave: -# 1) When there is no I/O thread -# 2) When there are no semi sync enabled I/O thread (i.e.,async replication). -############################################################################### - ---source include/have_semisync_plugin.inc ---source include/not_embedded.inc ---source include/have_binlog_format_statement.inc ---source include/master-slave.inc - -call mtr.add_suppression("Read semi-sync reply network error"); -call mtr.add_suppression("Timeout waiting for reply of binlog"); - -############################################################################### -# Case 1: Uninstallation of semi sync plugins should be allowed when it is -# not in use i.e., when asynchronous replication is active. -############################################################################### -# Step 1.1: Install semi sync master plugin on master -INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master'; - -# Step 1.2: Install semi sync slave plugin on slave ---connection slave -INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave'; - -# Step 1.3: Uninstallation of semisync plugin on master and slave should be -# allowed at this state as there is no semi sync replication enabled between -# master and slave. -UNINSTALL PLUGIN rpl_semi_sync_slave; ---connection master -UNINSTALL PLUGIN rpl_semi_sync_master; - -# Step 1.4: Check that replication is working fine at the end of the test case. -CREATE TABLE t1(i int); -INSERT INTO t1 values (1); -DROP TABLE t1; ---sync_slave_with_master - -############################################################################### -# Case 2: Uninstallation of semi sync plugins should be disallowed -# when it is in use i.e., when semi sync replication is active -############################################################################### -# Step 2.1: Install and enable semi sync replication between master and slave ---source include/install_semisync.inc - -# Step 2.2: Check that rpl_semi_sync_slave uninstallation on Slave is not -# possible at this state ---connection slave -show global status like "Slave%_running"; - -UNINSTALL PLUGIN rpl_semi_sync_slave; -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; - -# Step 2.3: Check that rpl_semi_sync_master uninstallation on Master is not -# possible at this state ---connection master - -# The following is to catch errors if the next uninstall plugin would succeed -show global status like "Slave%_connect%"; - -UNINSTALL PLUGIN rpl_semi_sync_master; -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; - -# Step 2.4: Check that replication is working fine at the end of the test case. -CREATE TABLE t1(i int); -INSERT INTO t1 values (2); -DROP TABLE t1; ---sync_slave_with_master - -# Step 2.5: Make sure rpl_semi_sync_master_status on Master and -# rpl_semi_sync_slave_staus on Slave are ON -show status like "Rpl_semi_sync_slave_status"; - -############################################################################### -# Case 3: Uninstallation of semi sync plugin should be disallowed when there -# are semi sync slaves even though rpl_semi_sync_master_enabled= OFF;. -############################################################################### -# Step 3.1: Disable semi sync on master ---connection master -show status like "Rpl_semi_sync_master_status"; - -# Step 3.2: Check that still Rpl_semi_sync_master_clients is 1 -show status like "Rpl_semi_sync_master_clients"; - -# Step 3.3: Since Rpl_semi_sync_master_clients is 1, uninstallation of -# rpl_semi_sync_master should be disallowed. -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; - -############################################################################### -# Case 4: Uninstallation of semi sync plugin should be allowed when it is not -# in use. Same as Case 1 but this case is to check the case after enabling and -# disabling semi sync replication. -############################################################################### - -# Step 4.1: Stop IO thread on slave. ---connection slave ---source include/stop_slave.inc - -# Step 4.2: Disable semi sync on slave. -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; - ---connection master -# Send something to the slave so that the master would notice that nobody's listening. -create table t2 (a int); drop table t2; -# and wait for plugin to be unloaded automatically -let $wait_condition=select count(*) = 0 from information_schema.plugins where plugin_name like 'rpl_%'; ---source include/wait_condition.inc - ---connection slave - -# Step 4.3: Start IO thread on slave. ---source include/start_slave.inc - -# Step 4.4: Uninstall semi sync plugin, it should be successful now. -select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%'; - -# Step 4.7: Check that replication is working fine at the end of the test case ---connection master -CREATE TABLE t1(i int); -INSERT INTO t1 values (3); -DROP TABLE t1; ---sync_slave_with_master - -# Cleanup -source include/rpl_end.inc; diff --git a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test index 6e4dc456a27..dcff4030fdb 100644 --- a/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test +++ b/mysql-test/suite/rpl/t/rpl_semi_sync_wait_point.test @@ -1,4 +1,3 @@ -source include/have_semisync.inc; source include/not_embedded.inc; source include/have_innodb.inc; diff --git a/mysql-test/suite/rpl/t/semisync_future-7591.test b/mysql-test/suite/rpl/t/semisync_future-7591.test index daf3d2f8571..866041d2579 100644 --- a/mysql-test/suite/rpl/t/semisync_future-7591.test +++ b/mysql-test/suite/rpl/t/semisync_future-7591.test @@ -1,4 +1,3 @@ ---source include/have_semisync.inc --source include/master-slave.inc call mtr.add_suppression("Timeout waiting for reply of binlog*"); diff --git a/mysql-test/suite/rpl/t/semisync_memleak_4066.test b/mysql-test/suite/rpl/t/semisync_memleak_4066.test index f888f764b43..e88e2335696 100644 --- a/mysql-test/suite/rpl/t/semisync_memleak_4066.test +++ b/mysql-test/suite/rpl/t/semisync_memleak_4066.test @@ -1,7 +1,6 @@ # # MDEV-4066 semisync_master + temporary tables causes memory leaks # -source include/have_semisync.inc; source include/have_binlog_format_row.inc; source include/master-slave.inc; diff --git a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result index 8591f4b0c28..376123fa88d 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result +++ b/mysql-test/suite/sys_vars/r/sysvars_server_notembedded.result @@ -4001,6 +4001,104 @@ NUMERIC_BLOCK_SIZE 1 ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME RPL_SEMI_SYNC_MASTER_ENABLED +SESSION_VALUE NULL +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Enable semi-synchronous replication master (disabled by default). +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TIMEOUT +SESSION_VALUE NULL +GLOBAL_VALUE 10000 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 10000 +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT The timeout value (in ms) for semi-synchronous replication in the master +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TRACE_LEVEL +SESSION_VALUE NULL +GLOBAL_VALUE 32 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 32 +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT The tracing level for semi-sync replication. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME RPL_SEMI_SYNC_MASTER_WAIT_NO_SLAVE +SESSION_VALUE NULL +GLOBAL_VALUE ON +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE ON +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Wait until timeout when no semi-synchronous replication slave available (enabled by default). +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME RPL_SEMI_SYNC_MASTER_WAIT_POINT +SESSION_VALUE NULL +GLOBAL_VALUE AFTER_COMMIT +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE AFTER_COMMIT +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE ENUM +VARIABLE_COMMENT Should transaction wait for semi-sync ack after having synced binlog, or after having committed in storage engine. +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST AFTER_SYNC,AFTER_COMMIT +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED +VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_ENABLED +SESSION_VALUE NULL +GLOBAL_VALUE OFF +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE OFF +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BOOLEAN +VARIABLE_COMMENT Enable semi-synchronous replication slave (disabled by default). +NUMERIC_MIN_VALUE NULL +NUMERIC_MAX_VALUE NULL +NUMERIC_BLOCK_SIZE NULL +ENUM_VALUE_LIST OFF,ON +READ_ONLY NO +COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL +SESSION_VALUE NULL +GLOBAL_VALUE 32 +GLOBAL_VALUE_ORIGIN COMPILE-TIME +DEFAULT_VALUE 32 +VARIABLE_SCOPE GLOBAL +VARIABLE_TYPE BIGINT UNSIGNED +VARIABLE_COMMENT The tracing level for semi-sync replication. +NUMERIC_MIN_VALUE 0 +NUMERIC_MAX_VALUE 18446744073709551615 +NUMERIC_BLOCK_SIZE 1 +ENUM_VALUE_LIST NULL +READ_ONLY NO +COMMAND_LINE_ARGUMENT REQUIRED VARIABLE_NAME SECURE_AUTH SESSION_VALUE NULL GLOBAL_VALUE ON diff --git a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_enabled_basic.test b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_enabled_basic.test index 2ff03a53c42..da22d0535f4 100644 --- a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_enabled_basic.test +++ b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_enabled_basic.test @@ -6,7 +6,6 @@ # # source include/not_embedded.inc; -source include/have_semisync.inc; select @@global.rpl_semi_sync_master_enabled; SET @start_global_value = @@global.rpl_semi_sync_master_enabled; diff --git a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_timeout_basic.test b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_timeout_basic.test index 74d3c41150b..d312fa1c367 100644 --- a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_timeout_basic.test +++ b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_timeout_basic.test @@ -5,7 +5,6 @@ # 2010-01-21 OBN - Added # source include/not_embedded.inc; -source include/have_semisync.inc; select @@global.rpl_semi_sync_master_timeout; SET @start_global_value = @@global.rpl_semi_sync_master_timeout; diff --git a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_trace_level_basic.test b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_trace_level_basic.test index c41b53fe5e6..3419254bafd 100644 --- a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_trace_level_basic.test +++ b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_trace_level_basic.test @@ -5,7 +5,6 @@ # 2010-01-21 OBN - Added # source include/not_embedded.inc; -source include/have_semisync.inc; select @@global.rpl_semi_sync_master_trace_level; SET @start_global_value = @@global.rpl_semi_sync_master_trace_level; diff --git a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_no_slave_basic.test b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_no_slave_basic.test index d4a46a08140..60ca4425e5b 100644 --- a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_no_slave_basic.test +++ b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_no_slave_basic.test @@ -6,7 +6,6 @@ # # source include/not_embedded.inc; -source include/have_semisync.inc; select @@global.rpl_semi_sync_master_wait_no_slave; SET @start_global_value = @@global.rpl_semi_sync_master_wait_no_slave; diff --git a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_point_basic.test b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_point_basic.test index 8125cf8d653..2f8cd8ec160 100644 --- a/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_point_basic.test +++ b/mysql-test/suite/sys_vars/t/rpl_semi_sync_master_wait_point_basic.test @@ -1,5 +1,4 @@ source include/not_embedded.inc; -source include/have_semisync.inc; select @@global.rpl_semi_sync_master_wait_point; SET @start_global_value = @@global.rpl_semi_sync_master_wait_point; diff --git a/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_enabled_basic.test b/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_enabled_basic.test index c7ce371970d..71be941cbdc 100644 --- a/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_enabled_basic.test +++ b/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_enabled_basic.test @@ -6,7 +6,6 @@ # # source include/not_embedded.inc; -source include/have_semisync.inc; select @@global.rpl_semi_sync_slave_enabled; SET @start_global_value = @@global.rpl_semi_sync_slave_enabled; diff --git a/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_trace_level_basic.test b/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_trace_level_basic.test index d7e001b7322..74b6ac0a6ae 100644 --- a/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_trace_level_basic.test +++ b/mysql-test/suite/sys_vars/t/rpl_semi_sync_slave_trace_level_basic.test @@ -5,7 +5,6 @@ # 2010-01-21 OBN - Added # source include/not_embedded.inc; -source include/have_semisync.inc; select @@global.rpl_semi_sync_slave_trace_level; SET @start_global_value = @@global.rpl_semi_sync_slave_trace_level; diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index f859d7dd9d6..520384f3ab3 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -30,7 +30,7 @@ perl; feedback debug temp-pool ssl des-key-file xtradb sequence thread-concurrency super-large-pages mutex-deadlock-detector connect null-audit aria oqgraph sphinx thread-handling - test-sql-discovery rpl-semi-sync query-cache-info + test-sql-discovery query-cache-info query-response-time metadata-lock-info locales unix-socket wsrep file-key-management cracklib-password-check user-variables/; diff --git a/plugin/semisync/CMakeLists.txt b/plugin/semisync/CMakeLists.txt deleted file mode 100644 index 88998fb3093..00000000000 --- a/plugin/semisync/CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; version 2 of the License. -# -# 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 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 - -SET(SEMISYNC_MASTER_SOURCES - semisync.cc semisync_master.cc semisync_master_plugin.cc - semisync.h semisync_master.h) - -MYSQL_ADD_PLUGIN(semisync_master ${SEMISYNC_MASTER_SOURCES} - RECOMPILE_FOR_EMBEDDED) - -SET(SEMISYNC_SLAVE_SOURCES semisync.cc semisync_slave.cc - semisync_slave_plugin.cc semisync.h semisync_slave.h ) - -MYSQL_ADD_PLUGIN(semisync_slave ${SEMISYNC_SLAVE_SOURCES} - RECOMPILE_FOR_EMBEDDED) - diff --git a/plugin/semisync/semisync_master_plugin.cc b/plugin/semisync/semisync_master_plugin.cc deleted file mode 100644 index b46cf5d79cb..00000000000 --- a/plugin/semisync/semisync_master_plugin.cc +++ /dev/null @@ -1,496 +0,0 @@ -/* Copyright (C) 2007 Google Inc. - Copyright (c) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc. - Use is subject to license terms. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - 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 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 <my_global.h> -#include "semisync_master.h" -#include "sql_class.h" // THD - -static ReplSemiSyncMaster repl_semisync; - -C_MODE_START - -int repl_semi_report_binlog_update(Binlog_storage_param *param, - const char *log_file, - my_off_t log_pos, uint32 flags) -{ - int error= 0; - - if (repl_semisync.getMasterEnabled()) - { - /* - Let us store the binlog file name and the position, so that - we know how long to wait for the binlog to the replicated to - the slave in synchronous replication. - */ - error= repl_semisync.writeTranxInBinlog(log_file, - log_pos); - } - - return error; -} - -int repl_semi_request_commit(Trans_param *param) -{ - return 0; -} - -int repl_semi_report_binlog_sync(Binlog_storage_param *param, - const char *log_file, - my_off_t log_pos, uint32 flags) -{ - int error= 0; - if (rpl_semi_sync_master_wait_point == - SEMI_SYNC_MASTER_WAIT_POINT_AFTER_BINLOG_SYNC) - { - error = repl_semisync.commitTrx(log_file, log_pos); - } - - return error; -} - -int repl_semi_report_commit(Trans_param *param) -{ - if (rpl_semi_sync_master_wait_point != - SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT) - { - return 0; - } - - bool is_real_trans= param->flags & TRANS_IS_REAL_TRANS; - - if (is_real_trans && param->log_pos) - { - const char *binlog_name= param->log_file; - return repl_semisync.commitTrx(binlog_name, param->log_pos); - } - return 0; -} - -int repl_semi_report_rollback(Trans_param *param) -{ - return repl_semi_report_commit(param); -} - -int repl_semi_binlog_dump_start(Binlog_transmit_param *param, - const char *log_file, - my_off_t log_pos) -{ - bool semi_sync_slave= repl_semisync.is_semi_sync_slave(); - - if (semi_sync_slave) - { - /* One more semi-sync slave */ - repl_semisync.add_slave(); - - /* - Let's assume this semi-sync slave has already received all - binlog events before the filename and position it requests. - */ - repl_semisync.reportReplyBinlog(param->server_id, log_file, log_pos); - } - sql_print_information("Start %s binlog_dump to slave (server_id: %d), pos(%s, %lu)", - semi_sync_slave ? "semi-sync" : "asynchronous", - param->server_id, log_file, (unsigned long)log_pos); - - return 0; -} - -int repl_semi_binlog_dump_end(Binlog_transmit_param *param) -{ - bool semi_sync_slave= repl_semisync.is_semi_sync_slave(); - - sql_print_information("Stop %s binlog_dump to slave (server_id: %d)", - semi_sync_slave ? "semi-sync" : "asynchronous", - param->server_id); - if (semi_sync_slave) - { - /* One less semi-sync slave */ - repl_semisync.remove_slave(); - } - return 0; -} - -int repl_semi_reserve_header(Binlog_transmit_param *param, - unsigned char *header, - unsigned long size, unsigned long *len) -{ - *len += repl_semisync.reserveSyncHeader(header, size); - return 0; -} - -int repl_semi_before_send_event(Binlog_transmit_param *param, - unsigned char *packet, unsigned long len, - const char *log_file, my_off_t log_pos) -{ - return repl_semisync.updateSyncHeader(packet, - log_file, - log_pos, - param->server_id); -} - -int repl_semi_after_send_event(Binlog_transmit_param *param, - const char *event_buf, unsigned long len) -{ - if (repl_semisync.is_semi_sync_slave()) - { - THD *thd= current_thd; - /* - Possible errors in reading slave reply are ignored deliberately - because we do not want dump thread to quit on this. Error - messages are already reported. - */ - (void) repl_semisync.readSlaveReply(&thd->net, - param->server_id, event_buf); - thd->clear_error(); - } - return 0; -} - -int repl_semi_reset_master(Binlog_transmit_param *param) -{ - if (repl_semisync.resetMaster()) - return 1; - return 0; -} - -C_MODE_END - -/* - semisync system variables - */ -static void fix_rpl_semi_sync_master_timeout(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val); - -static void fix_rpl_semi_sync_master_trace_level(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val); - -static void fix_rpl_semi_sync_master_enabled(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val); - -static MYSQL_SYSVAR_BOOL(enabled, rpl_semi_sync_master_enabled, - PLUGIN_VAR_OPCMDARG, - "Enable semi-synchronous replication master (disabled by default). ", - NULL, // check - &fix_rpl_semi_sync_master_enabled, // update - 0); - -/* NOTE: must match order of rpl_semi_sync_master_wait_point_t */ -static const char *rpl_semi_sync_master_wait_point_names[] = -{ - "AFTER_SYNC", - "AFTER_COMMIT", - NullS -}; - -static TYPELIB rpl_semi_sync_master_wait_point_typelib = -{ - array_elements(rpl_semi_sync_master_wait_point_names) - 1, - "", - rpl_semi_sync_master_wait_point_names, - NULL -}; - -static MYSQL_SYSVAR_ENUM( - wait_point, - rpl_semi_sync_master_wait_point, - PLUGIN_VAR_RQCMDARG, - "Should transaction wait for semi-sync ack after having synced binlog, " - "or after having committed in storeage engine.", - NULL, // check - NULL, // update - SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT, - &rpl_semi_sync_master_wait_point_typelib); - -static MYSQL_SYSVAR_ULONG(timeout, rpl_semi_sync_master_timeout, - PLUGIN_VAR_OPCMDARG, - "The timeout value (in ms) for semi-synchronous replication in the master", - NULL, // check - fix_rpl_semi_sync_master_timeout, // update - 10000, 0, ~0UL, 1); - -static MYSQL_SYSVAR_BOOL(wait_no_slave, rpl_semi_sync_master_wait_no_slave, - PLUGIN_VAR_OPCMDARG, - "Wait until timeout when no semi-synchronous replication slave available (enabled by default). ", - NULL, // check - NULL, // update - 1); - -static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_master_trace_level, - PLUGIN_VAR_OPCMDARG, - "The tracing level for semi-sync replication.", - NULL, // check - &fix_rpl_semi_sync_master_trace_level, // update - 32, 0, ~0UL, 1); - -static SYS_VAR* semi_sync_master_system_vars[]= { - MYSQL_SYSVAR(enabled), - MYSQL_SYSVAR(wait_point), - MYSQL_SYSVAR(timeout), - MYSQL_SYSVAR(wait_no_slave), - MYSQL_SYSVAR(trace_level), - NULL, -}; - - -static void fix_rpl_semi_sync_master_timeout(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val) -{ - *(unsigned long *)ptr= *(unsigned long *)val; - repl_semisync.setWaitTimeout(rpl_semi_sync_master_timeout); - return; -} - -static void fix_rpl_semi_sync_master_trace_level(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val) -{ - *(unsigned long *)ptr= *(unsigned long *)val; - repl_semisync.setTraceLevel(rpl_semi_sync_master_trace_level); - return; -} - -static void fix_rpl_semi_sync_master_enabled(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val) -{ - *(char *)ptr= *(char *)val; - if (rpl_semi_sync_master_enabled) - { - if (repl_semisync.enableMaster() != 0) - rpl_semi_sync_master_enabled = false; - } - else - { - if (repl_semisync.disableMaster() != 0) - rpl_semi_sync_master_enabled = true; - } - - return; -} - -Trans_observer trans_observer = { - sizeof(Trans_observer), // len - - repl_semi_report_commit, // after_commit - repl_semi_report_rollback, // after_rollback -}; - -Binlog_storage_observer storage_observer = { - sizeof(Binlog_storage_observer), // len - - repl_semi_report_binlog_update, // report_update - repl_semi_report_binlog_sync, // after_sync -}; - -Binlog_transmit_observer transmit_observer = { - sizeof(Binlog_transmit_observer), // len - - repl_semi_binlog_dump_start, // start - repl_semi_binlog_dump_end, // stop - repl_semi_reserve_header, // reserve_header - repl_semi_before_send_event, // before_send_event - repl_semi_after_send_event, // after_send_event - repl_semi_reset_master, // reset -}; - - -#define SHOW_FNAME(name) \ - rpl_semi_sync_master_show_##name - -#define DEF_SHOW_FUNC(name, show_type) \ - static int SHOW_FNAME(name)(MYSQL_THD thd, SHOW_VAR *var, char *buff) \ - { \ - repl_semisync.setExportStats(); \ - var->type= show_type; \ - var->value= (char *)&rpl_semi_sync_master_##name; \ - return 0; \ - } - -DEF_SHOW_FUNC(status, SHOW_BOOL) -DEF_SHOW_FUNC(clients, SHOW_LONG) -DEF_SHOW_FUNC(wait_sessions, SHOW_LONG) -DEF_SHOW_FUNC(trx_wait_time, SHOW_LONGLONG) -DEF_SHOW_FUNC(trx_wait_num, SHOW_LONGLONG) -DEF_SHOW_FUNC(net_wait_time, SHOW_LONGLONG) -DEF_SHOW_FUNC(net_wait_num, SHOW_LONGLONG) -DEF_SHOW_FUNC(avg_net_wait_time, SHOW_LONG) -DEF_SHOW_FUNC(avg_trx_wait_time, SHOW_LONG) - - -/* plugin status variables */ -static SHOW_VAR semi_sync_master_status_vars[]= { - {"Rpl_semi_sync_master_status", - (char*) &SHOW_FNAME(status), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_clients", - (char*) &SHOW_FNAME(clients), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_yes_tx", - (char*) &rpl_semi_sync_master_yes_transactions, - SHOW_LONG}, - {"Rpl_semi_sync_master_no_tx", - (char*) &rpl_semi_sync_master_no_transactions, - SHOW_LONG}, - {"Rpl_semi_sync_master_wait_sessions", - (char*) &SHOW_FNAME(wait_sessions), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_no_times", - (char*) &rpl_semi_sync_master_off_times, - SHOW_LONG}, - {"Rpl_semi_sync_master_timefunc_failures", - (char*) &rpl_semi_sync_master_timefunc_fails, - SHOW_LONG}, - {"Rpl_semi_sync_master_wait_pos_backtraverse", - (char*) &rpl_semi_sync_master_wait_pos_backtraverse, - SHOW_LONG}, - {"Rpl_semi_sync_master_tx_wait_time", - (char*) &SHOW_FNAME(trx_wait_time), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_tx_waits", - (char*) &SHOW_FNAME(trx_wait_num), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_tx_avg_wait_time", - (char*) &SHOW_FNAME(avg_trx_wait_time), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_net_wait_time", - (char*) &SHOW_FNAME(net_wait_time), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_net_waits", - (char*) &SHOW_FNAME(net_wait_num), - SHOW_SIMPLE_FUNC}, - {"Rpl_semi_sync_master_net_avg_wait_time", - (char*) &SHOW_FNAME(avg_net_wait_time), - SHOW_SIMPLE_FUNC}, - {NULL, NULL, SHOW_LONG}, -}; - -#ifdef HAVE_PSI_INTERFACE -PSI_mutex_key key_ss_mutex_LOCK_binlog_; - -static PSI_mutex_info all_semisync_mutexes[]= -{ - { &key_ss_mutex_LOCK_binlog_, "LOCK_binlog_", 0} -}; - -PSI_cond_key key_ss_cond_COND_binlog_send_; - -static PSI_cond_info all_semisync_conds[]= -{ - { &key_ss_cond_COND_binlog_send_, "COND_binlog_send_", 0} -}; -#endif /* HAVE_PSI_INTERFACE */ - -PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave= -{ 0, "Waiting for semi-sync ACK from slave", 0}; - -#ifdef HAVE_PSI_INTERFACE -PSI_stage_info *all_semisync_stages[]= -{ - & stage_waiting_for_semi_sync_ack_from_slave -}; - -static void init_semisync_psi_keys(void) -{ - const char* category= "semisync"; - int count; - - count= array_elements(all_semisync_mutexes); - mysql_mutex_register(category, all_semisync_mutexes, count); - - count= array_elements(all_semisync_conds); - mysql_cond_register(category, all_semisync_conds, count); - - count= array_elements(all_semisync_stages); - mysql_stage_register(category, all_semisync_stages, count); -} -#endif /* HAVE_PSI_INTERFACE */ - -static int semi_sync_master_plugin_init(void *p) -{ -#ifdef HAVE_PSI_INTERFACE - init_semisync_psi_keys(); -#endif - - if (repl_semisync.initObject()) - return 1; - if (register_trans_observer(&trans_observer, p)) - return 1; - if (register_binlog_storage_observer(&storage_observer, p)) - return 1; - if (register_binlog_transmit_observer(&transmit_observer, p)) - return 1; - return 0; -} - -static int semi_sync_master_plugin_deinit(void *p) -{ - if (unregister_trans_observer(&trans_observer, p)) - { - sql_print_error("unregister_trans_observer failed"); - return 1; - } - if (unregister_binlog_storage_observer(&storage_observer, p)) - { - sql_print_error("unregister_binlog_storage_observer failed"); - return 1; - } - if (unregister_binlog_transmit_observer(&transmit_observer, p)) - { - sql_print_error("unregister_binlog_transmit_observer failed"); - return 1; - } - repl_semisync.cleanup(); - sql_print_information("unregister_replicator OK"); - return 0; -} - -struct Mysql_replication semi_sync_master_plugin= { - MYSQL_REPLICATION_INTERFACE_VERSION -}; - -/* - Plugin library descriptor -*/ -maria_declare_plugin(semisync_master) -{ - MYSQL_REPLICATION_PLUGIN, - &semi_sync_master_plugin, - "rpl_semi_sync_master", - "He Zhenxing", - "Semi-synchronous replication master", - PLUGIN_LICENSE_GPL, - semi_sync_master_plugin_init, /* Plugin Init */ - semi_sync_master_plugin_deinit, /* Plugin Deinit */ - 0x0100 /* 1.0 */, - semi_sync_master_status_vars, /* status variables */ - semi_sync_master_system_vars, /* system variables */ - "1.0", - MariaDB_PLUGIN_MATURITY_STABLE -} -maria_declare_plugin_end; - diff --git a/plugin/semisync/semisync_slave_plugin.cc b/plugin/semisync/semisync_slave_plugin.cc deleted file mode 100644 index df9e8e10429..00000000000 --- a/plugin/semisync/semisync_slave_plugin.cc +++ /dev/null @@ -1,234 +0,0 @@ -/* Copyright (C) 2007 Google Inc. - Copyright (C) 2008 MySQL AB - Use is subject to license terms - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; version 2 of the License. - - 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 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 <my_global.h> -#include "semisync_slave.h" -#include <mysql.h> - -static ReplSemiSyncSlave repl_semisync; - -/* - indicate whether or not the slave should send a reply to the master. - - This is set to true in repl_semi_slave_read_event if the current - event read is the last event of a transaction. And the value is - checked in repl_semi_slave_queue_event. -*/ -bool semi_sync_need_reply= false; - -C_MODE_START - -int repl_semi_reset_slave(Binlog_relay_IO_param *param) -{ - // TODO: reset semi-sync slave status here - return 0; -} - -int repl_semi_slave_request_dump(Binlog_relay_IO_param *param, - uint32 flags) -{ - MYSQL *mysql= param->mysql; - MYSQL_RES *res= 0; - MYSQL_ROW row; - const char *query; - - if (!repl_semisync.getSlaveEnabled()) - return 0; - - /* Check if master server has semi-sync plugin installed */ - query= "SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled'"; - if (mysql_real_query(mysql, query, strlen(query)) || - !(res= mysql_store_result(mysql))) - { - sql_print_error("Execution failed on master: %s", query); - return 1; - } - - row= mysql_fetch_row(res); - if (!row) - { - /* Master does not support semi-sync */ - sql_print_warning("Master server does not support semi-sync, " - "fallback to asynchronous replication"); - rpl_semi_sync_slave_status= 0; - mysql_free_result(res); - return 0; - } - mysql_free_result(res); - - /* - Tell master dump thread that we want to do semi-sync - replication - */ - query= "SET @rpl_semi_sync_slave= 1"; - if (mysql_real_query(mysql, query, strlen(query))) - { - sql_print_error("Set 'rpl_semi_sync_slave=1' on master failed"); - return 1; - } - mysql_free_result(mysql_store_result(mysql)); - rpl_semi_sync_slave_status= 1; - return 0; -} - -int repl_semi_slave_read_event(Binlog_relay_IO_param *param, - const char *packet, unsigned long len, - const char **event_buf, unsigned long *event_len) -{ - if (rpl_semi_sync_slave_status) - return repl_semisync.slaveReadSyncHeader(packet, len, - &semi_sync_need_reply, - event_buf, event_len); - *event_buf= packet; - *event_len= len; - return 0; -} - -int repl_semi_slave_queue_event(Binlog_relay_IO_param *param, - const char *event_buf, - unsigned long event_len, - uint32 flags) -{ - if (rpl_semi_sync_slave_status && semi_sync_need_reply) - { - /* - We deliberately ignore the error in slaveReply, such error - should not cause the slave IO thread to stop, and the error - messages are already reported. - */ - (void) repl_semisync.slaveReply(param->mysql, - param->master_log_name, - param->master_log_pos); - } - return 0; -} - -int repl_semi_slave_io_start(Binlog_relay_IO_param *param) -{ - return repl_semisync.slaveStart(param); -} - -int repl_semi_slave_io_end(Binlog_relay_IO_param *param) -{ - return repl_semisync.slaveStop(param); -} - -C_MODE_END - -static void fix_rpl_semi_sync_slave_enabled(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val) -{ - *(char *)ptr= *(char *)val; - repl_semisync.setSlaveEnabled(rpl_semi_sync_slave_enabled != 0); - return; -} - -static void fix_rpl_semi_sync_trace_level(MYSQL_THD thd, - SYS_VAR *var, - void *ptr, - const void *val) -{ - *(unsigned long *)ptr= *(unsigned long *)val; - repl_semisync.setTraceLevel(rpl_semi_sync_slave_trace_level); - return; -} - -/* plugin system variables */ -static MYSQL_SYSVAR_BOOL(enabled, rpl_semi_sync_slave_enabled, - PLUGIN_VAR_OPCMDARG, - "Enable semi-synchronous replication slave (disabled by default). ", - NULL, // check - &fix_rpl_semi_sync_slave_enabled, // update - 0); - -static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_slave_trace_level, - PLUGIN_VAR_OPCMDARG, - "The tracing level for semi-sync replication.", - NULL, // check - &fix_rpl_semi_sync_trace_level, // update - 32, 0, ~0UL, 1); - -static SYS_VAR* semi_sync_slave_system_vars[]= { - MYSQL_SYSVAR(enabled), - MYSQL_SYSVAR(trace_level), - NULL, -}; - - -/* plugin status variables */ -static SHOW_VAR semi_sync_slave_status_vars[]= { - {"Rpl_semi_sync_slave_status", - (char*) &rpl_semi_sync_slave_status, SHOW_BOOL}, - {NULL, NULL, SHOW_BOOL}, -}; - -Binlog_relay_IO_observer relay_io_observer = { - sizeof(Binlog_relay_IO_observer), // len - - repl_semi_slave_io_start, // start - repl_semi_slave_io_end, // stop - repl_semi_slave_request_dump, // request_transmit - repl_semi_slave_read_event, // after_read_event - repl_semi_slave_queue_event, // after_queue_event - repl_semi_reset_slave, // reset -}; - -static int semi_sync_slave_plugin_init(void *p) -{ - if (repl_semisync.initObject()) - return 1; - if (register_binlog_relay_io_observer(&relay_io_observer, p)) - return 1; - return 0; -} - -static int semi_sync_slave_plugin_deinit(void *p) -{ - if (unregister_binlog_relay_io_observer(&relay_io_observer, p)) - return 1; - return 0; -} - - -struct Mysql_replication semi_sync_slave_plugin= { - MYSQL_REPLICATION_INTERFACE_VERSION -}; - -/* - Plugin library descriptor -*/ -maria_declare_plugin(semisync_slave) -{ - MYSQL_REPLICATION_PLUGIN, - &semi_sync_slave_plugin, - "rpl_semi_sync_slave", - "He Zhenxing", - "Semi-synchronous replication slave", - PLUGIN_LICENSE_GPL, - semi_sync_slave_plugin_init, /* Plugin Init */ - semi_sync_slave_plugin_deinit, /* Plugin Deinit */ - 0x0100 /* 1.0 */, - semi_sync_slave_status_vars, /* status variables */ - semi_sync_slave_system_vars, /* system variables */ - "1.0", - MariaDB_PLUGIN_MATURITY_STABLE -} -maria_declare_plugin_end; - diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 0f67032bcbe..6c63f3feca3 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -36,7 +36,7 @@ ELSE() ENDIF() INCLUDE_DIRECTORIES( -${CMAKE_SOURCE_DIR}/include +${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql ${PCRE_INCLUDES} ${ZLIB_INCLUDE_DIR} @@ -138,6 +138,7 @@ SET (SQL_SOURCE my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc my_json_writer.cc rpl_gtid.cc rpl_parallel.cc + semisync.cc semisync_master.cc semisync_slave.cc sql_type.cc item_windowfunc.cc sql_window.cc sql_cte.cc diff --git a/sql/mysqld.cc b/sql/mysqld.cc index f3cb39959a7..fc783ae5559 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -97,8 +97,9 @@ #include "set_var.h" #include "rpl_injector.h" - #include "rpl_handler.h" +#include "semisync_master.h" +#include "semisync_slave.h" #ifdef HAVE_SYS_PRCTL_H #include <sys/prctl.h> @@ -934,6 +935,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, PSI_mutex_key key_RELAYLOG_LOCK_index; PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry; +PSI_mutex_key key_LOCK_binlog; PSI_mutex_key key_LOCK_stats, key_LOCK_global_user_client_stats, key_LOCK_global_table_stats, @@ -1021,7 +1023,8 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_binlog_state, "LOCK_binlog_state", 0}, { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0}, { &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0}, - { &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0} + { &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0}, + { &key_LOCK_binlog, "LOCK_binlog", 0} }; PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger, @@ -1062,7 +1065,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_rpl_group_info_sleep_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, - key_COND_start_thread, + key_COND_start_thread, key_COND_binlog_send, key_BINLOG_COND_queue_busy; PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready, key_COND_wait_commit; @@ -1124,7 +1127,8 @@ static PSI_cond_info all_server_conds[]= { &key_COND_slave_background, "COND_slave_background", 0}, { &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL}, { &key_COND_wait_gtid, "COND_wait_gtid", 0}, - { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0} + { &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0}, + { &key_COND_binlog_send, "COND_binlog_send", 0} }; PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert, @@ -2217,6 +2221,10 @@ void clean_up(bool print_message) ha_end(); if (tc_log) tc_log->close(); +#ifdef HAVE_REPLICATION + semi_sync_master_deinit(); + semi_sync_slave_deinit(); +#endif delegates_destroy(); xid_cache_free(); tdc_deinit(); @@ -5170,6 +5178,9 @@ static int init_server_components() "this server. However this will be ignored as the " "--log-bin option is not defined."); } + + semi_sync_master_init(); + semi_sync_slave_init(); #endif if (opt_bin_log) @@ -8230,6 +8241,27 @@ static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff, return 0; } +#define SHOW_FNAME(name) \ + rpl_semi_sync_master_show_##name + +#define DEF_SHOW_FUNC(name, show_type) \ + static int SHOW_FNAME(name)(MYSQL_THD thd, SHOW_VAR *var, char *buff) \ + { \ + repl_semisync_master.setExportStats(); \ + var->type= show_type; \ + var->value= (char *)&rpl_semi_sync_master_##name; \ + return 0; \ + } + +DEF_SHOW_FUNC(status, SHOW_BOOL) +DEF_SHOW_FUNC(clients, SHOW_LONG) +DEF_SHOW_FUNC(wait_sessions, SHOW_LONG) +DEF_SHOW_FUNC(trx_wait_time, SHOW_LONGLONG) +DEF_SHOW_FUNC(trx_wait_num, SHOW_LONGLONG) +DEF_SHOW_FUNC(net_wait_time, SHOW_LONGLONG) +DEF_SHOW_FUNC(net_wait_num, SHOW_LONGLONG) +DEF_SHOW_FUNC(avg_net_wait_time, SHOW_LONG) +DEF_SHOW_FUNC(avg_trx_wait_time, SHOW_LONG) #ifdef HAVE_YASSL @@ -8548,6 +8580,30 @@ SHOW_VAR status_vars[]= { {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS}, {"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS}, {"Rows_tmp_read", (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS}, +#ifdef HAVE_REPLICATION + {"Rpl_semi_sync_master_status", (char*) &SHOW_FNAME(status), SHOW_FUNC}, + {"Rpl_semi_sync_master_clients", (char*) &SHOW_FNAME(clients), SHOW_FUNC}, + {"Rpl_semi_sync_master_yes_tx", (char*) &rpl_semi_sync_master_yes_transactions, SHOW_LONG}, + {"Rpl_semi_sync_master_no_tx", (char*) &rpl_semi_sync_master_no_transactions, SHOW_LONG}, + {"Rpl_semi_sync_master_wait_sessions", (char*) &SHOW_FNAME(wait_sessions), SHOW_FUNC}, + {"Rpl_semi_sync_master_no_times", (char*) &rpl_semi_sync_master_off_times, SHOW_LONG}, + {"Rpl_semi_sync_master_timefunc_failures", (char*) &rpl_semi_sync_master_timefunc_fails, SHOW_LONG}, + {"Rpl_semi_sync_master_wait_pos_backtraverse", (char*) &rpl_semi_sync_master_wait_pos_backtraverse, SHOW_LONG}, + {"Rpl_semi_sync_master_tx_wait_time", (char*) &SHOW_FNAME(trx_wait_time), SHOW_FUNC}, + {"Rpl_semi_sync_master_tx_waits", (char*) &SHOW_FNAME(trx_wait_num), SHOW_FUNC}, + {"Rpl_semi_sync_master_tx_avg_wait_time", (char*) &SHOW_FNAME(avg_trx_wait_time), SHOW_FUNC}, + {"Rpl_semi_sync_master_net_wait_time", (char*) &SHOW_FNAME(net_wait_time), SHOW_FUNC}, + {"Rpl_semi_sync_master_net_waits", (char*) &SHOW_FNAME(net_wait_num), SHOW_FUNC}, + {"Rpl_semi_sync_master_net_avg_wait_time", (char*) &SHOW_FNAME(avg_net_wait_time), SHOW_FUNC}, +#ifdef HAVE_ACC_RECEIVER + {"Rpl_semi_sync_master_request_ack", (char*) &rpl_semi_sync_master_request_ack, SHOW_LONGLONG}, + {"Rpl_semi_sync_master_get_ack", (char*)&rpl_semi_sync_master_get_ack, SHOW_LONGLONG}, +#endif + {"Rpl_semi_sync_slave_status", (char*) &rpl_semi_sync_slave_status, SHOW_BOOL}, +#ifdef HAVE_ACC_RECEIVER + {"Rpl_semi_sync_slave_send_ack", (char*) &rpl_semi_sync_slave_send_ack, SHOW_LONGLONG}, +#endif +#endif /* HAVE_REPLICATION */ #ifdef HAVE_QUERY_CACHE {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH}, {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH}, @@ -10285,6 +10341,8 @@ PSI_stage_info stage_waiting_for_insert= { 0, "Waiting for INSERT", 0}; PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0}; PSI_stage_info stage_waiting_for_master_update= { 0, "Waiting for master update", 0}; PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0}; +PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave= +{ 0, "Waiting for semi-sync ACK from slave", 0}; PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0}; PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0}; PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0}; diff --git a/sql/replication.h b/sql/replication.h index 4731c2246ef..d8672310110 100644 --- a/sql/replication.h +++ b/sql/replication.h @@ -18,16 +18,14 @@ /*************************************************************************** NOTE: plugin locking. - This API was created specifically for the semisync plugin and its locking - logic is also matches semisync plugin usage pattern. In particular, a plugin - is locked on Binlog_transmit_observer::transmit_start and is unlocked after - Binlog_transmit_observer::transmit_stop. All other master observable events - happen between these two and don't lock the plugin at all. This works well - for the semisync_master plugin. + + The plugin is locked on Binlog_transmit_observer::transmit_start and is + unlocked after Binlog_transmit_observer::transmit_stop. All other + master observable events happen between these two and don't lock the + plugin at all. Also a plugin is locked on Binlog_relay_IO_observer::thread_start - and unlocked after Binlog_relay_IO_observer::thread_stop. This works well for - the semisync_slave plugin. + and unlocked after Binlog_relay_IO_observer::thread_stop. ***************************************************************************/ #include <mysql.h> diff --git a/sql/rpl_handler.cc b/sql/rpl_handler.cc index e3ff2a17a6a..27e411ca6de 100644 --- a/sql/rpl_handler.cc +++ b/sql/rpl_handler.cc @@ -149,13 +149,17 @@ void delegates_destroy() { if (transaction_delegate) transaction_delegate->~Trans_delegate(); + transaction_delegate= 0; if (binlog_storage_delegate) binlog_storage_delegate->~Binlog_storage_delegate(); + binlog_storage_delegate= 0; #ifdef HAVE_REPLICATION if (binlog_transmit_delegate) binlog_transmit_delegate->~Binlog_transmit_delegate(); + binlog_transmit_delegate= 0; if (binlog_relay_io_delegate) binlog_relay_io_delegate->~Binlog_relay_IO_delegate(); + binlog_relay_io_delegate= 0; #endif /* HAVE_REPLICATION */ } @@ -171,13 +175,11 @@ void delegates_destroy() Observer_info *info= iter++; \ for (; info; info= iter++) \ { \ - if (do_lock) plugin_lock(thd, plugin_int_to_ref(info->plugin_int)); \ if (((Observer *)info->observer)->f \ && ((Observer *)info->observer)->f args) \ { \ r= 1; \ - sql_print_error("Run function '" #f "' in plugin '%s' failed", \ - info->plugin_int->name.str); \ + sql_print_error("Run function '" #f "' failed"); \ break; \ } \ } \ diff --git a/plugin/semisync/semisync.cc b/sql/semisync.cc index df37f03ec2f..df37f03ec2f 100644 --- a/plugin/semisync/semisync.cc +++ b/sql/semisync.cc diff --git a/plugin/semisync/semisync.h b/sql/semisync.h index 28577296817..3142f920f1e 100644 --- a/plugin/semisync/semisync.h +++ b/sql/semisync.h @@ -1,6 +1,5 @@ /* Copyright (C) 2007 Google Inc. Copyright (C) 2008 MySQL AB - Use is subject to license terms This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,18 +18,9 @@ #ifndef SEMISYNC_H #define SEMISYNC_H -#define MYSQL_SERVER -#define HAVE_REPLICATION -#include <my_pthread.h> -#include <sql_priv.h> -#include <sql_class.h> -#include "unireg.h" -#include <replication.h> -#include "log.h" /* sql_print_information */ - -typedef struct st_mysql_show_var SHOW_VAR; -typedef struct st_mysql_sys_var SYS_VAR; - +#include "mysqld.h" +#include "log_event.h" +#include "replication.h" /** This class is used to trace function calls and other process diff --git a/plugin/semisync/semisync_master.cc b/sql/semisync_master.cc index 975b2e13253..21c52addce9 100644 --- a/plugin/semisync/semisync_master.cc +++ b/sql/semisync_master.cc @@ -24,34 +24,35 @@ #define TIME_BILLION 1000000000 /* This indicates whether semi-synchronous replication is enabled. */ -char rpl_semi_sync_master_enabled; -unsigned long rpl_semi_sync_master_wait_point = +my_bool rpl_semi_sync_master_enabled; +my_bool rpl_semi_sync_master_wait_no_slave = 1; +my_bool rpl_semi_sync_master_status = 0; +ulong rpl_semi_sync_master_wait_point = SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT; -unsigned long rpl_semi_sync_master_timeout; -unsigned long rpl_semi_sync_master_trace_level; -char rpl_semi_sync_master_status = 0; -unsigned long rpl_semi_sync_master_yes_transactions = 0; -unsigned long rpl_semi_sync_master_no_transactions = 0; -unsigned long rpl_semi_sync_master_off_times = 0; -unsigned long rpl_semi_sync_master_timefunc_fails = 0; -unsigned long rpl_semi_sync_master_wait_timeouts = 0; -unsigned long rpl_semi_sync_master_wait_sessions = 0; -unsigned long rpl_semi_sync_master_wait_pos_backtraverse = 0; -unsigned long rpl_semi_sync_master_avg_trx_wait_time = 0; -unsigned long long rpl_semi_sync_master_trx_wait_num = 0; -unsigned long rpl_semi_sync_master_avg_net_wait_time = 0; -unsigned long long rpl_semi_sync_master_net_wait_num = 0; -unsigned long rpl_semi_sync_master_clients = 0; -unsigned long long rpl_semi_sync_master_net_wait_time = 0; -unsigned long long rpl_semi_sync_master_trx_wait_time = 0; -char rpl_semi_sync_master_wait_no_slave = 1; - +ulong rpl_semi_sync_master_timeout; +ulong rpl_semi_sync_master_trace_level; +ulong rpl_semi_sync_master_yes_transactions = 0; +ulong rpl_semi_sync_master_no_transactions = 0; +ulong rpl_semi_sync_master_off_times = 0; +ulong rpl_semi_sync_master_timefunc_fails = 0; +ulong rpl_semi_sync_master_wait_timeouts = 0; +ulong rpl_semi_sync_master_wait_sessions = 0; +ulong rpl_semi_sync_master_wait_pos_backtraverse = 0; +ulong rpl_semi_sync_master_avg_trx_wait_time = 0; +ulonglong rpl_semi_sync_master_trx_wait_num = 0; +ulong rpl_semi_sync_master_avg_net_wait_time = 0; +ulonglong rpl_semi_sync_master_net_wait_num = 0; +ulong rpl_semi_sync_master_clients = 0; +ulonglong rpl_semi_sync_master_net_wait_time = 0; +ulonglong rpl_semi_sync_master_trx_wait_time = 0; + +ReplSemiSyncMaster repl_semisync_master; static int getWaitTime(const struct timespec& start_ts); -static unsigned long long timespec_to_usec(const struct timespec *ts) +static ulonglong timespec_to_usec(const struct timespec *ts) { - return (unsigned long long) ts->tv_sec * TIME_MILLION + ts->tv_nsec / TIME_THOUSAND; + return (ulonglong) ts->tv_sec * TIME_MILLION + ts->tv_nsec / TIME_THOUSAND; } /******************************************************************************* @@ -61,7 +62,7 @@ static unsigned long long timespec_to_usec(const struct timespec *ts) ******************************************************************************/ ActiveTranx::ActiveTranx(mysql_mutex_t *lock, - unsigned long trace_level) + ulong trace_level) : Trace(trace_level), allocator_(max_connections), num_entries_(max_connections << 1), /* Transaction hash table size * is set to double the size @@ -141,7 +142,7 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name, if (!ins_node) { sql_print_error("%s: transaction node allocation failed for: (%s, %lu)", - kWho, log_file_name, (unsigned long)log_file_pos); + kWho, log_file_name, (ulong)log_file_pos); result = -1; goto l_end; } @@ -174,8 +175,8 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name, */ sql_print_error("%s: binlog write out-of-order, tail (%s, %lu), " "new node (%s, %lu)", kWho, - trx_rear_->log_name_, (unsigned long)trx_rear_->log_pos_, - ins_node->log_name_, (unsigned long)ins_node->log_pos_); + trx_rear_->log_name_, (ulong)trx_rear_->log_pos_, + ins_node->log_name_, (ulong)ins_node->log_pos_); result = -1; goto l_end; } @@ -187,7 +188,7 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name, if (trace_level_ & kTraceDetail) sql_print_information("%s: insert (%s, %lu) in entry(%u)", kWho, - ins_node->log_name_, (unsigned long)ins_node->log_pos_, + ins_node->log_name_, (ulong)ins_node->log_pos_, hash_val); l_end: @@ -213,7 +214,7 @@ bool ActiveTranx::is_tranx_end_pos(const char *log_file_name, if (trace_level_ & kTraceDetail) sql_print_information("%s: probe (%s, %lu) in entry(%u)", kWho, - log_file_name, (unsigned long)log_file_pos, hash_val); + log_file_name, (ulong)log_file_pos, hash_val); function_exit(kWho, (entry != NULL)); return (entry != NULL); @@ -296,7 +297,7 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name, if (trace_level_ & kTraceDetail) sql_print_information("%s: cleared %d nodes back until pos (%s, %lu)", kWho, n_frees, - trx_front_->log_name_, (unsigned long)trx_front_->log_pos_); + trx_front_->log_name_, (ulong)trx_front_->log_pos_); } return function_exit(kWho, 0); @@ -358,10 +359,10 @@ int ReplSemiSyncMaster::initObject() setTraceLevel(rpl_semi_sync_master_trace_level); /* Mutex initialization can only be done after MY_INIT(). */ - mysql_mutex_init(key_ss_mutex_LOCK_binlog_, - &LOCK_binlog_, MY_MUTEX_INIT_FAST); - mysql_cond_init(key_ss_cond_COND_binlog_send_, - &COND_binlog_send_, NULL); + mysql_mutex_init(key_LOCK_binlog, + &LOCK_binlog, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_binlog_send, + &COND_binlog_send, NULL); if (rpl_semi_sync_master_enabled) result = enableMaster(); @@ -380,7 +381,7 @@ int ReplSemiSyncMaster::enableMaster() if (!getMasterEnabled()) { - active_tranxs_ = new ActiveTranx(&LOCK_binlog_, trace_level_); + active_tranxs_ = new ActiveTranx(&LOCK_binlog, trace_level_); if (active_tranxs_ != NULL) { commit_file_name_inited_ = false; @@ -389,6 +390,7 @@ int ReplSemiSyncMaster::enableMaster() set_master_enabled(true); state_ = true; + run_hooks_enabled= 1; sql_print_information("Semi-sync replication enabled on the master."); } else @@ -436,8 +438,8 @@ void ReplSemiSyncMaster::cleanup() { if (init_done_) { - mysql_mutex_destroy(&LOCK_binlog_); - mysql_cond_destroy(&COND_binlog_send_); + mysql_mutex_destroy(&LOCK_binlog); + mysql_cond_destroy(&COND_binlog_send); init_done_= 0; } @@ -446,17 +448,17 @@ void ReplSemiSyncMaster::cleanup() void ReplSemiSyncMaster::lock() { - mysql_mutex_lock(&LOCK_binlog_); + mysql_mutex_lock(&LOCK_binlog); } void ReplSemiSyncMaster::unlock() { - mysql_mutex_unlock(&LOCK_binlog_); + mysql_mutex_unlock(&LOCK_binlog); } void ReplSemiSyncMaster::cond_broadcast() { - mysql_cond_broadcast(&COND_binlog_send_); + mysql_cond_broadcast(&COND_binlog_send); } int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time) @@ -465,8 +467,8 @@ int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time) int wait_res; function_enter(kWho); - wait_res= mysql_cond_timedwait(&COND_binlog_send_, - &LOCK_binlog_, wait_time); + wait_res= mysql_cond_timedwait(&COND_binlog_send, + &LOCK_binlog, wait_time); return function_exit(kWho, wait_res); } @@ -566,7 +568,7 @@ int ReplSemiSyncMaster::reportReplyBinlog(uint32 server_id, if (trace_level_ & kTraceDetail) sql_print_information("%s: Got reply at (%s, %lu)", kWho, - log_file_name, (unsigned long)log_file_pos); + log_file_name, (ulong)log_file_pos); } if (rpl_semi_sync_master_wait_sessions > 0) @@ -621,7 +623,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, lock(); /* This must be called after acquired the lock */ - THD_ENTER_COND(NULL, &COND_binlog_send_, &LOCK_binlog_, + THD_ENTER_COND(NULL, &COND_binlog_send, &LOCK_binlog, & stage_waiting_for_semi_sync_ack_from_slave, & old_stage); @@ -632,7 +634,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, if (trace_level_ & kTraceDetail) { sql_print_information("%s: wait pos (%s, %lu), repl(%d)\n", kWho, - trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos, + trx_wait_binlog_name, (ulong)trx_wait_binlog_pos, (int)is_on()); } @@ -649,7 +651,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, */ if (trace_level_ & kTraceDetail) sql_print_information("%s: Binlog reply is ahead (%s, %lu),", - kWho, reply_file_name_, (unsigned long)reply_file_pos_); + kWho, reply_file_name_, (ulong)reply_file_pos_); break; } } @@ -670,7 +672,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, rpl_semi_sync_master_wait_pos_backtraverse++; if (trace_level_ & kTraceDetail) sql_print_information("%s: move back wait position (%s, %lu),", - kWho, wait_file_name_, (unsigned long)wait_file_pos_); + kWho, wait_file_name_, (ulong)wait_file_pos_); } } else @@ -681,16 +683,16 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, if (trace_level_ & kTraceDetail) sql_print_information("%s: init wait position (%s, %lu),", - kWho, wait_file_name_, (unsigned long)wait_file_pos_); + kWho, wait_file_name_, (ulong)wait_file_pos_); } /* Calcuate the waiting period. */ - long diff_secs = (long) (wait_timeout_ / TIME_THOUSAND); + long diff_secs = (long) (wait_timeout_ / TIME_THOUSAND); long diff_nsecs = (long) ((wait_timeout_ % TIME_THOUSAND) * TIME_MILLION); long nsecs = start_ts.tv_nsec + diff_nsecs; abstime.tv_sec = start_ts.tv_sec + diff_secs + nsecs/TIME_BILLION; abstime.tv_nsec = nsecs % TIME_BILLION; - + /* In semi-synchronous replication, we wait until the binlog-dump * thread has received the reply on the relevant binlog segment from the * replication slave. @@ -700,31 +702,31 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, * these waiting threads. */ rpl_semi_sync_master_wait_sessions++; - + if (trace_level_ & kTraceDetail) sql_print_information("%s: wait %lu ms for binlog sent (%s, %lu)", kWho, wait_timeout_, - wait_file_name_, (unsigned long)wait_file_pos_); - + wait_file_name_, (ulong)wait_file_pos_); + wait_result = cond_timewait(&abstime); rpl_semi_sync_master_wait_sessions--; - + if (wait_result != 0) { /* This is a real wait timeout. */ sql_print_warning("Timeout waiting for reply of binlog (file: %s, pos: %lu), " "semi-sync up to file %s, position %lu.", - trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos, - reply_file_name_, (unsigned long)reply_file_pos_); + trx_wait_binlog_name, (ulong)trx_wait_binlog_pos, + reply_file_name_, (ulong)reply_file_pos_); rpl_semi_sync_master_wait_timeouts++; - + /* switch semi-sync off */ switch_off(); } else { int wait_time; - + wait_time = getWaitTime(start_ts); if (wait_time < 0) { @@ -732,7 +734,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, { sql_print_error("Replication semi-sync getWaitTime fail at " "wait position (%s, %lu)", - trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos); + trx_wait_binlog_name, (ulong)trx_wait_binlog_pos); } rpl_semi_sync_master_timefunc_fails++; } @@ -753,7 +755,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, assert(thd_killed(current_thd) || !active_tranxs_ || !active_tranxs_->is_tranx_end_pos(trx_wait_binlog_name, trx_wait_binlog_pos)); - + l_end: /* Update the status counter. */ if (is_on()) @@ -770,7 +772,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, } /* Indicate that semi-sync replication is OFF now. - * + * * What should we do when it is disabled? The problem is that we want * the semi-sync replication enabled again when the slave catches up * later. But, it is not that easy to detect that the slave has caught @@ -842,14 +844,14 @@ int ReplSemiSyncMaster::try_switch_on(int server_id, sql_print_information("Semi-sync replication switched ON with slave (server_id: %d) " "at (%s, %lu)", server_id, log_file_name, - (unsigned long)log_file_pos); + (ulong)log_file_pos); } return function_exit(kWho, 0); } int ReplSemiSyncMaster::reserveSyncHeader(unsigned char *header, - unsigned long size) + ulong size) { const char *kWho = "ReplSemiSyncMaster::reserveSyncHeader"; function_enter(kWho); @@ -870,7 +872,7 @@ int ReplSemiSyncMaster::reserveSyncHeader(unsigned char *header, disableMaster(); return 0; } - + /* Set the magic number and the sync status. By default, no sync * is required. */ @@ -930,13 +932,13 @@ int ReplSemiSyncMaster::updateSyncHeader(unsigned char *packet, { cmp = 1; } - + /* If we are already waiting for some transaction replies which * are later in binlog, do not wait for this one event. */ if (cmp >= 0) { - /* + /* * We only wait if the event is a transaction's ending event. */ assert(active_tranxs_ != NULL); @@ -961,7 +963,7 @@ int ReplSemiSyncMaster::updateSyncHeader(unsigned char *packet, if (trace_level_ & kTraceDetail) sql_print_information("%s: server(%d), (%s, %lu) sync(%d), repl(%d)", kWho, server_id, log_file_name, - (unsigned long)log_file_pos, sync, (int)is_on()); + (ulong)log_file_pos, sync, (int)is_on()); l_end: unlock(); @@ -1181,27 +1183,27 @@ void ReplSemiSyncMaster::setExportStats() rpl_semi_sync_master_status = state_; rpl_semi_sync_master_avg_trx_wait_time= ((rpl_semi_sync_master_trx_wait_num) ? - (unsigned long)((double)rpl_semi_sync_master_trx_wait_time / + (ulong)((double)rpl_semi_sync_master_trx_wait_time / ((double)rpl_semi_sync_master_trx_wait_num)) : 0); rpl_semi_sync_master_avg_net_wait_time= ((rpl_semi_sync_master_net_wait_num) ? - (unsigned long)((double)rpl_semi_sync_master_net_wait_time / + (ulong)((double)rpl_semi_sync_master_net_wait_time / ((double)rpl_semi_sync_master_net_wait_num)) : 0); unlock(); } /* Get the waiting time given the wait's staring time. - * + * * Return: * >= 0: the waiting time in microsecons(us) * < 0: error in get time or time back traverse */ static int getWaitTime(const struct timespec& start_ts) { - unsigned long long start_usecs, end_usecs; + ulonglong start_usecs, end_usecs; struct timespec end_ts; - + /* Starting time in microseconds(us). */ start_usecs = timespec_to_usec(&start_ts); @@ -1216,3 +1218,213 @@ static int getWaitTime(const struct timespec& start_ts) return (int)(end_usecs - start_usecs); } + +/*************************************************************************** + Semisync master interface setup and deinit +***************************************************************************/ + +C_MODE_START + +int repl_semi_report_binlog_update(Binlog_storage_param *param, + const char *log_file, + my_off_t log_pos, uint32 flags) +{ + int error= 0; + + if (repl_semisync_master.getMasterEnabled()) + { + /* + Let us store the binlog file name and the position, so that + we know how long to wait for the binlog to the replicated to + the slave in synchronous replication. + */ + error= repl_semisync_master.writeTranxInBinlog(log_file, + log_pos); + } + + return error; +} + +int repl_semi_request_commit(Trans_param *param) +{ + return 0; +} + +int repl_semi_report_binlog_sync(Binlog_storage_param *param, + const char *log_file, + my_off_t log_pos, uint32 flags) +{ + int error= 0; + if (rpl_semi_sync_master_wait_point == + SEMI_SYNC_MASTER_WAIT_POINT_AFTER_BINLOG_SYNC) + { + error= repl_semisync_master.commitTrx(log_file, log_pos); + } + + return error; +} + +int repl_semi_report_commit(Trans_param *param) +{ + if (rpl_semi_sync_master_wait_point != + SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT) + { + return 0; + } + + bool is_real_trans= param->flags & TRANS_IS_REAL_TRANS; + + if (is_real_trans && param->log_pos) + { + const char *binlog_name= param->log_file; + return repl_semisync_master.commitTrx(binlog_name, param->log_pos); + } + return 0; +} + +int repl_semi_report_rollback(Trans_param *param) +{ + return repl_semi_report_commit(param); +} + +int repl_semi_binlog_dump_start(Binlog_transmit_param *param, + const char *log_file, + my_off_t log_pos) +{ + bool semi_sync_slave= repl_semisync_master.is_semi_sync_slave(); + + if (semi_sync_slave) + { + /* One more semi-sync slave */ + repl_semisync_master.add_slave(); + + /* + Let's assume this semi-sync slave has already received all + binlog events before the filename and position it requests. + */ + repl_semisync_master.reportReplyBinlog(param->server_id, log_file, log_pos); + } + sql_print_information("Start %s binlog_dump to slave (server_id: %d), pos(%s, %lu)", + semi_sync_slave ? "semi-sync" : "asynchronous", + param->server_id, log_file, (ulong)log_pos); + + return 0; +} + +int repl_semi_binlog_dump_end(Binlog_transmit_param *param) +{ + bool semi_sync_slave= repl_semisync_master.is_semi_sync_slave(); + + sql_print_information("Stop %s binlog_dump to slave (server_id: %d)", + semi_sync_slave ? "semi-sync" : "asynchronous", + param->server_id); + if (semi_sync_slave) + { + /* One less semi-sync slave */ + repl_semisync_master.remove_slave(); + } + return 0; +} + +int repl_semi_reserve_header(Binlog_transmit_param *param, + unsigned char *header, + ulong size, ulong *len) +{ + *len += repl_semisync_master.reserveSyncHeader(header, size); + return 0; +} + +int repl_semi_before_send_event(Binlog_transmit_param *param, + unsigned char *packet, ulong len, + const char *log_file, my_off_t log_pos) +{ + return repl_semisync_master.updateSyncHeader(packet, + log_file, + log_pos, + param->server_id); +} + +int repl_semi_after_send_event(Binlog_transmit_param *param, + const char *event_buf, ulong len) +{ + if (repl_semisync_master.is_semi_sync_slave()) + { + THD *thd= current_thd; + /* + Possible errors in reading slave reply are ignored deliberately + because we do not want dump thread to quit on this. Error + messages are already reported. + */ + (void) repl_semisync_master.readSlaveReply(&thd->net, + param->server_id, event_buf); + thd->clear_error(); + } + return 0; +} + +int repl_semi_reset_master(Binlog_transmit_param *param) +{ + if (repl_semisync_master.resetMaster()) + return 1; + return 0; +} + +C_MODE_END + +Trans_observer trans_observer= +{ + sizeof(Trans_observer), // len + + repl_semi_report_commit, // after_commit + repl_semi_report_rollback, // after_rollback +}; + +Binlog_storage_observer storage_observer= +{ + sizeof(Binlog_storage_observer), // len + + repl_semi_report_binlog_update, // report_update + repl_semi_report_binlog_sync, // after_sync +}; + +Binlog_transmit_observer transmit_observer= +{ + sizeof(Binlog_transmit_observer), // len + + repl_semi_binlog_dump_start, // start + repl_semi_binlog_dump_end, // stop + repl_semi_reserve_header, // reserve_header + repl_semi_before_send_event, // before_send_event + repl_semi_after_send_event, // after_send_event + repl_semi_reset_master, // reset +}; + +static bool semi_sync_master_inited= 0; + +int semi_sync_master_init() +{ + void *p= 0; + if (repl_semisync_master.initObject()) + return 1; + if (register_trans_observer(&trans_observer, p)) + return 1; + if (register_binlog_storage_observer(&storage_observer, p)) + return 1; + if (register_binlog_transmit_observer(&transmit_observer, p)) + return 1; + semi_sync_master_inited= 1; + return 0; +} + +void semi_sync_master_deinit() +{ + void *p= 0; + if (!semi_sync_master_inited) + return; + + unregister_trans_observer(&trans_observer, p); + unregister_binlog_storage_observer(&storage_observer, p); + unregister_binlog_transmit_observer(&transmit_observer, p); + repl_semisync_master.cleanup(); + semi_sync_master_inited= 0; +} diff --git a/plugin/semisync/semisync_master.h b/sql/semisync_master.h index c2862476ec8..ff1e3dd48b4 100644 --- a/plugin/semisync/semisync_master.h +++ b/sql/semisync_master.h @@ -22,8 +22,8 @@ #include "semisync.h" #ifdef HAVE_PSI_INTERFACE -extern PSI_mutex_key key_ss_mutex_LOCK_binlog_; -extern PSI_cond_key key_ss_cond_COND_binlog_send_; +extern PSI_mutex_key key_LOCK_binlog; +extern PSI_cond_key key_COND_binlog_send; #endif extern PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave; @@ -379,14 +379,14 @@ class ReplSemiSyncMaster /* This cond variable is signaled when enough binlog has been sent to slave, * so that a waiting trx can return the 'ok' to the client for a commit. */ - mysql_cond_t COND_binlog_send_; + mysql_cond_t COND_binlog_send; /* Mutex that protects the following state variables and the active * transaction list. * Under no cirumstances we can acquire mysql_bin_log.LOCK_log if we are * already holding LOCK_binlog_ because it can cause deadlocks. */ - mysql_mutex_t LOCK_binlog_; + mysql_mutex_t LOCK_binlog; /* This is set to true when reply_file_name_ contains meaningful data. */ bool reply_file_name_inited_; @@ -600,26 +600,26 @@ enum rpl_semi_sync_master_wait_point_t { }; /* System and status variables for the master component */ -extern char rpl_semi_sync_master_enabled; -extern char rpl_semi_sync_master_status; -extern unsigned long rpl_semi_sync_master_wait_point; -extern unsigned long rpl_semi_sync_master_clients; -extern unsigned long rpl_semi_sync_master_timeout; -extern unsigned long rpl_semi_sync_master_trace_level; -extern unsigned long rpl_semi_sync_master_yes_transactions; -extern unsigned long rpl_semi_sync_master_no_transactions; -extern unsigned long rpl_semi_sync_master_off_times; -extern unsigned long rpl_semi_sync_master_wait_timeouts; -extern unsigned long rpl_semi_sync_master_timefunc_fails; -extern unsigned long rpl_semi_sync_master_num_timeouts; -extern unsigned long rpl_semi_sync_master_wait_sessions; -extern unsigned long rpl_semi_sync_master_wait_pos_backtraverse; -extern unsigned long rpl_semi_sync_master_avg_trx_wait_time; -extern unsigned long rpl_semi_sync_master_avg_net_wait_time; -extern unsigned long long rpl_semi_sync_master_net_wait_num; -extern unsigned long long rpl_semi_sync_master_trx_wait_num; -extern unsigned long long rpl_semi_sync_master_net_wait_time; -extern unsigned long long rpl_semi_sync_master_trx_wait_time; +extern my_bool rpl_semi_sync_master_enabled; +extern my_bool rpl_semi_sync_master_status; +extern ulong rpl_semi_sync_master_wait_point; +extern ulong rpl_semi_sync_master_clients; +extern ulong rpl_semi_sync_master_timeout; +extern ulong rpl_semi_sync_master_trace_level; +extern ulong rpl_semi_sync_master_yes_transactions; +extern ulong rpl_semi_sync_master_no_transactions; +extern ulong rpl_semi_sync_master_off_times; +extern ulong rpl_semi_sync_master_wait_timeouts; +extern ulong rpl_semi_sync_master_timefunc_fails; +extern ulong rpl_semi_sync_master_num_timeouts; +extern ulong rpl_semi_sync_master_wait_sessions; +extern ulong rpl_semi_sync_master_wait_pos_backtraverse; +extern ulong rpl_semi_sync_master_avg_trx_wait_time; +extern ulong rpl_semi_sync_master_avg_net_wait_time; +extern ulonglong rpl_semi_sync_master_net_wait_num; +extern ulonglong rpl_semi_sync_master_trx_wait_num; +extern ulonglong rpl_semi_sync_master_net_wait_time; +extern ulonglong rpl_semi_sync_master_trx_wait_time; /* This indicates whether we should keep waiting if no semi-sync slave @@ -628,5 +628,9 @@ extern unsigned long long rpl_semi_sync_master_trx_wait_time; 1 (default) : keep waiting until timeout even no available semi-sync slave. */ extern char rpl_semi_sync_master_wait_no_slave; +extern ReplSemiSyncMaster repl_semisync_master; + +int semi_sync_master_init(); +void semi_sync_master_deinit(); #endif /* SEMISYNC_MASTER_H */ diff --git a/plugin/semisync/semisync_slave.cc b/sql/semisync_slave.cc index ff8a40aafac..63bf9dca0e8 100644 --- a/plugin/semisync/semisync_slave.cc +++ b/sql/semisync_slave.cc @@ -18,9 +18,20 @@ #include <my_global.h> #include "semisync_slave.h" -char rpl_semi_sync_slave_enabled; -char rpl_semi_sync_slave_status= 0; -unsigned long rpl_semi_sync_slave_trace_level; +my_bool rpl_semi_sync_slave_enabled; +my_bool rpl_semi_sync_slave_status= 0; +ulong rpl_semi_sync_slave_trace_level; +ReplSemiSyncSlave repl_semisync_slave; + +/* + indicate whether or not the slave should send a reply to the master. + + This is set to true in repl_semi_slave_read_event if the current + event read is the last event of a transaction. And the value is + checked in repl_semi_slave_queue_event. +*/ +bool semi_sync_need_reply= false; + int ReplSemiSyncSlave::initObject() { @@ -73,7 +84,7 @@ int ReplSemiSyncSlave::slaveReadSyncHeader(const char *header, int ReplSemiSyncSlave::slaveStart(Binlog_relay_IO_param *param) { bool semi_sync= getSlaveEnabled(); - + sql_print_information("Slave I/O thread: Start %s replication to\ master '%s@%s:%d' in log '%s' at position %lu", semi_sync ? "semi-sync" : "asynchronous", @@ -138,3 +149,140 @@ int ReplSemiSyncSlave::slaveReply(MYSQL *mysql, return function_exit(kWho, reply_res); } + +/*************************************************************************** + Semisync slave interface setup and deinit +***************************************************************************/ + +C_MODE_START + +int repl_semi_reset_slave(Binlog_relay_IO_param *param) +{ + // TODO: reset semi-sync slave status here + return 0; +} + +int repl_semi_slave_request_dump(Binlog_relay_IO_param *param, + uint32 flags) +{ + MYSQL *mysql= param->mysql; + MYSQL_RES *res= 0; + MYSQL_ROW row; + const char *query; + + if (!repl_semisync_slave.getSlaveEnabled()) + return 0; + + /* Check if master server has semi-sync plugin installed */ + query= "SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled'"; + if (mysql_real_query(mysql, query, strlen(query)) || + !(res= mysql_store_result(mysql))) + { + sql_print_error("Execution failed on master: %s", query); + return 1; + } + + row= mysql_fetch_row(res); + if (!row) + { + /* Master does not support semi-sync */ + sql_print_warning("Master server does not support semi-sync, " + "fallback to asynchronous replication"); + rpl_semi_sync_slave_status= 0; + mysql_free_result(res); + return 0; + } + mysql_free_result(res); + + /* + Tell master dump thread that we want to do semi-sync + replication + */ + query= "SET @rpl_semi_sync_slave= 1"; + if (mysql_real_query(mysql, query, strlen(query))) + { + sql_print_error("Set 'rpl_semi_sync_slave=1' on master failed"); + return 1; + } + mysql_free_result(mysql_store_result(mysql)); + rpl_semi_sync_slave_status= 1; + return 0; +} + +int repl_semi_slave_read_event(Binlog_relay_IO_param *param, + const char *packet, unsigned long len, + const char **event_buf, unsigned long *event_len) +{ + if (rpl_semi_sync_slave_status) + return repl_semisync_slave.slaveReadSyncHeader(packet, len, + &semi_sync_need_reply, + event_buf, event_len); + *event_buf= packet; + *event_len= len; + return 0; +} + +int repl_semi_slave_queue_event(Binlog_relay_IO_param *param, + const char *event_buf, + unsigned long event_len, + uint32 flags) +{ + if (rpl_semi_sync_slave_status && semi_sync_need_reply) + { + /* + We deliberately ignore the error in slaveReply, such error + should not cause the slave IO thread to stop, and the error + messages are already reported. + */ + (void) repl_semisync_slave.slaveReply(param->mysql, + param->master_log_name, + param->master_log_pos); + } + return 0; +} + +int repl_semi_slave_io_start(Binlog_relay_IO_param *param) +{ + return repl_semisync_slave.slaveStart(param); +} + +int repl_semi_slave_io_end(Binlog_relay_IO_param *param) +{ + return repl_semisync_slave.slaveStop(param); +} + +C_MODE_END + +Binlog_relay_IO_observer relay_io_observer= +{ + sizeof(Binlog_relay_IO_observer), // len + + repl_semi_slave_io_start, // start + repl_semi_slave_io_end, // stop + repl_semi_slave_request_dump, // request_transmit + repl_semi_slave_read_event, // after_read_event + repl_semi_slave_queue_event, // after_queue_event + repl_semi_reset_slave, // reset +}; + +static bool semi_sync_slave_inited= 0; + +int semi_sync_slave_init() +{ + void *p= 0; + if (repl_semisync_slave.initObject()) + return 1; + if (register_binlog_relay_io_observer(&relay_io_observer, p)) + return 1; + semi_sync_slave_inited= 1; + return 0; +} + +void semi_sync_slave_deinit() +{ + void *p= 0; + if (!semi_sync_slave_inited) + return; + unregister_binlog_relay_io_observer(&relay_io_observer, p); + semi_sync_slave_inited= 0; +} diff --git a/plugin/semisync/semisync_slave.h b/sql/semisync_slave.h index 1bf8cf31972..9cca8bbbdb4 100644 --- a/plugin/semisync/semisync_slave.h +++ b/sql/semisync_slave.h @@ -90,8 +90,12 @@ private: /* System and status variables for the slave component */ -extern char rpl_semi_sync_slave_enabled; -extern unsigned long rpl_semi_sync_slave_trace_level; -extern char rpl_semi_sync_slave_status; +extern my_bool rpl_semi_sync_slave_enabled; +extern my_bool rpl_semi_sync_slave_status; +extern ulong rpl_semi_sync_slave_trace_level; +extern ReplSemiSyncSlave repl_semisync_slave; + +int semi_sync_slave_init(); +void semi_sync_slave_deinit(); #endif /* SEMISYNC_SLAVE_H */ diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 82f8359fefc..e897b6c21ce 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -61,6 +61,8 @@ #include "sql_repl.h" #include "opt_range.h" #include "rpl_parallel.h" +#include "semisync_master.h" +#include "semisync_slave.h" #include <ssl_compat.h> /* @@ -3039,8 +3041,188 @@ static Sys_var_replicate_events_marked_for_skip Replicate_events_marked_for_skip "the slave).", GLOBAL_VAR(opt_replicate_events_marked_for_skip), CMD_LINE(REQUIRED_ARG), replicate_events_marked_for_skip_names, DEFAULT(RPL_SKIP_REPLICATE)); + +/* new options for semisync */ + +static bool fix_rpl_semi_sync_master_enabled(sys_var *self, THD *thd, + enum_var_type type) +{ + if (rpl_semi_sync_master_enabled) + { + if (repl_semisync_master.enableMaster() != 0) + rpl_semi_sync_master_enabled= false; +#ifdef HAVE_ACC_RECEIVER + else if (ack_receiver.start()) + { + repl_semisync_master.disableMaster(); + rpl_semi_sync_master_enabled= false; + } +#endif + } + else + { + if (repl_semisync_master.disableMaster() != 0) + rpl_semi_sync_master_enabled= true; +#ifdef HAVE_ACC_RECEIVER + if (!rpl_semi_sync_master_enabled) + ack_receiver.stop(); +#endif + } + return false; +} + +static bool fix_rpl_semi_sync_master_timeout(sys_var *self, THD *thd, + enum_var_type type) +{ + repl_semisync_master.setWaitTimeout(rpl_semi_sync_master_timeout); + return false; +} + +static bool fix_rpl_semi_sync_master_trace_level(sys_var *self, THD *thd, + enum_var_type type) +{ + repl_semisync_master.setTraceLevel(rpl_semi_sync_master_trace_level); +#ifdef HAVE_ACC_RECEIVER + ack_receiver.setTraceLevel(rpl_semi_sync_master_trace_level); +#endif + return false; +} + +static bool fix_rpl_semi_sync_master_wait_point(sys_var *self, THD *thd, + enum_var_type type) +{ +#ifdef HAVE_ACC_RECEIVER + repl_semisync_master.setWaitPoint(rpl_semi_sync_master_wait_point); #endif + return false; +} + +static bool fix_rpl_semi_sync_master_wait_no_slave(sys_var *self, THD *thd, + enum_var_type type) +{ +#ifdef HAVE_ACC_RECEIVER + repl_semisync_master.checkAndSwitch(); +#endif + return false; +} + +static Sys_var_mybool Sys_semisync_master_enabled( + "rpl_semi_sync_master_enabled", + "Enable semi-synchronous replication master (disabled by default).", + GLOBAL_VAR(rpl_semi_sync_master_enabled), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_master_enabled)); + +static Sys_var_ulong Sys_semisync_master_timeout( + "rpl_semi_sync_master_timeout", + "The timeout value (in ms) for semi-synchronous replication in the " + "master", + GLOBAL_VAR(rpl_semi_sync_master_timeout), + CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0,~0L),DEFAULT(10000),BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_master_timeout)); +static Sys_var_mybool Sys_semisync_master_wait_no_slave( + "rpl_semi_sync_master_wait_no_slave", + "Wait until timeout when no semi-synchronous replication slave " + "available (enabled by default).", + GLOBAL_VAR(rpl_semi_sync_master_wait_no_slave), + CMD_LINE(OPT_ARG), DEFAULT(TRUE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_master_wait_no_slave)); + +static Sys_var_ulong Sys_semisync_master_trace_level( + "rpl_semi_sync_master_trace_level", + "The tracing level for semi-sync replication.", + GLOBAL_VAR(rpl_semi_sync_master_trace_level), + CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0,~0L),DEFAULT(32),BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_master_trace_level)); + +static const char *repl_semisync_wait_point[]= +{"AFTER_SYNC", "AFTER_COMMIT", NullS}; + +static Sys_var_enum Sys_semisync_master_wait_point( + "rpl_semi_sync_master_wait_point", + "Should transaction wait for semi-sync ack after having synced binlog, " + "or after having committed in storage engine.", + GLOBAL_VAR(rpl_semi_sync_master_wait_point), CMD_LINE(REQUIRED_ARG), + repl_semisync_wait_point, DEFAULT(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG,ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_master_wait_point)); + +static bool fix_rpl_semi_sync_slave_enabled(sys_var *self, THD *thd, + enum_var_type type) +{ + repl_semisync_slave.setSlaveEnabled(rpl_semi_sync_slave_enabled != 0); + return false; +} + +static bool fix_rpl_semi_sync_slave_trace_level(sys_var *self, THD *thd, + enum_var_type type) +{ + repl_semisync_slave.setTraceLevel(rpl_semi_sync_slave_trace_level); + return false; +} + +#ifdef HAVE_ACC_RECEIVER +static bool fix_rpl_semi_sync_slave_delay_master(sys_var *self, THD *thd, + enum_var_type type) +{ + repl_semisync_slave.setDelayMaster(rpl_semi_sync_slave_delay_master); + return false; +} + +static bool fix_rpl_semi_sync_slave_kill_conn_timeout(sys_var *self, THD *thd, + enum_var_type type) +{ + repl_semisync_slave.setKillConnTimeout(rpl_semi_sync_slave_kill_conn_timeout); + return false; +} +#endif + + +static Sys_var_mybool Sys_semisync_slave_enabled( + "rpl_semi_sync_slave_enabled", + "Enable semi-synchronous replication slave (disabled by default).", + GLOBAL_VAR(rpl_semi_sync_slave_enabled), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_slave_enabled)); + +static Sys_var_ulong Sys_semisync_slave_trace_level( + "rpl_semi_sync_slave_trace_level", + "The tracing level for semi-sync replication.", + GLOBAL_VAR(rpl_semi_sync_slave_trace_level), + CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0,~0L),DEFAULT(32),BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_slave_trace_level)); + +#ifdef HAVE_ACC_RECEIVER +static Sys_var_mybool Sys_semisync_slave_delay_master( + "rpl_semi_sync_slave_delay_master", + "Only write master info file when ack is needed.", + GLOBAL_VAR(rpl_semi_sync_slave_delay_master), + CMD_LINE(OPT_ARG), DEFAULT(FALSE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_slave_delay_master)); + +static Sys_var_uint Sys_semisync_slave_kill_conn_timeout( + "rpl_semi_sync_slave_kill_conn_timeout", + "Timeout for the mysql connection used to kill the slave io_thread's " + "connection on master. This timeout comes into play when stop slave " + "is executed.", + GLOBAL_VAR(rpl_semi_sync_slave_kill_conn_timeout), + CMD_LINE(OPT_ARG), + VALID_RANGE(0, UINT_MAX), DEFAULT(5), BLOCK_SIZE(1), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(fix_rpl_semi_sync_slave_kill_conn_timeout)); +#endif +#endif /* HAVE_REPLICATION */ static Sys_var_ulong Sys_slow_launch_time( "slow_launch_time", |