Skip to content

Commit

Permalink
[raft] Support for dumping raft logs to vanilla async replicas
Browse files Browse the repository at this point in the history
Summary:
[Porting Notes]
We want to dump raft logs to vanilla async replicas regardless
of whether it's the relay log or binlog. Effectively after this change
we'll dump relay logs on the followers and binlogs on the leader. When
the raft role changes, the logs to the dumped are also changed.
Dump_log class is introduced as a thin wrapper/continer around
mysql_bin_log or rli->relay_log and is inited with mysql_bin_log
to emulate vanilla mysql behavior. Dump threads use the global
dump_log object instead of mysql_bin_log directly. We switch the log
in dump log only when raft role changes (in binlog_change_to_binlog()
and binlog_change_to_apply_log()).
During raft role change we take all log releated locks (LOCK_log,
LOCK_index, LOCK_binlog_end_pos, and dump log lock) to serialize it with
other log operations like dumping logs.

Related doc - https://fb.quip.com/oTVAAdgEi4zY

This diff contains below 7 patches:
D23013977
D24766787
D24716539
D24900223
D24955284
D25174166
D25775525

Reviewed By: luqun

Differential Revision: D26141496

-------------------------------------------------------------------------------

Passing raw_log pointer to wait_with_heartbeat() and wait_without_heartbeat()

Summary:
When enable_raft_plugin is OFF Dump_log::lock() is a no-op.
Which means that when enable_raft_plugin is OFF there can be a race
between log switching and dump threads. This could lead to a scenario
where the raw_log that wait_next_event() is working on might be
different than what wait_with_heartbeat()/wait_without_heartbeat() is
working on. This can cause deadlocks because
wait_with_heartbeat()/wait_without_heartbeat()'s mysql_cond_wait would
unlock and then lock a different log's LOCK_binlog_end_pos mutex which
would then never be unlocked by wait_next_event().

Reviewed By: anirbanr-fb

Differential Revision: D32152658

-----------------------------------------------------------------------------------------

Fix rpl_raft_dump_raft_logs

Summary:
This tests completes but fails because the following warning exists:
```
2022-08-30T16:28:00.159525Z 11 [ERROR] [MY-013114] [Repl] Slave I/O for channel '': Got fatal error 1236 from master when reading data from binary log: 'Slave has more GTIDs than the master has, using the master's SERVER_UUID. This may indicate that the end of the binary log was truncated or that the last binary log file was lost, e.g., after a power or disk failure when sync_binlog != 1. The master may or may not have rolled back transactions that were already replicated to the slave. Suggest to replicate any transactions that master has rolled back from slave to master, and/or commit empty transactions on master to account for transactions that have been', Error_code: MY-013114
```
Since the MTR result file is valid, we can suppress this error.

Reviewed By: yichenshen

Differential Revision: D39141846

-------------------------------------------------------------------------------

Fix heap overflow in group_relay_log_name handling

Summary:
We were accessing group_relay_log_name in
Query_log_event::do_apply_event_worker() but it's assigned only after
the coordinator thread encounters an end event (i.e. xid event or a
query event with "COMMIT" or "ROLLBACK" query). This was causing a race
between accessing group_relay_log_name in the worker thread and writing
it on the coordinator thread. We don't need to set transaction position
in events other than end event, so now we set transaction position in
query event only if it's an end event. The race is eliminated because
group_relay_log_name is set before enqueuing the event to the worker
thread (in both dep repl and vanilla mts).

Reviewed By: lth

Differential Revision: D28767430

-------------------------------------------------------------------------------

fix memory during MYSQL_BIN_LOG::open_existing_binlog

Summary:
asandebug complain there are memory leaks during MYSQL_BIN_LOG open

Direct leak of 50 byte(s) in 1 object(s) allocated from:
    #0 0x67460ef in malloc
    facebook#1 0x93f0777 in my_raw_malloc(unsigned long, int)
    facebook#2 0x93f064a in my_malloc(unsigned int, unsigned long, int)
    facebook#3 0x93f0eb0 in my_strdup(unsigned int, char const*, int)
    facebook#4 0x8af01a6 in MYSQL_BIN_LOG::open(unsigned int, char const*, char const*, unsigned int)
    facebook#5 0x8af8064 in MYSQL_BIN_LOG::open_binlog(char const*, char const*, unsigned long, bool, bool, bool, Format_description_log_event*, unsigned int, RaftRotateInfo*, bool)
    facebook#6 0x8b00c00 in MYSQL_BIN_LOG::new_file_impl(bool, Format_description_log_event*, RaftRotateInfo*)
    facebook#7 0x8d65e47 in rotate_relay_log(Master_info*, bool, bool, bool, RaftRotateInfo*)
    facebook#8 0x8d661c0 in rotate_relay_log_for_raft(RaftRotateInfo*)
    facebook#9 0x8c7696a in process_raft_queue
    facebook#10 0xa0fa1fd in pfs_spawn_thread(void*)
    facebook#11 0x7f8c9a12b20b in start_thread

release these memory before assign them

Reviewed By: Pushapgl

Differential Revision: D28819752
  • Loading branch information
Pushapgl authored and Herman Lee committed Oct 18, 2023
1 parent fda5d57 commit 5ef40c4
Show file tree
Hide file tree
Showing 16 changed files with 1,110 additions and 101 deletions.
288 changes: 288 additions & 0 deletions mysql-test/suite/rpl_raft/r/rpl_raft_dump_raft_logs.result
@@ -0,0 +1,288 @@
include/raft_3_node.inc
Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
[connection master]
include/rpl_connect.inc [creating server_4]
include/rpl_connect.inc [creating server_5]
RESET MASTER;
RESET SLAVE;
SET @@GLOBAL.ENABLE_RAFT_PLUGIN = 0;
CHANGE MASTER TO MASTER_HOST = '::1', MASTER_PORT = SERVER_MYPORT_1, MASTER_USER = 'root', MASTER_CONNECT_RETRY = 1, MASTER_AUTO_POSITION = 1;
Warnings:
Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
Note 1760 Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
START SLAVE;
RESET MASTER;
RESET SLAVE;
SET @@GLOBAL.ENABLE_RAFT_PLUGIN = 0;
CHANGE MASTER TO MASTER_HOST = '::1', MASTER_PORT = SERVER_MYPORT_2, MASTER_USER = 'root', MASTER_CONNECT_RETRY = 1, MASTER_AUTO_POSITION = 1;
Warnings:
Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
Note 1760 Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
START SLAVE;
show status like 'rpl_raft_role';
Variable_name Value
Rpl_raft_role LEADER
show status like 'rpl_raft_role';
Variable_name Value
Rpl_raft_role FOLLOWER
show status like 'rpl_raft_role';
Variable_name Value
Rpl_raft_role FOLLOWER
show status like 'rpl_raft_role';
Variable_name Value
Rpl_raft_role
show status like 'rpl_raft_role';
Variable_name Value
Rpl_raft_role
create table t1 (a int primary key) engine = innodb;
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
SELECT "LOGNAME" LIKE "binary-logs%";
"LOGNAME" LIKE "binary-logs%"
1
SELECT "LOGNAME" LIKE "binary-logs%";
"LOGNAME" LIKE "binary-logs%"
1
insert into t1 values(1);
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
select * from t1;
a
1
select * from t1;
a
1
select * from t1;
a
1
select * from t1;
a
1
include/raft_promote_to_leader.inc
insert into t1 values(2);
insert into t1 values(3);
insert into t1 values(4);
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
select * from t1;
a
1
2
3
4
select * from t1;
a
1
2
3
4
select * from t1;
a
1
2
3
4
select * from t1;
a
1
2
3
4
SELECT "LOGNAME" LIKE "binary-logs%";
"LOGNAME" LIKE "binary-logs%"
1
SELECT "LOGNAME" LIKE "binary-logs%";
"LOGNAME" LIKE "binary-logs%"
1
include/raft_promote_to_leader.inc
flush binary logs;
insert into t1 values(5);
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
select * from t1;
a
1
2
3
4
5
select * from t1;
a
1
2
3
4
5
select * from t1;
a
1
2
3
4
5
select * from t1;
a
1
2
3
4
5
set @@global.debug='+d,dump_wait_before_find_next_log';
insert into t1 values(6);
insert into t1 values(7);
flush binary logs;
insert into t1 values(8);
insert into t1 values(9);
flush binary logs;
insert into t1 values(10);
insert into t1 values(11);
set debug_sync= 'now wait_for signal.reached';
purge raft logs to 'LOGNAME';
set debug_sync= 'now signal signal.done';
set @@global.debug='-d,dump_wait_before_find_next_log';
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
include/stop_slave.inc
include/rpl_restart_server.inc [server_number=2]
include/rpl_restart_server.inc [server_number=1]
include/raft_promote_to_leader.inc
START SLAVE IO_THREAD;
START SLAVE IO_THREAD;
insert into t1 values(12);
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
12
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
12
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
12
select * from t1;
a
1
2
3
4
5
6
7
8
9
10
11
12
drop table t1;
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
stop slave;
reset slave all;
stop slave;
reset slave all;
include/rpl_end.inc
@@ -0,0 +1,34 @@
include/raft_3_node.inc
Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
Warnings:
Note #### Sending passwords in plain text without SSL/TLS is extremely insecure.
Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
[connection master]
include/rpl_connect.inc [creating server_4]
include/rpl_connect.inc [creating server_5]
create table t1 (a int) engine = innodb;
insert into t1 values(1);
insert into t1 values(2);
set @@global.rpl_raft_new_leader_uuid = 'uuid2';
change master to master_host='localhost', master_port=port2, master_auto_position=1, master_user='root';
Warnings:
Note 1759 Sending passwords in plain text without SSL/TLS is extremely insecure.
Note 1760 Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information.
include/start_slave.inc
insert into t1 values(3);
include/sync_slave_sql_with_master.inc
select * from t1;
a
1
2
3
set @@global.rpl_raft_new_leader_uuid = 'uuid1';
drop table t1;
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/sync_slave_sql_with_master.inc
include/stop_slave.inc
reset slave all;
include/rpl_end.inc

0 comments on commit 5ef40c4

Please sign in to comment.