Commit 2e9a39f3 authored by Monty's avatar Monty Committed by Andrei Elkin

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.
parent 343bcb15
...@@ -52,8 +52,6 @@ usr/lib/mysql/plugin/locales.so ...@@ -52,8 +52,6 @@ usr/lib/mysql/plugin/locales.so
usr/lib/mysql/plugin/metadata_lock_info.so usr/lib/mysql/plugin/metadata_lock_info.so
usr/lib/mysql/plugin/query_cache_info.so usr/lib/mysql/plugin/query_cache_info.so
usr/lib/mysql/plugin/query_response_time.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/server_audit.so
usr/lib/mysql/plugin/simple_password_check.so usr/lib/mysql/plugin/simple_password_check.so
usr/lib/mysql/plugin/sql_errlog.so usr/lib/mysql/plugin/sql_errlog.so
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
# Please check all dependent tests after modifying it # Please check all dependent tests after modifying it
# #
source include/have_semisync.inc;
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_innodb.inc; source include/have_innodb.inc;
source include/master-slave.inc; source include/master-slave.inc;
......
if (`select count(*) < 2 from information_schema.plugins where plugin_name like 'rpl_semi_sync_%'`)
{
--skip Test requires semisync plugins
}
--plugin-load-add=$SEMISYNC_MASTER_SO
--plugin-load-add=$SEMISYNC_SLAVE_SO
--loose-rpl-semi-sync-master
--loose-rpl-semi-sync-slave
#
# 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
#
# 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
...@@ -927,6 +927,27 @@ The following options may be given as the first argument: ...@@ -927,6 +927,27 @@ The following options may be given as the first argument:
--rowid-merge-buff-size=# --rowid-merge-buff-size=#
The size of the buffers used [NOT] IN evaluation via The size of the buffers used [NOT] IN evaluation via
partial matching 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-mode Skip some optimize stages (for testing). Deprecated.
--safe-user-create Don't allow new user creation by the user who has no --safe-user-create Don't allow new user creation by the user who has no
write privileges to the mysql.user table. write privileges to the mysql.user table.
...@@ -1463,6 +1484,13 @@ report-password (No default value) ...@@ -1463,6 +1484,13 @@ report-password (No default value)
report-port 0 report-port 0
report-user (No default value) report-user (No default value)
rowid-merge-buff-size 8388608 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 safe-user-create FALSE
secure-auth TRUE secure-auth TRUE
secure-file-priv (No default value) secure-file-priv (No default value)
......
...@@ -13,7 +13,7 @@ wait/synch/mutex/sql/HA_DATA_PARTITION::LOCK_auto_inc YES YES ...@@ -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_active_mi YES YES
wait/synch/mutex/sql/LOCK_after_binlog_sync 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_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 select * from performance_schema.setup_instruments
where name like 'Wait/Synch/Rwlock/sql/%' where name like 'Wait/Synch/Rwlock/sql/%'
and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock') and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')
...@@ -36,6 +36,7 @@ where name like 'Wait/Synch/Cond/sql/%' ...@@ -36,6 +36,7 @@ where name like 'Wait/Synch/Cond/sql/%'
'wait/synch/cond/sql/DEBUG_SYNC::cond') 'wait/synch/cond/sql/DEBUG_SYNC::cond')
order by name limit 10; order by name limit 10;
NAME ENABLED TIMED 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_flush_thread_cache YES YES
wait/synch/cond/sql/COND_group_commit_orderer YES YES wait/synch/cond/sql/COND_group_commit_orderer YES YES
wait/synch/cond/sql/COND_gtid_ignore_duplicates 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 ...@@ -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_queue_state YES YES
wait/synch/cond/sql/COND_rpl_thread 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_pool YES YES
wait/synch/cond/sql/COND_rpl_thread_queue YES YES
select * from performance_schema.setup_instruments select * from performance_schema.setup_instruments
where name='Wait'; where name='Wait';
select * from performance_schema.setup_instruments select * from performance_schema.setup_instruments
......
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
--source include/have_semisync.inc
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/have_debug_sync.inc --source include/have_debug_sync.inc
--source include/have_binlog_format_mixed_or_statement.inc --source include/have_binlog_format_mixed_or_statement.inc
......
source include/have_semisync.inc;
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_innodb.inc; source include/have_innodb.inc;
source include/master-slave.inc; source include/master-slave.inc;
......
###############################################################################
# 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;
source include/have_semisync.inc;
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_innodb.inc; source include/have_innodb.inc;
......
--source include/have_semisync.inc
--source include/master-slave.inc --source include/master-slave.inc
call mtr.add_suppression("Timeout waiting for reply of binlog*"); call mtr.add_suppression("Timeout waiting for reply of binlog*");
......
# #
# MDEV-4066 semisync_master + temporary tables causes memory leaks # MDEV-4066 semisync_master + temporary tables causes memory leaks
# #
source include/have_semisync.inc;
source include/have_binlog_format_row.inc; source include/have_binlog_format_row.inc;
source include/master-slave.inc; source include/master-slave.inc;
......
...@@ -3817,6 +3817,104 @@ NUMERIC_BLOCK_SIZE 1 ...@@ -3817,6 +3817,104 @@ NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL ENUM_VALUE_LIST NULL
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED 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 VARIABLE_NAME SECURE_AUTH
SESSION_VALUE NULL SESSION_VALUE NULL
GLOBAL_VALUE ON GLOBAL_VALUE ON
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
# #
# #
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_enabled; select @@global.rpl_semi_sync_master_enabled;
SET @start_global_value = @@global.rpl_semi_sync_master_enabled; SET @start_global_value = @@global.rpl_semi_sync_master_enabled;
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
# 2010-01-21 OBN - Added # 2010-01-21 OBN - Added
# #
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_timeout; select @@global.rpl_semi_sync_master_timeout;
SET @start_global_value = @@global.rpl_semi_sync_master_timeout; SET @start_global_value = @@global.rpl_semi_sync_master_timeout;
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
# 2010-01-21 OBN - Added # 2010-01-21 OBN - Added
# #
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_trace_level; select @@global.rpl_semi_sync_master_trace_level;
SET @start_global_value = @@global.rpl_semi_sync_master_trace_level; SET @start_global_value = @@global.rpl_semi_sync_master_trace_level;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
# #
# #
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_wait_no_slave; select @@global.rpl_semi_sync_master_wait_no_slave;
SET @start_global_value = @@global.rpl_semi_sync_master_wait_no_slave; SET @start_global_value = @@global.rpl_semi_sync_master_wait_no_slave;
......
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_wait_point; select @@global.rpl_semi_sync_master_wait_point;
SET @start_global_value = @@global.rpl_semi_sync_master_wait_point; SET @start_global_value = @@global.rpl_semi_sync_master_wait_point;
......
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
# #
# #
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_slave_enabled; select @@global.rpl_semi_sync_slave_enabled;
SET @start_global_value = @@global.rpl_semi_sync_slave_enabled; SET @start_global_value = @@global.rpl_semi_sync_slave_enabled;
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
# 2010-01-21 OBN - Added # 2010-01-21 OBN - Added
# #
source include/not_embedded.inc; source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_slave_trace_level; select @@global.rpl_semi_sync_slave_trace_level;
SET @start_global_value = @@global.rpl_semi_sync_slave_trace_level; SET @start_global_value = @@global.rpl_semi_sync_slave_trace_level;
......
...@@ -30,7 +30,7 @@ perl; ...@@ -30,7 +30,7 @@ perl;
feedback debug temp-pool ssl des-key-file xtradb sequence feedback debug temp-pool ssl des-key-file xtradb sequence
thread-concurrency super-large-pages mutex-deadlock-detector thread-concurrency super-large-pages mutex-deadlock-detector
connect null-audit aria oqgraph sphinx thread-handling 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 query-response-time metadata-lock-info locales unix-socket
wsrep file-key-management cracklib-password-check user-variables/; wsrep file-key-management cracklib-password-check user-variables/;
......
# 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)
/* 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 "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;
/* 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 "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;
...@@ -36,7 +36,7 @@ ELSE() ...@@ -36,7 +36,7 @@ ELSE()
ENDIF() ENDIF()
INCLUDE_DIRECTORIES( INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/sql
${PCRE_INCLUDES} ${PCRE_INCLUDES}
${ZLIB_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR}
...@@ -135,6 +135,7 @@ SET (SQL_SOURCE ...@@ -135,6 +135,7 @@ SET (SQL_SOURCE
my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc
my_json_writer.cc my_json_writer.cc
rpl_gtid.cc rpl_parallel.cc rpl_gtid.cc rpl_parallel.cc
semisync.cc semisync_master.cc semisync_slave.cc
sql_type.cc sql_type.cc
item_windowfunc.cc sql_window.cc item_windowfunc.cc sql_window.cc
sql_cte.cc sql_cte.cc
......
...@@ -96,8 +96,9 @@ ...@@ -96,8 +96,9 @@
#include "set_var.h" #include "set_var.h"
#include "rpl_injector.h" #include "rpl_injector.h"
#include "rpl_handler.h" #include "rpl_handler.h"
#include "semisync_master.h"
#include "semisync_slave.h"
#ifdef HAVE_SYS_PRCTL_H #ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h> #include <sys/prctl.h>
...@@ -935,6 +936,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, ...@@ -935,6 +936,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
PSI_mutex_key key_RELAYLOG_LOCK_index; PSI_mutex_key key_RELAYLOG_LOCK_index;
PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state,
key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry; 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, PSI_mutex_key key_LOCK_stats,
key_LOCK_global_user_client_stats, key_LOCK_global_table_stats, key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
...@@ -1022,7 +1024,8 @@ static PSI_mutex_info all_server_mutexes[]= ...@@ -1022,7 +1024,8 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_LOCK_binlog_state, "LOCK_binlog_state", 0}, { &key_LOCK_binlog_state, "LOCK_binlog_state", 0},
{ &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0}, { &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0},
{ &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 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, PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
...@@ -1060,7 +1063,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, ...@@ -1060,7 +1063,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond,
key_rpl_group_info_sleep_cond, key_rpl_group_info_sleep_cond,
key_TABLE_SHARE_cond, key_user_level_lock_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_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; key_BINLOG_COND_queue_busy;
PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready, PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready,
key_COND_wait_commit; key_COND_wait_commit;
...@@ -1122,7 +1125,8 @@ static PSI_cond_info all_server_conds[]= ...@@ -1122,7 +1125,8 @@ static PSI_cond_info all_server_conds[]=
{ &key_COND_slave_background, "COND_slave_background", 0}, { &key_COND_slave_background, "COND_slave_background", 0},
{ &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL}, { &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL},
{ &key_COND_wait_gtid, "COND_wait_gtid", 0}, { &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, PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
...@@ -2215,6 +2219,10 @@ void clean_up(bool print_message) ...@@ -2215,6 +2219,10 @@ void clean_up(bool print_message)
ha_end(); ha_end();
if (tc_log) if (tc_log)
tc_log->close(); tc_log->close();
#ifdef HAVE_REPLICATION
semi_sync_master_deinit();
semi_sync_slave_deinit();
#endif
delegates_destroy(); delegates_destroy();
xid_cache_free(); xid_cache_free();
tdc_deinit(); tdc_deinit();
...@@ -5105,6 +5113,9 @@ static int init_server_components() ...@@ -5105,6 +5113,9 @@ static int init_server_components()
"this server. However this will be ignored as the " "this server. However this will be ignored as the "
"--log-bin option is not defined."); "--log-bin option is not defined.");
} }
semi_sync_master_init();
semi_sync_slave_init();
#endif #endif
if (opt_bin_log) if (opt_bin_log)
...@@ -8162,6 +8173,27 @@ static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff, ...@@ -8162,6 +8173,27 @@ static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff,
return 0; 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 #ifdef HAVE_YASSL
...@@ -8475,6 +8507,30 @@ SHOW_VAR status_vars[]= { ...@@ -8475,6 +8507,30 @@ SHOW_VAR status_vars[]= {
{"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS}, {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
{"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), 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}, {"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 #ifdef HAVE_QUERY_CACHE
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH}, {"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
{"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH}, {"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
...@@ -10194,6 +10250,8 @@ PSI_stage_info stage_waiting_for_insert= { 0, "Waiting for INSERT", 0}; ...@@ -10194,6 +10250,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_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_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_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_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_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}; PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0};
......
...@@ -18,16 +18,14 @@ ...@@ -18,16 +18,14 @@
/*************************************************************************** /***************************************************************************
NOTE: plugin locking. 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 The plugin is locked on Binlog_transmit_observer::transmit_start and is
is locked on Binlog_transmit_observer::transmit_start and is unlocked after unlocked after Binlog_transmit_observer::transmit_stop. All other
Binlog_transmit_observer::transmit_stop. All other master observable events master observable events happen between these two and don't lock the
happen between these two and don't lock the plugin at all. This works well plugin at all.
for the semisync_master plugin.
Also a plugin is locked on Binlog_relay_IO_observer::thread_start 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 and unlocked after Binlog_relay_IO_observer::thread_stop.
the semisync_slave plugin.
***************************************************************************/ ***************************************************************************/
#include <mysql.h> #include <mysql.h>
......
...@@ -149,13 +149,17 @@ void delegates_destroy() ...@@ -149,13 +149,17 @@ void delegates_destroy()
{ {
if (transaction_delegate) if (transaction_delegate)
transaction_delegate->~Trans_delegate(); transaction_delegate->~Trans_delegate();
transaction_delegate= 0;
if (binlog_storage_delegate) if (binlog_storage_delegate)
binlog_storage_delegate->~Binlog_storage_delegate(); binlog_storage_delegate->~Binlog_storage_delegate();
binlog_storage_delegate= 0;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
if (binlog_transmit_delegate) if (binlog_transmit_delegate)
binlog_transmit_delegate->~Binlog_transmit_delegate(); binlog_transmit_delegate->~Binlog_transmit_delegate();
binlog_transmit_delegate= 0;
if (binlog_relay_io_delegate) if (binlog_relay_io_delegate)
binlog_relay_io_delegate->~Binlog_relay_IO_delegate(); binlog_relay_io_delegate->~Binlog_relay_IO_delegate();
binlog_relay_io_delegate= 0;
#endif /* HAVE_REPLICATION */ #endif /* HAVE_REPLICATION */
} }
...@@ -171,13 +175,11 @@ void delegates_destroy() ...@@ -171,13 +175,11 @@ void delegates_destroy()
Observer_info *info= iter++; \ Observer_info *info= iter++; \
for (; 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 \ if (((Observer *)info->observer)->f \
&& ((Observer *)info->observer)->f args) \ && ((Observer *)info->observer)->f args) \
{ \ { \
r= 1; \ r= 1; \
sql_print_error("Run function '" #f "' in plugin '%s' failed", \ sql_print_error("Run function '" #f "' failed"); \
info->plugin_int->name.str); \
break; \ break; \
} \ } \
} \ } \
......
/* Copyright (C) 2007 Google Inc. /* Copyright (C) 2007 Google Inc.
Copyright (C) 2008 MySQL AB Copyright (C) 2008 MySQL AB
Use is subject to license terms
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -19,18 +18,9 @@ ...@@ -19,18 +18,9 @@
#ifndef SEMISYNC_H #ifndef SEMISYNC_H
#define SEMISYNC_H #define SEMISYNC_H
#define MYSQL_SERVER #include "mysqld.h"
#define HAVE_REPLICATION #include "log_event.h"
#include <my_pthread.h> #include "replication.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;
/** /**
This class is used to trace function calls and other process This class is used to trace function calls and other process
......
...@@ -23,34 +23,35 @@ ...@@ -23,34 +23,35 @@
#define TIME_BILLION 1000000000 #define TIME_BILLION 1000000000
/* This indicates whether semi-synchronous replication is enabled. */ /* This indicates whether semi-synchronous replication is enabled. */
char rpl_semi_sync_master_enabled; my_bool rpl_semi_sync_master_enabled;
unsigned long rpl_semi_sync_master_wait_point = 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; SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT;
unsigned long rpl_semi_sync_master_timeout; ulong rpl_semi_sync_master_timeout;
unsigned long rpl_semi_sync_master_trace_level; ulong rpl_semi_sync_master_trace_level;
char rpl_semi_sync_master_status = 0; ulong rpl_semi_sync_master_yes_transactions = 0;
unsigned long rpl_semi_sync_master_yes_transactions = 0; ulong rpl_semi_sync_master_no_transactions = 0;
unsigned long rpl_semi_sync_master_no_transactions = 0; ulong rpl_semi_sync_master_off_times = 0;
unsigned long rpl_semi_sync_master_off_times = 0; ulong rpl_semi_sync_master_timefunc_fails = 0;
unsigned long rpl_semi_sync_master_timefunc_fails = 0; ulong rpl_semi_sync_master_wait_timeouts = 0;
unsigned long rpl_semi_sync_master_wait_timeouts = 0; ulong rpl_semi_sync_master_wait_sessions = 0;
unsigned long rpl_semi_sync_master_wait_sessions = 0; ulong rpl_semi_sync_master_wait_pos_backtraverse = 0;
unsigned long rpl_semi_sync_master_wait_pos_backtraverse = 0; ulong rpl_semi_sync_master_avg_trx_wait_time = 0;
unsigned long rpl_semi_sync_master_avg_trx_wait_time = 0; ulonglong rpl_semi_sync_master_trx_wait_num = 0;
unsigned long long rpl_semi_sync_master_trx_wait_num = 0; ulong rpl_semi_sync_master_avg_net_wait_time = 0;
unsigned long rpl_semi_sync_master_avg_net_wait_time = 0; ulonglong rpl_semi_sync_master_net_wait_num = 0;
unsigned long long rpl_semi_sync_master_net_wait_num = 0; ulong rpl_semi_sync_master_clients = 0;
unsigned long rpl_semi_sync_master_clients = 0; ulonglong rpl_semi_sync_master_net_wait_time = 0;
unsigned long long rpl_semi_sync_master_net_wait_time = 0; ulonglong rpl_semi_sync_master_trx_wait_time = 0;
unsigned long long rpl_semi_sync_master_trx_wait_time = 0;
char rpl_semi_sync_master_wait_no_slave = 1; ReplSemiSyncMaster repl_semisync_master;
static int getWaitTime(const struct timespec& start_ts); 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;
} }
/******************************************************************************* /*******************************************************************************
...@@ -60,7 +61,7 @@ static unsigned long long timespec_to_usec(const struct timespec *ts) ...@@ -60,7 +61,7 @@ static unsigned long long timespec_to_usec(const struct timespec *ts)
******************************************************************************/ ******************************************************************************/
ActiveTranx::ActiveTranx(mysql_mutex_t *lock, ActiveTranx::ActiveTranx(mysql_mutex_t *lock,
unsigned long trace_level) ulong trace_level)
: Trace(trace_level), allocator_(max_connections), : Trace(trace_level), allocator_(max_connections),
num_entries_(max_connections << 1), /* Transaction hash table size num_entries_(max_connections << 1), /* Transaction hash table size
* is set to double the size * is set to double the size
...@@ -140,7 +141,7 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name, ...@@ -140,7 +141,7 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name,
if (!ins_node) if (!ins_node)
{ {
sql_print_error("%s: transaction node allocation failed for: (%s, %lu)", 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; result = -1;
goto l_end; goto l_end;
} }
...@@ -173,8 +174,8 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name, ...@@ -173,8 +174,8 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name,
*/ */
sql_print_error("%s: binlog write out-of-order, tail (%s, %lu), " sql_print_error("%s: binlog write out-of-order, tail (%s, %lu), "
"new node (%s, %lu)", kWho, "new node (%s, %lu)", kWho,
trx_rear_->log_name_, (unsigned long)trx_rear_->log_pos_, trx_rear_->log_name_, (ulong)trx_rear_->log_pos_,
ins_node->log_name_, (unsigned long)ins_node->log_pos_); ins_node->log_name_, (ulong)ins_node->log_pos_);
result = -1; result = -1;
goto l_end; goto l_end;
} }
...@@ -186,7 +187,7 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name, ...@@ -186,7 +187,7 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name,
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: insert (%s, %lu) in entry(%u)", kWho, 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); hash_val);
l_end: l_end:
...@@ -212,7 +213,7 @@ bool ActiveTranx::is_tranx_end_pos(const char *log_file_name, ...@@ -212,7 +213,7 @@ bool ActiveTranx::is_tranx_end_pos(const char *log_file_name,
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: probe (%s, %lu) in entry(%u)", kWho, 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)); function_exit(kWho, (entry != NULL));
return (entry != NULL); return (entry != NULL);
...@@ -295,7 +296,7 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name, ...@@ -295,7 +296,7 @@ int ActiveTranx::clear_active_tranx_nodes(const char *log_file_name,
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: cleared %d nodes back until pos (%s, %lu)", sql_print_information("%s: cleared %d nodes back until pos (%s, %lu)",
kWho, n_frees, 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); return function_exit(kWho, 0);
...@@ -357,10 +358,10 @@ int ReplSemiSyncMaster::initObject() ...@@ -357,10 +358,10 @@ int ReplSemiSyncMaster::initObject()
setTraceLevel(rpl_semi_sync_master_trace_level); setTraceLevel(rpl_semi_sync_master_trace_level);
/* Mutex initialization can only be done after MY_INIT(). */ /* Mutex initialization can only be done after MY_INIT(). */
mysql_mutex_init(key_ss_mutex_LOCK_binlog_, mysql_mutex_init(key_LOCK_binlog,
&LOCK_binlog_, MY_MUTEX_INIT_FAST); &LOCK_binlog, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_ss_cond_COND_binlog_send_, mysql_cond_init(key_COND_binlog_send,
&COND_binlog_send_, NULL); &COND_binlog_send, NULL);
if (rpl_semi_sync_master_enabled) if (rpl_semi_sync_master_enabled)
result = enableMaster(); result = enableMaster();
...@@ -379,7 +380,7 @@ int ReplSemiSyncMaster::enableMaster() ...@@ -379,7 +380,7 @@ int ReplSemiSyncMaster::enableMaster()
if (!getMasterEnabled()) if (!getMasterEnabled())
{ {
active_tranxs_ = new ActiveTranx(&LOCK_binlog_, trace_level_); active_tranxs_ = new ActiveTranx(&LOCK_binlog, trace_level_);
if (active_tranxs_ != NULL) if (active_tranxs_ != NULL)
{ {
commit_file_name_inited_ = false; commit_file_name_inited_ = false;
...@@ -388,6 +389,7 @@ int ReplSemiSyncMaster::enableMaster() ...@@ -388,6 +389,7 @@ int ReplSemiSyncMaster::enableMaster()
set_master_enabled(true); set_master_enabled(true);
state_ = true; state_ = true;
run_hooks_enabled= 1;
sql_print_information("Semi-sync replication enabled on the master."); sql_print_information("Semi-sync replication enabled on the master.");
} }
else else
...@@ -435,8 +437,8 @@ void ReplSemiSyncMaster::cleanup() ...@@ -435,8 +437,8 @@ void ReplSemiSyncMaster::cleanup()
{ {
if (init_done_) if (init_done_)
{ {
mysql_mutex_destroy(&LOCK_binlog_); mysql_mutex_destroy(&LOCK_binlog);
mysql_cond_destroy(&COND_binlog_send_); mysql_cond_destroy(&COND_binlog_send);
init_done_= 0; init_done_= 0;
} }
...@@ -445,17 +447,17 @@ void ReplSemiSyncMaster::cleanup() ...@@ -445,17 +447,17 @@ void ReplSemiSyncMaster::cleanup()
void ReplSemiSyncMaster::lock() void ReplSemiSyncMaster::lock()
{ {
mysql_mutex_lock(&LOCK_binlog_); mysql_mutex_lock(&LOCK_binlog);
} }
void ReplSemiSyncMaster::unlock() void ReplSemiSyncMaster::unlock()
{ {
mysql_mutex_unlock(&LOCK_binlog_); mysql_mutex_unlock(&LOCK_binlog);
} }
void ReplSemiSyncMaster::cond_broadcast() void ReplSemiSyncMaster::cond_broadcast()
{ {
mysql_cond_broadcast(&COND_binlog_send_); mysql_cond_broadcast(&COND_binlog_send);
} }
int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time) int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time)
...@@ -464,8 +466,8 @@ int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time) ...@@ -464,8 +466,8 @@ int ReplSemiSyncMaster::cond_timewait(struct timespec *wait_time)
int wait_res; int wait_res;
function_enter(kWho); function_enter(kWho);
wait_res= mysql_cond_timedwait(&COND_binlog_send_, wait_res= mysql_cond_timedwait(&COND_binlog_send,
&LOCK_binlog_, wait_time); &LOCK_binlog, wait_time);
return function_exit(kWho, wait_res); return function_exit(kWho, wait_res);
} }
...@@ -565,7 +567,7 @@ int ReplSemiSyncMaster::reportReplyBinlog(uint32 server_id, ...@@ -565,7 +567,7 @@ int ReplSemiSyncMaster::reportReplyBinlog(uint32 server_id,
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: Got reply at (%s, %lu)", kWho, 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) if (rpl_semi_sync_master_wait_sessions > 0)
...@@ -620,7 +622,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -620,7 +622,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
lock(); lock();
/* This must be called after acquired the 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, & stage_waiting_for_semi_sync_ack_from_slave,
& old_stage); & old_stage);
...@@ -631,7 +633,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -631,7 +633,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
{ {
sql_print_information("%s: wait pos (%s, %lu), repl(%d)\n", kWho, 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()); (int)is_on());
} }
...@@ -648,7 +650,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -648,7 +650,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
*/ */
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: Binlog reply is ahead (%s, %lu),", 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; break;
} }
} }
...@@ -669,7 +671,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -669,7 +671,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
rpl_semi_sync_master_wait_pos_backtraverse++; rpl_semi_sync_master_wait_pos_backtraverse++;
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: move back wait position (%s, %lu),", 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 else
...@@ -680,16 +682,16 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -680,16 +682,16 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: init wait position (%s, %lu),", 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. */ /* 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 diff_nsecs = (long) ((wait_timeout_ % TIME_THOUSAND) * TIME_MILLION);
long nsecs = start_ts.tv_nsec + diff_nsecs; long nsecs = start_ts.tv_nsec + diff_nsecs;
abstime.tv_sec = start_ts.tv_sec + diff_secs + nsecs/TIME_BILLION; abstime.tv_sec = start_ts.tv_sec + diff_secs + nsecs/TIME_BILLION;
abstime.tv_nsec = nsecs % TIME_BILLION; abstime.tv_nsec = nsecs % TIME_BILLION;
/* In semi-synchronous replication, we wait until the binlog-dump /* In semi-synchronous replication, we wait until the binlog-dump
* thread has received the reply on the relevant binlog segment from the * thread has received the reply on the relevant binlog segment from the
* replication slave. * replication slave.
...@@ -699,31 +701,31 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -699,31 +701,31 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
* these waiting threads. * these waiting threads.
*/ */
rpl_semi_sync_master_wait_sessions++; rpl_semi_sync_master_wait_sessions++;
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: wait %lu ms for binlog sent (%s, %lu)", sql_print_information("%s: wait %lu ms for binlog sent (%s, %lu)",
kWho, wait_timeout_, kWho, wait_timeout_,
wait_file_name_, (unsigned long)wait_file_pos_); wait_file_name_, (ulong)wait_file_pos_);
wait_result = cond_timewait(&abstime); wait_result = cond_timewait(&abstime);
rpl_semi_sync_master_wait_sessions--; rpl_semi_sync_master_wait_sessions--;
if (wait_result != 0) if (wait_result != 0)
{ {
/* This is a real wait timeout. */ /* This is a real wait timeout. */
sql_print_warning("Timeout waiting for reply of binlog (file: %s, pos: %lu), " sql_print_warning("Timeout waiting for reply of binlog (file: %s, pos: %lu), "
"semi-sync up to file %s, position %lu.", "semi-sync up to file %s, position %lu.",
trx_wait_binlog_name, (unsigned long)trx_wait_binlog_pos, trx_wait_binlog_name, (ulong)trx_wait_binlog_pos,
reply_file_name_, (unsigned long)reply_file_pos_); reply_file_name_, (ulong)reply_file_pos_);
rpl_semi_sync_master_wait_timeouts++; rpl_semi_sync_master_wait_timeouts++;
/* switch semi-sync off */ /* switch semi-sync off */
switch_off(); switch_off();
} }
else else
{ {
int wait_time; int wait_time;
wait_time = getWaitTime(start_ts); wait_time = getWaitTime(start_ts);
if (wait_time < 0) if (wait_time < 0)
{ {
...@@ -731,7 +733,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -731,7 +733,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
{ {
sql_print_error("Replication semi-sync getWaitTime fail at " sql_print_error("Replication semi-sync getWaitTime fail at "
"wait position (%s, %lu)", "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++; rpl_semi_sync_master_timefunc_fails++;
} }
...@@ -752,7 +754,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -752,7 +754,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
assert(thd_killed(current_thd) || !active_tranxs_ || assert(thd_killed(current_thd) || !active_tranxs_ ||
!active_tranxs_->is_tranx_end_pos(trx_wait_binlog_name, !active_tranxs_->is_tranx_end_pos(trx_wait_binlog_name,
trx_wait_binlog_pos)); trx_wait_binlog_pos));
l_end: l_end:
/* Update the status counter. */ /* Update the status counter. */
if (is_on()) if (is_on())
...@@ -769,7 +771,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name, ...@@ -769,7 +771,7 @@ int ReplSemiSyncMaster::commitTrx(const char* trx_wait_binlog_name,
} }
/* Indicate that semi-sync replication is OFF now. /* Indicate that semi-sync replication is OFF now.
* *
* What should we do when it is disabled? The problem is that we want * 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 * 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 * later. But, it is not that easy to detect that the slave has caught
...@@ -841,14 +843,14 @@ int ReplSemiSyncMaster::try_switch_on(int server_id, ...@@ -841,14 +843,14 @@ int ReplSemiSyncMaster::try_switch_on(int server_id,
sql_print_information("Semi-sync replication switched ON with slave (server_id: %d) " sql_print_information("Semi-sync replication switched ON with slave (server_id: %d) "
"at (%s, %lu)", "at (%s, %lu)",
server_id, log_file_name, server_id, log_file_name,
(unsigned long)log_file_pos); (ulong)log_file_pos);
} }
return function_exit(kWho, 0); return function_exit(kWho, 0);
} }
int ReplSemiSyncMaster::reserveSyncHeader(unsigned char *header, int ReplSemiSyncMaster::reserveSyncHeader(unsigned char *header,
unsigned long size) ulong size)
{ {
const char *kWho = "ReplSemiSyncMaster::reserveSyncHeader"; const char *kWho = "ReplSemiSyncMaster::reserveSyncHeader";
function_enter(kWho); function_enter(kWho);
...@@ -869,7 +871,7 @@ int ReplSemiSyncMaster::reserveSyncHeader(unsigned char *header, ...@@ -869,7 +871,7 @@ int ReplSemiSyncMaster::reserveSyncHeader(unsigned char *header,
disableMaster(); disableMaster();
return 0; return 0;
} }
/* Set the magic number and the sync status. By default, no sync /* Set the magic number and the sync status. By default, no sync
* is required. * is required.
*/ */
...@@ -929,13 +931,13 @@ int ReplSemiSyncMaster::updateSyncHeader(unsigned char *packet, ...@@ -929,13 +931,13 @@ int ReplSemiSyncMaster::updateSyncHeader(unsigned char *packet,
{ {
cmp = 1; cmp = 1;
} }
/* If we are already waiting for some transaction replies which /* If we are already waiting for some transaction replies which
* are later in binlog, do not wait for this one event. * are later in binlog, do not wait for this one event.
*/ */
if (cmp >= 0) if (cmp >= 0)
{ {
/* /*
* We only wait if the event is a transaction's ending event. * We only wait if the event is a transaction's ending event.
*/ */
assert(active_tranxs_ != NULL); assert(active_tranxs_ != NULL);
...@@ -960,7 +962,7 @@ int ReplSemiSyncMaster::updateSyncHeader(unsigned char *packet, ...@@ -960,7 +962,7 @@ int ReplSemiSyncMaster::updateSyncHeader(unsigned char *packet,
if (trace_level_ & kTraceDetail) if (trace_level_ & kTraceDetail)
sql_print_information("%s: server(%d), (%s, %lu) sync(%d), repl(%d)", sql_print_information("%s: server(%d), (%s, %lu) sync(%d), repl(%d)",
kWho, server_id, log_file_name, 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: l_end:
unlock(); unlock();
...@@ -1180,27 +1182,27 @@ void ReplSemiSyncMaster::setExportStats() ...@@ -1180,27 +1182,27 @@ void ReplSemiSyncMaster::setExportStats()
rpl_semi_sync_master_status = state_; rpl_semi_sync_master_status = state_;
rpl_semi_sync_master_avg_trx_wait_time= rpl_semi_sync_master_avg_trx_wait_time=
((rpl_semi_sync_master_trx_wait_num) ? ((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); ((double)rpl_semi_sync_master_trx_wait_num)) : 0);
rpl_semi_sync_master_avg_net_wait_time= rpl_semi_sync_master_avg_net_wait_time=
((rpl_semi_sync_master_net_wait_num) ? ((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); ((double)rpl_semi_sync_master_net_wait_num)) : 0);
unlock(); unlock();
} }
/* Get the waiting time given the wait's staring time. /* Get the waiting time given the wait's staring time.
* *
* Return: * Return:
* >= 0: the waiting time in microsecons(us) * >= 0: the waiting time in microsecons(us)
* < 0: error in get time or time back traverse * < 0: error in get time or time back traverse
*/ */
static int getWaitTime(const struct timespec& start_ts) static int getWaitTime(const struct timespec& start_ts)
{ {
unsigned long long start_usecs, end_usecs; ulonglong start_usecs, end_usecs;
struct timespec end_ts; struct timespec end_ts;
/* Starting time in microseconds(us). */ /* Starting time in microseconds(us). */
start_usecs = timespec_to_usec(&start_ts); start_usecs = timespec_to_usec(&start_ts);
...@@ -1215,3 +1217,213 @@ static int getWaitTime(const struct timespec& start_ts) ...@@ -1215,3 +1217,213 @@ static int getWaitTime(const struct timespec& start_ts)
return (int)(end_usecs - start_usecs); 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;
}
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
#include "semisync.h" #include "semisync.h"
#ifdef HAVE_PSI_INTERFACE #ifdef HAVE_PSI_INTERFACE
extern PSI_mutex_key key_ss_mutex_LOCK_binlog_; extern PSI_mutex_key key_LOCK_binlog;
extern PSI_cond_key key_ss_cond_COND_binlog_send_; extern PSI_cond_key key_COND_binlog_send;
#endif #endif
extern PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave; extern PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave;
...@@ -379,14 +379,14 @@ class ReplSemiSyncMaster ...@@ -379,14 +379,14 @@ class ReplSemiSyncMaster
/* This cond variable is signaled when enough binlog has been sent to slave, /* 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. * 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 /* Mutex that protects the following state variables and the active
* transaction list. * transaction list.
* Under no cirumstances we can acquire mysql_bin_log.LOCK_log if we are * Under no cirumstances we can acquire mysql_bin_log.LOCK_log if we are
* already holding LOCK_binlog_ because it can cause deadlocks. * 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. */ /* This is set to true when reply_file_name_ contains meaningful data. */
bool reply_file_name_inited_; bool reply_file_name_inited_;
...@@ -600,26 +600,26 @@ enum rpl_semi_sync_master_wait_point_t { ...@@ -600,26 +600,26 @@ enum rpl_semi_sync_master_wait_point_t {
}; };
/* System and status variables for the master component */ /* System and status variables for the master component */
extern char rpl_semi_sync_master_enabled; extern my_bool rpl_semi_sync_master_enabled;
extern char rpl_semi_sync_master_status; extern my_bool rpl_semi_sync_master_status;
extern unsigned long rpl_semi_sync_master_wait_point; extern ulong rpl_semi_sync_master_wait_point;
extern unsigned long rpl_semi_sync_master_clients; extern ulong rpl_semi_sync_master_clients;
extern unsigned long rpl_semi_sync_master_timeout; extern ulong rpl_semi_sync_master_timeout;
extern unsigned long rpl_semi_sync_master_trace_level; extern ulong rpl_semi_sync_master_trace_level;
extern unsigned long rpl_semi_sync_master_yes_transactions; extern ulong rpl_semi_sync_master_yes_transactions;
extern unsigned long rpl_semi_sync_master_no_transactions; extern ulong rpl_semi_sync_master_no_transactions;
extern unsigned long rpl_semi_sync_master_off_times; extern ulong rpl_semi_sync_master_off_times;
extern unsigned long rpl_semi_sync_master_wait_timeouts; extern ulong rpl_semi_sync_master_wait_timeouts;
extern unsigned long rpl_semi_sync_master_timefunc_fails; extern ulong rpl_semi_sync_master_timefunc_fails;
extern unsigned long rpl_semi_sync_master_num_timeouts; extern ulong rpl_semi_sync_master_num_timeouts;
extern unsigned long rpl_semi_sync_master_wait_sessions; extern ulong rpl_semi_sync_master_wait_sessions;
extern unsigned long rpl_semi_sync_master_wait_pos_backtraverse; extern ulong rpl_semi_sync_master_wait_pos_backtraverse;
extern unsigned long rpl_semi_sync_master_avg_trx_wait_time; extern ulong rpl_semi_sync_master_avg_trx_wait_time;
extern unsigned long rpl_semi_sync_master_avg_net_wait_time; extern ulong rpl_semi_sync_master_avg_net_wait_time;
extern unsigned long long rpl_semi_sync_master_net_wait_num; extern ulonglong rpl_semi_sync_master_net_wait_num;
extern unsigned long long rpl_semi_sync_master_trx_wait_num; extern ulonglong rpl_semi_sync_master_trx_wait_num;
extern unsigned long long rpl_semi_sync_master_net_wait_time; extern ulonglong rpl_semi_sync_master_net_wait_time;
extern unsigned long long rpl_semi_sync_master_trx_wait_time; extern ulonglong rpl_semi_sync_master_trx_wait_time;
/* /*
This indicates whether we should keep waiting if no semi-sync slave 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; ...@@ -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. 1 (default) : keep waiting until timeout even no available semi-sync slave.
*/ */
extern char rpl_semi_sync_master_wait_no_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 */ #endif /* SEMISYNC_MASTER_H */
...@@ -17,9 +17,20 @@ ...@@ -17,9 +17,20 @@
#include "semisync_slave.h" #include "semisync_slave.h"
char rpl_semi_sync_slave_enabled; my_bool rpl_semi_sync_slave_enabled;
char rpl_semi_sync_slave_status= 0; my_bool rpl_semi_sync_slave_status= 0;
unsigned long rpl_semi_sync_slave_trace_level; 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() int ReplSemiSyncSlave::initObject()
{ {
...@@ -72,7 +83,7 @@ int ReplSemiSyncSlave::slaveReadSyncHeader(const char *header, ...@@ -72,7 +83,7 @@ int ReplSemiSyncSlave::slaveReadSyncHeader(const char *header,
int ReplSemiSyncSlave::slaveStart(Binlog_relay_IO_param *param) int ReplSemiSyncSlave::slaveStart(Binlog_relay_IO_param *param)
{ {
bool semi_sync= getSlaveEnabled(); bool semi_sync= getSlaveEnabled();
sql_print_information("Slave I/O thread: Start %s replication to\ sql_print_information("Slave I/O thread: Start %s replication to\
master '%s@%s:%d' in log '%s' at position %lu", master '%s@%s:%d' in log '%s' at position %lu",
semi_sync ? "semi-sync" : "asynchronous", semi_sync ? "semi-sync" : "asynchronous",
...@@ -137,3 +148,140 @@ int ReplSemiSyncSlave::slaveReply(MYSQL *mysql, ...@@ -137,3 +148,140 @@ int ReplSemiSyncSlave::slaveReply(MYSQL *mysql,
return function_exit(kWho, reply_res); 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;
}
...@@ -90,8 +90,12 @@ class ReplSemiSyncSlave ...@@ -90,8 +90,12 @@ class ReplSemiSyncSlave
/* System and status variables for the slave component */ /* System and status variables for the slave component */
extern char rpl_semi_sync_slave_enabled; extern my_bool rpl_semi_sync_slave_enabled;
extern unsigned long rpl_semi_sync_slave_trace_level; extern my_bool rpl_semi_sync_slave_status;
extern char 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 */ #endif /* SEMISYNC_SLAVE_H */
...@@ -62,6 +62,8 @@ ...@@ -62,6 +62,8 @@
#include "sql_repl.h" #include "sql_repl.h"
#include "opt_range.h" #include "opt_range.h"
#include "rpl_parallel.h" #include "rpl_parallel.h"
#include "semisync_master.h"
#include "semisync_slave.h"
#include <ssl_compat.h> #include <ssl_compat.h>
/* /*
...@@ -2978,9 +2980,189 @@ static Sys_var_replicate_events_marked_for_skip Replicate_events_marked_for_skip ...@@ -2978,9 +2980,189 @@ static Sys_var_replicate_events_marked_for_skip Replicate_events_marked_for_skip
"the slave).", "the slave).",
GLOBAL_VAR(opt_replicate_events_marked_for_skip), CMD_LINE(REQUIRED_ARG), GLOBAL_VAR(opt_replicate_events_marked_for_skip), CMD_LINE(REQUIRED_ARG),
replicate_events_marked_for_skip_names, DEFAULT(RPL_SKIP_REPLICATE)); 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 #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( static Sys_var_ulong Sys_slow_launch_time(
"slow_launch_time", "slow_launch_time",
"If creating the thread takes longer than this value (in seconds), " "If creating the thread takes longer than this value (in seconds), "
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment