Skip to content

MDEV-23077: --flashback + --table produces buggy results #3968

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: 10.11
Choose a base branch
from
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
14 changes: 8 additions & 6 deletions client/mysqlbinlog.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

What #1674 did was copy-pasting the else branch of the next if to the previous if tree as a new branch for (skip_event && opt_flashback && is_stmt_end).
Here, I reimplement it by skipping this intermediate “step” (?) for that exact condition.

While the diff is now smaller, it has become proof that our code is 🍝.

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;

Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
83 changes: 83 additions & 0 deletions mysql-test/suite/binlog/r/flashback.result
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,89 @@ 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".
#
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;
# < CASE 9 >
# --flashback + --database
#
CREATE DATABASE d1;
CREATE DATABASE d2;
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;
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 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;
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;
i
1
-2
NOT FOUND /### Row event for unknown table/ in mysqlbinlog_row_flashback_9_2.sql
DROP DATABASE d1;
DROP DATABASE d2;
#
# MDEV-30698 Cover missing test cases for mariadb-binlog options
# --raw [and] --flashback
Expand Down
107 changes: 106 additions & 1 deletion mysql-test/suite/binlog/t/flashback.test
Original file line number Diff line number Diff line change
Expand Up @@ -364,13 +364,118 @@ 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
--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
--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 (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;
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 BINARY LOGS;

--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 #

--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)
SELECT * FROM d1.t;
# 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;

--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
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have a real Case 8 now.


## Clear
SET binlog_format=statement;
Expand Down