[Commits] 096722b61eb: MDEV-11154: Write_on_release_cache(log_event.cc) function will not write "COMMIT", if use "mysqlbinlog ... | mysql ..."

sujatha sujatha.sivakumar at mariadb.com
Thu Jul 11 13:29:43 EEST 2019


revision-id: 096722b61ebe66ffe510156d358d4ddbeb53241a (mariadb-10.2.25-35-g096722b61eb)
parent(s): 41f6e68878df46dd7abc8a98234f58a1fa030592
author: Sujatha
committer: Sujatha
timestamp: 2019-07-11 12:33:32 +0530
message:

MDEV-11154: Write_on_release_cache(log_event.cc) function will not write "COMMIT", if use "mysqlbinlog ... | mysql ..."

Problem:
=======
Executing command, "mysqlbinlog --read-from-remote-server --host='xx.xx.xx.xx'
--port=3306 --user=xxx --password=xxx --database=mysql --to-last-log
mysql-bin.000001 --start-position=1098699 --stop-never |mysql -uxxx -pxxx", we
found that last data read from remote couldn't commit.

Analysis:
========
The purpose of 'Write_on_release_cache' is that the contents of the Cache will
automatically be written to a dedicated result file on destruction. Flush
operation on the result file is controlled by a flag 'FLUSH_F'. Events which
require force flush upon their destruction will have to enable this
'Write_on_release_cache::FLUSH_F'. At present the 'FLUSH_F' flag is defined as
an enum as shown below.

enum flag
{
  FLUSH_F
};

Since 'FLUSH_F' is the first member without initialization it get the default
value '0'. Because of this the following flush condition never succeeds.

if (m_flags & FLUSH_F)
  fflush(m_file);

At present the file gets flushed only during my_fclose(result_file) operation.
When continuous streaming is enabled through --stop-never option it never gets
flushed and hence events are not replicated.

Fix:
===
Initialize the enum value to non zero value.

FLUSH_F is effective when event cache is copied to file. From 10.2 onwards the
event cache can also be copied to a string. This string is appended to
result_file at the end of processing the event. An additional flush needs
to be done after the event is written to the result_file.

---
 client/mysqlbinlog.cc                              |  1 +
 .../binlog/r/binlog_mysqlbinlog_stop_never.result  | 16 ++++++
 .../binlog/t/binlog_mysqlbinlog_stop_never.test    | 66 ++++++++++++++++++++++
 sql/log_event.cc                                   |  2 +-
 4 files changed, 84 insertions(+), 1 deletion(-)

diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 1516e08284b..acccf0a3411 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1534,6 +1534,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
       {
         my_fwrite(result_file, (const uchar *) tmp_str.str, tmp_str.length,
                   MYF(MY_NABP));
+        fflush(result_file);
         my_free(tmp_str.str);
       }
     }
diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_stop_never.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_stop_never.result
new file mode 100644
index 00000000000..e94f17b9489
--- /dev/null
+++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_stop_never.result
@@ -0,0 +1,16 @@
+RESET MASTER;
+include/stop_dump_threads.inc
+# Step-1: Execute some dummy statements.
+CREATE TABLE t1(i int);
+INSERT INTO t1 values (1);
+# Step-2: Disable binary log temporarily and drop the table 't1'.
+set @@SESSION.SQL_LOG_BIN = 0;
+DROP TABLE t1;
+set @@SESSION.SQL_LOG_BIN = 1;
+# Step-3: Execute MYSQL_BINLOG with --stop-never and source it to mysql client.
+# Step-4: Wait till dump thread transfer is completed.
+# Step-5: Check that the data is there.
+# Step-6: Cleanup
+# kill the dump thread serving the mysqlbinlog --stop-never process
+include/stop_dump_threads.inc
+DROP TABLE t1;
diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test
new file mode 100644
index 00000000000..d73e453ce96
--- /dev/null
+++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_stop_never.test
@@ -0,0 +1,66 @@
+# ==== Purpose ====
+#
+# Test verifies that continuous streaming of binary log content using the
+# "mysqlbinlog --stop-never" option and sourcing it to mysql client works
+# fine.
+#
+# ==== Implementation ====
+#
+# Steps:
+#    1 - Create a table on a server on which binary log is enabled and insert
+#        a row.
+#    2 - Disable the binary log on the server and drop the table.
+#    3 - Capture the binary log output using "mysqlbinlog --stop_never" option
+#        and source it to mysql client.
+#    4 - Query the PROCESSLIST table to ensure that the dump thread which is
+#        serving "stop_never" option has read entire binlog.
+#    5 - Verify that the table is populated on the server.
+#    6 - Cleanup.
+#
+# ==== References ====
+#
+# MDEV-11154: Write_on_release_cache(log_event.cc) function will not write
+#             "COMMIT", if use "mysqlbinlog ... | mysql ..."
+
+--source include/not_windows.inc
+
+# Test is not specific to any binlog format. Hence Running only for 'row'.
+--source include/have_binlog_format_row.inc
+
+# binlog file name is needed in the test. To use master-bin.000001,
+# RESET MASTER is needed.
+RESET MASTER;
+# kill the dump threads if there any dump threads (may be from previous test)
+--source include/stop_dump_threads.inc
+
+--echo # Step-1: Execute some dummy statements.
+CREATE TABLE t1(i int);
+INSERT INTO t1 values (1);
+
+--echo # Step-2: Disable binary log temporarily and drop the table 't1'.
+set @@SESSION.SQL_LOG_BIN = 0;
+DROP TABLE t1;
+set @@SESSION.SQL_LOG_BIN = 1;
+
+--echo # Step-3: Execute MYSQL_BINLOG with --stop-never and source it to mysql client.
+--write_file $MYSQL_TMP_DIR/mysqlbinlog_stop_never.sh
+(`$MYSQL_BINLOG --read-from-remote-server --stop-never --user=root --host=127.0.0.1 --port=$MASTER_MYPORT  master-bin.000001 | $MYSQL --user=root --protocol=tcp --host=127.0.0.1 --port=$MASTER_MYPORT`) < /dev/null > /dev/null 2>&1  &
+EOF
+--exec /bin/bash $MYSQL_TMP_DIR/mysqlbinlog_stop_never.sh
+
+--echo # Step-4: Wait till dump thread transfer is completed.
+let $wait_condition= SELECT id from information_schema.processlist where processlist.command like '%Binlog%' and state like '%Master has sent%';
+--source include/wait_condition.inc
+
+--echo # Step-5: Check that the data is there.
+let $count= 1;
+let $table= test.t1;
+source include/wait_until_rows_count.inc;
+
+--echo # Step-6: Cleanup
+--echo # kill the dump thread serving the mysqlbinlog --stop-never process
+--source include/stop_dump_threads.inc
+
+DROP TABLE t1;
+--remove_file $MYSQL_TMP_DIR/mysqlbinlog_stop_never.sh
+
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 01f31aceff7..0e0d69b515c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -296,7 +296,7 @@ class Write_on_release_cache
 public:
   enum flag
   {
-    FLUSH_F
+    FLUSH_F= 1
   };
 
   typedef unsigned short flag_set;


More information about the commits mailing list