summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result28
-rw-r--r--mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test50
-rw-r--r--sql/log_event.cc30
-rw-r--r--sql/log_event.h9
4 files changed, 106 insertions, 11 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result b/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result
index 2a7ed37cf9b..12623bdeb3a 100644
--- a/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result
+++ b/mysql-test/suite/rpl/r/rpl_mariadb_slave_capability.result
@@ -62,6 +62,32 @@ slave-relay-bin.000007 # Query # # # Dummy ev
slave-relay-bin.000007 # Table_map # # table_id: # (test.t1)
slave-relay-bin.000007 # Write_rows # # table_id: # flags: STMT_END_F
slave-relay-bin.000007 # Query # # COMMIT
+*** MDEV-5754: MySQL 5.5 slaves cannot replicate from MariaDB 10.0 ***
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+INSERT INTO t2 VALUES (1);
+SET debug_sync='now WAIT_FOR master_queued1';
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+INSERT INTO t2 VALUES (2);
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+SET debug_sync='RESET';
+SET debug_sync='RESET';
+SET debug_sync='RESET';
+show binlog events in 'master-bin.000003' from <binlog_start> limit 0, 8;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000003 # Table_map # # table_id: # (test.t2)
+master-bin.000003 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000003 # Xid # # COMMIT /* XID */
+master-bin.000003 # Gtid # # BEGIN GTID #-#-# cid=#
+master-bin.000003 # Table_map # # table_id: # (test.t2)
+master-bin.000003 # Write_rows # # table_id: # flags: STMT_END_F
+master-bin.000003 # Xid # # COMMIT /* XID */
+SELECT * FROM t2 ORDER BY a;
+a
+1
+2
# Test that slave which cannot tolerate holes in binlog stream but
# knows the event does not get dummy event
include/stop_slave.inc
@@ -95,5 +121,5 @@ select @@global.replicate_annotate_row_events;
set @@global.debug_dbug= @old_slave_dbug;
Clean up.
set @@global.binlog_checksum = @old_master_binlog_checksum;
-DROP TABLE t1;
+DROP TABLE t1, t2;
include/rpl_end.inc
diff --git a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test
index 99a371eac44..7a2f5f3e699 100644
--- a/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test
+++ b/mysql-test/suite/rpl/t/rpl_mariadb_slave_capability.test
@@ -1,6 +1,8 @@
--source include/master-slave.inc
--source include/have_debug.inc
+--source include/have_debug_sync.inc
--source include/have_binlog_format_row.inc
+--source include/have_innodb.inc
connection master;
@@ -71,6 +73,52 @@ let $binlog_start= 0;
let $binlog_limit=7,5;
--source include/show_relaylog_events.inc
+
+--echo *** MDEV-5754: MySQL 5.5 slaves cannot replicate from MariaDB 10.0 ***
+
+# The problem was that for a group commit, we get commit id into the
+# GTID event, and there was a bug in the code that replaces GTID with
+# dummy that failed when commit id was present.
+#
+# So setup a group commit in InnoDB.
+
+--connection master
+CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
+let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
+let $binlog_start= query_get_value(SHOW MASTER STATUS, Position, 1);
+
+--connect (con1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued1 WAIT_FOR master_cont1';
+send INSERT INTO t2 VALUES (1);
+
+--connection master
+SET debug_sync='now WAIT_FOR master_queued1';
+
+--connect (con2,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
+SET debug_sync='commit_after_release_LOCK_prepare_ordered SIGNAL master_queued2';
+send INSERT INTO t2 VALUES (2);
+
+--connection master
+SET debug_sync='now WAIT_FOR master_queued2';
+SET debug_sync='now SIGNAL master_cont1';
+
+--connection con1
+REAP;
+SET debug_sync='RESET';
+--connection con2
+REAP;
+SET debug_sync='RESET';
+--connection master
+SET debug_sync='RESET';
+let $binlog_limit= 0, 8;
+--source include/show_binlog_events.inc
+--save_master_pos
+
+--connection slave
+--sync_with_master
+SELECT * FROM t2 ORDER BY a;
+
+
--echo # Test that slave which cannot tolerate holes in binlog stream but
--echo # knows the event does not get dummy event
@@ -106,6 +154,6 @@ set @@global.debug_dbug= @old_slave_dbug;
--echo Clean up.
connection master;
set @@global.binlog_checksum = @old_master_binlog_checksum;
-DROP TABLE t1;
+DROP TABLE t1, t2;
sync_slave_with_master;
--source include/rpl_end.inc
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 361efe4428e..acdf370cf76 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -3639,9 +3639,14 @@ Query_log_event::begin_event(String *packet, ulong ev_offset,
DBUG_ASSERT(checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF ||
checksum_alg == BINLOG_CHECKSUM_ALG_OFF);
- /* Currently we only need to replace GTID event. */
- DBUG_ASSERT(data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN);
- if (data_len != LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN)
+ /*
+ Currently we only need to replace GTID event.
+ The length of GTID differs depending on whether it contains commit id.
+ */
+ DBUG_ASSERT(data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN ||
+ data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN + 2);
+ if (data_len != LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN &&
+ data_len != LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN + 2)
return 1;
flags= uint2korr(p + FLAGS_OFFSET);
@@ -3654,9 +3659,22 @@ Query_log_event::begin_event(String *packet, ulong ev_offset,
int4store(q + Q_EXEC_TIME_OFFSET, 0);
q[Q_DB_LEN_OFFSET]= 0;
int2store(q + Q_ERR_CODE_OFFSET, 0);
- int2store(q + Q_STATUS_VARS_LEN_OFFSET, 0);
- q[Q_DATA_OFFSET]= 0; /* Zero terminator for empty db */
- q+= Q_DATA_OFFSET + 1;
+ if (data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN)
+ {
+ int2store(q + Q_STATUS_VARS_LEN_OFFSET, 0);
+ q[Q_DATA_OFFSET]= 0; /* Zero terminator for empty db */
+ q+= Q_DATA_OFFSET + 1;
+ }
+ else
+ {
+ DBUG_ASSERT(data_len == LOG_EVENT_HEADER_LEN + GTID_HEADER_LEN + 2);
+ /* Put in an empty time_zone_str to take up the extra 2 bytes. */
+ int2store(q + Q_STATUS_VARS_LEN_OFFSET, 2);
+ q[Q_DATA_OFFSET]= Q_TIME_ZONE_CODE;
+ q[Q_DATA_OFFSET+1]= 0; /* Zero length for empty time_zone_str */
+ q[Q_DATA_OFFSET+2]= 0; /* Zero terminator for empty db */
+ q+= Q_DATA_OFFSET + 3;
+ }
memcpy(q, "BEGIN", 5);
if (checksum_alg == BINLOG_CHECKSUM_ALG_CRC32)
diff --git a/sql/log_event.h b/sql/log_event.h
index 312a9656d01..415332c46bc 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -3105,12 +3105,15 @@ public:
<td>flags</td>
<td>1 byte bitfield</td>
<td>Bit 0 set indicates stand-alone event (no terminating COMMIT)</td>
+ <td>Bit 1 set indicates group commit, and that commit id exists</td>
</tr>
<tr>
- <td>Reserved</td>
- <td>6 bytes</td>
- <td>Reserved bytes, set to 0. Maybe be used for future expansion.</td>
+ <td>Reserved (no group commit) / commit id (group commit) (see flags bit 1)</td>
+ <td>6 bytes / 8 bytes</td>
+ <td>Reserved bytes, set to 0. Maybe be used for future expansion (no
+ group commit). OR commit id, same for all GTIDs in the same group
+ commit (see flags bit 1).</td>
</tr>
</table>