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:
@@ -68,6 +68,7 @@ CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
|
|||||||
|
|
||||||
/* Needed for Flashback */
|
/* Needed for Flashback */
|
||||||
DYNAMIC_ARRAY binlog_events; // Storing the events output string
|
DYNAMIC_ARRAY binlog_events; // Storing the events output string
|
||||||
|
DYNAMIC_ARRAY events_in_stmt; // Storing the events that in one statement
|
||||||
String stop_event_string; // Storing the STOP_EVENT output string
|
String stop_event_string; // Storing the STOP_EVENT output string
|
||||||
|
|
||||||
char server_version[SERVER_VERSION_LENGTH];
|
char server_version[SERVER_VERSION_LENGTH];
|
||||||
@@ -894,6 +895,25 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
|||||||
print_event_info->m_table_map_ignored.get_table(table_id);
|
print_event_info->m_table_map_ignored.get_table(table_id);
|
||||||
bool skip_event= (ignored_map != NULL);
|
bool skip_event= (ignored_map != NULL);
|
||||||
|
|
||||||
|
if (opt_flashback)
|
||||||
|
{
|
||||||
|
Rows_log_event *e= (Rows_log_event*) ev;
|
||||||
|
// The last Row_log_event will be the first event in Flashback
|
||||||
|
if (is_stmt_end)
|
||||||
|
e->clear_flags(Rows_log_event::STMT_END_F);
|
||||||
|
// The first Row_log_event will be the last event in Flashback
|
||||||
|
if (events_in_stmt.elements == 0)
|
||||||
|
e->set_flags(Rows_log_event::STMT_END_F);
|
||||||
|
// Update the temp_buf
|
||||||
|
e->update_flags();
|
||||||
|
|
||||||
|
if (insert_dynamic(&events_in_stmt, (uchar *) &ev))
|
||||||
|
{
|
||||||
|
error("Out of memory: can't allocate memory to store the flashback events.");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
end of statement check:
|
end of statement check:
|
||||||
i) destroy/free ignored maps
|
i) destroy/free ignored maps
|
||||||
@@ -945,7 +965,36 @@ static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
|||||||
if (skip_event)
|
if (skip_event)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (!opt_flashback)
|
||||||
return print_base64(print_event_info, ev);
|
return print_base64(print_event_info, ev);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (is_stmt_end)
|
||||||
|
{
|
||||||
|
bool res= false;
|
||||||
|
Log_event *e= NULL;
|
||||||
|
|
||||||
|
// Print the row_event from the last one to the first one
|
||||||
|
for (uint i= events_in_stmt.elements; i > 0; --i)
|
||||||
|
{
|
||||||
|
e= *(dynamic_element(&events_in_stmt, i - 1, Log_event**));
|
||||||
|
res= res || print_base64(print_event_info, e);
|
||||||
|
}
|
||||||
|
// Copy all output into the Log_event
|
||||||
|
ev->output_buf.copy(e->output_buf);
|
||||||
|
// Delete Log_event
|
||||||
|
for (uint i= 0; i < events_in_stmt.elements-1; ++i)
|
||||||
|
{
|
||||||
|
e= *(dynamic_element(&events_in_stmt, i, Log_event**));
|
||||||
|
delete e;
|
||||||
|
}
|
||||||
|
reset_dynamic(&events_in_stmt);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1386,6 +1435,8 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
|||||||
}
|
}
|
||||||
if (print_base64(print_event_info, ev))
|
if (print_base64(print_event_info, ev))
|
||||||
goto err;
|
goto err;
|
||||||
|
if (opt_flashback)
|
||||||
|
reset_dynamic(&events_in_stmt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WRITE_ROWS_EVENT:
|
case WRITE_ROWS_EVENT:
|
||||||
@@ -1402,9 +1453,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
|||||||
case DELETE_ROWS_COMPRESSED_EVENT_V1:
|
case DELETE_ROWS_COMPRESSED_EVENT_V1:
|
||||||
{
|
{
|
||||||
Rows_log_event *e= (Rows_log_event*) ev;
|
Rows_log_event *e= (Rows_log_event*) ev;
|
||||||
|
bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
|
||||||
if (print_row_event(print_event_info, ev, e->get_table_id(),
|
if (print_row_event(print_event_info, ev, e->get_table_id(),
|
||||||
e->get_flags(Rows_log_event::STMT_END_F)))
|
e->get_flags(Rows_log_event::STMT_END_F)))
|
||||||
goto err;
|
goto err;
|
||||||
|
if (!is_stmt_end)
|
||||||
|
destroy_evt= FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case PRE_GA_WRITE_ROWS_EVENT:
|
case PRE_GA_WRITE_ROWS_EVENT:
|
||||||
@@ -1412,9 +1466,12 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
|
|||||||
case PRE_GA_UPDATE_ROWS_EVENT:
|
case PRE_GA_UPDATE_ROWS_EVENT:
|
||||||
{
|
{
|
||||||
Old_rows_log_event *e= (Old_rows_log_event*) ev;
|
Old_rows_log_event *e= (Old_rows_log_event*) ev;
|
||||||
|
bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
|
||||||
if (print_row_event(print_event_info, ev, e->get_table_id(),
|
if (print_row_event(print_event_info, ev, e->get_table_id(),
|
||||||
e->get_flags(Old_rows_log_event::STMT_END_F)))
|
e->get_flags(Old_rows_log_event::STMT_END_F)))
|
||||||
goto err;
|
goto err;
|
||||||
|
if (!is_stmt_end)
|
||||||
|
destroy_evt= FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case START_ENCRYPTION_EVENT:
|
case START_ENCRYPTION_EVENT:
|
||||||
@@ -1459,7 +1516,7 @@ end:
|
|||||||
&my_charset_bin);
|
&my_charset_bin);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (push_dynamic(&binlog_events, (uchar *) &tmp_str))
|
if (insert_dynamic(&binlog_events, (uchar *) &tmp_str))
|
||||||
{
|
{
|
||||||
error("Out of memory: can't allocate memory to store the flashback events.");
|
error("Out of memory: can't allocate memory to store the flashback events.");
|
||||||
exit(1);
|
exit(1);
|
||||||
@@ -2915,9 +2972,12 @@ int main(int argc, char** argv)
|
|||||||
my_set_max_open_files(open_files_limit);
|
my_set_max_open_files(open_files_limit);
|
||||||
|
|
||||||
if (opt_flashback)
|
if (opt_flashback)
|
||||||
|
{
|
||||||
my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024,
|
my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024,
|
||||||
MYF(0));
|
MYF(0));
|
||||||
|
my_init_dynamic_array(&events_in_stmt, sizeof(Rows_log_event*), 1024, 1024,
|
||||||
|
MYF(0));
|
||||||
|
}
|
||||||
if (opt_stop_never)
|
if (opt_stop_never)
|
||||||
to_last_remote_log= TRUE;
|
to_last_remote_log= TRUE;
|
||||||
|
|
||||||
@@ -3031,6 +3091,7 @@ int main(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
fprintf(result_file, "COMMIT\n/*!*/;\n");
|
fprintf(result_file, "COMMIT\n/*!*/;\n");
|
||||||
delete_dynamic(&binlog_events);
|
delete_dynamic(&binlog_events);
|
||||||
|
delete_dynamic(&events_in_stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set delimiter back to semicolon */
|
/* Set delimiter back to semicolon */
|
||||||
|
@@ -6,7 +6,7 @@ DROP TABLE IF EXISTS t1;
|
|||||||
# We need a fixed timestamp to avoid varying results.
|
# We need a fixed timestamp to avoid varying results.
|
||||||
#
|
#
|
||||||
SET timestamp=1000000000;
|
SET timestamp=1000000000;
|
||||||
#
|
# < CASE 1 >
|
||||||
# Delete all existing binary logs.
|
# Delete all existing binary logs.
|
||||||
#
|
#
|
||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
@@ -20,22 +20,22 @@ c06 char(10),
|
|||||||
c07 varchar(20),
|
c07 varchar(20),
|
||||||
c08 TEXT
|
c08 TEXT
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
#
|
# < CASE 1 >
|
||||||
# Insert data to t1
|
# Insert data to t1
|
||||||
#
|
#
|
||||||
INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
|
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(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));
|
INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 255));
|
||||||
#
|
# < CASE 1 >
|
||||||
# Update t1
|
# Update t1
|
||||||
#
|
#
|
||||||
UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3;
|
UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3;
|
||||||
#
|
# < CASE 1 >
|
||||||
# Clear t1
|
# Clear t1
|
||||||
#
|
#
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
#
|
# < CASE 1 >
|
||||||
# Show mysqlbinlog result without -B
|
# Show mysqlbinlog result without -B
|
||||||
#
|
#
|
||||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
|
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
|
||||||
@@ -258,7 +258,7 @@ DELIMITER ;
|
|||||||
ROLLBACK /* added by mysqlbinlog */;
|
ROLLBACK /* added by mysqlbinlog */;
|
||||||
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
||||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
||||||
#
|
# < CASE 1 >
|
||||||
# Show mysqlbinlog result with -B
|
# Show mysqlbinlog result with -B
|
||||||
#
|
#
|
||||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
|
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
|
||||||
@@ -426,14 +426,14 @@ DELIMITER ;
|
|||||||
ROLLBACK /* added by mysqlbinlog */;
|
ROLLBACK /* added by mysqlbinlog */;
|
||||||
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
|
||||||
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;
|
||||||
#
|
# < CASE 1 >
|
||||||
# Insert data to t1
|
# Insert data to t1
|
||||||
#
|
#
|
||||||
TRUNCATE TABLE t1;
|
TRUNCATE TABLE t1;
|
||||||
INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
|
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(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));
|
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.
|
# Delete all existing binary logs.
|
||||||
#
|
#
|
||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
@@ -442,7 +442,7 @@ c01 c02 c03 c04 c05 c06 c07 c08
|
|||||||
0 0 0 0 0
|
0 0 0 0 0
|
||||||
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
||||||
127 32767 8388607 2147483647 9223372036854775807 aaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
127 32767 8388607 2147483647 9223372036854775807 aaaaaaaaaa aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
#
|
# < CASE 1 >
|
||||||
# Operate some data
|
# Operate some data
|
||||||
#
|
#
|
||||||
UPDATE t1 SET c01=20;
|
UPDATE t1 SET c01=20;
|
||||||
@@ -450,7 +450,7 @@ UPDATE t1 SET c02=200;
|
|||||||
UPDATE t1 SET c03=2000;
|
UPDATE t1 SET c03=2000;
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
#
|
# < CASE 1 >
|
||||||
# Flashback & Check the result
|
# Flashback & Check the result
|
||||||
#
|
#
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
@@ -459,7 +459,7 @@ c01 c02 c03 c04 c05 c06 c07 c08
|
|||||||
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
||||||
0 0 0 0 0
|
0 0 0 0 0
|
||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
#
|
# < CASE 2 >
|
||||||
# UPDATE multi-rows in one event
|
# UPDATE multi-rows in one event
|
||||||
#
|
#
|
||||||
BEGIN;
|
BEGIN;
|
||||||
@@ -467,7 +467,7 @@ UPDATE t1 SET c01=10 WHERE c01=0;
|
|||||||
UPDATE t1 SET c01=20 WHERE c01=10;
|
UPDATE t1 SET c01=20 WHERE c01=10;
|
||||||
COMMIT;
|
COMMIT;
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
#
|
# < CASE 2 >
|
||||||
# Flashback & Check the result
|
# Flashback & Check the result
|
||||||
#
|
#
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
@@ -476,7 +476,7 @@ c01 c02 c03 c04 c05 c06 c07 c08
|
|||||||
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
1 2 3 4 5 abc abcdefg abcedfghijklmnopqrstuvwxyz
|
||||||
0 0 0 0 0
|
0 0 0 0 0
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
#
|
# < CASE 3 >
|
||||||
# Self-referencing foreign keys
|
# Self-referencing foreign keys
|
||||||
#
|
#
|
||||||
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB;
|
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;
|
RESET MASTER;
|
||||||
DELETE FROM t1 ORDER BY a DESC;
|
DELETE FROM t1 ORDER BY a DESC;
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
#
|
# < CASE 3 >
|
||||||
# Flashback & Check the result
|
# Flashback & Check the result
|
||||||
#
|
#
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
@@ -502,9 +502,180 @@ a b
|
|||||||
2 1
|
2 1
|
||||||
3 2
|
3 2
|
||||||
4 3
|
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;
|
SET binlog_format=statement;
|
||||||
Warnings:
|
Warnings:
|
||||||
Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT
|
Warning 1105 MariaDB Galera and flashback do not support binlog format: STATEMENT
|
||||||
SET GLOBAL binlog_format=statement;
|
SET GLOBAL binlog_format=statement;
|
||||||
ERROR HY000: Flashback does not support binlog_format STATEMENT
|
ERROR HY000: Flashback does not support binlog_format STATEMENT
|
||||||
DROP TABLE t1;
|
|
||||||
|
@@ -13,12 +13,11 @@ DROP TABLE IF EXISTS t1;
|
|||||||
--echo #
|
--echo #
|
||||||
SET timestamp=1000000000;
|
SET timestamp=1000000000;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Delete all existing binary logs.
|
--echo # Delete all existing binary logs.
|
||||||
--echo #
|
--echo #
|
||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE t1 (
|
CREATE TABLE t1 (
|
||||||
c01 tinyint,
|
c01 tinyint,
|
||||||
c02 smallint,
|
c02 smallint,
|
||||||
@@ -30,7 +29,7 @@ CREATE TABLE t1 (
|
|||||||
c08 TEXT
|
c08 TEXT
|
||||||
) ENGINE=InnoDB;
|
) ENGINE=InnoDB;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Insert data to t1
|
--echo # Insert data to t1
|
||||||
--echo #
|
--echo #
|
||||||
INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
|
INSERT INTO t1 VALUES(0,0,0,0,0,'','','');
|
||||||
@@ -38,19 +37,19 @@ 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));
|
INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 255));
|
||||||
|
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Update t1
|
--echo # Update t1
|
||||||
--echo #
|
--echo #
|
||||||
UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3;
|
UPDATE t1 SET c01=100 WHERE c02=0 OR c03=3;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Clear t1
|
--echo # Clear t1
|
||||||
--echo #
|
--echo #
|
||||||
DELETE FROM t1;
|
DELETE FROM t1;
|
||||||
|
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Show mysqlbinlog result without -B
|
--echo # Show mysqlbinlog result without -B
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
@@ -59,7 +58,7 @@ let $MYSQLD_DATADIR= `select @@datadir`;
|
|||||||
--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/
|
--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/
|
||||||
--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
|
--exec $MYSQL_BINLOG --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Show mysqlbinlog result with -B
|
--echo # Show mysqlbinlog result with -B
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
@@ -68,7 +67,7 @@ let $MYSQLD_DATADIR= `select @@datadir`;
|
|||||||
--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/
|
--replace_regex /SQL_LOAD_MB-[0-9]-[0-9]/SQL_LOAD_MB-#-#/ /exec_time=[0-9]*/exec_time=#/ /end_log_pos [0-9]*/end_log_pos #/ /# at [0-9]*/# at #/ /Xid = [0-9]*/Xid = #/ /thread_id=[0-9]*/thread_id=#/ /table id [0-9]*/table id #/ /mapped to number [0-9]*/mapped to number #/ /server v [^ ]*/server v #.##.##/ /CRC32 0x[0-9a-f]*/CRC32 XXX/
|
||||||
--exec $MYSQL_BINLOG -B --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
|
--exec $MYSQL_BINLOG -B --base64-output=decode-rows -v -v $MYSQLD_DATADIR/master-bin.000001
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Insert data to t1
|
--echo # Insert data to t1
|
||||||
--echo #
|
--echo #
|
||||||
TRUNCATE TABLE t1;
|
TRUNCATE TABLE t1;
|
||||||
@@ -76,13 +75,13 @@ 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(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));
|
INSERT INTO t1 VALUES(127, 32767, 8388607, 2147483647, 9223372036854775807, repeat('a', 10), repeat('a', 20), repeat('a', 60));
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Delete all existing binary logs.
|
--echo # Delete all existing binary logs.
|
||||||
--echo #
|
--echo #
|
||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Operate some data
|
--echo # Operate some data
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
@@ -94,12 +93,13 @@ DELETE FROM t1;
|
|||||||
|
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 1 >
|
||||||
--echo # Flashback & Check the result
|
--echo # Flashback & Check the result
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_1.sql
|
||||||
--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql
|
--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql
|
||||||
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql;"
|
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_1.sql;"
|
||||||
|
|
||||||
@@ -107,9 +107,10 @@ SELECT * FROM t1;
|
|||||||
|
|
||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 2 >
|
||||||
--echo # UPDATE multi-rows in one event
|
--echo # UPDATE multi-rows in one event
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
UPDATE t1 SET c01=10 WHERE c01=0;
|
UPDATE t1 SET c01=10 WHERE c01=0;
|
||||||
UPDATE t1 SET c01=20 WHERE c01=10;
|
UPDATE t1 SET c01=20 WHERE c01=10;
|
||||||
@@ -117,12 +118,13 @@ COMMIT;
|
|||||||
|
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 2 >
|
||||||
--echo # Flashback & Check the result
|
--echo # Flashback & Check the result
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_2.sql
|
||||||
--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql
|
--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql
|
||||||
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql;"
|
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_2.sql;"
|
||||||
|
|
||||||
@@ -130,9 +132,10 @@ SELECT * FROM t1;
|
|||||||
|
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 3 >
|
||||||
--echo # Self-referencing foreign keys
|
--echo # Self-referencing foreign keys
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB;
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, FOREIGN KEY my_fk(b) REFERENCES t1(a)) ENGINE=InnoDB;
|
||||||
|
|
||||||
BEGIN;
|
BEGIN;
|
||||||
@@ -149,19 +152,191 @@ DELETE FROM t1 ORDER BY a DESC;
|
|||||||
|
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
|
|
||||||
--echo #
|
--echo # < CASE 3 >
|
||||||
--echo # Flashback & Check the result
|
--echo # Flashback & Check the result
|
||||||
--echo #
|
--echo #
|
||||||
|
|
||||||
let $MYSQLD_DATADIR= `select @@datadir`;
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_3.sql
|
||||||
--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql
|
--exec $MYSQL_BINLOG -B -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql
|
||||||
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql;"
|
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_3.sql;"
|
||||||
|
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
--echo # < CASE 4 >
|
||||||
|
--echo # Trigger
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
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;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
CREATE TRIGGER trg1 BEFORE INSERT ON t1 FOR EACH ROW DELETE FROM t2 WHERE a = NEW.b;
|
||||||
|
|
||||||
|
# New binlog
|
||||||
|
RESET MASTER;
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (5, 6), (7, 8);
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
--echo # < CASE 4 >
|
||||||
|
--echo # Flashback & Check the result
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_4.sql
|
||||||
|
--exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql
|
||||||
|
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_4.sql;"
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
SELECT * FROM t2;
|
||||||
|
|
||||||
|
DROP TRIGGER trg1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
DROP TABLE t2;
|
||||||
|
|
||||||
|
--echo # < CASE 5 >
|
||||||
|
--echo # REPLCAE Queries
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
# New binlog
|
||||||
|
RESET MASTER;
|
||||||
|
|
||||||
|
REPLACE INTO t1 VALUES (3, 100);
|
||||||
|
REPLACE INTO t1 SET a=4, b=200;
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
REPLACE INTO t1 VALUES (5,5);
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
FLUSH LOGS;
|
||||||
|
|
||||||
|
--echo # < CASE 5 >
|
||||||
|
--echo # Flashback & Check the result
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--exec $MYSQL_BINLOG -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_5.sql
|
||||||
|
--exec $MYSQL_BINLOG -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql
|
||||||
|
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_5.sql;"
|
||||||
|
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo # < CASE 6 >
|
||||||
|
--echo # Test Case from MDEV-21067
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
# Init Structure
|
||||||
|
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;
|
||||||
|
|
||||||
|
# Insert test data
|
||||||
|
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;
|
||||||
|
|
||||||
|
--echo # < CASE 6 >
|
||||||
|
--echo # Flashback & Check the result
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
let $MYSQLD_DATADIR= `select @@datadir`;
|
||||||
|
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
|
||||||
|
--exec $MYSQL_BINLOG --database=world --table=City -vv $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_original_6.sql
|
||||||
|
--exec $MYSQL_BINLOG --database=world --table=City -B $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql
|
||||||
|
--exec $MYSQL -e "SET binlog_format= ROW; source $MYSQLTEST_VARDIR/tmp/mysqlbinlog_row_flashback_6.sql;"
|
||||||
|
|
||||||
|
SELECT * FROM world.City;
|
||||||
|
|
||||||
|
SELECT * FROM test.test;
|
||||||
|
|
||||||
|
CHECKSUM TABLE world.City;
|
||||||
|
|
||||||
|
DROP TABLE test.test;
|
||||||
|
DROP TABLE world.City;
|
||||||
|
DROP DATABASE world;
|
||||||
|
|
||||||
|
## Clear
|
||||||
|
|
||||||
SET binlog_format=statement;
|
SET binlog_format=statement;
|
||||||
--error ER_FLASHBACK_NOT_SUPPORTED
|
--error ER_FLASHBACK_NOT_SUPPORTED
|
||||||
SET GLOBAL binlog_format=statement;
|
SET GLOBAL binlog_format=statement;
|
||||||
|
|
||||||
DROP TABLE t1;
|
|
||||||
|
@@ -3477,7 +3477,8 @@ void Log_event::print_base64(IO_CACHE* file,
|
|||||||
#ifdef WHEN_FLASHBACK_REVIEW_READY
|
#ifdef WHEN_FLASHBACK_REVIEW_READY
|
||||||
if (print_event_info->verbose || need_flashback_review)
|
if (print_event_info->verbose || need_flashback_review)
|
||||||
#else
|
#else
|
||||||
if (print_event_info->verbose)
|
// Flashback need the table_map to parse the event
|
||||||
|
if (print_event_info->verbose || is_flashback)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Rows_log_event *ev= NULL;
|
Rows_log_event *ev= NULL;
|
||||||
@@ -3564,6 +3565,7 @@ void Log_event::print_base64(IO_CACHE* file,
|
|||||||
close_cached_file(&tmp_cache);
|
close_cached_file(&tmp_cache);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
if (print_event_info->verbose)
|
||||||
ev->print_verbose(file, print_event_info);
|
ev->print_verbose(file, print_event_info);
|
||||||
#endif
|
#endif
|
||||||
delete ev;
|
delete ev;
|
||||||
@@ -10251,6 +10253,7 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
|
|||||||
post_start+= RW_FLAGS_OFFSET;
|
post_start+= RW_FLAGS_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_flags_pos= post_start - buf;
|
||||||
m_flags= uint2korr(post_start);
|
m_flags= uint2korr(post_start);
|
||||||
post_start+= 2;
|
post_start+= 2;
|
||||||
|
|
||||||
@@ -11299,18 +11302,18 @@ void Rows_log_event::print_helper(FILE *file,
|
|||||||
|
|
||||||
if (get_flags(STMT_END_F))
|
if (get_flags(STMT_END_F))
|
||||||
{
|
{
|
||||||
reinit_io_cache(head, READ_CACHE, 0L, FALSE, FALSE);
|
LEX_STRING tmp_str;
|
||||||
output_buf.append(head, head->end_of_file);
|
|
||||||
reinit_io_cache(head, WRITE_CACHE, 0, FALSE, TRUE);
|
|
||||||
|
|
||||||
reinit_io_cache(body, READ_CACHE, 0L, FALSE, FALSE);
|
|
||||||
output_buf.append(body, body->end_of_file);
|
|
||||||
reinit_io_cache(body, WRITE_CACHE, 0, FALSE, TRUE);
|
|
||||||
|
|
||||||
|
copy_event_cache_to_string_and_reinit(head, &tmp_str);
|
||||||
|
output_buf.append(&tmp_str);
|
||||||
|
my_free(tmp_str.str);
|
||||||
|
copy_event_cache_to_string_and_reinit(body, &tmp_str);
|
||||||
|
output_buf.append(&tmp_str);
|
||||||
|
my_free(tmp_str.str);
|
||||||
#ifdef WHEN_FLASHBACK_REVIEW_READY
|
#ifdef WHEN_FLASHBACK_REVIEW_READY
|
||||||
reinit_io_cache(sql, READ_CACHE, 0L, FALSE, FALSE);
|
copy_event_cache_to_string_and_reinit(sql, &tmp_str);
|
||||||
output_buf.append(sql, sql->end_of_file);
|
output_buf.append(&tmp_str);
|
||||||
reinit_io_cache(sql, WRITE_CACHE, 0, FALSE, TRUE);
|
my_free(tmp_str.str);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4397,6 +4397,7 @@ public:
|
|||||||
void set_flags(flag_set flags_arg) { m_flags |= flags_arg; }
|
void set_flags(flag_set flags_arg) { m_flags |= flags_arg; }
|
||||||
void clear_flags(flag_set flags_arg) { m_flags &= ~flags_arg; }
|
void clear_flags(flag_set flags_arg) { m_flags &= ~flags_arg; }
|
||||||
flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; }
|
flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; }
|
||||||
|
void update_flags() { int2store(temp_buf + m_flags_pos, m_flags); }
|
||||||
|
|
||||||
Log_event_type get_type_code() { return m_type; } /* Specific type (_V1 etc) */
|
Log_event_type get_type_code() { return m_type; } /* Specific type (_V1 etc) */
|
||||||
virtual Log_event_type get_general_type_code() = 0; /* General rows op type, no version */
|
virtual Log_event_type get_general_type_code() = 0; /* General rows op type, no version */
|
||||||
@@ -4555,6 +4556,7 @@ protected:
|
|||||||
uchar *m_rows_end; /* One-after the end of the allocated space */
|
uchar *m_rows_end; /* One-after the end of the allocated space */
|
||||||
|
|
||||||
size_t m_rows_before_size; /* The length before m_rows_buf */
|
size_t m_rows_before_size; /* The length before m_rows_buf */
|
||||||
|
size_t m_flags_pos; /* The position of the m_flags */
|
||||||
|
|
||||||
flag_set m_flags; /* Flags for row-level events */
|
flag_set m_flags; /* Flags for row-level events */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user