Merge of MDEV-4984, MDEV-4726, and MDEV-5636 into 10.0-base.
MDEV-4984: Implement MASTER_GTID_WAIT() and @@LAST_GTID. MDEV-4726: Race in mysql-test/suite/rpl/t/rpl_gtid_stop_start.test MDEV-5636: Deadlock in RESET MASTER
This commit is contained in:
commit
fefdb576bb
@ -915,6 +915,7 @@ static COMMANDS commands[] = {
|
|||||||
{ "MAKE_SET", 0, 0, 0, ""},
|
{ "MAKE_SET", 0, 0, 0, ""},
|
||||||
{ "MAKEDATE", 0, 0, 0, ""},
|
{ "MAKEDATE", 0, 0, 0, ""},
|
||||||
{ "MAKETIME", 0, 0, 0, ""},
|
{ "MAKETIME", 0, 0, 0, ""},
|
||||||
|
{ "MASTER_GTID_WAIT", 0, 0, 0, ""},
|
||||||
{ "MASTER_POS_WAIT", 0, 0, 0, ""},
|
{ "MASTER_POS_WAIT", 0, 0, 0, ""},
|
||||||
{ "MAX", 0, 0, 0, ""},
|
{ "MAX", 0, 0, 0, ""},
|
||||||
{ "MBRCONTAINS", 0, 0, 0, ""},
|
{ "MBRCONTAINS", 0, 0, 0, ""},
|
||||||
|
@ -51,6 +51,7 @@ typedef struct st_queue {
|
|||||||
|
|
||||||
#define queue_first_element(queue) 1
|
#define queue_first_element(queue) 1
|
||||||
#define queue_last_element(queue) (queue)->elements
|
#define queue_last_element(queue) (queue)->elements
|
||||||
|
#define queue_empty(queue) ((queue)->elements == 0)
|
||||||
#define queue_top(queue) ((queue)->root[1])
|
#define queue_top(queue) ((queue)->root[1])
|
||||||
#define queue_element(queue,index) ((queue)->root[index])
|
#define queue_element(queue,index) ((queue)->root[index])
|
||||||
#define queue_end(queue) ((queue)->root[(queue)->elements])
|
#define queue_end(queue) ((queue)->root[(queue)->elements])
|
||||||
|
28
mysql-test/include/save_master_gtid.inc
Normal file
28
mysql-test/include/save_master_gtid.inc
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# Save the current binlog GTID position on the master, to be used
|
||||||
|
# with include/sync_with_master_gtid.inc.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# ==== Usage ====
|
||||||
|
#
|
||||||
|
# [--let $rpl_debug= 1]
|
||||||
|
# --source include/save_master_gtid.inc
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $rpl_debug
|
||||||
|
# See include/rpl_init.inc
|
||||||
|
|
||||||
|
|
||||||
|
--let $include_filename= save_master_gtid.inc
|
||||||
|
--source include/begin_include_file.inc
|
||||||
|
|
||||||
|
--let $master_pos= `SELECT @@gtid_binlog_pos`
|
||||||
|
|
||||||
|
if ($rpl_debug)
|
||||||
|
{
|
||||||
|
--echo save_master_gtid saved master_pos='$master_pos'
|
||||||
|
}
|
||||||
|
|
||||||
|
--let $include_filename= save_master_gtid.inc
|
||||||
|
--source include/end_include_file.inc
|
48
mysql-test/include/sync_with_master_gtid.inc
Normal file
48
mysql-test/include/sync_with_master_gtid.inc
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# ==== Purpose ====
|
||||||
|
#
|
||||||
|
# Wait until the slave has reached a certain GTID position.
|
||||||
|
# Similar to --sync_with_master, but using GTID instead of old-style
|
||||||
|
# binlog file/offset coordinates.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
# ==== Usage ====
|
||||||
|
#
|
||||||
|
# --let $master_pos= `SELECT @@GLOBAL.gtid_binlog_pos`
|
||||||
|
# [--let $slave_timeout= NUMBER]
|
||||||
|
# [--let $rpl_debug= 1]
|
||||||
|
# --source include/sync_with_master_gtid.inc
|
||||||
|
#
|
||||||
|
# Syncs slave to the specified GTID position.
|
||||||
|
#
|
||||||
|
# Must be called on the slave.
|
||||||
|
#
|
||||||
|
# Parameters:
|
||||||
|
# $master_pos
|
||||||
|
# The GTID position to sync to. Typically obtained from
|
||||||
|
# @@GLOBAL.gtid_binlog_pos on the master.
|
||||||
|
#
|
||||||
|
# $slave_timeout
|
||||||
|
# Timeout in seconds. The default is 2 minutes.
|
||||||
|
#
|
||||||
|
# $rpl_debug
|
||||||
|
# See include/rpl_init.inc
|
||||||
|
|
||||||
|
--let $include_filename= sync_with_master_gtid.inc
|
||||||
|
--source include/begin_include_file.inc
|
||||||
|
|
||||||
|
let $_slave_timeout= $slave_timeout;
|
||||||
|
if (!$_slave_timeout)
|
||||||
|
{
|
||||||
|
let $_slave_timeout= 120;
|
||||||
|
}
|
||||||
|
|
||||||
|
--let $_result= `SELECT master_gtid_wait('$master_pos', $_slave_timeout)`
|
||||||
|
if ($_result == -1)
|
||||||
|
{
|
||||||
|
--let $_current_gtid_pos= `SELECT @@GLOBAL.gtid_slave_pos`
|
||||||
|
--echo Timeout in master_gtid_wait('$master_pos', $_slave_timeout), current slave GTID position is: $_current_gtid_pos.
|
||||||
|
--die Failed to sync with master
|
||||||
|
}
|
||||||
|
|
||||||
|
--let $include_filename= sync_with_master_gtid.inc
|
||||||
|
--source include/end_include_file.inc
|
@ -37,6 +37,7 @@ wait/synch/mutex/mysys/THR_LOCK_threads
|
|||||||
wait/synch/mutex/mysys/TMPDIR_mutex
|
wait/synch/mutex/mysys/TMPDIR_mutex
|
||||||
wait/synch/mutex/sql/Cversion_lock
|
wait/synch/mutex/sql/Cversion_lock
|
||||||
wait/synch/mutex/sql/Event_scheduler::LOCK_scheduler_state
|
wait/synch/mutex/sql/Event_scheduler::LOCK_scheduler_state
|
||||||
|
wait/synch/mutex/sql/gtid_waiting::LOCK_gtid_waiting
|
||||||
wait/synch/mutex/sql/hash_filo::lock
|
wait/synch/mutex/sql/hash_filo::lock
|
||||||
wait/synch/mutex/sql/LOCK_active_mi
|
wait/synch/mutex/sql/LOCK_active_mi
|
||||||
wait/synch/mutex/sql/LOCK_audit_mask
|
wait/synch/mutex/sql/LOCK_audit_mask
|
||||||
|
@ -7,13 +7,13 @@ NAME ENABLED TIMED
|
|||||||
wait/synch/mutex/sql/Cversion_lock YES YES
|
wait/synch/mutex/sql/Cversion_lock YES YES
|
||||||
wait/synch/mutex/sql/Delayed_insert::mutex YES YES
|
wait/synch/mutex/sql/Delayed_insert::mutex YES YES
|
||||||
wait/synch/mutex/sql/Event_scheduler::LOCK_scheduler_state YES YES
|
wait/synch/mutex/sql/Event_scheduler::LOCK_scheduler_state YES YES
|
||||||
|
wait/synch/mutex/sql/gtid_waiting::LOCK_gtid_waiting YES YES
|
||||||
wait/synch/mutex/sql/hash_filo::lock YES YES
|
wait/synch/mutex/sql/hash_filo::lock YES YES
|
||||||
wait/synch/mutex/sql/HA_DATA_PARTITION::LOCK_auto_inc YES YES
|
wait/synch/mutex/sql/HA_DATA_PARTITION::LOCK_auto_inc YES YES
|
||||||
wait/synch/mutex/sql/LOCK_active_mi YES YES
|
wait/synch/mutex/sql/LOCK_active_mi YES YES
|
||||||
wait/synch/mutex/sql/LOCK_audit_mask YES YES
|
wait/synch/mutex/sql/LOCK_audit_mask YES YES
|
||||||
wait/synch/mutex/sql/LOCK_binlog_state YES YES
|
wait/synch/mutex/sql/LOCK_binlog_state YES YES
|
||||||
wait/synch/mutex/sql/LOCK_commit_ordered YES YES
|
wait/synch/mutex/sql/LOCK_commit_ordered YES YES
|
||||||
wait/synch/mutex/sql/LOCK_connection_count YES YES
|
|
||||||
select * from performance_schema.setup_instruments
|
select * from performance_schema.setup_instruments
|
||||||
where name like 'Wait/Synch/Rwlock/sql/%'
|
where name like 'Wait/Synch/Rwlock/sql/%'
|
||||||
and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')
|
and name not in ('wait/synch/rwlock/sql/CRYPTO_dynlock_value::lock')
|
||||||
|
@ -99,13 +99,13 @@ a b
|
|||||||
5 j1a
|
5 j1a
|
||||||
*** Now move C to D, after letting it fall a little behind ***
|
*** Now move C to D, after letting it fall a little behind ***
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
BEGIN;
|
|
||||||
INSERT INTO t2 VALUES (6, "i6b");
|
INSERT INTO t2 VALUES (6, "i6b");
|
||||||
INSERT INTO t2 VALUES (7, "i7b");
|
INSERT INTO t2 VALUES (7, "i7b");
|
||||||
COMMIT;
|
include/save_master_gtid.inc
|
||||||
CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4,
|
CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_4,
|
||||||
MASTER_USE_GTID=CURRENT_POS;
|
MASTER_USE_GTID=CURRENT_POS;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t2 ORDER BY a;
|
SELECT * FROM t2 ORDER BY a;
|
||||||
a b
|
a b
|
||||||
1 i1
|
1 i1
|
||||||
@ -116,6 +116,7 @@ a b
|
|||||||
6 i6b
|
6 i6b
|
||||||
7 i7b
|
7 i7b
|
||||||
*** Now change everything back to what it was, to make rpl_end.inc happy
|
*** Now change everything back to what it was, to make rpl_end.inc happy
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_MYPORT;
|
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_MYPORT;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
@ -123,10 +124,12 @@ include/wait_for_slave_to_start.inc
|
|||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
CHANGE MASTER TO master_host = '127.0.0.1', master_port = SLAVE_MYPORT;
|
CHANGE MASTER TO master_host = '127.0.0.1', master_port = SLAVE_MYPORT;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_3;
|
CHANGE MASTER TO master_host = '127.0.0.1', master_port = SERVER_MYPORT_3;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
include/save_master_gtid.inc
|
||||||
*** A few more checks for BINLOG_GTID_POS function ***
|
*** A few more checks for BINLOG_GTID_POS function ***
|
||||||
SELECT BINLOG_GTID_POS();
|
SELECT BINLOG_GTID_POS();
|
||||||
ERROR 42000: Incorrect parameter count in the call to native function 'BINLOG_GTID_POS'
|
ERROR 42000: Incorrect parameter count in the call to native function 'BINLOG_GTID_POS'
|
||||||
@ -163,6 +166,7 @@ NULL
|
|||||||
Warnings:
|
Warnings:
|
||||||
Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated.
|
Warning 1916 Got overflow when converting '18446744073709551616' to INT. Value truncated.
|
||||||
*** Some tests of @@GLOBAL.gtid_binlog_state ***
|
*** Some tests of @@GLOBAL.gtid_binlog_state ***
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
SET @old_state= @@GLOBAL.gtid_binlog_state;
|
SET @old_state= @@GLOBAL.gtid_binlog_state;
|
||||||
SET GLOBAL gtid_binlog_state = '';
|
SET GLOBAL gtid_binlog_state = '';
|
||||||
@ -196,10 +200,121 @@ SET GLOBAL gtid_binlog_state = @old_state;
|
|||||||
CREATE TABLE t1 (a INT PRIMARY KEY);
|
CREATE TABLE t1 (a INT PRIMARY KEY);
|
||||||
SET gtid_seq_no=100;
|
SET gtid_seq_no=100;
|
||||||
INSERT INTO t1 VALUES (1);
|
INSERT INTO t1 VALUES (1);
|
||||||
|
include/save_master_gtid.inc
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
Gtid_IO_Pos = '0-1-100'
|
Gtid_IO_Pos = '0-1-100'
|
||||||
|
*** Test @@LAST_GTID and MASTER_GTID_WAIT() ***
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
include/stop_slave.inc
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
@@last_gtid
|
||||||
|
|
||||||
|
SET gtid_seq_no=110;
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
@@last_gtid
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
@@last_gtid
|
||||||
|
|
||||||
|
INSERT INTO t1 VALUES (2);
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
@@last_gtid
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
@@last_gtid
|
||||||
|
0-1-110
|
||||||
|
SET @pos= '0-1-110';
|
||||||
|
SELECT master_gtid_wait(NULL);
|
||||||
|
master_gtid_wait(NULL)
|
||||||
|
NULL
|
||||||
|
SELECT master_gtid_wait('', NULL);
|
||||||
|
master_gtid_wait('', NULL)
|
||||||
|
0
|
||||||
|
SELECT master_gtid_wait(@pos, 0.5);
|
||||||
|
master_gtid_wait(@pos, 0.5)
|
||||||
|
-1
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a
|
||||||
|
SELECT master_gtid_wait(@pos);
|
||||||
|
include/start_slave.inc
|
||||||
|
master_gtid_wait(@pos)
|
||||||
|
0
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
a
|
||||||
|
2
|
||||||
|
include/stop_slave.inc
|
||||||
|
SET gtid_domain_id= 1;
|
||||||
|
INSERT INTO t1 VALUES (3);
|
||||||
|
SET @pos= '1-1-1,0-1-110';
|
||||||
|
SELECT master_gtid_wait(@pos, 0);
|
||||||
|
master_gtid_wait(@pos, 0)
|
||||||
|
-1
|
||||||
|
SELECT * FROM t1 WHERE a >= 3;
|
||||||
|
a
|
||||||
|
SELECT master_gtid_wait(@pos, -1);
|
||||||
|
include/start_slave.inc
|
||||||
|
master_gtid_wait(@pos, -1)
|
||||||
|
0
|
||||||
|
SELECT * FROM t1 WHERE a >= 3;
|
||||||
|
a
|
||||||
|
3
|
||||||
|
SELECT master_gtid_wait('1-1-1', 0);
|
||||||
|
master_gtid_wait('1-1-1', 0)
|
||||||
|
0
|
||||||
|
SELECT master_gtid_wait('2-1-1,1-1-4,0-1-110');
|
||||||
|
SELECT master_gtid_wait('0-1-1000', 0.5);
|
||||||
|
SELECT master_gtid_wait('0-1-2000');
|
||||||
|
SELECT master_gtid_wait('2-1-10');
|
||||||
|
SELECT master_gtid_wait('2-1-6', 1);
|
||||||
|
SELECT master_gtid_wait('2-1-5');
|
||||||
|
SELECT master_gtid_wait('2-1-10');
|
||||||
|
SELECT master_gtid_wait('2-1-5,1-1-4,0-1-110');
|
||||||
|
SELECT master_gtid_wait('2-1-2');
|
||||||
|
SELECT master_gtid_wait('1-1-1');
|
||||||
|
master_gtid_wait('1-1-1')
|
||||||
|
0
|
||||||
|
SELECT master_gtid_wait('0-1-109');
|
||||||
|
SELECT master_gtid_wait('2-1-2', 0.5);
|
||||||
|
master_gtid_wait('2-1-2', 0.5)
|
||||||
|
-1
|
||||||
|
KILL QUERY KILL_ID;
|
||||||
|
ERROR 70100: Query execution was interrupted
|
||||||
|
SET gtid_domain_id=2;
|
||||||
|
SET gtid_seq_no=2;
|
||||||
|
INSERT INTO t1 VALUES (4);
|
||||||
|
master_gtid_wait('2-1-2')
|
||||||
|
0
|
||||||
|
KILL CONNECTION KILL_ID;
|
||||||
|
ERROR HY000: Lost connection to MySQL server during query
|
||||||
|
SET gtid_domain_id=1;
|
||||||
|
SET gtid_seq_no=4;
|
||||||
|
INSERT INTO t1 VALUES (5);
|
||||||
|
SET gtid_domain_id=2;
|
||||||
|
SET gtid_seq_no=5;
|
||||||
|
INSERT INTO t1 VALUES (6);
|
||||||
|
master_gtid_wait('2-1-5,1-1-4,0-1-110')
|
||||||
|
0
|
||||||
|
master_gtid_wait('2-1-1,1-1-4,0-1-110')
|
||||||
|
0
|
||||||
|
master_gtid_wait('0-1-1000', 0.5)
|
||||||
|
-1
|
||||||
|
master_gtid_wait('2-1-6', 1)
|
||||||
|
-1
|
||||||
|
master_gtid_wait('0-1-109')
|
||||||
|
0
|
||||||
|
SET gtid_domain_id=2;
|
||||||
|
SET gtid_seq_no=10;
|
||||||
|
INSERT INTO t1 VALUES (7);
|
||||||
|
master_gtid_wait('2-1-10')
|
||||||
|
0
|
||||||
|
master_gtid_wait('2-1-10')
|
||||||
|
0
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
include/rpl_end.inc
|
include/rpl_end.inc
|
||||||
|
@ -12,10 +12,14 @@ MASTER_USE_GTID=CURRENT_POS;
|
|||||||
INSERT INTO t1 VALUES (2,1);
|
INSERT INTO t1 VALUES (2,1);
|
||||||
INSERT INTO t1 VALUES (3,1);
|
INSERT INTO t1 VALUES (3,1);
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
include/save_master_gtid.inc
|
||||||
SET SESSION debug_dbug="+d,crash_dispatch_command_before";
|
SET SESSION debug_dbug="+d,crash_dispatch_command_before";
|
||||||
SELECT 1;
|
SELECT 1;
|
||||||
Got one of the listed errors
|
Got one of the listed errors
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
INSERT INTO t1 VALUES (1000, 3);
|
INSERT INTO t1 VALUES (1000, 3);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
*** Test crashing the master mysqld and check that binlog state is recovered. ***
|
*** Test crashing the master mysqld and check that binlog state is recovered. ***
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
@ -64,22 +68,32 @@ include/stop_slave.inc
|
|||||||
SET GLOBAL debug_dbug="+d,inject_crash_before_write_rpl_slave_state";
|
SET GLOBAL debug_dbug="+d,inject_crash_before_write_rpl_slave_state";
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
SET GLOBAL debug_dbug="+d,crash_commit_before";
|
SET GLOBAL debug_dbug="+d,crash_commit_before";
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
INSERT INTO t1 VALUES (5);
|
INSERT INTO t1 VALUES (5);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
SET GLOBAL debug_dbug="+d,crash_commit_after";
|
SET GLOBAL debug_dbug="+d,crash_commit_after";
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
INSERT INTO t1 VALUES (6);
|
INSERT INTO t1 VALUES (6);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
SET GLOBAL debug_dbug="+d,inject_crash_before_flush_rli";
|
SET GLOBAL debug_dbug="+d,inject_crash_before_flush_rli";
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
INSERT INTO t1 VALUES (7);
|
INSERT INTO t1 VALUES (7);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
SET GLOBAL debug_dbug="+d,inject_crash_after_flush_rli";
|
SET GLOBAL debug_dbug="+d,inject_crash_after_flush_rli";
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
INSERT INTO t1 VALUES (8);
|
INSERT INTO t1 VALUES (8);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
|
@ -57,6 +57,7 @@ include/stop_slave.inc
|
|||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
INSERT INTO t1 VALUES (2);
|
INSERT INTO t1 VALUES (2);
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
include/save_master_gtid.inc
|
||||||
SET sql_log_bin = 0;
|
SET sql_log_bin = 0;
|
||||||
INSERT INTO t1 VALUES (2);
|
INSERT INTO t1 VALUES (2);
|
||||||
SET sql_log_bin = 1;
|
SET sql_log_bin = 1;
|
||||||
@ -84,6 +85,7 @@ Warning 1948 Specified value for @@gtid_slave_pos contains no value for replicat
|
|||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
SET GLOBAL gtid_slave_pos = "0-1-1";
|
SET GLOBAL gtid_slave_pos = "0-1-1";
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@ -93,6 +95,7 @@ a
|
|||||||
*** MDEV-4688: Empty value of @@GLOBAL.gtid_slave_pos ***
|
*** MDEV-4688: Empty value of @@GLOBAL.gtid_slave_pos ***
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
INSERT INTO t1 VALUES (5);
|
INSERT INTO t1 VALUES (5);
|
||||||
|
include/save_master_gtid.inc
|
||||||
SET @old_dbug= @@GLOBAL.debug_dbug;
|
SET @old_dbug= @@GLOBAL.debug_dbug;
|
||||||
SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
|
SET GLOBAL debug_dbug="+d,dummy_disable_default_dbug_output";
|
||||||
SET GLOBAL debug_dbug="+d,gtid_fail_after_record_gtid";
|
SET GLOBAL debug_dbug="+d,gtid_fail_after_record_gtid";
|
||||||
@ -112,6 +115,7 @@ a
|
|||||||
4
|
4
|
||||||
SET GLOBAL debug_dbug= @old_dbug;
|
SET GLOBAL debug_dbug= @old_dbug;
|
||||||
START SLAVE SQL_THREAD;
|
START SLAVE SQL_THREAD;
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@ -136,6 +140,8 @@ SET GLOBAL gtid_slave_pos = "0-1-3";
|
|||||||
START SLAVE;
|
START SLAVE;
|
||||||
include/wait_for_slave_to_start.inc
|
include/wait_for_slave_to_start.inc
|
||||||
INSERT INTO t1 VALUES (6);
|
INSERT INTO t1 VALUES (6);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
|
@ -23,6 +23,7 @@ START SLAVE;
|
|||||||
include/wait_for_slave_to_start.inc
|
include/wait_for_slave_to_start.inc
|
||||||
INSERT INTO t1 VALUES (3, 2);
|
INSERT INTO t1 VALUES (3, 2);
|
||||||
INSERT INTO t1 VALUES (4, 2);
|
INSERT INTO t1 VALUES (4, 2);
|
||||||
|
include/save_master_gtid.inc
|
||||||
show binlog events from <binlog_start>;
|
show binlog events from <binlog_start>;
|
||||||
Log_name Pos Event_type Server_id End_log_pos Info
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
@ -31,6 +32,7 @@ slave-bin.000001 # Query # # COMMIT
|
|||||||
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
slave-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||||
slave-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4, 2)
|
slave-bin.000001 # Query # # use `test`; INSERT INTO t1 VALUES (4, 2)
|
||||||
slave-bin.000001 # Query # # COMMIT
|
slave-bin.000001 # Query # # COMMIT
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a b
|
a b
|
||||||
1 1
|
1 1
|
||||||
@ -41,9 +43,11 @@ include/stop_slave.inc
|
|||||||
RESET SLAVE;
|
RESET SLAVE;
|
||||||
INSERT INTO t1 VALUES (5, 1);
|
INSERT INTO t1 VALUES (5, 1);
|
||||||
INSERT INTO t1 VALUES (6, 1);
|
INSERT INTO t1 VALUES (6, 1);
|
||||||
|
include/save_master_gtid.inc
|
||||||
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT,
|
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT,
|
||||||
master_use_gtid = current_pos;
|
master_use_gtid = current_pos;
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a b
|
a b
|
||||||
1 1
|
1 1
|
||||||
|
@ -43,10 +43,12 @@ SET sql_log_bin=1;
|
|||||||
*** Test that we give warning when explict @@gtid_slave_pos=xxx that conflicts with what is in our binary log ***
|
*** Test that we give warning when explict @@gtid_slave_pos=xxx that conflicts with what is in our binary log ***
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
INSERT INTO t1 VALUES(3);
|
INSERT INTO t1 VALUES(3);
|
||||||
|
include/save_master_gtid.inc
|
||||||
SET GLOBAL gtid_slave_pos='0-1-3';
|
SET GLOBAL gtid_slave_pos='0-1-3';
|
||||||
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT,
|
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT,
|
||||||
MASTER_USE_GTID=CURRENT_POS;
|
MASTER_USE_GTID=CURRENT_POS;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER by a;
|
SELECT * FROM t1 ORDER by a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@ -54,6 +56,7 @@ a
|
|||||||
3
|
3
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
include/save_master_gtid.inc
|
||||||
INSERT INTO t1 VALUES (10);
|
INSERT INTO t1 VALUES (10);
|
||||||
DELETE FROM t1 WHERE a=10;
|
DELETE FROM t1 WHERE a=10;
|
||||||
SET GLOBAL gtid_slave_pos='0-1-4';
|
SET GLOBAL gtid_slave_pos='0-1-4';
|
||||||
@ -62,6 +65,7 @@ Warning 1947 Specified GTID 0-1-4 conflicts with the binary log which contains a
|
|||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
SET GLOBAL gtid_slave_pos='0-1-4';
|
SET GLOBAL gtid_slave_pos='0-1-4';
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER by a;
|
SELECT * FROM t1 ORDER by a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@ -125,6 +129,8 @@ STOP SLAVE IO_THREAD;
|
|||||||
CHANGE MASTER TO MASTER_USE_GTID=CURRENT_POS;
|
CHANGE MASTER TO MASTER_USE_GTID=CURRENT_POS;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
INSERT INTO t1 VALUES(3);
|
INSERT INTO t1 VALUES(3);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@ -136,6 +142,8 @@ SET SQL_LOG_BIN=1;
|
|||||||
*** Test reconnecting slave with GTID after purge logs on master. ***
|
*** Test reconnecting slave with GTID after purge logs on master. ***
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
include/stop_slave.inc
|
include/stop_slave.inc
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
@ -144,8 +152,10 @@ show binary logs;
|
|||||||
Log_name File_size
|
Log_name File_size
|
||||||
master-bin.000004 #
|
master-bin.000004 #
|
||||||
INSERT INTO t1 VALUES (5);
|
INSERT INTO t1 VALUES (5);
|
||||||
|
include/save_master_gtid.inc
|
||||||
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT;
|
CHANGE MASTER TO master_host = '127.0.0.1', master_port = MASTER_PORT;
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@ -160,7 +170,9 @@ SET GLOBAL gtid_slave_pos="";
|
|||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
TRUNCATE TABLE t1;
|
TRUNCATE TABLE t1;
|
||||||
INSERT INTO t1 VALUES (10);
|
INSERT INTO t1 VALUES (10);
|
||||||
|
include/save_master_gtid.inc
|
||||||
include/start_slave.inc
|
include/start_slave.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
a
|
a
|
||||||
10
|
10
|
||||||
|
@ -14,10 +14,12 @@ master-bin.000002 #
|
|||||||
INSERT INTO t1 VALUES (2);
|
INSERT INTO t1 VALUES (2);
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
INSERT INTO t1 VALUES (3);
|
INSERT INTO t1 VALUES (3);
|
||||||
|
include/save_master_gtid.inc
|
||||||
show binary logs;
|
show binary logs;
|
||||||
Log_name File_size
|
Log_name File_size
|
||||||
master-bin.000002 #
|
master-bin.000002 #
|
||||||
master-bin.000003 #
|
master-bin.000003 #
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
@ -43,6 +45,8 @@ master-bin.000003 #
|
|||||||
master-bin.000004 #
|
master-bin.000004 #
|
||||||
master-bin.000005 #
|
master-bin.000005 #
|
||||||
INSERT INTO t1 VALUES(5);
|
INSERT INTO t1 VALUES(5);
|
||||||
|
include/save_master_gtid.inc
|
||||||
|
include/sync_with_master_gtid.inc
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
a
|
a
|
||||||
1
|
1
|
||||||
|
@ -97,19 +97,16 @@ connection server_3;
|
|||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
connection server_1;
|
connection server_1;
|
||||||
BEGIN;
|
|
||||||
INSERT INTO t2 VALUES (6, "i6b");
|
INSERT INTO t2 VALUES (6, "i6b");
|
||||||
INSERT INTO t2 VALUES (7, "i7b");
|
INSERT INTO t2 VALUES (7, "i7b");
|
||||||
COMMIT;
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
connection server_3;
|
connection server_3;
|
||||||
--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4
|
--replace_result $SERVER_MYPORT_4 SERVER_MYPORT_4
|
||||||
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4,
|
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_4,
|
||||||
MASTER_USE_GTID=CURRENT_POS;
|
MASTER_USE_GTID=CURRENT_POS;
|
||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
# This time, let's sync up without reference to binlog on D.
|
--source include/sync_with_master_gtid.inc
|
||||||
--let $wait_condition= SELECT COUNT(*) = 7 FROM t2
|
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t2 ORDER BY a;
|
SELECT * FROM t2 ORDER BY a;
|
||||||
|
|
||||||
--echo *** Now change everything back to what it was, to make rpl_end.inc happy
|
--echo *** Now change everything back to what it was, to make rpl_end.inc happy
|
||||||
@ -118,8 +115,7 @@ connection server_2;
|
|||||||
# We need to sync up server_2 before switching. If it happened to have reached
|
# We need to sync up server_2 before switching. If it happened to have reached
|
||||||
# the point 'UPDATE t2 SET b="j1a" WHERE a=5' it will fail to connect to
|
# the point 'UPDATE t2 SET b="j1a" WHERE a=5' it will fail to connect to
|
||||||
# server_1, which is (deliberately) missing that transaction.
|
# server_1, which is (deliberately) missing that transaction.
|
||||||
--let $wait_condition= SELECT COUNT(*) = 7 FROM t2
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
--replace_result $MASTER_MYPORT MASTER_MYPORT
|
||||||
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT;
|
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT;
|
||||||
@ -131,8 +127,7 @@ connection server_3;
|
|||||||
--replace_result $SLAVE_MYPORT SLAVE_MYPORT
|
--replace_result $SLAVE_MYPORT SLAVE_MYPORT
|
||||||
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SLAVE_MYPORT;
|
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SLAVE_MYPORT;
|
||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
--let $wait_condition= SELECT COUNT(*) = 7 FROM t2
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
connection server_4;
|
connection server_4;
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
@ -142,6 +137,7 @@ eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $SERVER_MYPORT_3;
|
|||||||
|
|
||||||
connection server_1;
|
connection server_1;
|
||||||
DROP TABLE t1,t2;
|
DROP TABLE t1,t2;
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--echo *** A few more checks for BINLOG_GTID_POS function ***
|
--echo *** A few more checks for BINLOG_GTID_POS function ***
|
||||||
--let $valid_binlog_name = query_get_value(SHOW BINARY LOGS,Log_name,1)
|
--let $valid_binlog_name = query_get_value(SHOW BINARY LOGS,Log_name,1)
|
||||||
@ -163,6 +159,7 @@ eval SELECT BINLOG_GTID_POS('$valid_binlog_name',18446744073709551616);
|
|||||||
|
|
||||||
--echo *** Some tests of @@GLOBAL.gtid_binlog_state ***
|
--echo *** Some tests of @@GLOBAL.gtid_binlog_state ***
|
||||||
--connection server_2
|
--connection server_2
|
||||||
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
@ -192,21 +189,183 @@ SET GLOBAL gtid_binlog_state = @old_state;
|
|||||||
CREATE TABLE t1 (a INT PRIMARY KEY);
|
CREATE TABLE t1 (a INT PRIMARY KEY);
|
||||||
SET gtid_seq_no=100;
|
SET gtid_seq_no=100;
|
||||||
INSERT INTO t1 VALUES (1);
|
INSERT INTO t1 VALUES (1);
|
||||||
--let $master_pos= `SELECT @@GLOBAL.gtid_binlog_pos`
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
# We cannot just use sync_with_master as we've done RESET MASTER, so
|
# We cannot just use sync_with_master as we've done RESET MASTER, so
|
||||||
# slave old-style position is wrong.
|
# slave old-style position is wrong.
|
||||||
# So sync on gtid position instead.
|
# So sync on gtid position instead.
|
||||||
--let $wait_condition= SELECT @@GLOBAL.gtid_binlog_pos = '$master_pos'
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
# Check that the IO gtid position in SHOW SLAVE STATUS is also correct.
|
# Check that the IO gtid position in SHOW SLAVE STATUS is also correct.
|
||||||
--let $status_items= Gtid_IO_Pos
|
--let $status_items= Gtid_IO_Pos
|
||||||
--source include/show_slave_status.inc
|
--source include/show_slave_status.inc
|
||||||
|
|
||||||
|
--echo *** Test @@LAST_GTID and MASTER_GTID_WAIT() ***
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=InnoDB;
|
||||||
|
--save_master_pos
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--sync_with_master
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
--connect (m1,127.0.0.1,root,,test,$SERVER_MYPORT_1,)
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
SET gtid_seq_no=110;
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
BEGIN;
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
INSERT INTO t1 VALUES (2);
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
COMMIT;
|
||||||
|
SELECT @@last_gtid;
|
||||||
|
--let $pos= `SELECT @@gtid_binlog_pos`
|
||||||
|
|
||||||
|
--connect (s1,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
eval SET @pos= '$pos';
|
||||||
|
# Check NULL argument.
|
||||||
|
SELECT master_gtid_wait(NULL);
|
||||||
|
# Check empty argument returns immediately.
|
||||||
|
SELECT master_gtid_wait('', NULL);
|
||||||
|
# Let's check that we get a timeout
|
||||||
|
SELECT master_gtid_wait(@pos, 0.5);
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
# Now actually wait until the slave reaches the position
|
||||||
|
send SELECT master_gtid_wait(@pos);
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--connection s1
|
||||||
|
reap;
|
||||||
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
# Test waiting on a domain that does not exist yet.
|
||||||
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
SET gtid_domain_id= 1;
|
||||||
|
INSERT INTO t1 VALUES (3);
|
||||||
|
--let $pos= `SELECT @@gtid_binlog_pos`
|
||||||
|
|
||||||
|
--connection s1
|
||||||
|
eval SET @pos= '$pos';
|
||||||
|
SELECT master_gtid_wait(@pos, 0);
|
||||||
|
SELECT * FROM t1 WHERE a >= 3;
|
||||||
|
send SELECT master_gtid_wait(@pos, -1);
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--source include/start_slave.inc
|
||||||
|
|
||||||
|
--connection s1
|
||||||
|
reap;
|
||||||
|
SELECT * FROM t1 WHERE a >= 3;
|
||||||
|
# Waiting for only part of the position.
|
||||||
|
SELECT master_gtid_wait('1-1-1', 0);
|
||||||
|
|
||||||
|
# Now test a lot of parallel master_gtid_wait() calls, completing in different
|
||||||
|
# order, and some of which time out or get killed on the way.
|
||||||
|
|
||||||
|
--connection s1
|
||||||
|
send SELECT master_gtid_wait('2-1-1,1-1-4,0-1-110');
|
||||||
|
|
||||||
|
--connect (s2,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
# This will time out.
|
||||||
|
send SELECT master_gtid_wait('0-1-1000', 0.5);
|
||||||
|
|
||||||
|
--connect (s3,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
# This one we will kill
|
||||||
|
--let $kill1_id= `SELECT connection_id()`
|
||||||
|
send SELECT master_gtid_wait('0-1-2000');
|
||||||
|
|
||||||
|
--connect (s4,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
send SELECT master_gtid_wait('2-1-10');
|
||||||
|
|
||||||
|
--connect (s5,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
send SELECT master_gtid_wait('2-1-6', 1);
|
||||||
|
|
||||||
|
# This one we will kill also.
|
||||||
|
--connect (s6,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
--let $kill2_id= `SELECT connection_id()`
|
||||||
|
send SELECT master_gtid_wait('2-1-5');
|
||||||
|
|
||||||
|
--connect (s7,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
send SELECT master_gtid_wait('2-1-10');
|
||||||
|
|
||||||
|
--connect (s8,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
send SELECT master_gtid_wait('2-1-5,1-1-4,0-1-110');
|
||||||
|
|
||||||
|
--connect (s9,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
send SELECT master_gtid_wait('2-1-2');
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
# This one completes immediately.
|
||||||
|
SELECT master_gtid_wait('1-1-1');
|
||||||
|
|
||||||
|
--connect (s10,127.0.0.1,root,,test,$SERVER_MYPORT_2,)
|
||||||
|
send SELECT master_gtid_wait('0-1-109');
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
# This one should time out.
|
||||||
|
SELECT master_gtid_wait('2-1-2', 0.5);
|
||||||
|
|
||||||
|
--replace_result $kill1_id KILL_ID
|
||||||
|
eval KILL QUERY $kill1_id;
|
||||||
|
--connection s3
|
||||||
|
--error ER_QUERY_INTERRUPTED
|
||||||
|
reap;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
SET gtid_domain_id=2;
|
||||||
|
SET gtid_seq_no=2;
|
||||||
|
INSERT INTO t1 VALUES (4);
|
||||||
|
|
||||||
|
--connection s9
|
||||||
|
reap;
|
||||||
|
|
||||||
|
--connection server_2
|
||||||
|
--replace_result $kill2_id KILL_ID
|
||||||
|
eval KILL CONNECTION $kill2_id;
|
||||||
|
|
||||||
|
--connection s6
|
||||||
|
--error 2013
|
||||||
|
reap;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
SET gtid_domain_id=1;
|
||||||
|
SET gtid_seq_no=4;
|
||||||
|
INSERT INTO t1 VALUES (5);
|
||||||
|
SET gtid_domain_id=2;
|
||||||
|
SET gtid_seq_no=5;
|
||||||
|
INSERT INTO t1 VALUES (6);
|
||||||
|
|
||||||
|
--connection s8
|
||||||
|
reap;
|
||||||
|
--connection s1
|
||||||
|
reap;
|
||||||
|
--connection s2
|
||||||
|
reap;
|
||||||
|
--connection s5
|
||||||
|
reap;
|
||||||
|
--connection s10
|
||||||
|
reap;
|
||||||
|
|
||||||
|
--connection server_1
|
||||||
|
SET gtid_domain_id=2;
|
||||||
|
SET gtid_seq_no=10;
|
||||||
|
INSERT INTO t1 VALUES (7);
|
||||||
|
|
||||||
|
--connection s4
|
||||||
|
reap;
|
||||||
|
--connection s7
|
||||||
|
reap;
|
||||||
|
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
@ -46,6 +46,7 @@ while ($1)
|
|||||||
dec $1;
|
dec $1;
|
||||||
}
|
}
|
||||||
--enable_query_log
|
--enable_query_log
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
SET SESSION debug_dbug="+d,crash_dispatch_command_before";
|
SET SESSION debug_dbug="+d,crash_dispatch_command_before";
|
||||||
--error 2006,2013
|
--error 2006,2013
|
||||||
@ -60,15 +61,14 @@ EOF
|
|||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--let $wait_condition= SELECT COUNT(*) = 200 FROM t1 WHERE b=2
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES (1000, 3);
|
INSERT INTO t1 VALUES (1000, 3);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--let $wait_condition= SELECT COUNT(*) = 1 FROM t1 WHERE b=3
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
DROP TABLE t1;
|
DROP TABLE t1;
|
||||||
@ -141,6 +141,7 @@ START SLAVE;
|
|||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/wait_until_disconnected.inc
|
--source include/wait_until_disconnected.inc
|
||||||
@ -152,8 +153,7 @@ EOF
|
|||||||
--enable_reconnect
|
--enable_reconnect
|
||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
--let $wait_condition= SELECT COUNT(*) = 4 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
# Crash the slave just before committing.
|
# Crash the slave just before committing.
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
@ -165,6 +165,7 @@ START SLAVE;
|
|||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES (5);
|
INSERT INTO t1 VALUES (5);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/wait_until_disconnected.inc
|
--source include/wait_until_disconnected.inc
|
||||||
@ -176,8 +177,7 @@ EOF
|
|||||||
--enable_reconnect
|
--enable_reconnect
|
||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
--let $wait_condition= SELECT COUNT(*) = 5 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
# Crash the slave just after committing.
|
# Crash the slave just after committing.
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
@ -189,6 +189,7 @@ START SLAVE;
|
|||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES (6);
|
INSERT INTO t1 VALUES (6);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/wait_until_disconnected.inc
|
--source include/wait_until_disconnected.inc
|
||||||
@ -200,8 +201,7 @@ EOF
|
|||||||
--enable_reconnect
|
--enable_reconnect
|
||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
--let $wait_condition= SELECT COUNT(*) = 6 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
# Crash the slave just before updating relay-log.info
|
# Crash the slave just before updating relay-log.info
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
@ -213,6 +213,7 @@ START SLAVE;
|
|||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES (7);
|
INSERT INTO t1 VALUES (7);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/wait_until_disconnected.inc
|
--source include/wait_until_disconnected.inc
|
||||||
@ -224,8 +225,7 @@ EOF
|
|||||||
--enable_reconnect
|
--enable_reconnect
|
||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
--let $wait_condition= SELECT COUNT(*) = 7 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
# Crash the slave just after updating relay-log.info
|
# Crash the slave just after updating relay-log.info
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
@ -237,6 +237,7 @@ START SLAVE;
|
|||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES (8);
|
INSERT INTO t1 VALUES (8);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/wait_until_disconnected.inc
|
--source include/wait_until_disconnected.inc
|
||||||
@ -248,8 +249,7 @@ EOF
|
|||||||
--enable_reconnect
|
--enable_reconnect
|
||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
--let $wait_condition= SELECT COUNT(*) = 8 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
|
|
||||||
# Check that everything was replicated correctly.
|
# Check that everything was replicated correctly.
|
||||||
|
@ -79,6 +79,7 @@ RESET MASTER;
|
|||||||
INSERT INTO t1 VALUES (2);
|
INSERT INTO t1 VALUES (2);
|
||||||
# And this will be GTID 0-1-2
|
# And this will be GTID 0-1-2
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection slave
|
--connection slave
|
||||||
SET sql_log_bin = 0;
|
SET sql_log_bin = 0;
|
||||||
@ -110,8 +111,7 @@ RESET MASTER;
|
|||||||
SET GLOBAL gtid_slave_pos = "0-1-1";
|
SET GLOBAL gtid_slave_pos = "0-1-1";
|
||||||
|
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
--let $wait_condition= SELECT COUNT(*) = 4 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
--echo *** MDEV-4688: Empty value of @@GLOBAL.gtid_slave_pos ***
|
--echo *** MDEV-4688: Empty value of @@GLOBAL.gtid_slave_pos ***
|
||||||
@ -125,6 +125,7 @@ SELECT * FROM t1 ORDER BY a;
|
|||||||
--connection master
|
--connection master
|
||||||
# This will be GTID 0-1-3
|
# This will be GTID 0-1-3
|
||||||
INSERT INTO t1 VALUES (5);
|
INSERT INTO t1 VALUES (5);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection slave
|
--connection slave
|
||||||
SET @old_dbug= @@GLOBAL.debug_dbug;
|
SET @old_dbug= @@GLOBAL.debug_dbug;
|
||||||
@ -141,8 +142,7 @@ SELECT @@GLOBAL.gtid_slave_pos;
|
|||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
SET GLOBAL debug_dbug= @old_dbug;
|
SET GLOBAL debug_dbug= @old_dbug;
|
||||||
START SLAVE SQL_THREAD;
|
START SLAVE SQL_THREAD;
|
||||||
--let $wait_condition= SELECT COUNT(*) = 5 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
|
||||||
@ -167,10 +167,10 @@ START SLAVE;
|
|||||||
|
|
||||||
--connection master
|
--connection master
|
||||||
INSERT INTO t1 VALUES (6);
|
INSERT INTO t1 VALUES (6);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection slave
|
--connection slave
|
||||||
--let $wait_condition= SELECT COUNT(*) = 6 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,12 +32,12 @@ START SLAVE;
|
|||||||
--connection server_2
|
--connection server_2
|
||||||
INSERT INTO t1 VALUES (3, 2);
|
INSERT INTO t1 VALUES (3, 2);
|
||||||
INSERT INTO t1 VALUES (4, 2);
|
INSERT INTO t1 VALUES (4, 2);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--source include/show_binlog_events.inc
|
--source include/show_binlog_events.inc
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
--let $wait_condition= SELECT COUNT(*) = 4 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
@ -45,14 +45,14 @@ SELECT * FROM t1 ORDER BY a;
|
|||||||
RESET SLAVE;
|
RESET SLAVE;
|
||||||
INSERT INTO t1 VALUES (5, 1);
|
INSERT INTO t1 VALUES (5, 1);
|
||||||
INSERT INTO t1 VALUES (6, 1);
|
INSERT INTO t1 VALUES (6, 1);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--replace_result $MASTER_MYPORT MASTER_PORT
|
--replace_result $MASTER_MYPORT MASTER_PORT
|
||||||
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
|
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
|
||||||
master_use_gtid = current_pos;
|
master_use_gtid = current_pos;
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
--let $wait_condition= SELECT COUNT(*) = 6 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
@ -67,6 +67,7 @@ SET sql_log_bin=1;
|
|||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES(3);
|
INSERT INTO t1 VALUES(3);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
SET GLOBAL gtid_slave_pos='0-1-3';
|
SET GLOBAL gtid_slave_pos='0-1-3';
|
||||||
@ -74,13 +75,13 @@ SET GLOBAL gtid_slave_pos='0-1-3';
|
|||||||
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
|
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT,
|
||||||
MASTER_USE_GTID=CURRENT_POS;
|
MASTER_USE_GTID=CURRENT_POS;
|
||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
--let $wait_condition= SELECT COUNT(*) = 3 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER by a;
|
SELECT * FROM t1 ORDER by a;
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
# Now add some local transactions that conflict with the GTID position
|
# Now add some local transactions that conflict with the GTID position
|
||||||
@ -93,8 +94,7 @@ SET GLOBAL gtid_slave_pos='0-1-4';
|
|||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
SET GLOBAL gtid_slave_pos='0-1-4';
|
SET GLOBAL gtid_slave_pos='0-1-4';
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
--let $wait_condition= SELECT COUNT(*) = 4 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER by a;
|
SELECT * FROM t1 ORDER by a;
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
@ -200,10 +200,10 @@ CHANGE MASTER TO MASTER_USE_GTID=CURRENT_POS;
|
|||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
INSERT INTO t1 VALUES(3);
|
INSERT INTO t1 VALUES(3);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--let $wait_condition= SELECT COUNT(*) = 3 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
SET SQL_LOG_BIN=0;
|
SET SQL_LOG_BIN=0;
|
||||||
call mtr.add_suppression("Slave: Table 't1' already exists error.* 1050");
|
call mtr.add_suppression("Slave: Table 't1' already exists error.* 1050");
|
||||||
@ -215,10 +215,10 @@ SET SQL_LOG_BIN=1;
|
|||||||
--connection server_1
|
--connection server_1
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
INSERT INTO t1 VALUES (4);
|
INSERT INTO t1 VALUES (4);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--let $wait_condition= SELECT COUNT(*) = 4 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
--source include/stop_slave.inc
|
--source include/stop_slave.inc
|
||||||
|
|
||||||
--connection server_1
|
--connection server_1
|
||||||
@ -228,13 +228,13 @@ FLUSH LOGS;
|
|||||||
--source include/wait_for_purge.inc
|
--source include/wait_for_purge.inc
|
||||||
--source include/show_binary_logs.inc
|
--source include/show_binary_logs.inc
|
||||||
INSERT INTO t1 VALUES (5);
|
INSERT INTO t1 VALUES (5);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--replace_result $MASTER_MYPORT MASTER_PORT
|
--replace_result $MASTER_MYPORT MASTER_PORT
|
||||||
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT;
|
eval CHANGE MASTER TO master_host = '127.0.0.1', master_port = $MASTER_MYPORT;
|
||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
--let $wait_condition= SELECT COUNT(*) = 5 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
|
||||||
@ -249,11 +249,11 @@ SET GLOBAL gtid_slave_pos="";
|
|||||||
RESET MASTER;
|
RESET MASTER;
|
||||||
TRUNCATE TABLE t1;
|
TRUNCATE TABLE t1;
|
||||||
INSERT INTO t1 VALUES (10); # Will be GTID 0-1-2
|
INSERT INTO t1 VALUES (10); # Will be GTID 0-1-2
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--source include/start_slave.inc
|
--source include/start_slave.inc
|
||||||
--let $wait_condition= SELECT COUNT(*) = 1 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
|
|
||||||
SELECT * FROM t1;
|
SELECT * FROM t1;
|
||||||
--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1)
|
--let $value= query_get_value(SHOW SLAVE STATUS, "Using_Gtid", 1)
|
||||||
|
@ -39,6 +39,7 @@ FLUSH LOGS;
|
|||||||
INSERT INTO t1 VALUES (2);
|
INSERT INTO t1 VALUES (2);
|
||||||
FLUSH LOGS;
|
FLUSH LOGS;
|
||||||
INSERT INTO t1 VALUES (3);
|
INSERT INTO t1 VALUES (3);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
--source include/show_binary_logs.inc
|
--source include/show_binary_logs.inc
|
||||||
|
|
||||||
# Let the slave mysqld server start again.
|
# Let the slave mysqld server start again.
|
||||||
@ -50,8 +51,7 @@ EOF
|
|||||||
--enable_reconnect
|
--enable_reconnect
|
||||||
--source include/wait_until_connected_again.inc
|
--source include/wait_until_connected_again.inc
|
||||||
|
|
||||||
--let $wait_condition= SELECT COUNT(*) = 3 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
|
|
||||||
@ -88,10 +88,10 @@ SHOW BINLOG EVENTS IN 'master-bin.000005' LIMIT 1,1;
|
|||||||
--source include/show_binary_logs.inc
|
--source include/show_binary_logs.inc
|
||||||
|
|
||||||
INSERT INTO t1 VALUES(5);
|
INSERT INTO t1 VALUES(5);
|
||||||
|
--source include/save_master_gtid.inc
|
||||||
|
|
||||||
--connection server_2
|
--connection server_2
|
||||||
--let $wait_condition= SELECT COUNT(*) = 5 FROM t1
|
--source include/sync_with_master_gtid.inc
|
||||||
--source include/wait_condition.inc
|
|
||||||
SELECT * FROM t1 ORDER BY a;
|
SELECT * FROM t1 ORDER BY a;
|
||||||
|
|
||||||
--echo *** Test that @@gtid_slave_pos and @@gtid_current_pos are correctly loaded even if slave threads have not started. ***
|
--echo *** Test that @@gtid_slave_pos and @@gtid_current_pos are correctly loaded even if slave threads have not started. ***
|
||||||
|
9
mysql-test/suite/sys_vars/r/last_gtid_basic.result
Normal file
9
mysql-test/suite/sys_vars/r/last_gtid_basic.result
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
SELECT @@global.last_gtid;
|
||||||
|
ERROR HY000: Variable 'last_gtid' is a SESSION variable
|
||||||
|
SET GLOBAL last_gtid= 10;
|
||||||
|
ERROR HY000: Variable 'last_gtid' is a read only variable
|
||||||
|
SET SESSION last_gtid= 20;
|
||||||
|
ERROR HY000: Variable 'last_gtid' is a read only variable
|
||||||
|
SELECT @@session.last_gtid;
|
||||||
|
@@session.last_gtid
|
||||||
|
|
11
mysql-test/suite/sys_vars/t/last_gtid_basic.test
Normal file
11
mysql-test/suite/sys_vars/t/last_gtid_basic.test
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
--source include/not_embedded.inc
|
||||||
|
|
||||||
|
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||||
|
SELECT @@global.last_gtid;
|
||||||
|
|
||||||
|
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||||
|
SET GLOBAL last_gtid= 10;
|
||||||
|
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
|
||||||
|
SET SESSION last_gtid= 20;
|
||||||
|
|
||||||
|
SELECT @@session.last_gtid;
|
@ -1783,6 +1783,19 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Create_func_master_gtid_wait : public Create_native_func
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual Item *create_native(THD *thd, LEX_STRING name, List<Item> *item_list);
|
||||||
|
|
||||||
|
static Create_func_master_gtid_wait s_singleton;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Create_func_master_gtid_wait() {}
|
||||||
|
virtual ~Create_func_master_gtid_wait() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class Create_func_md5 : public Create_func_arg1
|
class Create_func_md5 : public Create_func_arg1
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -4590,6 +4603,47 @@ Create_func_master_pos_wait::create_native(THD *thd, LEX_STRING name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Create_func_master_gtid_wait Create_func_master_gtid_wait::s_singleton;
|
||||||
|
|
||||||
|
Item*
|
||||||
|
Create_func_master_gtid_wait::create_native(THD *thd, LEX_STRING name,
|
||||||
|
List<Item> *item_list)
|
||||||
|
{
|
||||||
|
Item *func= NULL;
|
||||||
|
int arg_count= 0;
|
||||||
|
|
||||||
|
thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_SYSTEM_FUNCTION);
|
||||||
|
|
||||||
|
if (item_list != NULL)
|
||||||
|
arg_count= item_list->elements;
|
||||||
|
|
||||||
|
if (arg_count < 1 || arg_count > 2)
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT, MYF(0), name.str);
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
thd->lex->safe_to_cache_query= 0;
|
||||||
|
|
||||||
|
Item *param_1= item_list->pop();
|
||||||
|
switch (arg_count) {
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
func= new (thd->mem_root) Item_master_gtid_wait(param_1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
Item *param_2= item_list->pop();
|
||||||
|
func= new (thd->mem_root) Item_master_gtid_wait(param_1, param_2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Create_func_md5 Create_func_md5::s_singleton;
|
Create_func_md5 Create_func_md5::s_singleton;
|
||||||
|
|
||||||
Item*
|
Item*
|
||||||
@ -5536,6 +5590,7 @@ static Native_func_registry func_array[] =
|
|||||||
{ { C_STRING_WITH_LEN("MAKEDATE") }, BUILDER(Create_func_makedate)},
|
{ { C_STRING_WITH_LEN("MAKEDATE") }, BUILDER(Create_func_makedate)},
|
||||||
{ { C_STRING_WITH_LEN("MAKETIME") }, BUILDER(Create_func_maketime)},
|
{ { C_STRING_WITH_LEN("MAKETIME") }, BUILDER(Create_func_maketime)},
|
||||||
{ { C_STRING_WITH_LEN("MAKE_SET") }, BUILDER(Create_func_make_set)},
|
{ { C_STRING_WITH_LEN("MAKE_SET") }, BUILDER(Create_func_make_set)},
|
||||||
|
{ { C_STRING_WITH_LEN("MASTER_GTID_WAIT") }, BUILDER(Create_func_master_gtid_wait)},
|
||||||
{ { C_STRING_WITH_LEN("MASTER_POS_WAIT") }, BUILDER(Create_func_master_pos_wait)},
|
{ { C_STRING_WITH_LEN("MASTER_POS_WAIT") }, BUILDER(Create_func_master_pos_wait)},
|
||||||
{ { C_STRING_WITH_LEN("MBRCONTAINS") }, GEOM_BUILDER(Create_func_mbr_contains)},
|
{ { C_STRING_WITH_LEN("MBRCONTAINS") }, GEOM_BUILDER(Create_func_mbr_contains)},
|
||||||
{ { C_STRING_WITH_LEN("MBRDISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
|
{ { C_STRING_WITH_LEN("MBRDISJOINT") }, GEOM_BUILDER(Create_func_mbr_disjoint)},
|
||||||
|
@ -3991,6 +3991,34 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
longlong Item_master_gtid_wait::val_int()
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(fixed == 1);
|
||||||
|
longlong result= 0;
|
||||||
|
|
||||||
|
if (args[0]->null_value)
|
||||||
|
{
|
||||||
|
null_value= 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
null_value=0;
|
||||||
|
#ifdef HAVE_REPLICATION
|
||||||
|
THD* thd= current_thd;
|
||||||
|
longlong timeout_us;
|
||||||
|
String *gtid_pos = args[0]->val_str(&value);
|
||||||
|
|
||||||
|
if (arg_count==2 && !args[1]->null_value)
|
||||||
|
timeout_us= (longlong)(1e6*args[1]->val_real());
|
||||||
|
else
|
||||||
|
timeout_us= (longlong)-1;
|
||||||
|
|
||||||
|
result= rpl_global_gtid_waiting.wait_for_pos(thd, gtid_pos, timeout_us);
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enables a session to wait on a condition until a timeout or a network
|
Enables a session to wait on a condition until a timeout or a network
|
||||||
disconnect occurs.
|
disconnect occurs.
|
||||||
|
@ -1642,6 +1642,22 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Item_master_gtid_wait :public Item_int_func
|
||||||
|
{
|
||||||
|
String value;
|
||||||
|
public:
|
||||||
|
Item_master_gtid_wait(Item *a) :Item_int_func(a) {}
|
||||||
|
Item_master_gtid_wait(Item *a,Item *b) :Item_int_func(a,b) {}
|
||||||
|
longlong val_int();
|
||||||
|
const char *func_name() const { return "master_gtid_wait"; }
|
||||||
|
void fix_length_and_dec() { max_length=10+1+10+1+20+1; maybe_null=0;}
|
||||||
|
bool check_vcol_func_processor(uchar *int_arg)
|
||||||
|
{
|
||||||
|
return trace_unsupported_by_check_vcol_func_processor(func_name());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/* Handling of user definable variables */
|
/* Handling of user definable variables */
|
||||||
|
|
||||||
class user_var_entry;
|
class user_var_entry;
|
||||||
|
50
sql/log.cc
50
sql/log.cc
@ -2933,7 +2933,7 @@ const char *MYSQL_LOG::generate_name(const char *log_name,
|
|||||||
|
|
||||||
|
|
||||||
MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
|
MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period)
|
||||||
:reset_master_pending(false),
|
:reset_master_pending(false), mark_xid_done_waiting(0),
|
||||||
bytes_written(0), file_id(1), open_count(1),
|
bytes_written(0), file_id(1), open_count(1),
|
||||||
group_commit_queue(0), group_commit_queue_busy(FALSE),
|
group_commit_queue(0), group_commit_queue_busy(FALSE),
|
||||||
num_commits(0), num_group_commits(0),
|
num_commits(0), num_group_commits(0),
|
||||||
@ -3749,6 +3749,31 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log,
|
|||||||
const char* save_name;
|
const char* save_name;
|
||||||
DBUG_ENTER("reset_logs");
|
DBUG_ENTER("reset_logs");
|
||||||
|
|
||||||
|
if (!is_relay_log)
|
||||||
|
{
|
||||||
|
if (init_state && !is_empty_state())
|
||||||
|
{
|
||||||
|
my_error(ER_BINLOG_MUST_BE_EMPTY, MYF(0));
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Mark that a RESET MASTER is in progress.
|
||||||
|
This ensures that a binlog checkpoint will not try to write binlog
|
||||||
|
checkpoint events, which would be useless (as we are deleting the binlog
|
||||||
|
anyway) and could deadlock, as we are holding LOCK_log.
|
||||||
|
|
||||||
|
Wait for any mark_xid_done() calls that might be already running to
|
||||||
|
complete (mark_xid_done_waiting counter to drop to zero); we need to
|
||||||
|
do this before we take the LOCK_log to not deadlock.
|
||||||
|
*/
|
||||||
|
mysql_mutex_lock(&LOCK_xid_list);
|
||||||
|
reset_master_pending= true;
|
||||||
|
while (mark_xid_done_waiting > 0)
|
||||||
|
mysql_cond_wait(&COND_xid_list, &LOCK_xid_list);
|
||||||
|
mysql_mutex_unlock(&LOCK_xid_list);
|
||||||
|
}
|
||||||
|
|
||||||
if (thd)
|
if (thd)
|
||||||
ha_reset_logs(thd);
|
ha_reset_logs(thd);
|
||||||
/*
|
/*
|
||||||
@ -3760,24 +3785,6 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd, bool create_new_log,
|
|||||||
|
|
||||||
if (!is_relay_log)
|
if (!is_relay_log)
|
||||||
{
|
{
|
||||||
if (init_state && !is_empty_state())
|
|
||||||
{
|
|
||||||
my_error(ER_BINLOG_MUST_BE_EMPTY, MYF(0));
|
|
||||||
mysql_mutex_unlock(&LOCK_index);
|
|
||||||
mysql_mutex_unlock(&LOCK_log);
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Mark that a RESET MASTER is in progress.
|
|
||||||
This ensures that a binlog checkpoint will not try to write binlog
|
|
||||||
checkpoint events, which would be useless (as we are deleting the binlog
|
|
||||||
anyway) and could deadlock, as we are holding LOCK_log.
|
|
||||||
*/
|
|
||||||
mysql_mutex_lock(&LOCK_xid_list);
|
|
||||||
reset_master_pending= true;
|
|
||||||
mysql_mutex_unlock(&LOCK_xid_list);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We are going to nuke all binary log files.
|
We are going to nuke all binary log files.
|
||||||
Without binlog, we cannot XA recover prepared-but-not-committed
|
Without binlog, we cannot XA recover prepared-but-not-committed
|
||||||
@ -5446,6 +5453,7 @@ MYSQL_BIN_LOG::write_gtid_event(THD *thd, bool standalone,
|
|||||||
}
|
}
|
||||||
if (err)
|
if (err)
|
||||||
return true;
|
return true;
|
||||||
|
thd->last_commit_gtid= gtid;
|
||||||
|
|
||||||
Gtid_log_event gtid_event(thd, seq_no, domain_id, standalone,
|
Gtid_log_event gtid_event(thd, seq_no, domain_id, standalone,
|
||||||
LOG_EVENT_SUPPRESS_USE_F, is_transactional,
|
LOG_EVENT_SUPPRESS_USE_F, is_transactional,
|
||||||
@ -8833,9 +8841,13 @@ TC_LOG_BINLOG::mark_xid_done(ulong binlog_id, bool write_checkpoint)
|
|||||||
locks in the opposite order.
|
locks in the opposite order.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
++mark_xid_done_waiting;
|
||||||
mysql_mutex_unlock(&LOCK_xid_list);
|
mysql_mutex_unlock(&LOCK_xid_list);
|
||||||
mysql_mutex_lock(&LOCK_log);
|
mysql_mutex_lock(&LOCK_log);
|
||||||
mysql_mutex_lock(&LOCK_xid_list);
|
mysql_mutex_lock(&LOCK_xid_list);
|
||||||
|
--mark_xid_done_waiting;
|
||||||
|
if (unlikely(reset_master_pending))
|
||||||
|
mysql_cond_signal(&COND_xid_list);
|
||||||
/* We need to reload current_binlog_id due to release/re-take of lock. */
|
/* We need to reload current_binlog_id due to release/re-take of lock. */
|
||||||
current= current_binlog_id;
|
current= current_binlog_id;
|
||||||
|
|
||||||
|
@ -471,6 +471,7 @@ class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
|
|||||||
checkpoint arrives - when all have arrived, RESET MASTER will complete.
|
checkpoint arrives - when all have arrived, RESET MASTER will complete.
|
||||||
*/
|
*/
|
||||||
bool reset_master_pending;
|
bool reset_master_pending;
|
||||||
|
ulong mark_xid_done_waiting;
|
||||||
|
|
||||||
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
|
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */
|
||||||
mysql_mutex_t LOCK_index;
|
mysql_mutex_t LOCK_index;
|
||||||
|
@ -780,6 +780,7 @@ PSI_mutex_key key_LOCK_stats,
|
|||||||
key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
|
key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
|
||||||
key_LOCK_global_index_stats,
|
key_LOCK_global_index_stats,
|
||||||
key_LOCK_wakeup_ready, key_LOCK_wait_commit;
|
key_LOCK_wakeup_ready, key_LOCK_wait_commit;
|
||||||
|
PSI_mutex_key key_LOCK_gtid_waiting;
|
||||||
|
|
||||||
PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
|
PSI_mutex_key key_LOCK_prepare_ordered, key_LOCK_commit_ordered;
|
||||||
|
|
||||||
@ -825,6 +826,7 @@ static PSI_mutex_info all_server_mutexes[]=
|
|||||||
{ &key_LOCK_global_index_stats, "LOCK_global_index_stats", PSI_FLAG_GLOBAL},
|
{ &key_LOCK_global_index_stats, "LOCK_global_index_stats", PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0},
|
{ &key_LOCK_wakeup_ready, "THD::LOCK_wakeup_ready", 0},
|
||||||
{ &key_LOCK_wait_commit, "wait_for_commit::LOCK_wait_commit", 0},
|
{ &key_LOCK_wait_commit, "wait_for_commit::LOCK_wait_commit", 0},
|
||||||
|
{ &key_LOCK_gtid_waiting, "gtid_waiting::LOCK_gtid_waiting", 0},
|
||||||
{ &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
|
{ &key_LOCK_thd_data, "THD::LOCK_thd_data", 0},
|
||||||
{ &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
|
{ &key_LOCK_user_conn, "LOCK_user_conn", PSI_FLAG_GLOBAL},
|
||||||
{ &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL},
|
{ &key_LOCK_uuid_short_generator, "LOCK_uuid_short_generator", PSI_FLAG_GLOBAL},
|
||||||
@ -895,6 +897,7 @@ PSI_cond_key key_RELAYLOG_COND_queue_busy;
|
|||||||
PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy;
|
PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy;
|
||||||
PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_pool,
|
PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_pool,
|
||||||
key_COND_parallel_entry, key_COND_prepare_ordered;
|
key_COND_parallel_entry, key_COND_prepare_ordered;
|
||||||
|
PSI_cond_key key_COND_wait_gtid;
|
||||||
|
|
||||||
static PSI_cond_info all_server_conds[]=
|
static PSI_cond_info all_server_conds[]=
|
||||||
{
|
{
|
||||||
@ -940,7 +943,8 @@ static PSI_cond_info all_server_conds[]=
|
|||||||
{ &key_COND_rpl_thread, "COND_rpl_thread", 0},
|
{ &key_COND_rpl_thread, "COND_rpl_thread", 0},
|
||||||
{ &key_COND_rpl_thread_pool, "COND_rpl_thread_pool", 0},
|
{ &key_COND_rpl_thread_pool, "COND_rpl_thread_pool", 0},
|
||||||
{ &key_COND_parallel_entry, "COND_parallel_entry", 0},
|
{ &key_COND_parallel_entry, "COND_parallel_entry", 0},
|
||||||
{ &key_COND_prepare_ordered, "COND_prepare_ordered", 0}
|
{ &key_COND_prepare_ordered, "COND_prepare_ordered", 0},
|
||||||
|
{ &key_COND_wait_gtid, "COND_wait_gtid", 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
|
PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
|
||||||
@ -1821,6 +1825,7 @@ static void mysqld_exit(int exit_code)
|
|||||||
but if a kill -15 signal was sent, the signal thread did
|
but if a kill -15 signal was sent, the signal thread did
|
||||||
spawn the kill_server_thread thread, which is running concurrently.
|
spawn the kill_server_thread thread, which is running concurrently.
|
||||||
*/
|
*/
|
||||||
|
rpl_deinit_gtid_waiting();
|
||||||
rpl_deinit_gtid_slave_state();
|
rpl_deinit_gtid_slave_state();
|
||||||
wait_for_signal_thread_to_end();
|
wait_for_signal_thread_to_end();
|
||||||
mysql_audit_finalize();
|
mysql_audit_finalize();
|
||||||
@ -4202,6 +4207,7 @@ static int init_thread_environment()
|
|||||||
|
|
||||||
#ifdef HAVE_REPLICATION
|
#ifdef HAVE_REPLICATION
|
||||||
rpl_init_gtid_slave_state();
|
rpl_init_gtid_slave_state();
|
||||||
|
rpl_init_gtid_waiting();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
@ -256,6 +256,7 @@ extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state,
|
|||||||
extern PSI_mutex_key key_LOCK_stats,
|
extern PSI_mutex_key key_LOCK_stats,
|
||||||
key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
|
key_LOCK_global_user_client_stats, key_LOCK_global_table_stats,
|
||||||
key_LOCK_global_index_stats, key_LOCK_wakeup_ready, key_LOCK_wait_commit;
|
key_LOCK_global_index_stats, key_LOCK_wakeup_ready, key_LOCK_wait_commit;
|
||||||
|
extern PSI_mutex_key key_LOCK_gtid_waiting;
|
||||||
|
|
||||||
extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
|
extern PSI_rwlock_key key_rwlock_LOCK_grant, key_rwlock_LOCK_logger,
|
||||||
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
|
key_rwlock_LOCK_sys_init_connect, key_rwlock_LOCK_sys_init_slave,
|
||||||
@ -285,6 +286,7 @@ extern PSI_cond_key key_RELAYLOG_COND_queue_busy;
|
|||||||
extern PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy;
|
extern PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy;
|
||||||
extern PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_pool,
|
extern PSI_cond_key key_COND_rpl_thread, key_COND_rpl_thread_pool,
|
||||||
key_COND_parallel_entry;
|
key_COND_parallel_entry;
|
||||||
|
extern PSI_cond_key key_COND_wait_gtid;
|
||||||
|
|
||||||
extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
|
extern PSI_thread_key key_thread_bootstrap, key_thread_delayed_insert,
|
||||||
key_thread_handle_manager, key_thread_kill_server, key_thread_main,
|
key_thread_handle_manager, key_thread_kill_server, key_thread_main,
|
||||||
|
507
sql/rpl_gtid.cc
507
sql/rpl_gtid.cc
@ -43,9 +43,9 @@ rpl_slave_state::update_state_hash(uint64 sub_id, rpl_gtid *gtid)
|
|||||||
there will not be an attempt to delete the corresponding table row before
|
there will not be an attempt to delete the corresponding table row before
|
||||||
it is even committed.
|
it is even committed.
|
||||||
*/
|
*/
|
||||||
lock();
|
mysql_mutex_lock(&LOCK_slave_state);
|
||||||
err= update(gtid->domain_id, gtid->server_id, sub_id, gtid->seq_no);
|
err= update(gtid->domain_id, gtid->server_id, sub_id, gtid->seq_no);
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
if (err)
|
if (err)
|
||||||
{
|
{
|
||||||
sql_print_warning("Slave: Out of memory during slave state maintenance. "
|
sql_print_warning("Slave: Out of memory during slave state maintenance. "
|
||||||
@ -82,11 +82,20 @@ rpl_slave_state::record_and_update_gtid(THD *thd, rpl_group_info *rgi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
rpl_slave_state_free_element(void *arg)
|
||||||
|
{
|
||||||
|
struct rpl_slave_state::element *elem= (struct rpl_slave_state::element *)arg;
|
||||||
|
mysql_cond_destroy(&elem->COND_wait_gtid);
|
||||||
|
my_free(elem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
rpl_slave_state::rpl_slave_state()
|
rpl_slave_state::rpl_slave_state()
|
||||||
: last_sub_id(0), inited(false), loaded(false)
|
: last_sub_id(0), inited(false), loaded(false)
|
||||||
{
|
{
|
||||||
my_hash_init(&hash, &my_charset_bin, 32, offsetof(element, domain_id),
|
my_hash_init(&hash, &my_charset_bin, 32, offsetof(element, domain_id),
|
||||||
sizeof(uint32), NULL, my_free, HASH_UNIQUE);
|
sizeof(uint32), NULL, rpl_slave_state_free_element, HASH_UNIQUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -146,6 +155,21 @@ rpl_slave_state::update(uint32 domain_id, uint32 server_id, uint64 sub_id,
|
|||||||
if (!(elem= get_element(domain_id)))
|
if (!(elem= get_element(domain_id)))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (seq_no > elem->highest_seq_no)
|
||||||
|
elem->highest_seq_no= seq_no;
|
||||||
|
if (elem->gtid_waiter && elem->min_wait_seq_no <= seq_no)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Someone was waiting in MASTER_GTID_WAIT() for this GTID to appear.
|
||||||
|
Signal (and remove) them. The waiter will handle all the processing
|
||||||
|
of all pending MASTER_GTID_WAIT(), so we do not slow down the
|
||||||
|
replication SQL thread.
|
||||||
|
*/
|
||||||
|
mysql_mutex_assert_owner(&LOCK_slave_state);
|
||||||
|
elem->gtid_waiter= NULL;
|
||||||
|
mysql_cond_broadcast(&elem->COND_wait_gtid);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(list_elem= (list_element *)my_malloc(sizeof(*list_elem), MYF(MY_WME))))
|
if (!(list_elem= (list_element *)my_malloc(sizeof(*list_elem), MYF(MY_WME))))
|
||||||
return 1;
|
return 1;
|
||||||
list_elem->server_id= server_id;
|
list_elem->server_id= server_id;
|
||||||
@ -173,6 +197,9 @@ rpl_slave_state::get_element(uint32 domain_id)
|
|||||||
return NULL;
|
return NULL;
|
||||||
elem->list= NULL;
|
elem->list= NULL;
|
||||||
elem->domain_id= domain_id;
|
elem->domain_id= domain_id;
|
||||||
|
elem->highest_seq_no= 0;
|
||||||
|
elem->gtid_waiter= NULL;
|
||||||
|
mysql_cond_init(key_COND_wait_gtid, &elem->COND_wait_gtid, 0);
|
||||||
if (my_hash_insert(&hash, (uchar *)elem))
|
if (my_hash_insert(&hash, (uchar *)elem))
|
||||||
{
|
{
|
||||||
my_free(elem);
|
my_free(elem);
|
||||||
@ -378,10 +405,10 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock();
|
mysql_mutex_lock(&LOCK_slave_state);
|
||||||
if ((elem= get_element(gtid->domain_id)) == NULL)
|
if ((elem= get_element(gtid->domain_id)) == NULL)
|
||||||
{
|
{
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
err= 1;
|
err= 1;
|
||||||
goto end;
|
goto end;
|
||||||
@ -410,7 +437,7 @@ rpl_slave_state::record_gtid(THD *thd, const rpl_gtid *gtid, uint64 sub_id,
|
|||||||
cur->next= NULL;
|
cur->next= NULL;
|
||||||
elem->list= cur;
|
elem->list= cur;
|
||||||
}
|
}
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
|
|
||||||
if (!elist)
|
if (!elist)
|
||||||
goto end;
|
goto end;
|
||||||
@ -470,9 +497,9 @@ end:
|
|||||||
*/
|
*/
|
||||||
if (elist)
|
if (elist)
|
||||||
{
|
{
|
||||||
lock();
|
mysql_mutex_lock(&LOCK_slave_state);
|
||||||
put_back_list(gtid->domain_id, elist);
|
put_back_list(gtid->domain_id, elist);
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
ha_rollback_trans(thd, FALSE);
|
ha_rollback_trans(thd, FALSE);
|
||||||
@ -499,9 +526,9 @@ rpl_slave_state::next_sub_id(uint32 domain_id)
|
|||||||
{
|
{
|
||||||
uint64 sub_id= 0;
|
uint64 sub_id= 0;
|
||||||
|
|
||||||
lock();
|
mysql_mutex_lock(&LOCK_slave_state);
|
||||||
sub_id= ++last_sub_id;
|
sub_id= ++last_sub_id;
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
|
|
||||||
return sub_id;
|
return sub_id;
|
||||||
}
|
}
|
||||||
@ -541,7 +568,7 @@ rpl_slave_state::iterate(int (*cb)(rpl_gtid *, void *), void *data,
|
|||||||
my_hash_insert(>id_hash, (uchar *)(&extra_gtids[i])))
|
my_hash_insert(>id_hash, (uchar *)(&extra_gtids[i])))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
lock();
|
mysql_mutex_lock(&LOCK_slave_state);
|
||||||
|
|
||||||
for (i= 0; i < hash.records; ++i)
|
for (i= 0; i < hash.records; ++i)
|
||||||
{
|
{
|
||||||
@ -576,19 +603,19 @@ rpl_slave_state::iterate(int (*cb)(rpl_gtid *, void *), void *data,
|
|||||||
memcpy(&best_gtid, gtid, sizeof(best_gtid));
|
memcpy(&best_gtid, gtid, sizeof(best_gtid));
|
||||||
if (my_hash_delete(>id_hash, rec))
|
if (my_hash_delete(>id_hash, rec))
|
||||||
{
|
{
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res= (*cb)(&best_gtid, data)))
|
if ((res= (*cb)(&best_gtid, data)))
|
||||||
{
|
{
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
|
|
||||||
/* Also add any remaining extra domain_ids. */
|
/* Also add any remaining extra domain_ids. */
|
||||||
for (i= 0; i < gtid_hash.records; ++i)
|
for (i= 0; i < gtid_hash.records; ++i)
|
||||||
@ -659,11 +686,11 @@ rpl_slave_state::domain_to_gtid(uint32 domain_id, rpl_gtid *out_gtid)
|
|||||||
list_element *list;
|
list_element *list;
|
||||||
uint64 best_sub_id;
|
uint64 best_sub_id;
|
||||||
|
|
||||||
lock();
|
mysql_mutex_lock(&LOCK_slave_state);
|
||||||
elem= (element *)my_hash_search(&hash, (const uchar *)&domain_id, 0);
|
elem= (element *)my_hash_search(&hash, (const uchar *)&domain_id, 0);
|
||||||
if (!elem || !(list= elem->list))
|
if (!elem || !(list= elem->list))
|
||||||
{
|
{
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,7 +708,7 @@ rpl_slave_state::domain_to_gtid(uint32 domain_id, rpl_gtid *out_gtid)
|
|||||||
out_gtid->seq_no= list->seq_no;
|
out_gtid->seq_no= list->seq_no;
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -811,7 +838,7 @@ rpl_slave_state::is_empty()
|
|||||||
uint32 i;
|
uint32 i;
|
||||||
bool result= true;
|
bool result= true;
|
||||||
|
|
||||||
lock();
|
mysql_mutex_lock(&LOCK_slave_state);
|
||||||
for (i= 0; i < hash.records; ++i)
|
for (i= 0; i < hash.records; ++i)
|
||||||
{
|
{
|
||||||
element *e= (element *)my_hash_element(&hash, i);
|
element *e= (element *)my_hash_element(&hash, i);
|
||||||
@ -821,7 +848,7 @@ rpl_slave_state::is_empty()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
unlock();
|
mysql_mutex_unlock(&LOCK_slave_state);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -1647,3 +1674,445 @@ slave_connection_state::get_gtid_list(rpl_gtid *gtid_list, uint32 list_size)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Execute a MASTER_GTID_WAIT().
|
||||||
|
The position to wait for is in gtid_str in string form.
|
||||||
|
The timeout in microseconds is in timeout_us, zero means no timeout.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
1 for error.
|
||||||
|
0 for wait completed.
|
||||||
|
-1 for wait timed out.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
gtid_waiting::wait_for_pos(THD *thd, String *gtid_str, longlong timeout_us)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
rpl_gtid *wait_pos;
|
||||||
|
uint32 count, i;
|
||||||
|
struct timespec wait_until, *wait_until_ptr;
|
||||||
|
|
||||||
|
/* Wait for the empty position returns immediately. */
|
||||||
|
if (gtid_str->length() == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!(wait_pos= gtid_parse_string_to_list(gtid_str->ptr(), gtid_str->length(),
|
||||||
|
&count)))
|
||||||
|
{
|
||||||
|
my_error(ER_INCORRECT_GTID_STATE, MYF(0));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (timeout_us >= 0)
|
||||||
|
{
|
||||||
|
set_timespec_nsec(wait_until, (ulonglong)1000*timeout_us);
|
||||||
|
wait_until_ptr= &wait_until;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
wait_until_ptr= NULL;
|
||||||
|
err= 0;
|
||||||
|
for (i= 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
if ((err= wait_for_gtid(thd, &wait_pos[i], wait_until_ptr)))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
my_free(wait_pos);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
gtid_waiting::promote_new_waiter(gtid_waiting::hash_element *he)
|
||||||
|
{
|
||||||
|
queue_element *qe;
|
||||||
|
|
||||||
|
mysql_mutex_assert_owner(&LOCK_gtid_waiting);
|
||||||
|
if (queue_empty(&he->queue))
|
||||||
|
return;
|
||||||
|
qe= (queue_element *)queue_top(&he->queue);
|
||||||
|
qe->do_small_wait= true;
|
||||||
|
mysql_cond_signal(&qe->thd->COND_wakeup_ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtid_waiting::process_wait_hash(uint64 wakeup_seq_no,
|
||||||
|
gtid_waiting::hash_element *he)
|
||||||
|
{
|
||||||
|
mysql_mutex_assert_owner(&LOCK_gtid_waiting);
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
queue_element *qe;
|
||||||
|
|
||||||
|
if (queue_empty(&he->queue))
|
||||||
|
break;
|
||||||
|
qe= (queue_element *)queue_top(&he->queue);
|
||||||
|
if (qe->wait_seq_no > wakeup_seq_no)
|
||||||
|
break;
|
||||||
|
DBUG_ASSERT(!qe->done);
|
||||||
|
queue_remove_top(&he->queue);
|
||||||
|
qe->done= true;;
|
||||||
|
mysql_cond_signal(&qe->thd->COND_wakeup_ready);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Execute a MASTER_GTID_WAIT() for one specific domain.
|
||||||
|
|
||||||
|
The implementation is optimised primarily for (1) minimal performance impact
|
||||||
|
on the slave replication threads, and secondarily for (2) quick performance
|
||||||
|
of MASTER_GTID_WAIT() on a single GTID, which can be useful for consistent
|
||||||
|
read to clients in an async replication read-scaleout scenario.
|
||||||
|
|
||||||
|
To achieve (1), we have a "small" wait and a "large" wait. The small wait
|
||||||
|
contends with the replication threads on the lock on the gtid_slave_pos, so
|
||||||
|
only minimal processing is done under that lock, and only a single waiter at
|
||||||
|
a time does the small wait.
|
||||||
|
|
||||||
|
If there is already a small waiter, a new thread will either replace the
|
||||||
|
small waiter (if it needs to wait for an earlier sequence number), or
|
||||||
|
instead do a "large" wait.
|
||||||
|
|
||||||
|
Once awoken on the small wait, the waiting thread releases the lock shared
|
||||||
|
with the SQL threads quickly, and then processes all waiters currently doing
|
||||||
|
the large wait using a different lock that does not impact replication.
|
||||||
|
|
||||||
|
This way, the SQL threads only need to do a single check + possibly a
|
||||||
|
pthread_cond_signal() when updating the gtid_slave_state, and the time that
|
||||||
|
non-SQL threads contend for the lock on gtid_slave_state is minimized.
|
||||||
|
|
||||||
|
There is always at least one thread that has the responsibility to ensure
|
||||||
|
that there is a small waiter; this thread has queue_element::do_small_wait
|
||||||
|
set to true. This thread will do the small wait until it is done, at which
|
||||||
|
point it will make sure to pass on the responsibility to another thread.
|
||||||
|
Normally only one thread has do_small_wait==true, but it can occasionally
|
||||||
|
happen that there is more than one, when threads race one another for the
|
||||||
|
lock on the small wait (this results in slightly increased activity on the
|
||||||
|
small lock but is otherwise harmless).
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
0 Wait completed normally
|
||||||
|
-1 Wait completed due to timeout
|
||||||
|
1 An error (my_error() will have been called to set the error in the da)
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
gtid_waiting::wait_for_gtid(THD *thd, rpl_gtid *wait_gtid,
|
||||||
|
struct timespec *wait_until)
|
||||||
|
{
|
||||||
|
bool timed_out= false;
|
||||||
|
#ifdef HAVE_REPLICATION
|
||||||
|
queue_element elem;
|
||||||
|
uint32 domain_id= wait_gtid->domain_id;
|
||||||
|
uint64 seq_no= wait_gtid->seq_no;
|
||||||
|
hash_element *he;
|
||||||
|
rpl_slave_state::element *slave_state_elem= NULL;
|
||||||
|
const char *old_msg= NULL;
|
||||||
|
bool did_enter_cond= false;
|
||||||
|
|
||||||
|
elem.wait_seq_no= seq_no;
|
||||||
|
elem.thd= thd;
|
||||||
|
elem.done= false;
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_gtid_waiting);
|
||||||
|
if (!(he= get_entry(wait_gtid->domain_id)))
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_gtid_waiting);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
If there is already another waiter with seq_no no larger than our own,
|
||||||
|
we are sure that there is already a small waiter that will wake us up
|
||||||
|
(or later pass the small wait responsibility to us). So in this case, we
|
||||||
|
do not need to touch the small wait lock at all.
|
||||||
|
*/
|
||||||
|
elem.do_small_wait=
|
||||||
|
(queue_empty(&he->queue) ||
|
||||||
|
((queue_element *)queue_top(&he->queue))->wait_seq_no > seq_no);
|
||||||
|
|
||||||
|
if (register_in_wait_queue(thd, wait_gtid, he, &elem))
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&LOCK_gtid_waiting);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Loop, doing either the small or large wait as appropriate, until either
|
||||||
|
the position waited for is reached, or we get a kill or timeout.
|
||||||
|
*/
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
mysql_mutex_assert_owner(&LOCK_gtid_waiting);
|
||||||
|
|
||||||
|
if (elem.do_small_wait)
|
||||||
|
{
|
||||||
|
uint64 wakeup_seq_no;
|
||||||
|
queue_element *cur_waiter;
|
||||||
|
|
||||||
|
mysql_mutex_lock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
|
/*
|
||||||
|
The elements in the gtid_slave_state_hash are never re-allocated once
|
||||||
|
they enter the hash, so we do not need to re-do the lookup after releasing
|
||||||
|
and re-aquiring the lock.
|
||||||
|
*/
|
||||||
|
if (!slave_state_elem &&
|
||||||
|
!(slave_state_elem= rpl_global_gtid_slave_state.get_element(domain_id)))
|
||||||
|
{
|
||||||
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
|
remove_from_wait_queue(he, &elem);
|
||||||
|
promote_new_waiter(he);
|
||||||
|
if (did_enter_cond)
|
||||||
|
thd->exit_cond(old_msg);
|
||||||
|
else
|
||||||
|
mysql_mutex_unlock(&LOCK_gtid_waiting);
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((wakeup_seq_no= slave_state_elem->highest_seq_no) >= seq_no)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We do not have to wait. (We will be removed from the wait queue when
|
||||||
|
we call process_wait_hash() below.
|
||||||
|
*/
|
||||||
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
|
}
|
||||||
|
else if ((cur_waiter= slave_state_elem->gtid_waiter) &&
|
||||||
|
slave_state_elem->min_wait_seq_no <= seq_no)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
There is already a suitable small waiter, go do the large wait.
|
||||||
|
(Normally we would not have needed to check the small wait in this
|
||||||
|
case, but it can happen if we race with another thread for the small
|
||||||
|
lock).
|
||||||
|
*/
|
||||||
|
elem.do_small_wait= false;
|
||||||
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We have to do the small wait ourselves (stealing it from any thread
|
||||||
|
that might already be waiting for a later seq_no).
|
||||||
|
*/
|
||||||
|
slave_state_elem->gtid_waiter= &elem;
|
||||||
|
slave_state_elem->min_wait_seq_no= seq_no;
|
||||||
|
if (cur_waiter)
|
||||||
|
{
|
||||||
|
/* We stole the wait, so wake up the old waiting thread. */
|
||||||
|
mysql_cond_signal(&slave_state_elem->COND_wait_gtid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Release the large lock, and do the small wait. */
|
||||||
|
if (did_enter_cond)
|
||||||
|
{
|
||||||
|
thd->exit_cond(old_msg);
|
||||||
|
did_enter_cond= false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mysql_mutex_unlock(&LOCK_gtid_waiting);
|
||||||
|
old_msg=
|
||||||
|
thd->enter_cond(&slave_state_elem->COND_wait_gtid,
|
||||||
|
&rpl_global_gtid_slave_state.LOCK_slave_state,
|
||||||
|
"Waiting in MASTER_GTID_WAIT() (primary waiter)");
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (thd->check_killed())
|
||||||
|
break;
|
||||||
|
else if (wait_until)
|
||||||
|
{
|
||||||
|
int err=
|
||||||
|
mysql_cond_timedwait(&slave_state_elem->COND_wait_gtid,
|
||||||
|
&rpl_global_gtid_slave_state.LOCK_slave_state,
|
||||||
|
wait_until);
|
||||||
|
if (err == ETIMEDOUT || err == ETIME)
|
||||||
|
{
|
||||||
|
timed_out= true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mysql_cond_wait(&slave_state_elem->COND_wait_gtid,
|
||||||
|
&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
|
} while (slave_state_elem->gtid_waiter == &elem);
|
||||||
|
wakeup_seq_no= slave_state_elem->highest_seq_no;
|
||||||
|
/*
|
||||||
|
If we aborted due to timeout or kill, remove us as waiter.
|
||||||
|
|
||||||
|
If we were replaced by another waiter with a smaller seq_no, then we
|
||||||
|
no longer have responsibility for the small wait.
|
||||||
|
*/
|
||||||
|
if ((cur_waiter= slave_state_elem->gtid_waiter))
|
||||||
|
{
|
||||||
|
if (cur_waiter == &elem)
|
||||||
|
slave_state_elem->gtid_waiter= NULL;
|
||||||
|
else if (slave_state_elem->min_wait_seq_no <= seq_no)
|
||||||
|
elem.do_small_wait= false;
|
||||||
|
}
|
||||||
|
thd->exit_cond(old_msg);
|
||||||
|
|
||||||
|
mysql_mutex_lock(&LOCK_gtid_waiting);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Note that hash_entry pointers do not change once allocated, so we do
|
||||||
|
not need to lookup `he' again after re-aquiring LOCK_gtid_waiting.
|
||||||
|
*/
|
||||||
|
process_wait_hash(wakeup_seq_no, he);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Do the large wait. */
|
||||||
|
if (!did_enter_cond)
|
||||||
|
{
|
||||||
|
old_msg= thd->enter_cond(&thd->COND_wakeup_ready, &LOCK_gtid_waiting,
|
||||||
|
"Waiting in MASTER_GTID_WAIT()");
|
||||||
|
did_enter_cond= true;
|
||||||
|
}
|
||||||
|
while (!elem.done && !thd->check_killed())
|
||||||
|
{
|
||||||
|
thd_wait_begin(thd, THD_WAIT_BINLOG);
|
||||||
|
if (wait_until)
|
||||||
|
{
|
||||||
|
int err= mysql_cond_timedwait(&thd->COND_wakeup_ready,
|
||||||
|
&LOCK_gtid_waiting, wait_until);
|
||||||
|
if (err == ETIMEDOUT || err == ETIME)
|
||||||
|
timed_out= true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mysql_cond_wait(&thd->COND_wakeup_ready, &LOCK_gtid_waiting);
|
||||||
|
thd_wait_end(thd);
|
||||||
|
if (elem.do_small_wait || timed_out)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((thd->killed || timed_out) && !elem.done)
|
||||||
|
{
|
||||||
|
/* Aborted, so remove ourselves from the hash. */
|
||||||
|
remove_from_wait_queue(he, &elem);
|
||||||
|
elem.done= true;
|
||||||
|
}
|
||||||
|
if (elem.done)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
If our wait is done, but we have (or were passed) responsibility for
|
||||||
|
the small wait, then we need to pass on that task to someone else.
|
||||||
|
*/
|
||||||
|
if (elem.do_small_wait)
|
||||||
|
promote_new_waiter(he);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (did_enter_cond)
|
||||||
|
thd->exit_cond(old_msg);
|
||||||
|
else
|
||||||
|
mysql_mutex_unlock(&LOCK_gtid_waiting);
|
||||||
|
if (thd->killed)
|
||||||
|
thd->send_kill_message();
|
||||||
|
#endif /* HAVE_REPLICATION */
|
||||||
|
return timed_out ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
free_hash_element(void *p)
|
||||||
|
{
|
||||||
|
gtid_waiting::hash_element *e= (gtid_waiting::hash_element *)p;
|
||||||
|
delete_queue(&e->queue);
|
||||||
|
my_free(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
gtid_waiting::init()
|
||||||
|
{
|
||||||
|
my_hash_init(&hash, &my_charset_bin, 32,
|
||||||
|
offsetof(hash_element, domain_id), sizeof(uint32), NULL,
|
||||||
|
free_hash_element, HASH_UNIQUE);
|
||||||
|
mysql_mutex_init(key_LOCK_gtid_waiting, &LOCK_gtid_waiting, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
gtid_waiting::destroy()
|
||||||
|
{
|
||||||
|
mysql_mutex_destroy(&LOCK_gtid_waiting);
|
||||||
|
my_hash_free(&hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
cmp_queue_elem(void *, uchar *a, uchar *b)
|
||||||
|
{
|
||||||
|
uint64 seq_no_a= *(uint64 *)a;
|
||||||
|
uint64 seq_no_b= *(uint64 *)b;
|
||||||
|
if (seq_no_a < seq_no_b)
|
||||||
|
return -1;
|
||||||
|
else if (seq_no_a == seq_no_b)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gtid_waiting::hash_element *
|
||||||
|
gtid_waiting::get_entry(uint32 domain_id)
|
||||||
|
{
|
||||||
|
hash_element *e;
|
||||||
|
|
||||||
|
if ((e= (hash_element *)my_hash_search(&hash, (const uchar *)&domain_id, 0)))
|
||||||
|
return e;
|
||||||
|
|
||||||
|
if (!(e= (hash_element *)my_malloc(sizeof(*e), MYF(MY_WME))))
|
||||||
|
{
|
||||||
|
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(*e));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (init_queue(&e->queue, 8, offsetof(queue_element, wait_seq_no), 0,
|
||||||
|
cmp_queue_elem, NULL, 1+offsetof(queue_element, queue_idx), 1))
|
||||||
|
{
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
|
my_free(e);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
e->domain_id= domain_id;
|
||||||
|
if (my_hash_insert(&hash, (uchar *)e))
|
||||||
|
{
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
|
delete_queue(&e->queue);
|
||||||
|
my_free(e);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
gtid_waiting::register_in_wait_queue(THD *thd, rpl_gtid *wait_gtid,
|
||||||
|
gtid_waiting::hash_element *he,
|
||||||
|
gtid_waiting::queue_element *elem)
|
||||||
|
{
|
||||||
|
mysql_mutex_assert_owner(&LOCK_gtid_waiting);
|
||||||
|
|
||||||
|
if (queue_insert_safe(&he->queue, (uchar *)elem))
|
||||||
|
{
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
gtid_waiting::remove_from_wait_queue(gtid_waiting::hash_element *he,
|
||||||
|
gtid_waiting::queue_element *elem)
|
||||||
|
{
|
||||||
|
mysql_mutex_assert_owner(&LOCK_gtid_waiting);
|
||||||
|
|
||||||
|
queue_remove(&he->queue, elem->queue_idx);
|
||||||
|
}
|
||||||
|
@ -16,6 +16,10 @@
|
|||||||
#ifndef RPL_GTID_H
|
#ifndef RPL_GTID_H
|
||||||
#define RPL_GTID_H
|
#define RPL_GTID_H
|
||||||
|
|
||||||
|
#include "hash.h"
|
||||||
|
#include "queues.h"
|
||||||
|
|
||||||
|
|
||||||
/* Definitions for MariaDB global transaction ID (GTID). */
|
/* Definitions for MariaDB global transaction ID (GTID). */
|
||||||
|
|
||||||
|
|
||||||
@ -36,6 +40,57 @@ enum enum_gtid_skip_type {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Structure to keep track of threads waiting in MASTER_GTID_WAIT().
|
||||||
|
|
||||||
|
Since replication is (mostly) single-threaded, we want to minimise the
|
||||||
|
performance impact on that from MASTER_GTID_WAIT(). To achieve this, we
|
||||||
|
are careful to keep the common lock between replication threads and
|
||||||
|
MASTER_GTID_WAIT threads held for as short as possible. We keep only
|
||||||
|
a single thread waiting to be notified by the replication threads; this
|
||||||
|
thread then handles all the (potentially heavy) lifting of dealing with
|
||||||
|
all current waiting threads.
|
||||||
|
*/
|
||||||
|
struct gtid_waiting {
|
||||||
|
/* Elements in the hash, basically a priority queue for each domain. */
|
||||||
|
struct hash_element {
|
||||||
|
QUEUE queue;
|
||||||
|
uint32 domain_id;
|
||||||
|
};
|
||||||
|
/* A priority queue to handle waiters in one domain in seq_no order. */
|
||||||
|
struct queue_element {
|
||||||
|
uint64 wait_seq_no;
|
||||||
|
THD *thd;
|
||||||
|
int queue_idx;
|
||||||
|
/*
|
||||||
|
do_small_wait is true if we have responsibility for ensuring that there
|
||||||
|
is a small waiter.
|
||||||
|
*/
|
||||||
|
bool do_small_wait;
|
||||||
|
/*
|
||||||
|
The flag `done' is set when the wait is completed (either due to reaching
|
||||||
|
the position waited for, or due to timeout or kill). The queue_element
|
||||||
|
is in the queue if and only if `done' is true.
|
||||||
|
*/
|
||||||
|
bool done;
|
||||||
|
};
|
||||||
|
|
||||||
|
mysql_mutex_t LOCK_gtid_waiting;
|
||||||
|
HASH hash;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void destroy();
|
||||||
|
hash_element *get_entry(uint32 domain_id);
|
||||||
|
int wait_for_pos(THD *thd, String *gtid_str, longlong timeout_us);
|
||||||
|
void promote_new_waiter(gtid_waiting::hash_element *he);
|
||||||
|
int wait_for_gtid(THD *thd, rpl_gtid *wait_gtid, struct timespec *wait_until);
|
||||||
|
void process_wait_hash(uint64 wakeup_seq_no, gtid_waiting::hash_element *he);
|
||||||
|
int register_in_wait_queue(THD *thd, rpl_gtid *wait_gtid, hash_element *he,
|
||||||
|
queue_element *elem);
|
||||||
|
void remove_from_wait_queue(hash_element *he, queue_element *elem);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Replication slave state.
|
Replication slave state.
|
||||||
|
|
||||||
@ -61,6 +116,20 @@ struct rpl_slave_state
|
|||||||
{
|
{
|
||||||
struct list_element *list;
|
struct list_element *list;
|
||||||
uint32 domain_id;
|
uint32 domain_id;
|
||||||
|
/* Highest seq_no seen so far in this domain. */
|
||||||
|
uint64 highest_seq_no;
|
||||||
|
/*
|
||||||
|
If this is non-NULL, then it is the waiter responsible for the small
|
||||||
|
wait in MASTER_GTID_WAIT().
|
||||||
|
*/
|
||||||
|
gtid_waiting::queue_element *gtid_waiter;
|
||||||
|
/*
|
||||||
|
If gtid_waiter is non-NULL, then this is the seq_no that its
|
||||||
|
MASTER_GTID_WAIT() is waiting on. When we reach this seq_no, we need to
|
||||||
|
signal the waiter on COND_wait_gtid.
|
||||||
|
*/
|
||||||
|
uint64 min_wait_seq_no;
|
||||||
|
mysql_cond_t COND_wait_gtid;
|
||||||
|
|
||||||
list_element *grab_list() { list_element *l= list; list= NULL; return l; }
|
list_element *grab_list() { list_element *l= list; list= NULL; return l; }
|
||||||
void add(list_element *l)
|
void add(list_element *l)
|
||||||
@ -99,9 +168,6 @@ struct rpl_slave_state
|
|||||||
bool in_statement);
|
bool in_statement);
|
||||||
bool is_empty();
|
bool is_empty();
|
||||||
|
|
||||||
void lock() { DBUG_ASSERT(inited); mysql_mutex_lock(&LOCK_slave_state); }
|
|
||||||
void unlock() { DBUG_ASSERT(inited); mysql_mutex_unlock(&LOCK_slave_state); }
|
|
||||||
|
|
||||||
element *get_element(uint32 domain_id);
|
element *get_element(uint32 domain_id);
|
||||||
int put_back_list(uint32 domain_id, list_element *list);
|
int put_back_list(uint32 domain_id, list_element *list);
|
||||||
|
|
||||||
@ -204,6 +270,7 @@ struct slave_connection_state
|
|||||||
int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size);
|
int get_gtid_list(rpl_gtid *gtid_list, uint32 list_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern bool rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid,
|
extern bool rpl_slave_state_tostring_helper(String *dest, const rpl_gtid *gtid,
|
||||||
bool *first);
|
bool *first);
|
||||||
extern int gtid_check_rpl_slave_state_table(TABLE *table);
|
extern int gtid_check_rpl_slave_state_table(TABLE *table);
|
||||||
|
@ -37,6 +37,8 @@ static int count_relay_log_space(Relay_log_info* rli);
|
|||||||
domain).
|
domain).
|
||||||
*/
|
*/
|
||||||
rpl_slave_state rpl_global_gtid_slave_state;
|
rpl_slave_state rpl_global_gtid_slave_state;
|
||||||
|
/* Object used for MASTER_GTID_WAIT(). */
|
||||||
|
gtid_waiting rpl_global_gtid_waiting;
|
||||||
|
|
||||||
|
|
||||||
// Defined in slave.cc
|
// Defined in slave.cc
|
||||||
@ -1317,9 +1319,9 @@ rpl_load_gtid_slave_state(THD *thd)
|
|||||||
uint32 i;
|
uint32 i;
|
||||||
DBUG_ENTER("rpl_load_gtid_slave_state");
|
DBUG_ENTER("rpl_load_gtid_slave_state");
|
||||||
|
|
||||||
rpl_global_gtid_slave_state.lock();
|
mysql_mutex_lock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
bool loaded= rpl_global_gtid_slave_state.loaded;
|
bool loaded= rpl_global_gtid_slave_state.loaded;
|
||||||
rpl_global_gtid_slave_state.unlock();
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
if (loaded)
|
if (loaded)
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
@ -1419,10 +1421,10 @@ rpl_load_gtid_slave_state(THD *thd)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl_global_gtid_slave_state.lock();
|
mysql_mutex_lock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
if (rpl_global_gtid_slave_state.loaded)
|
if (rpl_global_gtid_slave_state.loaded)
|
||||||
{
|
{
|
||||||
rpl_global_gtid_slave_state.unlock();
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1434,7 +1436,7 @@ rpl_load_gtid_slave_state(THD *thd)
|
|||||||
tmp_entry.sub_id,
|
tmp_entry.sub_id,
|
||||||
tmp_entry.gtid.seq_no)))
|
tmp_entry.gtid.seq_no)))
|
||||||
{
|
{
|
||||||
rpl_global_gtid_slave_state.unlock();
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -1447,14 +1449,14 @@ rpl_load_gtid_slave_state(THD *thd)
|
|||||||
mysql_bin_log.bump_seq_no_counter_if_needed(entry->gtid.domain_id,
|
mysql_bin_log.bump_seq_no_counter_if_needed(entry->gtid.domain_id,
|
||||||
entry->gtid.seq_no))
|
entry->gtid.seq_no))
|
||||||
{
|
{
|
||||||
rpl_global_gtid_slave_state.unlock();
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rpl_global_gtid_slave_state.loaded= true;
|
rpl_global_gtid_slave_state.loaded= true;
|
||||||
rpl_global_gtid_slave_state.unlock();
|
mysql_mutex_unlock(&rpl_global_gtid_slave_state.LOCK_slave_state);
|
||||||
|
|
||||||
err= 0; /* Clear HA_ERR_END_OF_FILE */
|
err= 0; /* Clear HA_ERR_END_OF_FILE */
|
||||||
|
|
||||||
|
@ -708,6 +708,7 @@ int init_relay_log_info(Relay_log_info* rli, const char* info_fname);
|
|||||||
|
|
||||||
|
|
||||||
extern struct rpl_slave_state rpl_global_gtid_slave_state;
|
extern struct rpl_slave_state rpl_global_gtid_slave_state;
|
||||||
|
extern gtid_waiting rpl_global_gtid_waiting;
|
||||||
|
|
||||||
int rpl_load_gtid_slave_state(THD *thd);
|
int rpl_load_gtid_slave_state(THD *thd);
|
||||||
int event_group_new_gtid(rpl_group_info *rgi, Gtid_log_event *gev);
|
int event_group_new_gtid(rpl_group_info *rgi, Gtid_log_event *gev);
|
||||||
|
@ -6524,7 +6524,7 @@ ER_UNTIL_REQUIRES_USING_GTID
|
|||||||
ER_GTID_STRICT_OUT_OF_ORDER
|
ER_GTID_STRICT_OUT_OF_ORDER
|
||||||
eng "An attempt was made to binlog GTID %u-%u-%llu which would create an out-of-order sequence number with existing GTID %u-%u-%llu, and gtid strict mode is enabled."
|
eng "An attempt was made to binlog GTID %u-%u-%llu which would create an out-of-order sequence number with existing GTID %u-%u-%llu, and gtid strict mode is enabled."
|
||||||
ER_GTID_START_FROM_BINLOG_HOLE
|
ER_GTID_START_FROM_BINLOG_HOLE
|
||||||
eng "The binlog on the master is missing the GTID %u-%u-%llu requested by the slave (even though both a prior and a subsequent sequence number does exist), and GTID strict mode is enabled"
|
eng "The binlog on the master is missing the GTID %u-%u-%llu requested by the slave (even though a subsequent sequence number does exist), and GTID strict mode is enabled"
|
||||||
ER_SLAVE_UNEXPECTED_MASTER_SWITCH
|
ER_SLAVE_UNEXPECTED_MASTER_SWITCH
|
||||||
eng "Unexpected GTID received from master after reconnect. This normally indicates that the master server was replaced without restarting the slave threads. %s"
|
eng "Unexpected GTID received from master after reconnect. This normally indicates that the master server was replaced without restarting the slave threads. %s"
|
||||||
ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
|
ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_GTID_DOMAIN_ID_SEQ_NO
|
||||||
|
@ -1267,6 +1267,7 @@ void THD::init(void)
|
|||||||
set_status_var_init();
|
set_status_var_init();
|
||||||
bzero((char *) &org_status_var, sizeof(org_status_var));
|
bzero((char *) &org_status_var, sizeof(org_status_var));
|
||||||
start_bytes_received= 0;
|
start_bytes_received= 0;
|
||||||
|
last_commit_gtid.seq_no= 0;
|
||||||
|
|
||||||
if (variables.sql_log_bin)
|
if (variables.sql_log_bin)
|
||||||
variables.option_bits|= OPTION_BIN_LOG;
|
variables.option_bits|= OPTION_BIN_LOG;
|
||||||
|
@ -44,6 +44,7 @@
|
|||||||
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA,
|
#include "thr_lock.h" /* thr_lock_type, THR_LOCK_DATA,
|
||||||
THR_LOCK_INFO */
|
THR_LOCK_INFO */
|
||||||
#include "my_apc.h"
|
#include "my_apc.h"
|
||||||
|
#include "rpl_gtid.h"
|
||||||
|
|
||||||
class Reprepare_observer;
|
class Reprepare_observer;
|
||||||
class Relay_log_info;
|
class Relay_log_info;
|
||||||
@ -3410,6 +3411,12 @@ private:
|
|||||||
*/
|
*/
|
||||||
LEX_STRING invoker_user;
|
LEX_STRING invoker_user;
|
||||||
LEX_STRING invoker_host;
|
LEX_STRING invoker_host;
|
||||||
|
|
||||||
|
/* Protect against add/delete of temporary tables in parallel replication */
|
||||||
|
void rgi_lock_temporary_tables();
|
||||||
|
void rgi_unlock_temporary_tables();
|
||||||
|
bool rgi_have_temporary_tables();
|
||||||
|
public:
|
||||||
/*
|
/*
|
||||||
Flag, mutex and condition for a thread to wait for a signal from another
|
Flag, mutex and condition for a thread to wait for a signal from another
|
||||||
thread.
|
thread.
|
||||||
@ -3420,12 +3427,12 @@ private:
|
|||||||
bool wakeup_ready;
|
bool wakeup_ready;
|
||||||
mysql_mutex_t LOCK_wakeup_ready;
|
mysql_mutex_t LOCK_wakeup_ready;
|
||||||
mysql_cond_t COND_wakeup_ready;
|
mysql_cond_t COND_wakeup_ready;
|
||||||
|
/*
|
||||||
|
The GTID assigned to the last commit. If no GTID was assigned to any commit
|
||||||
|
so far, this is indicated by last_commit_gtid.seq_no == 0.
|
||||||
|
*/
|
||||||
|
rpl_gtid last_commit_gtid;
|
||||||
|
|
||||||
/* Protect against add/delete of temporary tables in parallel replication */
|
|
||||||
void rgi_lock_temporary_tables();
|
|
||||||
void rgi_unlock_temporary_tables();
|
|
||||||
bool rgi_have_temporary_tables();
|
|
||||||
public:
|
|
||||||
inline void lock_temporary_tables()
|
inline void lock_temporary_tables()
|
||||||
{
|
{
|
||||||
if (rgi_slave)
|
if (rgi_slave)
|
||||||
|
@ -3965,6 +3965,20 @@ rpl_deinit_gtid_slave_state()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rpl_init_gtid_waiting()
|
||||||
|
{
|
||||||
|
rpl_global_gtid_waiting.init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rpl_deinit_gtid_waiting()
|
||||||
|
{
|
||||||
|
rpl_global_gtid_waiting.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Format the current GTID state as a string, for returning the value of
|
Format the current GTID state as a string, for returning the value of
|
||||||
@@global.gtid_slave_pos.
|
@@global.gtid_slave_pos.
|
||||||
|
@ -70,6 +70,8 @@ void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
|
|||||||
extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state;
|
extern PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state;
|
||||||
void rpl_init_gtid_slave_state();
|
void rpl_init_gtid_slave_state();
|
||||||
void rpl_deinit_gtid_slave_state();
|
void rpl_deinit_gtid_slave_state();
|
||||||
|
void rpl_init_gtid_waiting();
|
||||||
|
void rpl_deinit_gtid_waiting();
|
||||||
int gtid_state_from_binlog_pos(const char *name, uint32 pos, String *out_str);
|
int gtid_state_from_binlog_pos(const char *name, uint32 pos, String *out_str);
|
||||||
int rpl_append_gtid_state(String *dest, bool use_binlog);
|
int rpl_append_gtid_state(String *dest, bool use_binlog);
|
||||||
int rpl_load_gtid_state(slave_connection_state *state, bool use_binlog);
|
int rpl_load_gtid_state(slave_connection_state *state, bool use_binlog);
|
||||||
|
@ -1538,6 +1538,33 @@ static Sys_var_gtid_binlog_state Sys_gtid_binlog_state(
|
|||||||
GLOBAL_VAR(opt_gtid_binlog_state_dummy), NO_CMD_LINE);
|
GLOBAL_VAR(opt_gtid_binlog_state_dummy), NO_CMD_LINE);
|
||||||
|
|
||||||
|
|
||||||
|
static Sys_var_last_gtid Sys_last_gtid(
|
||||||
|
"last_gtid", "The GTID of the last commit (if binlogging was enabled), "
|
||||||
|
"or the empty string if none.",
|
||||||
|
READ_ONLY sys_var::ONLY_SESSION, NO_CMD_LINE);
|
||||||
|
|
||||||
|
|
||||||
|
uchar *
|
||||||
|
Sys_var_last_gtid::session_value_ptr(THD *thd, LEX_STRING *base)
|
||||||
|
{
|
||||||
|
char buf[10+1+10+1+20+1];
|
||||||
|
String str(buf, sizeof(buf), system_charset_info);
|
||||||
|
char *p;
|
||||||
|
bool first= true;
|
||||||
|
|
||||||
|
str.length(0);
|
||||||
|
if ((thd->last_commit_gtid.seq_no > 0 &&
|
||||||
|
rpl_slave_state_tostring_helper(&str, &thd->last_commit_gtid, &first)) ||
|
||||||
|
!(p= thd->strmake(str.ptr(), str.length())))
|
||||||
|
{
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uchar *)p;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_slave_parallel_threads(sys_var *self, THD *thd, set_var *var)
|
check_slave_parallel_threads(sys_var *self, THD *thd, set_var *var)
|
||||||
{
|
{
|
||||||
|
@ -2211,3 +2211,53 @@ public:
|
|||||||
}
|
}
|
||||||
uchar *global_value_ptr(THD *thd, LEX_STRING *base);
|
uchar *global_value_ptr(THD *thd, LEX_STRING *base);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Class for @@session.last_gtid.
|
||||||
|
*/
|
||||||
|
class Sys_var_last_gtid: public sys_var
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Sys_var_last_gtid(const char *name_arg,
|
||||||
|
const char *comment, int flag_args, CMD_LINE getopt)
|
||||||
|
: sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
|
||||||
|
getopt.arg_type, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
|
||||||
|
NULL, NULL, NULL)
|
||||||
|
{
|
||||||
|
option.var_type= GET_STR;
|
||||||
|
}
|
||||||
|
bool do_check(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool session_update(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool global_update(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool check_update_type(Item_result type) {
|
||||||
|
DBUG_ASSERT(false);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
void session_save_default(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(false);
|
||||||
|
}
|
||||||
|
void global_save_default(THD *thd, set_var *var)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(false);
|
||||||
|
}
|
||||||
|
uchar *session_value_ptr(THD *thd, LEX_STRING *base);
|
||||||
|
uchar *global_value_ptr(THD *thd, LEX_STRING *base)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(false);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user