From f9b4dbb2768a709935fe3a82650ec900db72d52a Mon Sep 17 00:00:00 2001 From: ParadoxV5 Date: Fri, 11 Apr 2025 19:47:57 -0600 Subject: [PATCH 1/2] MDEV-23077: --flashback + --table produces buggy results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Events of skipped tables were still queued and generates extraneous “Row event for unknown table” when flashing back. * Skipping a statement-end event left prior non-skipped events processed incompletely. Co-Authored-By: lukexwang --- client/mysqlbinlog.cc | 14 ++-- mysql-test/suite/binlog/r/flashback.result | 58 +++++++++++++++ mysql-test/suite/binlog/t/flashback.test | 83 +++++++++++++++++++++- 3 files changed, 148 insertions(+), 7 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 77f74e0d42cae..f677586e43695 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -884,7 +884,7 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, char ll_buff[21]; bool result= 0; - if (opt_flashback) + if (opt_flashback && !skip_event) { Rows_log_event *e= (Rows_log_event*) ev; // The last Row_log_event will be the first event in Flashback @@ -936,7 +936,7 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, result_file (as it would happen in ev->print(...) if event was not skipped). */ - if (skip_event) + if (skip_event && !opt_flashback) { // append END-MARKER(') with delimiter IO_CACHE *const body_cache= &print_event_info->body_cache; @@ -955,14 +955,14 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, } /* skip the event check */ - if (skip_event) + if (skip_event && !(opt_flashback && is_stmt_end)) return 0; if (!opt_flashback) result= print_base64(print_event_info, ev); else { - if (is_stmt_end) + if (is_stmt_end && events_in_stmt.elements) { Log_event *e= NULL; @@ -1576,7 +1576,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, DBUG_PRINT("info", ("is_stmt_end: %d", (int) is_stmt_end)); if (is_stmt_end) print_event_info->found_row_event= 0; - else if (opt_flashback) + else if (opt_flashback && + !print_event_info->m_table_map_ignored.get_table(e->get_table_id())) destroy_evt= FALSE; break; } @@ -1590,7 +1591,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, e->get_flags(Old_rows_log_event::STMT_END_F))) goto err; DBUG_PRINT("info", ("is_stmt_end: %d", (int) is_stmt_end)); - if (!is_stmt_end && opt_flashback) + if (!is_stmt_end && opt_flashback && + !print_event_info->m_table_map_ignored.get_table(e->get_table_id())) destroy_evt= FALSE; break; } diff --git a/mysql-test/suite/binlog/r/flashback.result b/mysql-test/suite/binlog/r/flashback.result index da6dc7e07ff2a..af059c00ce962 100644 --- a/mysql-test/suite/binlog/r/flashback.result +++ b/mysql-test/suite/binlog/r/flashback.result @@ -702,6 +702,64 @@ include/assert.inc [Table t1 should have 0 rows.] # 6- Rows must be present upon restoring from flashback include/assert.inc [Table t1 should have six rows.] DROP TABLE t1; +# < CASE 8 > +# MDEV-23077: --flashback + --table produces buggy results +# +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1), (-1); +CREATE TABLE t2 (i INT); +INSERT INTO t2 VALUES (1), (-2); +RESET MASTER; +BEGIN; +UPDATE t1, t2 SET t1.i=2, t2.i=2 WHERE t1.i=t2.i AND t1.i=1; +DELETE t1, t2 FROM t1 INNER JOIN t2 WHERE t1.i=2; +COMMIT; +FLUSH BINARY LOGS; +SELECT * FROM t1; +i +-1 +SELECT * FROM t2; +i +# < CASE 8.1 > +# Only the table used in WHERE +# MDEV-23077 bug03: Only the first Base64 was in a BINLOG statement. +# +SELECT * FROM t1; +i +1 +-1 +SELECT * FROM t2; +i +# < CASE 8.2 > +# Ignore the table used in WHERE +# MDEV-23077 bug02: Output includes extraneous "unknown table". +# +NOT FOUND /### Row event for unknown table/ in mysqlbinlog_row_flashback_8_2.sql +DROP TABLE t1; +DROP TABLE t2; +# < CASE 9 > +# --flashback + --database +# +CREATE DATABASE d1; +CREATE DATABASE d2; +CREATE TABLE d1.t AS SELECT 1 AS a; +CREATE TABLE d2.t AS SELECT 2 AS a; +RESET MASTER; +BEGIN; +DELETE FROM d1.t; +DELETE FROM d2.t; +COMMIT; +FLUSH LOGS; +# < CASE 9 > +# Flashback & Check the result +# +SELECT * FROM d1.t; +a +1 +SELECT * FROM d2.t; +a +DROP DATABASE d1; +DROP DATABASE d2; # # MDEV-30698 Cover missing test cases for mariadb-binlog options # --raw [and] --flashback diff --git a/mysql-test/suite/binlog/t/flashback.test b/mysql-test/suite/binlog/t/flashback.test index 8daf3f43a2399..f227be5abf56a 100644 --- a/mysql-test/suite/binlog/t/flashback.test +++ b/mysql-test/suite/binlog/t/flashback.test @@ -364,13 +364,94 @@ FLUSH LOGS; DROP TABLE t1; +--echo # < CASE 8 > +--echo # MDEV-23077: --flashback + --table produces buggy results +--echo # + +CREATE TABLE t1 (i INT); +INSERT INTO t1 VALUES (1), (-1); +CREATE TABLE t2 (i INT); +INSERT INTO t2 VALUES (1), (-2); + +RESET MASTER; +BEGIN; + UPDATE t1, t2 SET t1.i=2, t2.i=2 WHERE t1.i=t2.i AND t1.i=1; + DELETE t1, t2 FROM t1 INNER JOIN t2 WHERE t1.i=2; +COMMIT; +FLUSH BINARY LOGS; + +# only (-1) +SELECT * FROM t1; +# empty +SELECT * FROM t2; + +--echo # < CASE 8.1 > +--echo # Only the table used in WHERE +--echo # MDEV-23077 bug03: Only the first Base64 was in a BINLOG statement. +--echo # + +--exec $MYSQL_BINLOG -Bvv --table=t1 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8_1.sql +--exec $MYSQL -e "SOURCE $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8_1.sql;" + +# (1), (-1) +SELECT * FROM t1; +# still empty +SELECT * FROM t2; + +--echo # < CASE 8.2 > +--echo # Ignore the table used in WHERE +--echo # MDEV-23077 bug02: Output includes extraneous "unknown table". +--echo # + +--exec $MYSQL_BINLOG -Bvv --table=t2 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8_2.sql + +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8_2.sql +--let SEARCH_PATTERN= ### Row event for unknown table +--source include/search_pattern_in_file.inc + +DROP TABLE t1; +DROP TABLE t2; + +--echo # < CASE 9 > +--echo # --flashback + --database +--echo # + +CREATE DATABASE d1; +CREATE DATABASE d2; +CREATE TABLE d1.t AS SELECT 1 AS a; +CREATE TABLE d2.t AS SELECT 2 AS a; + +RESET MASTER; +BEGIN; + # delete all data + DELETE FROM d1.t; + DELETE FROM d2.t; +COMMIT; +FLUSH LOGS; + +--echo # < CASE 9 > +--echo # Flashback & Check the result +--echo # + +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--exec $MYSQL_BINLOG -Bvv --database=d1 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9.sql +--exec $MYSQL -e "SOURCE $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9.sql;" + +# (1) +SELECT * FROM d1.t; +# empty +SELECT * FROM d2.t; + +DROP DATABASE d1; +DROP DATABASE d2; + --echo # --echo # MDEV-30698 Cover missing test cases for mariadb-binlog options --echo # --raw [and] --flashback --echo # --error 1 # --raw mode and --flashback mode are not allowed ---exec $MYSQL_BINLOG -vv -B --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000003> $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8.sql +--exec $MYSQL_BINLOG -vv -B --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT master-bin.000003> $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_0.sql ## Clear SET binlog_format=statement; From dec498fcfd24da801dfefc965a074c605e71761f Mon Sep 17 00:00:00 2001 From: ParadoxV5 Date: Thu, 17 Apr 2025 22:06:08 -0600 Subject: [PATCH 2/2] --flashback + --database also buggy results MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Events of skipped databases were still queued and generates extraneous “Row event for unknown table” when flashing back. * Skipping a statement-end event left prior non-skipped events processed incompletely. --- mysql-test/suite/binlog/r/flashback.result | 43 +++++++++++++++---- mysql-test/suite/binlog/t/flashback.test | 50 ++++++++++++++++------ 2 files changed, 71 insertions(+), 22 deletions(-) diff --git a/mysql-test/suite/binlog/r/flashback.result b/mysql-test/suite/binlog/r/flashback.result index af059c00ce962..6f9140684c516 100644 --- a/mysql-test/suite/binlog/r/flashback.result +++ b/mysql-test/suite/binlog/r/flashback.result @@ -734,6 +734,14 @@ i # Ignore the table used in WHERE # MDEV-23077 bug02: Output includes extraneous "unknown table". # +SELECT * FROM t1; +i +1 +-1 +SELECT * FROM t2; +i +1 +-2 NOT FOUND /### Row event for unknown table/ in mysqlbinlog_row_flashback_8_2.sql DROP TABLE t1; DROP TABLE t2; @@ -742,22 +750,39 @@ DROP TABLE t2; # CREATE DATABASE d1; CREATE DATABASE d2; -CREATE TABLE d1.t AS SELECT 1 AS a; -CREATE TABLE d2.t AS SELECT 2 AS a; +CREATE TABLE d1.t (i INT); +INSERT INTO d1.t VALUES (1), (-1); +CREATE TABLE d2.t (i INT); +INSERT INTO d2.t VALUES (1), (-2); RESET MASTER; BEGIN; -DELETE FROM d1.t; -DELETE FROM d2.t; +UPDATE d1.t, d2.t SET d1.t.i=2, d2.t.i=2 WHERE d1.t.i=d2.t.i AND d1.t.i=1; +DELETE d1.t, d2.t FROM d1.t INNER JOIN d2.t WHERE d1.t.i=2; COMMIT; -FLUSH LOGS; -# < CASE 9 > -# Flashback & Check the result +FLUSH BINARY LOGS; +# < CASE 9.1 > +# Only the database used in WHERE +# MDEV-23077 bug03: Only the first Base64 was in a BINLOG statement. # SELECT * FROM d1.t; -a +i +1 +-1 +SELECT * FROM d2.t; +i +# < CASE 9.2 > +# Ignore the database used in WHERE +# MDEV-23077 bug02: Output includes extraneous "unknown table". +# +SELECT * FROM d1.t; +i 1 +-1 SELECT * FROM d2.t; -a +i +1 +-2 +NOT FOUND /### Row event for unknown table/ in mysqlbinlog_row_flashback_9_2.sql DROP DATABASE d1; DROP DATABASE d2; # diff --git a/mysql-test/suite/binlog/t/flashback.test b/mysql-test/suite/binlog/t/flashback.test index f227be5abf56a..f93c175b46255 100644 --- a/mysql-test/suite/binlog/t/flashback.test +++ b/mysql-test/suite/binlog/t/flashback.test @@ -404,6 +404,12 @@ SELECT * FROM t2; --echo # --exec $MYSQL_BINLOG -Bvv --table=t2 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8_2.sql +--exec $MYSQL -e "SOURCE $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8_2.sql;" + +# (1), (-1) +SELECT * FROM t1; +# (1), (-2) +SELECT * FROM t2; --let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_8_2.sql --let SEARCH_PATTERN= ### Row event for unknown table @@ -418,30 +424,48 @@ DROP TABLE t2; CREATE DATABASE d1; CREATE DATABASE d2; -CREATE TABLE d1.t AS SELECT 1 AS a; -CREATE TABLE d2.t AS SELECT 2 AS a; +CREATE TABLE d1.t (i INT); +INSERT INTO d1.t VALUES (1), (-1); +CREATE TABLE d2.t (i INT); +INSERT INTO d2.t VALUES (1), (-2); RESET MASTER; BEGIN; - # delete all data - DELETE FROM d1.t; - DELETE FROM d2.t; + UPDATE d1.t, d2.t SET d1.t.i=2, d2.t.i=2 WHERE d1.t.i=d2.t.i AND d1.t.i=1; + DELETE d1.t, d2.t FROM d1.t INNER JOIN d2.t WHERE d1.t.i=2; COMMIT; -FLUSH LOGS; +FLUSH BINARY LOGS; ---echo # < CASE 9 > ---echo # Flashback & Check the result +--echo # < CASE 9.1 > +--echo # Only the database used in WHERE +--echo # MDEV-23077 bug03: Only the first Base64 was in a BINLOG statement. --echo # ---replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR ---exec $MYSQL_BINLOG -Bvv --database=d1 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9.sql ---exec $MYSQL -e "SOURCE $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9.sql;" +--exec $MYSQL_BINLOG -Bvv --database=d1 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9_1.sql +--exec $MYSQL -e "SOURCE $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9_1.sql;" -# (1) +# (1), (-1) SELECT * FROM d1.t; -# empty +# still empty +SELECT * FROM d2.t; + +--echo # < CASE 9.2 > +--echo # Ignore the database used in WHERE +--echo # MDEV-23077 bug02: Output includes extraneous "unknown table". +--echo # + +--exec $MYSQL_BINLOG -Bvv --database=d2 $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9_2.sql +--exec $MYSQL -e "SOURCE $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9_2.sql;" + +# (1), (-1) +SELECT * FROM d1.t; +# (1), (-2) SELECT * FROM d2.t; +--let SEARCH_FILE= $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_9_2.sql +--let SEARCH_PATTERN= ### Row event for unknown table +--source include/search_pattern_in_file.inc + DROP DATABASE d1; DROP DATABASE d2;