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
usr/lib/mysql/plugin/metadata_lock_info.so
usr/lib/mysql/plugin/query_cache_info.so
usr/lib/mysql/plugin/query_response_time.so
usr/lib/mysql/plugin/semisync_master.so
usr/lib/mysql/plugin/semisync_slave.so
usr/lib/mysql/plugin/server_audit.so
usr/lib/mysql/plugin/simple_password_check.so
usr/lib/mysql/plugin/sql_errlog.so
......
......@@ -4,7 +4,6 @@
# Please check all dependent tests after modifying it
#
source include/have_semisync.inc;
source include/not_embedded.inc;
source include/have_innodb.inc;
source include/master-slave.inc;
......
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:
--rowid-merge-buff-size=#
The size of the buffers used [NOT] IN evaluation via
partial matching
--rpl-semi-sync-master-enabled
Enable semi-synchronous replication master (disabled by
default).
--rpl-semi-sync-master-timeout=#
The timeout value (in ms) for semi-synchronous
replication in the master
--rpl-semi-sync-master-trace-level=#
The tracing level for semi-sync replication.
--rpl-semi-sync-master-wait-no-slave
Wait until timeout when no semi-synchronous replication
slave available (enabled by default).
(Defaults to on; use --skip-rpl-semi-sync-master-wait-no-slave to disable.)
--rpl-semi-sync-master-wait-point=name
Should transaction wait for semi-sync ack after having
synced binlog, or after having committed in storage
engine.. One of: AFTER_SYNC, AFTER_COMMIT
--rpl-semi-sync-slave-enabled
Enable semi-synchronous replication slave (disabled by
default).
--rpl-semi-sync-slave-trace-level=#
The tracing level for semi-sync replication.
--safe-mode Skip some optimize stages (for testing). Deprecated.
--safe-user-create Don't allow new user creation by the user who has no
write privileges to the mysql.user table.
......@@ -1463,6 +1484,13 @@ report-password (No default value)
report-port 0
report-user (No default value)
rowid-merge-buff-size 8388608
rpl-semi-sync-master-enabled FALSE
rpl-semi-sync-master-timeout 10000
rpl-semi-sync-master-trace-level 32
rpl-semi-sync-master-wait-no-slave TRUE
rpl-semi-sync-master-wait-point AFTER_COMMIT
rpl-semi-sync-slave-enabled FALSE
rpl-semi-sync-slave-trace-level 32
safe-user-create FALSE
secure-auth TRUE
secure-file-priv (No default value)
......
......@@ -13,7 +13,7 @@ wait/synch/mutex/sql/HA_DATA_PARTITION::LOCK_auto_inc YES YES
wait/synch/mutex/sql/LOCK_active_mi YES YES
wait/synch/mutex/sql/LOCK_after_binlog_sync YES YES
wait/synch/mutex/sql/LOCK_audit_mask YES YES
wait/synch/mutex/sql/LOCK_binlog_state YES YES
wait/synch/mutex/sql/LOCK_binlog YES YES
select * from performance_schema.setup_instruments
where name like 'Wait/Synch/Rwlock/sql/%'
and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')
......@@ -36,6 +36,7 @@ where name like 'Wait/Synch/Cond/sql/%'
'wait/synch/cond/sql/DEBUG_SYNC::cond')
order by name limit 10;
NAME ENABLED TIMED
wait/synch/cond/sql/COND_binlog_send YES YES
wait/synch/cond/sql/COND_flush_thread_cache YES YES
wait/synch/cond/sql/COND_group_commit_orderer YES YES
wait/synch/cond/sql/COND_gtid_ignore_duplicates YES YES
......@@ -45,7 +46,6 @@ wait/synch/cond/sql/COND_prepare_ordered YES YES
wait/synch/cond/sql/COND_queue_state YES YES
wait/synch/cond/sql/COND_rpl_thread YES YES
wait/synch/cond/sql/COND_rpl_thread_pool YES YES
wait/synch/cond/sql/COND_rpl_thread_queue YES YES
select * from performance_schema.setup_instruments
where name='Wait';
select * from performance_schema.setup_instruments
......
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/have_debug_sync.inc
--source include/have_binlog_format_mixed_or_statement.inc
......
source include/have_semisync.inc;
source include/not_embedded.inc;
source include/have_innodb.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/have_innodb.inc;
......
--source include/have_semisync.inc
--source include/master-slave.inc
call mtr.add_suppression("Timeout waiting for reply of binlog*");
......
#
# MDEV-4066 semisync_master + temporary tables causes memory leaks
#
source include/have_semisync.inc;
source include/have_binlog_format_row.inc;
source include/master-slave.inc;
......
......@@ -3817,6 +3817,104 @@ NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME RPL_SEMI_SYNC_MASTER_ENABLED
SESSION_VALUE NULL
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Enable semi-synchronous replication master (disabled by default).
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TIMEOUT
SESSION_VALUE NULL
GLOBAL_VALUE 10000
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 10000
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The timeout value (in ms) for semi-synchronous replication in the master
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 18446744073709551615
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME RPL_SEMI_SYNC_MASTER_TRACE_LEVEL
SESSION_VALUE NULL
GLOBAL_VALUE 32
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The tracing level for semi-sync replication.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 18446744073709551615
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME RPL_SEMI_SYNC_MASTER_WAIT_NO_SLAVE
SESSION_VALUE NULL
GLOBAL_VALUE ON
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE ON
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Wait until timeout when no semi-synchronous replication slave available (enabled by default).
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME RPL_SEMI_SYNC_MASTER_WAIT_POINT
SESSION_VALUE NULL
GLOBAL_VALUE AFTER_COMMIT
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE AFTER_COMMIT
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE ENUM
VARIABLE_COMMENT Should transaction wait for semi-sync ack after having synced binlog, or after having committed in storage engine.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST AFTER_SYNC,AFTER_COMMIT
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_ENABLED
SESSION_VALUE NULL
GLOBAL_VALUE OFF
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE OFF
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Enable semi-synchronous replication slave (disabled by default).
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME RPL_SEMI_SYNC_SLAVE_TRACE_LEVEL
SESSION_VALUE NULL
GLOBAL_VALUE 32
GLOBAL_VALUE_ORIGIN COMPILE-TIME
DEFAULT_VALUE 32
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT The tracing level for semi-sync replication.
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 18446744073709551615
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME SECURE_AUTH
SESSION_VALUE NULL
GLOBAL_VALUE ON
......
......@@ -6,7 +6,6 @@
#
#
source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_enabled;
SET @start_global_value = @@global.rpl_semi_sync_master_enabled;
......
......@@ -5,7 +5,6 @@
# 2010-01-21 OBN - Added
#
source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_timeout;
SET @start_global_value = @@global.rpl_semi_sync_master_timeout;
......
......@@ -5,7 +5,6 @@
# 2010-01-21 OBN - Added
#
source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_trace_level;
SET @start_global_value = @@global.rpl_semi_sync_master_trace_level;
......
......@@ -6,7 +6,6 @@
#
#
source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_wait_no_slave;
SET @start_global_value = @@global.rpl_semi_sync_master_wait_no_slave;
......
source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_master_wait_point;
SET @start_global_value = @@global.rpl_semi_sync_master_wait_point;
......
......@@ -6,7 +6,6 @@
#
#
source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_slave_enabled;
SET @start_global_value = @@global.rpl_semi_sync_slave_enabled;
......
......@@ -5,7 +5,6 @@
# 2010-01-21 OBN - Added
#
source include/not_embedded.inc;
source include/have_semisync.inc;
select @@global.rpl_semi_sync_slave_trace_level;
SET @start_global_value = @@global.rpl_semi_sync_slave_trace_level;
......
......@@ -30,7 +30,7 @@ perl;
feedback debug temp-pool ssl des-key-file xtradb sequence
thread-concurrency super-large-pages mutex-deadlock-detector
connect null-audit aria oqgraph sphinx thread-handling
test-sql-discovery rpl-semi-sync query-cache-info
test-sql-discovery query-cache-info
query-response-time metadata-lock-info locales unix-socket
wsrep file-key-management cracklib-password-check user-variables/;
......
# 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)
This diff is collapsed.
/* 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()
ENDIF()
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/sql
${PCRE_INCLUDES}
${ZLIB_INCLUDE_DIR}
......@@ -135,6 +135,7 @@ SET (SQL_SOURCE
my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc
my_json_writer.cc
rpl_gtid.cc rpl_parallel.cc
semisync.cc semisync_master.cc semisync_slave.cc
sql_type.cc
item_windowfunc.cc sql_window.cc
sql_cte.cc
......
......@@ -96,8 +96,9 @@
#include "set_var.h"
#include "rpl_injector.h"
#include "rpl_handler.h"
#include "semisync_master.h"
#include "semisync_slave.h"
#ifdef HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
......@@ -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_LOCK_slave_state, key_LOCK_binlog_state,
key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry;
PSI_mutex_key key_LOCK_binlog;
PSI_mutex_key key_LOCK_stats,
key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
......@@ -1022,7 +1024,8 @@ static PSI_mutex_info all_server_mutexes[]=
{ &key_LOCK_binlog_state, "LOCK_binlog_state", 0},
{ &key_LOCK_rpl_thread, "LOCK_rpl_thread", 0},
{ &key_LOCK_rpl_thread_pool, "LOCK_rpl_thread_pool", 0},
{ &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0}
{ &key_LOCK_parallel_entry, "LOCK_parallel_entry", 0},
{ &key_LOCK_binlog, "LOCK_binlog", 0}
};
PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
......@@ -1060,7 +1063,7 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond,
key_rpl_group_info_sleep_cond,
key_TABLE_SHARE_cond, key_user_level_lock_cond,
key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache,
key_COND_start_thread,
key_COND_start_thread, key_COND_binlog_send,
key_BINLOG_COND_queue_busy;
PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready,
key_COND_wait_commit;
......@@ -1122,7 +1125,8 @@ static PSI_cond_info all_server_conds[]=
{ &key_COND_slave_background, "COND_slave_background", 0},
{ &key_COND_start_thread, "COND_start_thread", PSI_FLAG_GLOBAL},
{ &key_COND_wait_gtid, "COND_wait_gtid", 0},
{ &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0}
{ &key_COND_gtid_ignore_duplicates, "COND_gtid_ignore_duplicates", 0},
{ &key_COND_binlog_send, "COND_binlog_send", 0}
};
PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
......@@ -2215,6 +2219,10 @@ void clean_up(bool print_message)
ha_end();
if (tc_log)
tc_log->close();
#ifdef HAVE_REPLICATION
semi_sync_master_deinit();
semi_sync_slave_deinit();
#endif
delegates_destroy();
xid_cache_free();
tdc_deinit();
......@@ -5105,6 +5113,9 @@ static int init_server_components()
"this server. However this will be ignored as the "
"--log-bin option is not defined.");
}
semi_sync_master_init();
semi_sync_slave_init();
#endif
if (opt_bin_log)
......@@ -8162,6 +8173,27 @@ static int show_ssl_get_cipher_list(THD *thd, SHOW_VAR *var, char *buff,
return 0;
}
#define SHOW_FNAME(name) \
rpl_semi_sync_master_show_##name
#define DEF_SHOW_FUNC(name, show_type) \
static int SHOW_FNAME(name)(MYSQL_THD thd, SHOW_VAR *var, char *buff) \
{ \
repl_semisync_master.setExportStats(); \
var->type= show_type; \
var->value= (char *)&rpl_semi_sync_master_##name; \
return 0; \
}
DEF_SHOW_FUNC(status, SHOW_BOOL)
DEF_SHOW_FUNC(clients, SHOW_LONG)
DEF_SHOW_FUNC(wait_sessions, SHOW_LONG)
DEF_SHOW_FUNC(trx_wait_time, SHOW_LONGLONG)
DEF_SHOW_FUNC(trx_wait_num, SHOW_LONGLONG)
DEF_SHOW_FUNC(net_wait_time, SHOW_LONGLONG)
DEF_SHOW_FUNC(net_wait_num, SHOW_LONGLONG)
DEF_SHOW_FUNC(avg_net_wait_time, SHOW_LONG)
DEF_SHOW_FUNC(avg_trx_wait_time, SHOW_LONG)
#ifdef HAVE_YASSL
......@@ -8475,6 +8507,30 @@ SHOW_VAR status_vars[]= {
{"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
{"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
{"Rows_tmp_read", (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS},
#ifdef HAVE_REPLICATION
{"Rpl_semi_sync_master_status", (char*) &SHOW_FNAME(status), SHOW_FUNC},
{"Rpl_semi_sync_master_clients", (char*) &SHOW_FNAME(clients), SHOW_FUNC},
{"Rpl_semi_sync_master_yes_tx", (char*) &rpl_semi_sync_master_yes_transactions, SHOW_LONG},
{"Rpl_semi_sync_master_no_tx", (char*) &rpl_semi_sync_master_no_transactions, SHOW_LONG},
{"Rpl_semi_sync_master_wait_sessions", (char*) &SHOW_FNAME(wait_sessions), SHOW_FUNC},
{"Rpl_semi_sync_master_no_times", (char*) &rpl_semi_sync_master_off_times, SHOW_LONG},
{"Rpl_semi_sync_master_timefunc_failures", (char*) &rpl_semi_sync_master_timefunc_fails, SHOW_LONG},
{"Rpl_semi_sync_master_wait_pos_backtraverse", (char*) &rpl_semi_sync_master_wait_pos_backtraverse, SHOW_LONG},
{"Rpl_semi_sync_master_tx_wait_time", (char*) &SHOW_FNAME(trx_wait_time), SHOW_FUNC},
{"Rpl_semi_sync_master_tx_waits", (char*) &SHOW_FNAME(trx_wait_num), SHOW_FUNC},
{"Rpl_semi_sync_master_tx_avg_wait_time", (char*) &SHOW_FNAME(avg_trx_wait_time), SHOW_FUNC},
{"Rpl_semi_sync_master_net_wait_time", (char*) &SHOW_FNAME(net_wait_time), SHOW_FUNC},
{"Rpl_semi_sync_master_net_waits", (char*) &SHOW_FNAME(net_wait_num), SHOW_FUNC},
{"Rpl_semi_sync_master_net_avg_wait_time", (char*) &SHOW_FNAME(avg_net_wait_time), SHOW_FUNC},
#ifdef HAVE_ACC_RECEIVER
{"Rpl_semi_sync_master_request_ack", (char*) &rpl_semi_sync_master_request_ack, SHOW_LONGLONG},
{"Rpl_semi_sync_master_get_ack", (char*)&rpl_semi_sync_master_get_ack, SHOW_LONGLONG},
#endif
{"Rpl_semi_sync_slave_status", (char*) &rpl_semi_sync_slave_status, SHOW_BOOL},
#ifdef HAVE_ACC_RECEIVER
{"Rpl_semi_sync_slave_send_ack", (char*) &rpl_semi_sync_slave_send_ack, SHOW_LONGLONG},
#endif
#endif /* HAVE_REPLICATION */
#ifdef HAVE_QUERY_CACHE
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
{"Qcache_free_memory", (char*) &query_cache.free_memory, SHOW_LONG_NOFLUSH},
......@@ -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_update= { 0, "Waiting for master update", 0};
PSI_stage_info stage_waiting_for_relay_log_space= { 0, "Waiting for the slave SQL thread to free enough relay log space", 0};
PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave=
{ 0, "Waiting for semi-sync ACK from slave", 0};
PSI_stage_info stage_waiting_for_slave_mutex_on_exit= { 0, "Waiting for slave mutex on exit", 0};
PSI_stage_info stage_waiting_for_slave_thread_to_start= { 0, "Waiting for slave thread to start", 0};
PSI_stage_info stage_waiting_for_table_flush= { 0, "Waiting for table flush", 0};
......
......@@ -18,16 +18,14 @@
/***************************************************************************
NOTE: plugin locking.
This API was created specifically for the semisync plugin and its locking
logic is also matches semisync plugin usage pattern. In particular, a plugin
is locked on Binlog_transmit_observer::transmit_start and is unlocked after
Binlog_transmit_observer::transmit_stop. All other master observable events
happen between these two and don't lock the plugin at all. This works well
for the semisync_master plugin.
The plugin is locked on Binlog_transmit_observer::transmit_start and is
unlocked after Binlog_transmit_observer::transmit_stop. All other
master observable events happen between these two and don't lock the
plugin at all.
Also a plugin is locked on Binlog_relay_IO_observer::thread_start
and unlocked after Binlog_relay_IO_observer::thread_stop. This works well for
the semisync_slave plugin.
and unlocked after Binlog_relay_IO_observer::thread_stop.
***************************************************************************/
#include <mysql.h>
......
......@@ -149,13 +149,17 @@ void delegates_destroy()
{
if (transaction_delegate)
transaction_delegate->~Trans_delegate();
transaction_delegate= 0;
if (binlog_storage_delegate)
binlog_storage_delegate->~Binlog_storage_delegate();
binlog_storage_delegate= 0;
#ifdef HAVE_REPLICATION
if (binlog_transmit_delegate)
binlog_transmit_delegate->~Binlog_transmit_delegate();
binlog_transmit_delegate= 0;
if (binlog_relay_io_delegate)
binlog_relay_io_delegate->~Binlog_relay_IO_delegate();
binlog_relay_io_delegate= 0;
#endif /* HAVE_REPLICATION */
}
......@@ -171,13 +175,11 @@ void delegates_destroy()
Observer_info *info= iter++; \
for (; info; info= iter++) \
{ \
if (do_lock) plugin_lock(thd, plugin_int_to_ref(info->plugin_int)); \
if (((Observer *)info->observer)->f \
&& ((Observer *)info->observer)->f args) \
{ \
r= 1; \
sql_print_error("Run function '" #f "' in plugin '%s' failed", \
info->plugin_int->name.str); \
sql_print_error("Run function '" #f "' failed"); \
break; \
} \
} \
......
/* Copyright (C) 2007 Google Inc.
Copyright (C) 2008 MySQL AB
Use is subject to license terms
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -19,18 +18,9 @@
#ifndef SEMISYNC_H
#define SEMISYNC_H
#define MYSQL_SERVER
#define HAVE_REPLICATION
#include <my_pthread.h>
#include <sql_priv.h>
#include <sql_class.h>
#include "unireg.h"
#include <replication.h>
#include "log.h" /* sql_print_information */
typedef struct st_mysql_show_var SHOW_VAR;
typedef struct st_mysql_sys_var SYS_VAR;
#include "mysqld.h"
#include "log_event.h"
#include "replication.h"
/**
This class is used to trace function calls and other process
......
......@@ -22,8 +22,8 @@
#include "semisync.h"
#ifdef HAVE_PSI_INTERFACE
extern PSI_mutex_key key_ss_mutex_LOCK_binlog_;
extern PSI_cond_key key_ss_cond_COND_binlog_send_;
extern PSI_mutex_key key_LOCK_binlog;
extern PSI_cond_key key_COND_binlog_send;
#endif
extern PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave;
......@@ -379,14 +379,14 @@ class ReplSemiSyncMaster
/* This cond variable is signaled when enough binlog has been sent to slave,
* so that a waiting trx can return the 'ok' to the client for a commit.
*/
mysql_cond_t COND_binlog_send_;
mysql_cond_t COND_binlog_send;
/* Mutex that protects the following state variables and the active
* transaction list.
* Under no cirumstances we can acquire mysql_bin_log.LOCK_log if we are
* already holding LOCK_binlog_ because it can cause deadlocks.
*/
mysql_mutex_t LOCK_binlog_;
mysql_mutex_t LOCK_binlog;
/* This is set to true when reply_file_name_ contains meaningful data. */
bool reply_file_name_inited_;
......@@ -600,26 +600,26 @@ enum rpl_semi_sync_master_wait_point_t {
};
/* System and status variables for the master component */
extern char rpl_semi_sync_master_enabled;
extern char rpl_semi_sync_master_status;
extern unsigned long rpl_semi_sync_master_wait_point;
extern unsigned long rpl_semi_sync_master_clients;
extern unsigned long rpl_semi_sync_master_timeout;
extern unsigned long rpl_semi_sync_master_trace_level;
extern unsigned long rpl_semi_sync_master_yes_transactions;
extern unsigned long rpl_semi_sync_master_no_transactions;
extern unsigned long rpl_semi_sync_master_off_times;
extern unsigned long rpl_semi_sync_master_wait_timeouts;
extern unsigned long rpl_semi_sync_master_timefunc_fails;
extern unsigned long rpl_semi_sync_master_num_timeouts;
extern unsigned long rpl_semi_sync_master_wait_sessions;
extern unsigned long rpl_semi_sync_master_wait_pos_backtraverse;
extern unsigned long rpl_semi_sync_master_avg_trx_wait_time;
extern unsigned long rpl_semi_sync_master_avg_net_wait_time;
extern unsigned long long rpl_semi_sync_master_net_wait_num;
extern unsigned long long rpl_semi_sync_master_trx_wait_num;
extern unsigned long long rpl_semi_sync_master_net_wait_time;
extern unsigned long long rpl_semi_sync_master_trx_wait_time;
extern my_bool rpl_semi_sync_master_enabled;
extern my_bool rpl_semi_sync_master_status;
extern ulong rpl_semi_sync_master_wait_point;
extern ulong rpl_semi_sync_master_clients;
extern ulong rpl_semi_sync_master_timeout;
extern ulong rpl_semi_sync_master_trace_level;
extern ulong rpl_semi_sync_master_yes_transactions;
extern ulong rpl_semi_sync_master_no_transactions;
extern ulong rpl_semi_sync_master_off_times;
extern ulong rpl_semi_sync_master_wait_timeouts;
extern ulong rpl_semi_sync_master_timefunc_fails;
extern ulong rpl_semi_sync_master_num_timeouts;
extern ulong rpl_semi_sync_master_wait_sessions;
extern ulong rpl_semi_sync_master_wait_pos_backtraverse;
extern ulong rpl_semi_sync_master_avg_trx_wait_time;
extern ulong rpl_semi_sync_master_avg_net_wait_time;
extern ulonglong rpl_semi_sync_master_net_wait_num;
extern ulonglong rpl_semi_sync_master_trx_wait_num;
extern ulonglong rpl_semi_sync_master_net_wait_time;
extern ulonglong rpl_semi_sync_master_trx_wait_time;
/*
This indicates whether we should keep waiting if no semi-sync slave
......@@ -628,5 +628,9 @@ extern unsigned long long rpl_semi_sync_master_trx_wait_time;
1 (default) : keep waiting until timeout even no available semi-sync slave.
*/
extern char rpl_semi_sync_master_wait_no_slave;
extern ReplSemiSyncMaster repl_semisync_master;
int semi_sync_master_init();
void semi_sync_master_deinit();
#endif /* SEMISYNC_MASTER_H */
......@@ -17,9 +17,20 @@
#include "semisync_slave.h"
char rpl_semi_sync_slave_enabled;
char rpl_semi_sync_slave_status= 0;
unsigned long rpl_semi_sync_slave_trace_level;
my_bool rpl_semi_sync_slave_enabled;
my_bool rpl_semi_sync_slave_status= 0;
ulong rpl_semi_sync_slave_trace_level;
ReplSemiSyncSlave repl_semisync_slave;
/*
indicate whether or not the slave should send a reply to the master.
This is set to true in repl_semi_slave_read_event if the current
event read is the last event of a transaction. And the value is
checked in repl_semi_slave_queue_event.
*/
bool semi_sync_need_reply= false;
int ReplSemiSyncSlave::initObject()
{
......@@ -72,7 +83,7 @@ int ReplSemiSyncSlave::slaveReadSyncHeader(const char *header,
int ReplSemiSyncSlave::slaveStart(Binlog_relay_IO_param *param)
{
bool semi_sync= getSlaveEnabled();
sql_print_information("Slave I/O thread: Start %s replication to\
master '%s@%s:%d' in log '%s' at position %lu",
semi_sync ? "semi-sync" : "asynchronous",
......@@ -137,3 +148,140 @@ int ReplSemiSyncSlave::slaveReply(MYSQL *mysql,
return function_exit(kWho, reply_res);
}
/***************************************************************************
Semisync slave interface setup and deinit
***************************************************************************/
C_MODE_START
int repl_semi_reset_slave(Binlog_relay_IO_param *param)
{
// TODO: reset semi-sync slave status here
return 0;
}
int repl_semi_slave_request_dump(Binlog_relay_IO_param *param,
uint32 flags)
{
MYSQL *mysql= param->mysql;
MYSQL_RES *res= 0;
MYSQL_ROW row;
const char *query;
if (!repl_semisync_slave.getSlaveEnabled())
return 0;
/* Check if master server has semi-sync plugin installed */
query= "SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled'";
if (mysql_real_query(mysql, query, strlen(query)) ||
!(res= mysql_store_result(mysql)))
{
sql_print_error("Execution failed on master: %s", query);
return 1;
}
row= mysql_fetch_row(res);
if (!row)
{
/* Master does not support semi-sync */
sql_print_warning("Master server does not support semi-sync, "
"fallback to asynchronous replication");
rpl_semi_sync_slave_status= 0;
mysql_free_result(res);
return 0;
}
mysql_free_result(res);
/*
Tell master dump thread that we want to do semi-sync
replication
*/
query= "SET @rpl_semi_sync_slave= 1";
if (mysql_real_query(mysql, query, strlen(query)))
{
sql_print_error("Set 'rpl_semi_sync_slave=1' on master failed");
return 1;
}
mysql_free_result(mysql_store_result(mysql));
rpl_semi_sync_slave_status= 1;
return 0;
}
int repl_semi_slave_read_event(Binlog_relay_IO_param *param,
const char *packet, unsigned long len,
const char **event_buf, unsigned long *event_len)
{
if (rpl_semi_sync_slave_status)
return repl_semisync_slave.slaveReadSyncHeader(packet, len,
&semi_sync_need_reply,
event_buf, event_len);
*event_buf= packet;
*event_len= len;
return 0;
}
int repl_semi_slave_queue_event(Binlog_relay_IO_param *param,
const char *event_buf,
unsigned long event_len,
uint32 flags)
{
if (rpl_semi_sync_slave_status && semi_sync_need_reply)
{
/*
We deliberately ignore the error in slaveReply, such error
should not cause the slave IO thread to stop, and the error
messages are already reported.
*/
(void) repl_semisync_slave.slaveReply(param->mysql,
param->master_log_name,
param->master_log_pos);
}
return 0;
}
int repl_semi_slave_io_start(Binlog_relay_IO_param *param)
{
return repl_semisync_slave.slaveStart(param);
}
int repl_semi_slave_io_end(Binlog_relay_IO_param *param)
{
return repl_semisync_slave.slaveStop(param);
}
C_MODE_END
Binlog_relay_IO_observer relay_io_observer=
{
sizeof(Binlog_relay_IO_observer), // len
repl_semi_slave_io_start, // start
repl_semi_slave_io_end, // stop
repl_semi_slave_request_dump, // request_transmit
repl_semi_slave_read_event, // after_read_event
repl_semi_slave_queue_event, // after_queue_event
repl_semi_reset_slave, // reset
};
static bool semi_sync_slave_inited= 0;
int semi_sync_slave_init()
{
void *p= 0;
if (repl_semisync_slave.initObject())
return 1;
if (register_binlog_relay_io_observer(&relay_io_observer, p))
return 1;
semi_sync_slave_inited= 1;
return 0;
}
void semi_sync_slave_deinit()
{
void *p= 0;
if (!semi_sync_slave_inited)
return;
unregister_binlog_relay_io_observer(&relay_io_observer, p);
semi_sync_slave_inited= 0;
}
......@@ -90,8 +90,12 @@ class ReplSemiSyncSlave
/* System and status variables for the slave component */
extern char rpl_semi_sync_slave_enabled;
extern unsigned long rpl_semi_sync_slave_trace_level;
extern char rpl_semi_sync_slave_status;
extern my_bool rpl_semi_sync_slave_enabled;
extern my_bool rpl_semi_sync_slave_status;
extern ulong rpl_semi_sync_slave_trace_level;
extern ReplSemiSyncSlave repl_semisync_slave;
int semi_sync_slave_init();
void semi_sync_slave_deinit();
#endif /* SEMISYNC_SLAVE_H */
......@@ -62,6 +62,8 @@
#include "sql_repl.h"
#include "opt_range.h"
#include "rpl_parallel.h"
#include "semisync_master.h"
#include "semisync_slave.h"
#include <ssl_compat.h>
/*
......@@ -2978,9 +2980,189 @@ static Sys_var_replicate_events_marked_for_skip Replicate_events_marked_for_skip
"the slave).",
GLOBAL_VAR(opt_replicate_events_marked_for_skip), CMD_LINE(REQUIRED_ARG),
replicate_events_marked_for_skip_names, DEFAULT(RPL_SKIP_REPLICATE));
/* new options for semisync */
static bool fix_rpl_semi_sync_master_enabled(sys_var *self, THD *thd,
enum_var_type type)
{
if (rpl_semi_sync_master_enabled)
{
if (repl_semisync_master.enableMaster() != 0)
rpl_semi_sync_master_enabled= false;
#ifdef HAVE_ACC_RECEIVER
else if (ack_receiver.start())
{
repl_semisync_master.disableMaster();
rpl_semi_sync_master_enabled= false;
}
#endif
}
else
{
if (repl_semisync_master.disableMaster() != 0)
rpl_semi_sync_master_enabled= true;
#ifdef HAVE_ACC_RECEIVER
if (!rpl_semi_sync_master_enabled)
ack_receiver.stop();
#endif
}
return false;
}
static bool fix_rpl_semi_sync_master_timeout(sys_var *self, THD *thd,
enum_var_type type)
{
repl_semisync_master.setWaitTimeout(rpl_semi_sync_master_timeout);
return false;
}
static bool fix_rpl_semi_sync_master_trace_level(sys_var *self, THD *thd,
enum_var_type type)
{
repl_semisync_master.setTraceLevel(rpl_semi_sync_master_trace_level);
#ifdef HAVE_ACC_RECEIVER
ack_receiver.setTraceLevel(rpl_semi_sync_master_trace_level);
#endif
return false;
}
static bool fix_rpl_semi_sync_master_wait_point(sys_var *self, THD *thd,
enum_var_type type)
{
#ifdef HAVE_ACC_RECEIVER
repl_semisync_master.setWaitPoint(rpl_semi_sync_master_wait_point);
#endif
return false;
}
static bool fix_rpl_semi_sync_master_wait_no_slave(sys_var *self, THD *thd,
enum_var_type type)
{
#ifdef HAVE_ACC_RECEIVER
repl_semisync_master.checkAndSwitch();
#endif
return false;
}
static Sys_var_mybool Sys_semisync_master_enabled(
"rpl_semi_sync_master_enabled",
"Enable semi-synchronous replication master (disabled by default).",
GLOBAL_VAR(rpl_semi_sync_master_enabled),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_master_enabled));
static Sys_var_ulong Sys_semisync_master_timeout(
"rpl_semi_sync_master_timeout",
"The timeout value (in ms) for semi-synchronous replication in the "
"master",
GLOBAL_VAR(rpl_semi_sync_master_timeout),
CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0,~0L),DEFAULT(10000),BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_master_timeout));
static Sys_var_mybool Sys_semisync_master_wait_no_slave(
"rpl_semi_sync_master_wait_no_slave",
"Wait until timeout when no semi-synchronous replication slave "
"available (enabled by default).",
GLOBAL_VAR(rpl_semi_sync_master_wait_no_slave),
CMD_LINE(OPT_ARG), DEFAULT(TRUE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_master_wait_no_slave));
static Sys_var_ulong Sys_semisync_master_trace_level(
"rpl_semi_sync_master_trace_level",
"The tracing level for semi-sync replication.",
GLOBAL_VAR(rpl_semi_sync_master_trace_level),
CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0,~0L),DEFAULT(32),BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_master_trace_level));
static const char *repl_semisync_wait_point[]=
{"AFTER_SYNC", "AFTER_COMMIT", NullS};
static Sys_var_enum Sys_semisync_master_wait_point(
"rpl_semi_sync_master_wait_point",
"Should transaction wait for semi-sync ack after having synced binlog, "
"or after having committed in storage engine.",
GLOBAL_VAR(rpl_semi_sync_master_wait_point), CMD_LINE(REQUIRED_ARG),
repl_semisync_wait_point, DEFAULT(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG,ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_master_wait_point));
static bool fix_rpl_semi_sync_slave_enabled(sys_var *self, THD *thd,
enum_var_type type)
{
repl_semisync_slave.setSlaveEnabled(rpl_semi_sync_slave_enabled != 0);
return false;
}
static bool fix_rpl_semi_sync_slave_trace_level(sys_var *self, THD *thd,
enum_var_type type)
{
repl_semisync_slave.setTraceLevel(rpl_semi_sync_slave_trace_level);
return false;
}
#ifdef HAVE_ACC_RECEIVER
static bool fix_rpl_semi_sync_slave_delay_master(sys_var *self, THD *thd,
enum_var_type type)
{
repl_semisync_slave.setDelayMaster(rpl_semi_sync_slave_delay_master);
return false;
}
static bool fix_rpl_semi_sync_slave_kill_conn_timeout(sys_var *self, THD *thd,
enum_var_type type)
{
repl_semisync_slave.setKillConnTimeout(rpl_semi_sync_slave_kill_conn_timeout);
return false;
}
#endif
static Sys_var_mybool Sys_semisync_slave_enabled(
"rpl_semi_sync_slave_enabled",
"Enable semi-synchronous replication slave (disabled by default).",
GLOBAL_VAR(rpl_semi_sync_slave_enabled),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_slave_enabled));
static Sys_var_ulong Sys_semisync_slave_trace_level(
"rpl_semi_sync_slave_trace_level",
"The tracing level for semi-sync replication.",
GLOBAL_VAR(rpl_semi_sync_slave_trace_level),
CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0,~0L),DEFAULT(32),BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_slave_trace_level));
#ifdef HAVE_ACC_RECEIVER
static Sys_var_mybool Sys_semisync_slave_delay_master(
"rpl_semi_sync_slave_delay_master",
"Only write master info file when ack is needed.",
GLOBAL_VAR(rpl_semi_sync_slave_delay_master),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_slave_delay_master));
static Sys_var_uint Sys_semisync_slave_kill_conn_timeout(
"rpl_semi_sync_slave_kill_conn_timeout",
"Timeout for the mysql connection used to kill the slave io_thread's "
"connection on master. This timeout comes into play when stop slave "
"is executed.",
GLOBAL_VAR(rpl_semi_sync_slave_kill_conn_timeout),
CMD_LINE(OPT_ARG),
VALID_RANGE(0, UINT_MAX), DEFAULT(5), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
ON_UPDATE(fix_rpl_semi_sync_slave_kill_conn_timeout));
#endif
#endif /* HAVE_REPLICATION */
static Sys_var_ulong Sys_slow_launch_time(
"slow_launch_time",
"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