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.
This commit is contained in:
parent
77030649fb
commit
2e53b96a0a
2
debian/mariadb-server-10.3.install
vendored
2
debian/mariadb-server-10.3.install
vendored
@ -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 @@
|
|||||||
# 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;
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
if (`select count(*) < 2 from information_schema.plugins where plugin_name like 'rpl_semi_sync_%'`)
|
|
||||||
{
|
|
||||||
--skip Test requires semisync plugins
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
--plugin-load-add=$SEMISYNC_MASTER_SO
|
|
||||||
--plugin-load-add=$SEMISYNC_SLAVE_SO
|
|
||||||
--loose-rpl-semi-sync-master
|
|
||||||
--loose-rpl-semi-sync-slave
|
|
@ -1,39 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
#
|
|
||||||
--let $include_filename= install_semisync.inc
|
|
||||||
--source include/begin_include_file.inc
|
|
||||||
|
|
||||||
--source include/not_embedded.inc
|
|
||||||
--source include/have_semisync_plugin.inc
|
|
||||||
|
|
||||||
--connection master
|
|
||||||
|
|
||||||
--disable_query_log
|
|
||||||
--let $value = query_get_value(show variables like 'rpl_semi_sync_master_enabled', Value, 1)
|
|
||||||
if ($value == No such row)
|
|
||||||
{
|
|
||||||
SET sql_log_bin = 0;
|
|
||||||
install plugin rpl_semi_sync_master soname 'semisync_master';
|
|
||||||
SET GLOBAL rpl_semi_sync_master_enabled = 1;
|
|
||||||
SET sql_log_bin = 1;
|
|
||||||
}
|
|
||||||
--enable_query_log
|
|
||||||
|
|
||||||
--connection slave
|
|
||||||
--source include/stop_slave_io.inc
|
|
||||||
|
|
||||||
--disable_query_log
|
|
||||||
--let $value= query_get_value(show variables like 'rpl_semi_sync_slave_enabled', Value, 1)
|
|
||||||
if ($value == No such row)
|
|
||||||
{
|
|
||||||
SET sql_log_bin = 0;
|
|
||||||
install plugin rpl_semi_sync_slave soname 'semisync_slave';
|
|
||||||
SET GLOBAL rpl_semi_sync_slave_enabled = 1;
|
|
||||||
SET sql_log_bin = 1;
|
|
||||||
}
|
|
||||||
START SLAVE IO_THREAD;
|
|
||||||
--source include/wait_for_slave_io_to_start.inc
|
|
||||||
--enable_query_log
|
|
||||||
|
|
||||||
--source include/end_include_file.inc
|
|
@ -1,29 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
#
|
|
||||||
--let $include_filename= uninstall_semisync.inc
|
|
||||||
--source include/begin_include_file.inc
|
|
||||||
|
|
||||||
--disable_query_log
|
|
||||||
--connection slave
|
|
||||||
--source include/stop_slave_io.inc
|
|
||||||
|
|
||||||
# Uninstall rpl_semi_sync_slave first
|
|
||||||
--disable_warnings
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_slave;
|
|
||||||
|
|
||||||
--connection master
|
|
||||||
# After BUG#17638477 fix, uninstallation of rpl_semi_sync_master
|
|
||||||
# is not allowed when there are semi sync slaves. Hence kill
|
|
||||||
# all dump threads before uninstalling it.
|
|
||||||
SET GLOBAL rpl_semi_sync_master_enabled = OFF;
|
|
||||||
--source include/stop_dump_threads.inc
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_master;
|
|
||||||
--enable_warnings
|
|
||||||
|
|
||||||
--connection slave
|
|
||||||
START SLAVE IO_THREAD;
|
|
||||||
--source include/wait_for_slave_io_to_start.inc
|
|
||||||
--enable_query_log
|
|
||||||
|
|
||||||
--source include/end_include_file.inc
|
|
@ -998,6 +998,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.
|
||||||
@ -1569,6 +1590,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
|
|||||||
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/%'
|
|||||||
'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
|
|||||||
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
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
include/master-slave.inc
|
|
||||||
[connection master]
|
|
||||||
call mtr.add_suppression("Read semi-sync reply network error");
|
|
||||||
call mtr.add_suppression("Timeout waiting for reply of binlog");
|
|
||||||
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master';
|
|
||||||
connection slave;
|
|
||||||
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave';
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_slave;
|
|
||||||
connection master;
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_master;
|
|
||||||
CREATE TABLE t1(i int);
|
|
||||||
INSERT INTO t1 values (1);
|
|
||||||
DROP TABLE t1;
|
|
||||||
connection slave;
|
|
||||||
include/install_semisync.inc
|
|
||||||
connection master;
|
|
||||||
connection slave;
|
|
||||||
connection slave;
|
|
||||||
show global status like "Slave%_running";
|
|
||||||
Variable_name Value
|
|
||||||
Slave_running ON
|
|
||||||
Slaves_running 1
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_slave;
|
|
||||||
Warnings:
|
|
||||||
Warning 1620 Plugin is busy and will be uninstalled on shutdown
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
plugin_name plugin_status
|
|
||||||
rpl_semi_sync_slave DELETED
|
|
||||||
connection master;
|
|
||||||
show global status like "Slave%_connect%";
|
|
||||||
Variable_name Value
|
|
||||||
Slave_connections 2
|
|
||||||
Slaves_connected 1
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_master;
|
|
||||||
Warnings:
|
|
||||||
Warning 1620 Plugin is busy and will be uninstalled on shutdown
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
plugin_name plugin_status
|
|
||||||
rpl_semi_sync_master DELETED
|
|
||||||
CREATE TABLE t1(i int);
|
|
||||||
INSERT INTO t1 values (2);
|
|
||||||
DROP TABLE t1;
|
|
||||||
connection slave;
|
|
||||||
show status like "Rpl_semi_sync_slave_status";
|
|
||||||
Variable_name Value
|
|
||||||
Rpl_semi_sync_slave_status ON
|
|
||||||
connection master;
|
|
||||||
show status like "Rpl_semi_sync_master_status";
|
|
||||||
Variable_name Value
|
|
||||||
Rpl_semi_sync_master_status ON
|
|
||||||
show status like "Rpl_semi_sync_master_clients";
|
|
||||||
Variable_name Value
|
|
||||||
Rpl_semi_sync_master_clients 1
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
plugin_name plugin_status
|
|
||||||
rpl_semi_sync_master DELETED
|
|
||||||
connection slave;
|
|
||||||
include/stop_slave.inc
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
plugin_name plugin_status
|
|
||||||
connection master;
|
|
||||||
create table t2 (a int);
|
|
||||||
drop table t2;
|
|
||||||
connection slave;
|
|
||||||
include/start_slave.inc
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
plugin_name plugin_status
|
|
||||||
connection master;
|
|
||||||
CREATE TABLE t1(i int);
|
|
||||||
INSERT INTO t1 values (3);
|
|
||||||
DROP TABLE t1;
|
|
||||||
connection slave;
|
|
||||||
include/rpl_end.inc
|
|
@ -1,4 +1,3 @@
|
|||||||
--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
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
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;
|
||||||
|
@ -1,132 +0,0 @@
|
|||||||
###############################################################################
|
|
||||||
# Bug#17638477 UNINSTALL AND INSTALL SEMI-SYNC PLUGIN CAUSES SLAVES TO BREAK
|
|
||||||
# Problem: Uninstallation of Semi sync plugin should be blocked when it is
|
|
||||||
# in use.
|
|
||||||
# Test case: Uninstallation of semi sync should be allowed
|
|
||||||
# On Master:
|
|
||||||
# 1) When there is no dump thread
|
|
||||||
# 2) When there are no semi sync slaves (i.e., async replication).
|
|
||||||
# On Slave:
|
|
||||||
# 1) When there is no I/O thread
|
|
||||||
# 2) When there are no semi sync enabled I/O thread (i.e.,async replication).
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
--source include/have_semisync_plugin.inc
|
|
||||||
--source include/not_embedded.inc
|
|
||||||
--source include/have_binlog_format_statement.inc
|
|
||||||
--source include/master-slave.inc
|
|
||||||
|
|
||||||
call mtr.add_suppression("Read semi-sync reply network error");
|
|
||||||
call mtr.add_suppression("Timeout waiting for reply of binlog");
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Case 1: Uninstallation of semi sync plugins should be allowed when it is
|
|
||||||
# not in use i.e., when asynchronous replication is active.
|
|
||||||
###############################################################################
|
|
||||||
# Step 1.1: Install semi sync master plugin on master
|
|
||||||
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master';
|
|
||||||
|
|
||||||
# Step 1.2: Install semi sync slave plugin on slave
|
|
||||||
--connection slave
|
|
||||||
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave';
|
|
||||||
|
|
||||||
# Step 1.3: Uninstallation of semisync plugin on master and slave should be
|
|
||||||
# allowed at this state as there is no semi sync replication enabled between
|
|
||||||
# master and slave.
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_slave;
|
|
||||||
--connection master
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_master;
|
|
||||||
|
|
||||||
# Step 1.4: Check that replication is working fine at the end of the test case.
|
|
||||||
CREATE TABLE t1(i int);
|
|
||||||
INSERT INTO t1 values (1);
|
|
||||||
DROP TABLE t1;
|
|
||||||
--sync_slave_with_master
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Case 2: Uninstallation of semi sync plugins should be disallowed
|
|
||||||
# when it is in use i.e., when semi sync replication is active
|
|
||||||
###############################################################################
|
|
||||||
# Step 2.1: Install and enable semi sync replication between master and slave
|
|
||||||
--source include/install_semisync.inc
|
|
||||||
|
|
||||||
# Step 2.2: Check that rpl_semi_sync_slave uninstallation on Slave is not
|
|
||||||
# possible at this state
|
|
||||||
--connection slave
|
|
||||||
show global status like "Slave%_running";
|
|
||||||
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_slave;
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
|
|
||||||
# Step 2.3: Check that rpl_semi_sync_master uninstallation on Master is not
|
|
||||||
# possible at this state
|
|
||||||
--connection master
|
|
||||||
|
|
||||||
# The following is to catch errors if the next uninstall plugin would succeed
|
|
||||||
show global status like "Slave%_connect%";
|
|
||||||
|
|
||||||
UNINSTALL PLUGIN rpl_semi_sync_master;
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
|
|
||||||
# Step 2.4: Check that replication is working fine at the end of the test case.
|
|
||||||
CREATE TABLE t1(i int);
|
|
||||||
INSERT INTO t1 values (2);
|
|
||||||
DROP TABLE t1;
|
|
||||||
--sync_slave_with_master
|
|
||||||
|
|
||||||
# Step 2.5: Make sure rpl_semi_sync_master_status on Master and
|
|
||||||
# rpl_semi_sync_slave_staus on Slave are ON
|
|
||||||
show status like "Rpl_semi_sync_slave_status";
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Case 3: Uninstallation of semi sync plugin should be disallowed when there
|
|
||||||
# are semi sync slaves even though rpl_semi_sync_master_enabled= OFF;.
|
|
||||||
###############################################################################
|
|
||||||
# Step 3.1: Disable semi sync on master
|
|
||||||
--connection master
|
|
||||||
show status like "Rpl_semi_sync_master_status";
|
|
||||||
|
|
||||||
# Step 3.2: Check that still Rpl_semi_sync_master_clients is 1
|
|
||||||
show status like "Rpl_semi_sync_master_clients";
|
|
||||||
|
|
||||||
# Step 3.3: Since Rpl_semi_sync_master_clients is 1, uninstallation of
|
|
||||||
# rpl_semi_sync_master should be disallowed.
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
# Case 4: Uninstallation of semi sync plugin should be allowed when it is not
|
|
||||||
# in use. Same as Case 1 but this case is to check the case after enabling and
|
|
||||||
# disabling semi sync replication.
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
# Step 4.1: Stop IO thread on slave.
|
|
||||||
--connection slave
|
|
||||||
--source include/stop_slave.inc
|
|
||||||
|
|
||||||
# Step 4.2: Disable semi sync on slave.
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
|
|
||||||
--connection master
|
|
||||||
# Send something to the slave so that the master would notice that nobody's listening.
|
|
||||||
create table t2 (a int); drop table t2;
|
|
||||||
# and wait for plugin to be unloaded automatically
|
|
||||||
let $wait_condition=select count(*) = 0 from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
--connection slave
|
|
||||||
|
|
||||||
# Step 4.3: Start IO thread on slave.
|
|
||||||
--source include/start_slave.inc
|
|
||||||
|
|
||||||
# Step 4.4: Uninstall semi sync plugin, it should be successful now.
|
|
||||||
select plugin_name,plugin_status from information_schema.plugins where plugin_name like 'rpl_%';
|
|
||||||
|
|
||||||
# Step 4.7: Check that replication is working fine at the end of the test case
|
|
||||||
--connection master
|
|
||||||
CREATE TABLE t1(i int);
|
|
||||||
INSERT INTO t1 values (3);
|
|
||||||
DROP TABLE t1;
|
|
||||||
--sync_slave_with_master
|
|
||||||
|
|
||||||
# Cleanup
|
|
||||||
source include/rpl_end.inc;
|
|
@ -1,4 +1,3 @@
|
|||||||
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;
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
--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*");
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#
|
#
|
||||||
# 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;
|
||||||
|
|
||||||
|
@ -4001,6 +4001,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 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
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 @@
|
|||||||
# 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 @@
|
|||||||
# 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 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
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;
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
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 @@
|
|||||||
#
|
#
|
||||||
#
|
#
|
||||||
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 @@
|
|||||||
# 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;
|
|||||||
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/;
|
||||||
|
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
#
|
|
||||||
# This program is free software; you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; version 2 of the License.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program; if not, write to the Free Software
|
|
||||||
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
||||||
|
|
||||||
SET(SEMISYNC_MASTER_SOURCES
|
|
||||||
semisync.cc semisync_master.cc semisync_master_plugin.cc
|
|
||||||
semisync.h semisync_master.h)
|
|
||||||
|
|
||||||
MYSQL_ADD_PLUGIN(semisync_master ${SEMISYNC_MASTER_SOURCES}
|
|
||||||
RECOMPILE_FOR_EMBEDDED)
|
|
||||||
|
|
||||||
SET(SEMISYNC_SLAVE_SOURCES semisync.cc semisync_slave.cc
|
|
||||||
semisync_slave_plugin.cc semisync.h semisync_slave.h )
|
|
||||||
|
|
||||||
MYSQL_ADD_PLUGIN(semisync_slave ${SEMISYNC_SLAVE_SOURCES}
|
|
||||||
RECOMPILE_FOR_EMBEDDED)
|
|
||||||
|
|
@ -1,496 +0,0 @@
|
|||||||
/* Copyright (C) 2007 Google Inc.
|
|
||||||
Copyright (c) 2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
|
|
||||||
Use is subject to license terms.
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
||||||
|
|
||||||
|
|
||||||
#include <my_global.h>
|
|
||||||
#include "semisync_master.h"
|
|
||||||
#include "sql_class.h" // THD
|
|
||||||
|
|
||||||
static ReplSemiSyncMaster repl_semisync;
|
|
||||||
|
|
||||||
C_MODE_START
|
|
||||||
|
|
||||||
int repl_semi_report_binlog_update(Binlog_storage_param *param,
|
|
||||||
const char *log_file,
|
|
||||||
my_off_t log_pos, uint32 flags)
|
|
||||||
{
|
|
||||||
int error= 0;
|
|
||||||
|
|
||||||
if (repl_semisync.getMasterEnabled())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Let us store the binlog file name and the position, so that
|
|
||||||
we know how long to wait for the binlog to the replicated to
|
|
||||||
the slave in synchronous replication.
|
|
||||||
*/
|
|
||||||
error= repl_semisync.writeTranxInBinlog(log_file,
|
|
||||||
log_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_request_commit(Trans_param *param)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_report_binlog_sync(Binlog_storage_param *param,
|
|
||||||
const char *log_file,
|
|
||||||
my_off_t log_pos, uint32 flags)
|
|
||||||
{
|
|
||||||
int error= 0;
|
|
||||||
if (rpl_semi_sync_master_wait_point ==
|
|
||||||
SEMI_SYNC_MASTER_WAIT_POINT_AFTER_BINLOG_SYNC)
|
|
||||||
{
|
|
||||||
error = repl_semisync.commitTrx(log_file, log_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_report_commit(Trans_param *param)
|
|
||||||
{
|
|
||||||
if (rpl_semi_sync_master_wait_point !=
|
|
||||||
SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_real_trans= param->flags & TRANS_IS_REAL_TRANS;
|
|
||||||
|
|
||||||
if (is_real_trans && param->log_pos)
|
|
||||||
{
|
|
||||||
const char *binlog_name= param->log_file;
|
|
||||||
return repl_semisync.commitTrx(binlog_name, param->log_pos);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_report_rollback(Trans_param *param)
|
|
||||||
{
|
|
||||||
return repl_semi_report_commit(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_binlog_dump_start(Binlog_transmit_param *param,
|
|
||||||
const char *log_file,
|
|
||||||
my_off_t log_pos)
|
|
||||||
{
|
|
||||||
bool semi_sync_slave= repl_semisync.is_semi_sync_slave();
|
|
||||||
|
|
||||||
if (semi_sync_slave)
|
|
||||||
{
|
|
||||||
/* One more semi-sync slave */
|
|
||||||
repl_semisync.add_slave();
|
|
||||||
|
|
||||||
/*
|
|
||||||
Let's assume this semi-sync slave has already received all
|
|
||||||
binlog events before the filename and position it requests.
|
|
||||||
*/
|
|
||||||
repl_semisync.reportReplyBinlog(param->server_id, log_file, log_pos);
|
|
||||||
}
|
|
||||||
sql_print_information("Start %s binlog_dump to slave (server_id: %d), pos(%s, %lu)",
|
|
||||||
semi_sync_slave ? "semi-sync" : "asynchronous",
|
|
||||||
param->server_id, log_file, (unsigned long)log_pos);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_binlog_dump_end(Binlog_transmit_param *param)
|
|
||||||
{
|
|
||||||
bool semi_sync_slave= repl_semisync.is_semi_sync_slave();
|
|
||||||
|
|
||||||
sql_print_information("Stop %s binlog_dump to slave (server_id: %d)",
|
|
||||||
semi_sync_slave ? "semi-sync" : "asynchronous",
|
|
||||||
param->server_id);
|
|
||||||
if (semi_sync_slave)
|
|
||||||
{
|
|
||||||
/* One less semi-sync slave */
|
|
||||||
repl_semisync.remove_slave();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_reserve_header(Binlog_transmit_param *param,
|
|
||||||
unsigned char *header,
|
|
||||||
unsigned long size, unsigned long *len)
|
|
||||||
{
|
|
||||||
*len += repl_semisync.reserveSyncHeader(header, size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_before_send_event(Binlog_transmit_param *param,
|
|
||||||
unsigned char *packet, unsigned long len,
|
|
||||||
const char *log_file, my_off_t log_pos)
|
|
||||||
{
|
|
||||||
return repl_semisync.updateSyncHeader(packet,
|
|
||||||
log_file,
|
|
||||||
log_pos,
|
|
||||||
param->server_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_after_send_event(Binlog_transmit_param *param,
|
|
||||||
const char *event_buf, unsigned long len)
|
|
||||||
{
|
|
||||||
if (repl_semisync.is_semi_sync_slave())
|
|
||||||
{
|
|
||||||
THD *thd= current_thd;
|
|
||||||
/*
|
|
||||||
Possible errors in reading slave reply are ignored deliberately
|
|
||||||
because we do not want dump thread to quit on this. Error
|
|
||||||
messages are already reported.
|
|
||||||
*/
|
|
||||||
(void) repl_semisync.readSlaveReply(&thd->net,
|
|
||||||
param->server_id, event_buf);
|
|
||||||
thd->clear_error();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_reset_master(Binlog_transmit_param *param)
|
|
||||||
{
|
|
||||||
if (repl_semisync.resetMaster())
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
C_MODE_END
|
|
||||||
|
|
||||||
/*
|
|
||||||
semisync system variables
|
|
||||||
*/
|
|
||||||
static void fix_rpl_semi_sync_master_timeout(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val);
|
|
||||||
|
|
||||||
static void fix_rpl_semi_sync_master_trace_level(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val);
|
|
||||||
|
|
||||||
static void fix_rpl_semi_sync_master_enabled(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val);
|
|
||||||
|
|
||||||
static MYSQL_SYSVAR_BOOL(enabled, rpl_semi_sync_master_enabled,
|
|
||||||
PLUGIN_VAR_OPCMDARG,
|
|
||||||
"Enable semi-synchronous replication master (disabled by default). ",
|
|
||||||
NULL, // check
|
|
||||||
&fix_rpl_semi_sync_master_enabled, // update
|
|
||||||
0);
|
|
||||||
|
|
||||||
/* NOTE: must match order of rpl_semi_sync_master_wait_point_t */
|
|
||||||
static const char *rpl_semi_sync_master_wait_point_names[] =
|
|
||||||
{
|
|
||||||
"AFTER_SYNC",
|
|
||||||
"AFTER_COMMIT",
|
|
||||||
NullS
|
|
||||||
};
|
|
||||||
|
|
||||||
static TYPELIB rpl_semi_sync_master_wait_point_typelib =
|
|
||||||
{
|
|
||||||
array_elements(rpl_semi_sync_master_wait_point_names) - 1,
|
|
||||||
"",
|
|
||||||
rpl_semi_sync_master_wait_point_names,
|
|
||||||
NULL
|
|
||||||
};
|
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ENUM(
|
|
||||||
wait_point,
|
|
||||||
rpl_semi_sync_master_wait_point,
|
|
||||||
PLUGIN_VAR_RQCMDARG,
|
|
||||||
"Should transaction wait for semi-sync ack after having synced binlog, "
|
|
||||||
"or after having committed in storeage engine.",
|
|
||||||
NULL, // check
|
|
||||||
NULL, // update
|
|
||||||
SEMI_SYNC_MASTER_WAIT_POINT_AFTER_STORAGE_COMMIT,
|
|
||||||
&rpl_semi_sync_master_wait_point_typelib);
|
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ULONG(timeout, rpl_semi_sync_master_timeout,
|
|
||||||
PLUGIN_VAR_OPCMDARG,
|
|
||||||
"The timeout value (in ms) for semi-synchronous replication in the master",
|
|
||||||
NULL, // check
|
|
||||||
fix_rpl_semi_sync_master_timeout, // update
|
|
||||||
10000, 0, ~0UL, 1);
|
|
||||||
|
|
||||||
static MYSQL_SYSVAR_BOOL(wait_no_slave, rpl_semi_sync_master_wait_no_slave,
|
|
||||||
PLUGIN_VAR_OPCMDARG,
|
|
||||||
"Wait until timeout when no semi-synchronous replication slave available (enabled by default). ",
|
|
||||||
NULL, // check
|
|
||||||
NULL, // update
|
|
||||||
1);
|
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_master_trace_level,
|
|
||||||
PLUGIN_VAR_OPCMDARG,
|
|
||||||
"The tracing level for semi-sync replication.",
|
|
||||||
NULL, // check
|
|
||||||
&fix_rpl_semi_sync_master_trace_level, // update
|
|
||||||
32, 0, ~0UL, 1);
|
|
||||||
|
|
||||||
static SYS_VAR* semi_sync_master_system_vars[]= {
|
|
||||||
MYSQL_SYSVAR(enabled),
|
|
||||||
MYSQL_SYSVAR(wait_point),
|
|
||||||
MYSQL_SYSVAR(timeout),
|
|
||||||
MYSQL_SYSVAR(wait_no_slave),
|
|
||||||
MYSQL_SYSVAR(trace_level),
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
static void fix_rpl_semi_sync_master_timeout(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val)
|
|
||||||
{
|
|
||||||
*(unsigned long *)ptr= *(unsigned long *)val;
|
|
||||||
repl_semisync.setWaitTimeout(rpl_semi_sync_master_timeout);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fix_rpl_semi_sync_master_trace_level(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val)
|
|
||||||
{
|
|
||||||
*(unsigned long *)ptr= *(unsigned long *)val;
|
|
||||||
repl_semisync.setTraceLevel(rpl_semi_sync_master_trace_level);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fix_rpl_semi_sync_master_enabled(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val)
|
|
||||||
{
|
|
||||||
*(char *)ptr= *(char *)val;
|
|
||||||
if (rpl_semi_sync_master_enabled)
|
|
||||||
{
|
|
||||||
if (repl_semisync.enableMaster() != 0)
|
|
||||||
rpl_semi_sync_master_enabled = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (repl_semisync.disableMaster() != 0)
|
|
||||||
rpl_semi_sync_master_enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Trans_observer trans_observer = {
|
|
||||||
sizeof(Trans_observer), // len
|
|
||||||
|
|
||||||
repl_semi_report_commit, // after_commit
|
|
||||||
repl_semi_report_rollback, // after_rollback
|
|
||||||
};
|
|
||||||
|
|
||||||
Binlog_storage_observer storage_observer = {
|
|
||||||
sizeof(Binlog_storage_observer), // len
|
|
||||||
|
|
||||||
repl_semi_report_binlog_update, // report_update
|
|
||||||
repl_semi_report_binlog_sync, // after_sync
|
|
||||||
};
|
|
||||||
|
|
||||||
Binlog_transmit_observer transmit_observer = {
|
|
||||||
sizeof(Binlog_transmit_observer), // len
|
|
||||||
|
|
||||||
repl_semi_binlog_dump_start, // start
|
|
||||||
repl_semi_binlog_dump_end, // stop
|
|
||||||
repl_semi_reserve_header, // reserve_header
|
|
||||||
repl_semi_before_send_event, // before_send_event
|
|
||||||
repl_semi_after_send_event, // after_send_event
|
|
||||||
repl_semi_reset_master, // reset
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#define SHOW_FNAME(name) \
|
|
||||||
rpl_semi_sync_master_show_##name
|
|
||||||
|
|
||||||
#define DEF_SHOW_FUNC(name, show_type) \
|
|
||||||
static int SHOW_FNAME(name)(MYSQL_THD thd, SHOW_VAR *var, char *buff) \
|
|
||||||
{ \
|
|
||||||
repl_semisync.setExportStats(); \
|
|
||||||
var->type= show_type; \
|
|
||||||
var->value= (char *)&rpl_semi_sync_master_##name; \
|
|
||||||
return 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
DEF_SHOW_FUNC(status, SHOW_BOOL)
|
|
||||||
DEF_SHOW_FUNC(clients, SHOW_LONG)
|
|
||||||
DEF_SHOW_FUNC(wait_sessions, SHOW_LONG)
|
|
||||||
DEF_SHOW_FUNC(trx_wait_time, SHOW_LONGLONG)
|
|
||||||
DEF_SHOW_FUNC(trx_wait_num, SHOW_LONGLONG)
|
|
||||||
DEF_SHOW_FUNC(net_wait_time, SHOW_LONGLONG)
|
|
||||||
DEF_SHOW_FUNC(net_wait_num, SHOW_LONGLONG)
|
|
||||||
DEF_SHOW_FUNC(avg_net_wait_time, SHOW_LONG)
|
|
||||||
DEF_SHOW_FUNC(avg_trx_wait_time, SHOW_LONG)
|
|
||||||
|
|
||||||
|
|
||||||
/* plugin status variables */
|
|
||||||
static SHOW_VAR semi_sync_master_status_vars[]= {
|
|
||||||
{"Rpl_semi_sync_master_status",
|
|
||||||
(char*) &SHOW_FNAME(status),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_clients",
|
|
||||||
(char*) &SHOW_FNAME(clients),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_yes_tx",
|
|
||||||
(char*) &rpl_semi_sync_master_yes_transactions,
|
|
||||||
SHOW_LONG},
|
|
||||||
{"Rpl_semi_sync_master_no_tx",
|
|
||||||
(char*) &rpl_semi_sync_master_no_transactions,
|
|
||||||
SHOW_LONG},
|
|
||||||
{"Rpl_semi_sync_master_wait_sessions",
|
|
||||||
(char*) &SHOW_FNAME(wait_sessions),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_no_times",
|
|
||||||
(char*) &rpl_semi_sync_master_off_times,
|
|
||||||
SHOW_LONG},
|
|
||||||
{"Rpl_semi_sync_master_timefunc_failures",
|
|
||||||
(char*) &rpl_semi_sync_master_timefunc_fails,
|
|
||||||
SHOW_LONG},
|
|
||||||
{"Rpl_semi_sync_master_wait_pos_backtraverse",
|
|
||||||
(char*) &rpl_semi_sync_master_wait_pos_backtraverse,
|
|
||||||
SHOW_LONG},
|
|
||||||
{"Rpl_semi_sync_master_tx_wait_time",
|
|
||||||
(char*) &SHOW_FNAME(trx_wait_time),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_tx_waits",
|
|
||||||
(char*) &SHOW_FNAME(trx_wait_num),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_tx_avg_wait_time",
|
|
||||||
(char*) &SHOW_FNAME(avg_trx_wait_time),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_net_wait_time",
|
|
||||||
(char*) &SHOW_FNAME(net_wait_time),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_net_waits",
|
|
||||||
(char*) &SHOW_FNAME(net_wait_num),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{"Rpl_semi_sync_master_net_avg_wait_time",
|
|
||||||
(char*) &SHOW_FNAME(avg_net_wait_time),
|
|
||||||
SHOW_SIMPLE_FUNC},
|
|
||||||
{NULL, NULL, SHOW_LONG},
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
PSI_mutex_key key_ss_mutex_LOCK_binlog_;
|
|
||||||
|
|
||||||
static PSI_mutex_info all_semisync_mutexes[]=
|
|
||||||
{
|
|
||||||
{ &key_ss_mutex_LOCK_binlog_, "LOCK_binlog_", 0}
|
|
||||||
};
|
|
||||||
|
|
||||||
PSI_cond_key key_ss_cond_COND_binlog_send_;
|
|
||||||
|
|
||||||
static PSI_cond_info all_semisync_conds[]=
|
|
||||||
{
|
|
||||||
{ &key_ss_cond_COND_binlog_send_, "COND_binlog_send_", 0}
|
|
||||||
};
|
|
||||||
#endif /* HAVE_PSI_INTERFACE */
|
|
||||||
|
|
||||||
PSI_stage_info stage_waiting_for_semi_sync_ack_from_slave=
|
|
||||||
{ 0, "Waiting for semi-sync ACK from slave", 0};
|
|
||||||
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
PSI_stage_info *all_semisync_stages[]=
|
|
||||||
{
|
|
||||||
& stage_waiting_for_semi_sync_ack_from_slave
|
|
||||||
};
|
|
||||||
|
|
||||||
static void init_semisync_psi_keys(void)
|
|
||||||
{
|
|
||||||
const char* category= "semisync";
|
|
||||||
int count;
|
|
||||||
|
|
||||||
count= array_elements(all_semisync_mutexes);
|
|
||||||
mysql_mutex_register(category, all_semisync_mutexes, count);
|
|
||||||
|
|
||||||
count= array_elements(all_semisync_conds);
|
|
||||||
mysql_cond_register(category, all_semisync_conds, count);
|
|
||||||
|
|
||||||
count= array_elements(all_semisync_stages);
|
|
||||||
mysql_stage_register(category, all_semisync_stages, count);
|
|
||||||
}
|
|
||||||
#endif /* HAVE_PSI_INTERFACE */
|
|
||||||
|
|
||||||
static int semi_sync_master_plugin_init(void *p)
|
|
||||||
{
|
|
||||||
#ifdef HAVE_PSI_INTERFACE
|
|
||||||
init_semisync_psi_keys();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (repl_semisync.initObject())
|
|
||||||
return 1;
|
|
||||||
if (register_trans_observer(&trans_observer, p))
|
|
||||||
return 1;
|
|
||||||
if (register_binlog_storage_observer(&storage_observer, p))
|
|
||||||
return 1;
|
|
||||||
if (register_binlog_transmit_observer(&transmit_observer, p))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int semi_sync_master_plugin_deinit(void *p)
|
|
||||||
{
|
|
||||||
if (unregister_trans_observer(&trans_observer, p))
|
|
||||||
{
|
|
||||||
sql_print_error("unregister_trans_observer failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (unregister_binlog_storage_observer(&storage_observer, p))
|
|
||||||
{
|
|
||||||
sql_print_error("unregister_binlog_storage_observer failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (unregister_binlog_transmit_observer(&transmit_observer, p))
|
|
||||||
{
|
|
||||||
sql_print_error("unregister_binlog_transmit_observer failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
repl_semisync.cleanup();
|
|
||||||
sql_print_information("unregister_replicator OK");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Mysql_replication semi_sync_master_plugin= {
|
|
||||||
MYSQL_REPLICATION_INTERFACE_VERSION
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Plugin library descriptor
|
|
||||||
*/
|
|
||||||
maria_declare_plugin(semisync_master)
|
|
||||||
{
|
|
||||||
MYSQL_REPLICATION_PLUGIN,
|
|
||||||
&semi_sync_master_plugin,
|
|
||||||
"rpl_semi_sync_master",
|
|
||||||
"He Zhenxing",
|
|
||||||
"Semi-synchronous replication master",
|
|
||||||
PLUGIN_LICENSE_GPL,
|
|
||||||
semi_sync_master_plugin_init, /* Plugin Init */
|
|
||||||
semi_sync_master_plugin_deinit, /* Plugin Deinit */
|
|
||||||
0x0100 /* 1.0 */,
|
|
||||||
semi_sync_master_status_vars, /* status variables */
|
|
||||||
semi_sync_master_system_vars, /* system variables */
|
|
||||||
"1.0",
|
|
||||||
MariaDB_PLUGIN_MATURITY_STABLE
|
|
||||||
}
|
|
||||||
maria_declare_plugin_end;
|
|
||||||
|
|
@ -1,234 +0,0 @@
|
|||||||
/* Copyright (C) 2007 Google Inc.
|
|
||||||
Copyright (C) 2008 MySQL AB
|
|
||||||
Use is subject to license terms
|
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation; version 2 of the License.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program; if not, write to the Free Software
|
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
|
||||||
|
|
||||||
|
|
||||||
#include <my_global.h>
|
|
||||||
#include "semisync_slave.h"
|
|
||||||
#include <mysql.h>
|
|
||||||
|
|
||||||
static ReplSemiSyncSlave repl_semisync;
|
|
||||||
|
|
||||||
/*
|
|
||||||
indicate whether or not the slave should send a reply to the master.
|
|
||||||
|
|
||||||
This is set to true in repl_semi_slave_read_event if the current
|
|
||||||
event read is the last event of a transaction. And the value is
|
|
||||||
checked in repl_semi_slave_queue_event.
|
|
||||||
*/
|
|
||||||
bool semi_sync_need_reply= false;
|
|
||||||
|
|
||||||
C_MODE_START
|
|
||||||
|
|
||||||
int repl_semi_reset_slave(Binlog_relay_IO_param *param)
|
|
||||||
{
|
|
||||||
// TODO: reset semi-sync slave status here
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_slave_request_dump(Binlog_relay_IO_param *param,
|
|
||||||
uint32 flags)
|
|
||||||
{
|
|
||||||
MYSQL *mysql= param->mysql;
|
|
||||||
MYSQL_RES *res= 0;
|
|
||||||
MYSQL_ROW row;
|
|
||||||
const char *query;
|
|
||||||
|
|
||||||
if (!repl_semisync.getSlaveEnabled())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/* Check if master server has semi-sync plugin installed */
|
|
||||||
query= "SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled'";
|
|
||||||
if (mysql_real_query(mysql, query, strlen(query)) ||
|
|
||||||
!(res= mysql_store_result(mysql)))
|
|
||||||
{
|
|
||||||
sql_print_error("Execution failed on master: %s", query);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
row= mysql_fetch_row(res);
|
|
||||||
if (!row)
|
|
||||||
{
|
|
||||||
/* Master does not support semi-sync */
|
|
||||||
sql_print_warning("Master server does not support semi-sync, "
|
|
||||||
"fallback to asynchronous replication");
|
|
||||||
rpl_semi_sync_slave_status= 0;
|
|
||||||
mysql_free_result(res);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
mysql_free_result(res);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Tell master dump thread that we want to do semi-sync
|
|
||||||
replication
|
|
||||||
*/
|
|
||||||
query= "SET @rpl_semi_sync_slave= 1";
|
|
||||||
if (mysql_real_query(mysql, query, strlen(query)))
|
|
||||||
{
|
|
||||||
sql_print_error("Set 'rpl_semi_sync_slave=1' on master failed");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
mysql_free_result(mysql_store_result(mysql));
|
|
||||||
rpl_semi_sync_slave_status= 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_slave_read_event(Binlog_relay_IO_param *param,
|
|
||||||
const char *packet, unsigned long len,
|
|
||||||
const char **event_buf, unsigned long *event_len)
|
|
||||||
{
|
|
||||||
if (rpl_semi_sync_slave_status)
|
|
||||||
return repl_semisync.slaveReadSyncHeader(packet, len,
|
|
||||||
&semi_sync_need_reply,
|
|
||||||
event_buf, event_len);
|
|
||||||
*event_buf= packet;
|
|
||||||
*event_len= len;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_slave_queue_event(Binlog_relay_IO_param *param,
|
|
||||||
const char *event_buf,
|
|
||||||
unsigned long event_len,
|
|
||||||
uint32 flags)
|
|
||||||
{
|
|
||||||
if (rpl_semi_sync_slave_status && semi_sync_need_reply)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
We deliberately ignore the error in slaveReply, such error
|
|
||||||
should not cause the slave IO thread to stop, and the error
|
|
||||||
messages are already reported.
|
|
||||||
*/
|
|
||||||
(void) repl_semisync.slaveReply(param->mysql,
|
|
||||||
param->master_log_name,
|
|
||||||
param->master_log_pos);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_slave_io_start(Binlog_relay_IO_param *param)
|
|
||||||
{
|
|
||||||
return repl_semisync.slaveStart(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
int repl_semi_slave_io_end(Binlog_relay_IO_param *param)
|
|
||||||
{
|
|
||||||
return repl_semisync.slaveStop(param);
|
|
||||||
}
|
|
||||||
|
|
||||||
C_MODE_END
|
|
||||||
|
|
||||||
static void fix_rpl_semi_sync_slave_enabled(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val)
|
|
||||||
{
|
|
||||||
*(char *)ptr= *(char *)val;
|
|
||||||
repl_semisync.setSlaveEnabled(rpl_semi_sync_slave_enabled != 0);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void fix_rpl_semi_sync_trace_level(MYSQL_THD thd,
|
|
||||||
SYS_VAR *var,
|
|
||||||
void *ptr,
|
|
||||||
const void *val)
|
|
||||||
{
|
|
||||||
*(unsigned long *)ptr= *(unsigned long *)val;
|
|
||||||
repl_semisync.setTraceLevel(rpl_semi_sync_slave_trace_level);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* plugin system variables */
|
|
||||||
static MYSQL_SYSVAR_BOOL(enabled, rpl_semi_sync_slave_enabled,
|
|
||||||
PLUGIN_VAR_OPCMDARG,
|
|
||||||
"Enable semi-synchronous replication slave (disabled by default). ",
|
|
||||||
NULL, // check
|
|
||||||
&fix_rpl_semi_sync_slave_enabled, // update
|
|
||||||
0);
|
|
||||||
|
|
||||||
static MYSQL_SYSVAR_ULONG(trace_level, rpl_semi_sync_slave_trace_level,
|
|
||||||
PLUGIN_VAR_OPCMDARG,
|
|
||||||
"The tracing level for semi-sync replication.",
|
|
||||||
NULL, // check
|
|
||||||
&fix_rpl_semi_sync_trace_level, // update
|
|
||||||
32, 0, ~0UL, 1);
|
|
||||||
|
|
||||||
static SYS_VAR* semi_sync_slave_system_vars[]= {
|
|
||||||
MYSQL_SYSVAR(enabled),
|
|
||||||
MYSQL_SYSVAR(trace_level),
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* plugin status variables */
|
|
||||||
static SHOW_VAR semi_sync_slave_status_vars[]= {
|
|
||||||
{"Rpl_semi_sync_slave_status",
|
|
||||||
(char*) &rpl_semi_sync_slave_status, SHOW_BOOL},
|
|
||||||
{NULL, NULL, SHOW_BOOL},
|
|
||||||
};
|
|
||||||
|
|
||||||
Binlog_relay_IO_observer relay_io_observer = {
|
|
||||||
sizeof(Binlog_relay_IO_observer), // len
|
|
||||||
|
|
||||||
repl_semi_slave_io_start, // start
|
|
||||||
repl_semi_slave_io_end, // stop
|
|
||||||
repl_semi_slave_request_dump, // request_transmit
|
|
||||||
repl_semi_slave_read_event, // after_read_event
|
|
||||||
repl_semi_slave_queue_event, // after_queue_event
|
|
||||||
repl_semi_reset_slave, // reset
|
|
||||||
};
|
|
||||||
|
|
||||||
static int semi_sync_slave_plugin_init(void *p)
|
|
||||||
{
|
|
||||||
if (repl_semisync.initObject())
|
|
||||||
return 1;
|
|
||||||
if (register_binlog_relay_io_observer(&relay_io_observer, p))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int semi_sync_slave_plugin_deinit(void *p)
|
|
||||||
{
|
|
||||||
if (unregister_binlog_relay_io_observer(&relay_io_observer, p))
|
|
||||||
return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct Mysql_replication semi_sync_slave_plugin= {
|
|
||||||
MYSQL_REPLICATION_INTERFACE_VERSION
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Plugin library descriptor
|
|
||||||
*/
|
|
||||||
maria_declare_plugin(semisync_slave)
|
|
||||||
{
|
|
||||||
MYSQL_REPLICATION_PLUGIN,
|
|
||||||
&semi_sync_slave_plugin,
|
|
||||||
"rpl_semi_sync_slave",
|
|
||||||
"He Zhenxing",
|
|
||||||
"Semi-synchronous replication slave",
|
|
||||||
PLUGIN_LICENSE_GPL,
|
|
||||||
semi_sync_slave_plugin_init, /* Plugin Init */
|
|
||||||
semi_sync_slave_plugin_deinit, /* Plugin Deinit */
|
|
||||||
0x0100 /* 1.0 */,
|
|
||||||
semi_sync_slave_status_vars, /* status variables */
|
|
||||||
semi_sync_slave_system_vars, /* system variables */
|
|
||||||
"1.0",
|
|
||||||
MariaDB_PLUGIN_MATURITY_STABLE
|
|
||||||
}
|
|
||||||
maria_declare_plugin_end;
|
|
||||||
|
|
@ -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}
|
||||||
@ -138,6 +138,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
|
||||||
|
@ -97,8 +97,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>
|
||||||
@ -934,6 +935,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
|
|||||||
PSI_mutex_key key_RELAYLOG_LOCK_index;
|
PSI_mutex_key key_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,
|
||||||
@ -1021,7 +1023,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,
|
||||||
@ -1062,7 +1065,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;
|
||||||
@ -1124,7 +1127,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,
|
||||||
@ -2217,6 +2221,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();
|
||||||
@ -5170,6 +5178,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)
|
||||||
@ -8230,6 +8241,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
|
||||||
|
|
||||||
@ -8548,6 +8580,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},
|
||||||
@ -10285,6 +10341,8 @@ PSI_stage_info stage_waiting_for_insert= { 0, "Waiting for INSERT", 0};
|
|||||||
PSI_stage_info stage_waiting_for_master_to_send_event= { 0, "Waiting for master to send event", 0};
|
PSI_stage_info stage_waiting_for_master_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 @@
|
|||||||
|
|
||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
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()
|
|||||||
{
|
{
|
||||||
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()
|
|||||||
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; \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/* 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 @@
|
|||||||
#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
|
@ -24,34 +24,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
@ -61,7 +62,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
|
||||||
@ -141,7 +142,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;
|
||||||
}
|
}
|
||||||
@ -174,8 +175,8 @@ int ActiveTranx::insert_tranx_node(const char *log_file_name,
|
|||||||
*/
|
*/
|
||||||
sql_print_error("%s: binlog write out-of-order, tail (%s, %lu), "
|
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;
|
||||||
}
|
}
|
||||||
@ -187,7 +188,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:
|
||||||
@ -213,7 +214,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);
|
||||||
@ -296,7 +297,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);
|
||||||
@ -358,10 +359,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();
|
||||||
@ -380,7 +381,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;
|
||||||
@ -389,6 +390,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
|
||||||
@ -436,8 +438,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,17 +448,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)
|
||||||
@ -465,8 +467,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);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -566,7 +568,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)
|
||||||
@ -621,7 +623,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);
|
||||||
|
|
||||||
@ -632,7 +634,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());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,7 +651,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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -670,7 +672,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
|
||||||
@ -681,16 +683,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.
|
||||||
@ -700,31 +702,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)
|
||||||
{
|
{
|
||||||
@ -732,7 +734,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++;
|
||||||
}
|
}
|
||||||
@ -753,7 +755,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())
|
||||||
@ -770,7 +772,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
|
||||||
@ -842,14 +844,14 @@ int ReplSemiSyncMaster::try_switch_on(int server_id,
|
|||||||
sql_print_information("Semi-sync replication switched ON with slave (server_id: %d) "
|
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);
|
||||||
@ -870,7 +872,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.
|
||||||
*/
|
*/
|
||||||
@ -930,13 +932,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);
|
||||||
@ -961,7 +963,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();
|
||||||
@ -1181,27 +1183,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);
|
||||||
|
|
||||||
@ -1216,3 +1218,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 @@
|
|||||||
#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
|
|||||||
/* 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 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* 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;
|
|||||||
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 */
|
@ -18,9 +18,20 @@
|
|||||||
#include <my_global.h>
|
#include <my_global.h>
|
||||||
#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()
|
||||||
{
|
{
|
||||||
@ -73,7 +84,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",
|
||||||
@ -138,3 +149,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 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
/* 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 */
|
182
sql/sys_vars.cc
182
sql/sys_vars.cc
@ -61,6 +61,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>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3039,9 +3041,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), "
|
||||||
|
Loading…
x
Reference in New Issue
Block a user