Commit 83ea839f authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-15405 Mixed replication fails with "Could not execute Delete_rows_v1...

MDEV-15405 Mixed replication fails with "Could not execute Delete_rows_v1 event" upon DELETE HISTORY

Allow slave thread to set time for system versioning

Note that every binlog event stores now(0), while microseconds
are only stored when they're actually used in the query.

Meaning for unversioned->versioned replication, there will be
no microseconds. Need to compensate for that.
parent ac2d4d49
include/master-slave.inc
[connection master]
CREATE TABLE t1 (pk INT PRIMARY KEY, i INT) WITH SYSTEM VERSIONING;
INSERT INTO t1 VALUES (1,10),(2,20);
UPDATE t1 SET i = 100;
SET BINLOG_FORMAT= ROW;
DELETE HISTORY FROM t1;
connection slave;
connection master;
drop table t1;
include/rpl_end.inc
--source include/have_binlog_format_mixed.inc
--source include/master-slave.inc
#
# MDEV-15405 Mixed replication fails with "Could not execute Delete_rows_v1 event" upon DELETE HISTORY
#
CREATE TABLE t1 (pk INT PRIMARY KEY, i INT) WITH SYSTEM VERSIONING;
INSERT INTO t1 VALUES (1,10),(2,20);
UPDATE t1 SET i = 100;
# This is to imitiate any real-life situation which causes a switch to row format
SET BINLOG_FORMAT= ROW;
DELETE HISTORY FROM t1;
--sync_slave_with_master
connection master;
drop table t1;
--source include/rpl_end.inc
...@@ -1312,7 +1312,7 @@ Log_event::Log_event(const char* buf, ...@@ -1312,7 +1312,7 @@ Log_event::Log_event(const char* buf,
thd = 0; thd = 0;
#endif #endif
when = uint4korr(buf); when = uint4korr(buf);
when_sec_part= 0; when_sec_part= ~0UL;
server_id = uint4korr(buf + SERVER_ID_OFFSET); server_id = uint4korr(buf + SERVER_ID_OFFSET);
data_written= uint4korr(buf + EVENT_LEN_OFFSET); data_written= uint4korr(buf + EVENT_LEN_OFFSET);
if (description_event->binlog_version==1) if (description_event->binlog_version==1)
...@@ -5090,7 +5090,7 @@ bool Query_log_event::print_query_header(IO_CACHE* file, ...@@ -5090,7 +5090,7 @@ bool Query_log_event::print_query_header(IO_CACHE* file,
} }
end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10); end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
if (when_sec_part) if (when_sec_part && when_sec_part <= TIME_MAX_SECOND_PART)
{ {
*end++= '.'; *end++= '.';
end=int10_to_str(when_sec_part, end, 10); end=int10_to_str(when_sec_part, end, 10);
......
...@@ -3434,8 +3434,8 @@ class THD :public Statement, ...@@ -3434,8 +3434,8 @@ class THD :public Statement,
ulong sec_part; ulong sec_part;
} system_time; } system_time;
ulong systime_sec_part() { return system_time.sec_part; } ulong systime_sec_part() { query_start_sec_part_used=1; return system_time.sec_part; }
my_time_t systime() { return system_time.sec; } my_time_t systime() { query_start_used=1; return system_time.sec; }
private: private:
void set_system_time() void set_system_time()
...@@ -3462,6 +3462,25 @@ class THD :public Statement, ...@@ -3462,6 +3462,25 @@ class THD :public Statement,
} }
} }
void set_system_time_from_user_time(bool with_sec_part)
{
if (with_sec_part)
{
system_time.sec= start_time;
system_time.sec_part= start_time_sec_part;
}
else
{
if (system_time.sec == start_time)
system_time.sec_part++;
else
{
system_time.sec= start_time;
system_time.sec_part= 0;
}
}
}
public: public:
inline void set_start_time() inline void set_start_time()
{ {
...@@ -3488,10 +3507,21 @@ class THD :public Statement, ...@@ -3488,10 +3507,21 @@ class THD :public Statement,
user_time= t; user_time= t;
set_time(); set_time();
} }
/*
this is only used by replication and BINLOG command.
usecs > TIME_MAX_SECOND_PART means "was not in binlog"
*/
inline void set_time(my_time_t t, ulong sec_part) inline void set_time(my_time_t t, ulong sec_part)
{ {
my_hrtime_t hrtime= { hrtime_from_time(t) + sec_part }; start_time= t;
set_time(hrtime); start_time_sec_part= sec_part > TIME_MAX_SECOND_PART ? 0 : sec_part;
user_time.val= hrtime_from_time(start_time) + start_time_sec_part;
if (slave_thread)
set_system_time_from_user_time(sec_part <= TIME_MAX_SECOND_PART);
else // BINLOG command
set_system_time();
PSI_CALL_set_thread_start_time(start_time);
start_utime= utime_after_lock= microsecond_interval_timer();
} }
void set_time_after_lock() void set_time_after_lock()
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment