Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions mysql-test/suite/multi_source/mix_semisync_async.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Test replicating from an additional connection of semi-sync mode `$mode2`
# does not interfere with the active connection of mode `$mode1`.
#
# Pre-Conditions:
# * On connection `slave`.
# * CHANGE MASTER `master1` and `master2` set up to
# replicate from the connection with the same name.
# * None of the replication threads are running.
# * User variables `$mode1` and `$mode2` contain
# corresponding `@@rpl_semi_sync_slave_enabled` values.
#
# Post-Conditions:
# * On connection `slave`.
# * None of the replication threads are running.
# * @@default_master_connection = 'master1',
# @@rpl_semi_sync_slave_enabled = $mode2

--let $status_var= Rpl_semi_sync_master_clients
--let $status_var_value= 1


# Start `master1`
SET @@SESSION.default_master_connection= 'master1';
--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= $mode1
--source include/start_slave.inc

# Start `master2`
SET @@SESSION.default_master_connection= 'master2';
--eval SET @@GLOBAL.rpl_semi_sync_slave_enabled= $mode2
--source include/start_slave.inc


# Verify `master2`
--connection master2
if ($mode2)
{
--source include/wait_for_status_var.inc
}
CREATE TABLE t2 (a INT);
DROP TABLE t2;
--save_master_pos
--connection slave
--sync_with_master 0, master2

# Verify `master1`
--connection master1
if ($mode1)
{
--source include/wait_for_status_var.inc
}
CREATE TABLE t1 (a INT);
--save_master_pos
--connection slave
--sync_with_master 0, master1
SHOW STATUS LIKE 'Rpl_semi_sync_slave_send_ack';


# Stop `master2`
--source include/stop_slave.inc

# Verify `master1`
--connection master1
DROP TABLE t1;
SHOW STATUS LIKE 'Rpl_semi_sync_master_clients';
--save_master_pos
--connection slave
--sync_with_master 0, master1
SHOW STATUS LIKE 'Rpl_semi_sync_slave_send_ack';

# Stop `master1`
SET @@SESSION.default_master_connection= 'master1';
--source include/stop_slave.inc
89 changes: 89 additions & 0 deletions mysql-test/suite/multi_source/mix_semisync_async.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Setup
connect master1, 127.0.0.1, root, , , $SERVER_MYPORT_1;
SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= 0;
SET @@GLOBAL.rpl_semi_sync_master_enabled= 1;
SET @@SESSION.gtid_domain_id= 1;
RESET MASTER;
connect master2, 127.0.0.1, root, , , $SERVER_MYPORT_2;
SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= 0;
SET @@GLOBAL.rpl_semi_sync_master_enabled= 1;
SET @@SESSION.gtid_domain_id= 2;
RESET MASTER;
connect slave, 127.0.0.1, root, , , $SERVER_MYPORT_3;
SET @@GLOBAL.gtid_slave_pos= '';
CHANGE MASTER 'master1' TO
master_host='127.0.0.1', master_port=SERVER_MYPORT_1,
master_user='root', master_ssl_verify_server_cert=0;
CHANGE MASTER 'master2' TO
master_host='127.0.0.1', master_port=SERVER_MYPORT_2,
master_user='root', master_ssl_verify_server_cert=0;
# Test semi-sync replication during async replication
SET @@SESSION.default_master_connection= 'master1';
SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0;
include/start_slave.inc
SET @@SESSION.default_master_connection= 'master2';
SET @@GLOBAL.rpl_semi_sync_slave_enabled= 1;
include/start_slave.inc
connection master2;
CREATE TABLE t2 (a INT);
DROP TABLE t2;
connection slave;
connection master1;
CREATE TABLE t1 (a INT);
connection slave;
SHOW STATUS LIKE 'Rpl_semi_sync_slave_send_ack';
Variable_name Value
Rpl_semi_sync_slave_send_ack 2
include/stop_slave.inc
connection master1;
DROP TABLE t1;
SHOW STATUS LIKE 'Rpl_semi_sync_master_clients';
Variable_name Value
Rpl_semi_sync_master_clients 0
connection slave;
SHOW STATUS LIKE 'Rpl_semi_sync_slave_send_ack';
Variable_name Value
Rpl_semi_sync_slave_send_ack 2
SET @@SESSION.default_master_connection= 'master1';
include/stop_slave.inc
# Test the other order
SET @@SESSION.default_master_connection= 'master1';
SET @@GLOBAL.rpl_semi_sync_slave_enabled= 1;
include/start_slave.inc
SET @@SESSION.default_master_connection= 'master2';
SET @@GLOBAL.rpl_semi_sync_slave_enabled= 0;
include/start_slave.inc
connection master2;
CREATE TABLE t2 (a INT);
DROP TABLE t2;
connection slave;
connection master1;
CREATE TABLE t1 (a INT);
connection slave;
SHOW STATUS LIKE 'Rpl_semi_sync_slave_send_ack';
Variable_name Value
Rpl_semi_sync_slave_send_ack 1
include/stop_slave.inc
connection master1;
DROP TABLE t1;
SHOW STATUS LIKE 'Rpl_semi_sync_master_clients';
Variable_name Value
Rpl_semi_sync_master_clients 1
connection slave;
SHOW STATUS LIKE 'Rpl_semi_sync_slave_send_ack';
Variable_name Value
Rpl_semi_sync_slave_send_ack 2
SET @@SESSION.default_master_connection= 'master1';
include/stop_slave.inc
# Cleanup
RESET SLAVE 'master1' ALL;
RESET SLAVE 'master2' ALL;
disconnect slave;
connection master1;
SET @@GLOBAL.rpl_semi_sync_master_enabled= 0;
SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= 1;
disconnect master1;
connection master2;
SET @@GLOBAL.rpl_semi_sync_master_enabled= 0;
SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= 1;
disconnect master2;
65 changes: 65 additions & 0 deletions mysql-test/suite/multi_source/mix_semisync_async.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# MDEV-32947 Async conflicts with semi-sync in multi-source
#
# With a async master and a semi-sync master,
# test replication does not mix async and semi-sync regardless of order

--source include/have_binlog_format_mixed.inc # format-agnostic
--let $orig_wait_no_slave= `SELECT @@GLOBAL.rpl_semi_sync_master_wait_no_slave`

--echo # Setup
# Enable semi-sync on both masters;
# the slave will disable semi-sync on one of its connections.

--connect (master1, 127.0.0.1, root, , , $SERVER_MYPORT_1)
SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= 0;
SET @@GLOBAL.rpl_semi_sync_master_enabled= 1;
SET @@SESSION.gtid_domain_id= 1;
RESET MASTER;

--connect (master2, 127.0.0.1, root, , , $SERVER_MYPORT_2)
SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= 0;
SET @@GLOBAL.rpl_semi_sync_master_enabled= 1;
SET @@SESSION.gtid_domain_id= 2;
RESET MASTER;

--connect (slave, 127.0.0.1, root, , , $SERVER_MYPORT_3)
--disable_warnings
SET @@GLOBAL.gtid_slave_pos= '';
--enable_warnings

--replace_result $SERVER_MYPORT_1 SERVER_MYPORT_1
eval CHANGE MASTER 'master1' TO
master_host='127.0.0.1', master_port=$SERVER_MYPORT_1,
master_user='root', master_ssl_verify_server_cert=0;
--replace_result $SERVER_MYPORT_2 SERVER_MYPORT_2
eval CHANGE MASTER 'master2' TO
master_host='127.0.0.1', master_port=$SERVER_MYPORT_2,
master_user='root', master_ssl_verify_server_cert=0;


--echo # Test semi-sync replication during async replication
--let $mode1= 0
--let $mode2= 1
--source mix_semisync_async.inc

--echo # Test the other order
--let $mode1= 1
--let $mode2= 0
--source mix_semisync_async.inc


--echo # Cleanup

RESET SLAVE 'master1' ALL;
RESET SLAVE 'master2' ALL;
--disconnect slave

--connection master1
SET @@GLOBAL.rpl_semi_sync_master_enabled= 0;
--eval SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= $orig_wait_no_slave
--disconnect master1

--connection master2
SET @@GLOBAL.rpl_semi_sync_master_enabled= 0;
--eval SET @@GLOBAL.rpl_semi_sync_master_wait_no_slave= $orig_wait_no_slave
--disconnect master2
1 change: 1 addition & 0 deletions sql/rpl_mi.h
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,7 @@ class Master_info : public Slave_reporting_capability
it must be ignored similarly to the replicate-same-server-id rule.
*/
bool do_accept_own_server_id= false;
bool semi_sync_enabled= false;
/*
Set to 1 when semi_sync is enabled. Set to 0 if there is any transmit
problems to the slave, in which case any furter semi-sync reply is
Expand Down
43 changes: 25 additions & 18 deletions sql/semisync_slave.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,29 +40,36 @@ int Repl_semi_sync_slave::init_object()
return result;
}

static bool local_semi_sync_enabled;

int rpl_semi_sync_enabled(THD *thd, SHOW_VAR *var, void *buff,
system_status_var *status_var,
enum_var_type scope)
{
local_semi_sync_enabled= repl_semisync_slave.get_slave_enabled();
var->type= SHOW_BOOL;
var->value= (char*) &local_semi_sync_enabled;
if (Master_info *mi=
get_master_info(&thd->variables.default_master_connection,
Sql_condition::WARN_LEVEL_NOTE))
{
*static_cast<bool *>(buff)=
repl_semisync_slave.get_slave_enabled(mi);
mi->release();
var->type= SHOW_BOOL;
var->value= buff;
}
else
var->type= SHOW_UNDEF;
return 0;
}
Comment on lines 46 to 60

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

matches Slave_running (show_slave_running()) 🤔 ¯\_(ツ)_/¯



int Repl_semi_sync_slave::slave_read_sync_header(const uchar *header,
unsigned long total_len,
int *semi_flags,
Master_info *mi,
const uchar **payload,
unsigned long *payload_len)
{
int read_res = 0;
DBUG_ENTER("Repl_semi_sync_slave::slave_read_sync_header");

if (get_slave_enabled())
if (get_slave_enabled(mi))
{
if (!DBUG_IF("semislave_corrupt_log")
&& header[0] == k_packet_magic_num)
Expand All @@ -76,9 +83,9 @@ int Repl_semi_sync_slave::slave_read_sync_header(const uchar *header,
semi_sync_need_reply));

if (semi_sync_need_reply)
*semi_flags |= SEMI_SYNC_NEED_ACK;
mi->semi_ack |= SEMI_SYNC_NEED_ACK;
if (is_delay_master())
*semi_flags |= SEMI_SYNC_SLAVE_DELAY_SYNC;
mi->semi_ack |= SEMI_SYNC_SLAVE_DELAY_SYNC;
}
else
{
Expand Down Expand Up @@ -111,7 +118,7 @@ void Repl_semi_sync_slave::slave_start(Master_info *mi)
*/
bool semi_sync= global_rpl_semi_sync_slave_enabled;

set_slave_enabled(semi_sync);
set_slave_enabled(mi, semi_sync);
mi->semi_sync_reply_enabled= 0;

sql_print_information("Slave I/O thread: Start %s replication to\
Expand All @@ -127,7 +134,7 @@ void Repl_semi_sync_slave::slave_start(Master_info *mi)

void Repl_semi_sync_slave::slave_stop(Master_info *mi)
{
if (get_slave_enabled())
if (get_slave_enabled(mi))
{
#ifdef ENABLED_DEBUG_SYNC
/*
Expand All @@ -144,7 +151,7 @@ void Repl_semi_sync_slave::slave_stop(Master_info *mi)
kill_connection(mi);
}

set_slave_enabled(0);
set_slave_enabled(mi, 0);
}

void Repl_semi_sync_slave::slave_reconnect(Master_info *mi)
Expand All @@ -153,7 +160,7 @@ void Repl_semi_sync_slave::slave_reconnect(Master_info *mi)
Start semi-sync either if it globally enabled or if was enabled
before the reconnect.
*/
if (global_rpl_semi_sync_slave_enabled || get_slave_enabled())
if (global_rpl_semi_sync_slave_enabled || get_slave_enabled(mi))
slave_start(mi);
}

Expand Down Expand Up @@ -215,15 +222,15 @@ int Repl_semi_sync_slave::request_transmit(Master_info *mi)
MYSQL_ROW row;
const char *query;

if (!get_slave_enabled())
if (!get_slave_enabled(mi))
return 0;

query= "SHOW VARIABLES LIKE 'rpl_semi_sync_master_enabled'";
if (mysql_real_query(mysql, query, (ulong)strlen(query)) ||
!(res= mysql_store_result(mysql)))
{
sql_print_error("Execution failed on master: %s, error :%s", query, mysql_error(mysql));
set_slave_enabled(0);
set_slave_enabled(mi, 0);
return 1;
}

Expand All @@ -234,7 +241,7 @@ int Repl_semi_sync_slave::request_transmit(Master_info *mi)
if (!row)
sql_print_warning("Master server does not support semi-sync, "
"fallback to asynchronous replication");
set_slave_enabled(0);
set_slave_enabled(mi, 0);
mysql_free_result(res);
return 0;
}
Expand All @@ -253,7 +260,7 @@ int Repl_semi_sync_slave::request_transmit(Master_info *mi)
if (mysql_real_query(mysql, query, (ulong)strlen(query)))
{
sql_print_error("%s on master failed", query);
set_slave_enabled(0);
set_slave_enabled(mi, 0);
return 1;
}
mi->semi_sync_reply_enabled= 1;
Expand All @@ -276,7 +283,7 @@ int Repl_semi_sync_slave::slave_reply(Master_info *mi)
int reply_res = 0;
size_t name_len = strlen(binlog_filename);
DBUG_ENTER("Repl_semi_sync_slave::slave_reply");
DBUG_ASSERT(get_slave_enabled() && mi->semi_sync_reply_enabled);
DBUG_ASSERT(get_slave_enabled(mi) && mi->semi_sync_reply_enabled);

/* Prepare the buffer of the reply. */
reply_buffer[REPLY_MAGIC_NUM_OFFSET] = k_packet_magic_num;
Expand Down
Loading