mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-12067 flashback does not correcly revert update/replace statements
Problem ------- For one-statement contains multiple row events, Flashback didn't reverse the sequence of row events inside one-statement. Solution -------- Using a new array 'events_in_stmt' to store the row events of one-statement, when parsed the last one event, then print from the last one to the first one. In the same time, fixed another bug, without -vv will not insert the table_map into print_event_info->m_table_map, then change_to_flashback_event() will not execute because of Table_map_log_event is empty.
This commit is contained in:
@@ -6,7 +6,7 @@ DROP TABLE IF EXISTS t1;
|
||||
# We need a fixed timestamp to avoid varying results.
|
||||
#
|
||||
SET timestamp=1000000000;
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Delete all existing binary logs.
|
||||
#
|
||||
RESET MASTER;
|
||||
@@ -20,22 +20,22 @@ c06 char(10),
|
||||
c07 varchar(20),
|
||||
c08 TEXT
|
||||
) ENGINE=InnoDB;
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Insert data to t1
|
||||
#
|
||||
INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
|
||||
INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz");
|
||||
INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 255));
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Update t1
|
||||
#
|
||||
UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3;
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Clear t1
|
||||
#
|
||||
DELETE FROM t1;
|
||||
FLUSH LOGS;
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Show mysqlbinlog result without -B
|
||||
#
|
||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
|
||||
@@ -258,7 +258,7 @@ DELIMITER ;
|
||||
ROLLBACK /* added by mysqlbinlog */;
|
||||
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Show mysqlbinlog result with -B
|
||||
#
|
||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
|
||||
@@ -426,14 +426,14 @@ DELIMITER ;
|
||||
ROLLBACK /* added by mysqlbinlog */;
|
||||
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Insert data to t1
|
||||
#
|
||||
TRUNCATE TABLE t1;
|
||||
INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
|
||||
INSERT INTO t1 VALUES(1,2,3,4,5, "abc", "abcdefg", "abcedfghijklmnopqrstuvwxyz");
|
||||
INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 60));
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Delete all existing binary logs.
|
||||
#
|
||||
RESET MASTER;
|
||||
@@ -442,7 +442,7 @@ c01 c02 c03 c04 c05 c06 c07 c08
|
||||
0 0 0 0 0
|
||||
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
||||
127 32767 8388607 2147483647 9223372036854775807 aaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Operate some data
|
||||
#
|
||||
UPDATE t1 SET c01=20;
|
||||
@@ -450,7 +450,7 @@ UPDATE t1 SET c02=200;
|
||||
UPDATE t1 SET c03=2000;
|
||||
DELETE FROM t1;
|
||||
FLUSH LOGS;
|
||||
#
|
||||
# < CASE 1 >
|
||||
# Flashback & Check the result
|
||||
#
|
||||
SELECT * FROM t1;
|
||||
@@ -459,7 +459,7 @@ c01 c02 c03 c04 c05 c06 c07 c08
|
||||
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
||||
0 0 0 0 0
|
||||
RESET MASTER;
|
||||
#
|
||||
# < CASE 2 >
|
||||
# UPDATE multi-rows in one event
|
||||
#
|
||||
BEGIN;
|
||||
@@ -467,7 +467,7 @@ UPDATE t1 SET c01=10 WHERE c01=0;
|
||||
UPDATE t1 SET c01=20 WHERE c01=10;
|
||||
COMMIT;
|
||||
FLUSH LOGS;
|
||||
#
|
||||
# < CASE 2 >
|
||||
# Flashback & Check the result
|
||||
#
|
||||
SELECT * FROM t1;
|
||||
@@ -476,7 +476,7 @@ c01 c02 c03 c04 c05 c06 c07 c08
|
||||
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
||||
0 0 0 0 0
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# < CASE 3 >
|
||||
# Self-referencing foreign keys
|
||||
#
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB;
|
||||
@@ -493,7 +493,7 @@ a b
|
||||
RESET MASTER;
|
||||
DELETE FROM t1 ORDER BY a DESC;
|
||||
FLUSH LOGS;
|
||||
#
|
||||
# < CASE 3 >
|
||||
# Flashback & Check the result
|
||||
#
|
||||
SELECT * FROM t1;
|
||||
@@ -502,9 +502,180 @@ a b
|
||||
2 1
|
||||
3 2
|
||||
4 3
|
||||
DROP TABLE t1;
|
||||
# < CASE 4 >
|
||||
# Trigger
|
||||
#
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
|
||||
CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, NULL);
|
||||
INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3);
|
||||
INSERT INTO t2 VALUES (6, 7), (7, 8), (8, 9);
|
||||
COMMIT;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 1
|
||||
3 2
|
||||
4 3
|
||||
SELECT * FROM t2;
|
||||
a b
|
||||
6 7
|
||||
7 8
|
||||
8 9
|
||||
CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t2 WHERE a = NEW.b;
|
||||
RESET MASTER;
|
||||
INSERT INTO t1 VALUES (5, 6), (7, 8);
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 1
|
||||
3 2
|
||||
4 3
|
||||
5 6
|
||||
7 8
|
||||
SELECT * FROM t2;
|
||||
a b
|
||||
7 8
|
||||
FLUSH LOGS;
|
||||
# < CASE 4 >
|
||||
# Flashback & Check the result
|
||||
#
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 1
|
||||
3 2
|
||||
4 3
|
||||
SELECT * FROM t2;
|
||||
a b
|
||||
6 7
|
||||
7 8
|
||||
8 9
|
||||
DROP TRIGGER trg1;
|
||||
DROP TABLE t1;
|
||||
DROP TABLE t2;
|
||||
# < CASE 5 >
|
||||
# REPLCAE Queries
|
||||
#
|
||||
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, UNIQUE uk(b)) ENGINE=InnoDB;
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES (1, NULL);
|
||||
INSERT INTO t1 VALUES (2, 1), (3, 2), (4, 3);
|
||||
INSERT INTO t1 VALUES (5, 4), (6, 5), (7, 6);
|
||||
COMMIT;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 1
|
||||
3 2
|
||||
4 3
|
||||
5 4
|
||||
6 5
|
||||
7 6
|
||||
RESET MASTER;
|
||||
REPLACE INTO t1 VALUES (3, 100);
|
||||
REPLACE INTO t1 SET a=4, b=200;
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 1
|
||||
5 4
|
||||
6 5
|
||||
7 6
|
||||
3 100
|
||||
4 200
|
||||
REPLACE INTO t1 VALUES (5,5);
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 1
|
||||
5 5
|
||||
7 6
|
||||
3 100
|
||||
4 200
|
||||
FLUSH LOGS;
|
||||
# < CASE 5 >
|
||||
# Flashback & Check the result
|
||||
#
|
||||
SELECT * FROM t1;
|
||||
a b
|
||||
1 NULL
|
||||
2 1
|
||||
3 2
|
||||
4 3
|
||||
5 4
|
||||
6 5
|
||||
7 6
|
||||
DROP TABLE t1;
|
||||
# < CASE 6 >
|
||||
# Test Case from MDEV-21067
|
||||
#
|
||||
CREATE DATABASE world;
|
||||
CREATE TABLE world.City (
|
||||
ID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
Name VARCHAR(64),
|
||||
CountryCode VARCHAR(64),
|
||||
District VARCHAR(64),
|
||||
Population INT
|
||||
) ENGINE=InnoDB;
|
||||
CREATE TABLE test.test (
|
||||
ID INT AUTO_INCREMENT PRIMARY KEY,
|
||||
REC VARCHAR(64),
|
||||
ts TIMESTAMP
|
||||
) ENGINE=InnoDB;
|
||||
INSERT INTO world.City VALUES (NULL, 'Davenport', 'USA', 'Iowa', 100);
|
||||
INSERT INTO world.City VALUES (NULL, 'Boulder', 'USA', 'Colorado', 1000);
|
||||
INSERT INTO world.City VALUES (NULL, 'Gweru', 'ZWE', 'Midlands', 10000);
|
||||
RESET MASTER;
|
||||
CHECKSUM TABLE world.City;
|
||||
Table Checksum
|
||||
world.City 563256876
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 1', CURRENT_TIMESTAMP());
|
||||
INSERT INTO world.City VALUES (NULL, 'Wrong value 1', '000', 'Wrong', 0);
|
||||
INSERT INTO world.City VALUES (NULL, 'Wrong value 2', '000', 'Wrong', 0) , (NULL, 'Wrong value 3', '000', 'Wrong', 0);
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 2', CURRENT_TIMESTAMP());
|
||||
UPDATE world.City SET Population = 99999999 WHERE ID IN (1, 2, 3);
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 3', CURRENT_TIMESTAMP());
|
||||
DELETE FROM world.City WHERE ID BETWEEN 1 AND 2;
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 5', CURRENT_TIMESTAMP());
|
||||
REPLACE INTO world.City VALUES (4074, 'Wrong value 4', '000', 'Wrong', 0);
|
||||
REPLACE INTO world.City VALUES (4078, 'Wrong value 5', '000', 'Wrong', 0), (NULL, 'Wrong value 6', '000', 'Wrong', 0);
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 6', CURRENT_TIMESTAMP());
|
||||
INSERT INTO world.City
|
||||
SELECT NULL, Name, CountryCode, District, Population FROM world.City WHERE ID BETWEEN 2 AND 10;
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 7', CURRENT_TIMESTAMP());
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 8', CURRENT_TIMESTAMP());
|
||||
DELETE FROM world.City;
|
||||
INSERT INTO test.test VALUES (NULL, 'Good record 9', CURRENT_TIMESTAMP());
|
||||
FLUSH LOGS;
|
||||
# < CASE 6 >
|
||||
# Flashback & Check the result
|
||||
#
|
||||
SELECT * FROM world.City;
|
||||
ID Name CountryCode District Population
|
||||
1 Davenport USA Iowa 100
|
||||
2 Boulder USA Colorado 1000
|
||||
3 Gweru ZWE Midlands 10000
|
||||
SELECT * FROM test.test;
|
||||
ID REC ts
|
||||
1 Good record 1 2001-09-09 09:46:40
|
||||
2 Good record 2 2001-09-09 09:46:40
|
||||
3 Good record 3 2001-09-09 09:46:40
|
||||
4 Good record 5 2001-09-09 09:46:40
|
||||
5 Good record 6 2001-09-09 09:46:40
|
||||
6 Good record 7 2001-09-09 09:46:40
|
||||
7 Good record 8 2001-09-09 09:46:40
|
||||
8 Good record 9 2001-09-09 09:46:40
|
||||
CHECKSUM TABLE world.City;
|
||||
Table Checksum
|
||||
world.City 563256876
|
||||
DROP TABLE test.test;
|
||||
DROP TABLE world.City;
|
||||
DROP DATABASE world;
|
||||
SET binlog_format=statement;
|
||||
Warnings:
|
||||
Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT
|
||||
SET GLOBAL binlog_format=statement;
|
||||
ERROR HY000: Flashback does not support binlog_format STATEMENT
|
||||
DROP TABLE t1;
|
||||
|
Reference in New Issue
Block a user