Commit d039346a authored by Kristian Nielsen's avatar Kristian Nielsen

MDEV-4991: GTID binlog indexing

Improve the performance of slave connect using B+-Tree indexes on each binlog
file. The index allows fast lookup of a GTID position to the corresponding
offset in the binlog file, as well as lookup of a position to find the
corresponding GTID position.

This eliminates a costly sequential scan of the starting binlog file
to find the GTID starting position when a slave connects. This is
especially costly if the binlog file is not cached in memory (IO
cost), or if it is encrypted or a lot of slaves connect simultaneously
(CPU cost).

The size of the index files is generally less than 1% of the binlog data, so
not expected to be an issue.

Most of the work writing the index is done as a background task, in
the binlog background thread. This minimises the performance impact on
transaction commit. A simple global mutex is used to protect index
reads and (background) index writes; this is fine as slave connect is
a relatively infrequent operation.

Here are the user-visible options and status variables. The feature is on by
default and is expected to need no tuning or configuration for most users.

binlog_gtid_index
  On by default. Can be used to disable the indexes for testing purposes.

binlog_gtid_index_page_size (default 4096)
  Page size to use for the binlog GTID index. This is the size of the nodes
  in the B+-tree used internally in the index. A very small page-size (64 is
  the minimum) will be less efficient, but can be used to stress the
  BTree-code during testing.

binlog_gtid_index_span_min (default 65536)
  Control sparseness of the binlog GTID index. If set to N, at most one
  index record will be added for every N bytes of binlog file written.
  This can be used to reduce the number of records in the index, at
  the cost only of having to scan a few more events in the binlog file
  before finding the target position

Two status variables are available to monitor the use of the GTID indexes:

  Binlog_gtid_index_hit
  Binlog_gtid_index_miss

The "hit" status increments for each successful lookup in a GTID index.
The "miss" increments when a lookup is not possible. This indicates that the
index file is missing (eg. binlog written by old server version
without GTID index support), or corrupt.
Signed-off-by: default avatarKristian Nielsen <knielsen@knielsen-hq.org>
parent 20741b92
...@@ -126,7 +126,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc ...@@ -126,7 +126,7 @@ SET(SQL_EMBEDDED_SOURCES emb_qcache.cc libmysqld.c lib_sql.cc
../sql/sql_expression_cache.cc ../sql/sql_expression_cache.cc
../sql/my_apc.cc ../sql/my_apc.h ../sql/my_apc.cc ../sql/my_apc.h
../sql/my_json_writer.cc ../sql/my_json_writer.h ../sql/my_json_writer.cc ../sql/my_json_writer.h
../sql/rpl_gtid.cc ../sql/rpl_gtid.cc ../sql/gtid_index.cc
../sql/sql_explain.cc ../sql/sql_explain.h ../sql/sql_explain.cc ../sql/sql_explain.h
../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h ../sql/sql_analyze_stmt.cc ../sql/sql_analyze_stmt.h
../sql/compat56.cc ../sql/compat56.cc
......
...@@ -98,6 +98,17 @@ The following specify which files/extra groups are read (specified before remain ...@@ -98,6 +98,17 @@ The following specify which files/extra groups are read (specified before remain
involve user-defined functions (i.e. UDFs) or the UUID() involve user-defined functions (i.e. UDFs) or the UUID()
function; for those, row-based binary logging is function; for those, row-based binary logging is
automatically used. automatically used.
--binlog-gtid-index Enable the creation of a GTID index for every binlog
file, and the use of such index for speeding up GTID
lookup in the binlog.
(Defaults to on; use --skip-binlog-gtid-index to disable.)
--binlog-gtid-index-page-size=#
Page size to use for the binlog GTID index.
--binlog-gtid-index-span-min=#
Control sparseness of the binlog GTID index. If set to N,
at most one index record will be added for every N bytes
of binlog file written, to reduce the size of the index.
Normally does not need tuning.
--binlog-ignore-db=name --binlog-ignore-db=name
Tells the master that updates to the given database Tells the master that updates to the given database
should not be logged to the binary log. should not be logged to the binary log.
...@@ -1597,6 +1608,9 @@ binlog-direct-non-transactional-updates FALSE ...@@ -1597,6 +1608,9 @@ binlog-direct-non-transactional-updates FALSE
binlog-expire-logs-seconds 0 binlog-expire-logs-seconds 0
binlog-file-cache-size 16384 binlog-file-cache-size 16384
binlog-format MIXED binlog-format MIXED
binlog-gtid-index TRUE
binlog-gtid-index-page-size 4096
binlog-gtid-index-span-min 65536
binlog-legacy-event-pos FALSE binlog-legacy-event-pos FALSE
binlog-optimize-thread-scheduling TRUE binlog-optimize-thread-scheduling TRUE
binlog-row-event-max-size 8192 binlog-row-event-max-size 8192
......
SET GLOBAL binlog_gtid_index= 0;
SET GLOBAL binlog_gtid_index= 1;
SET @gtid1= @@gtid_binlog_pos;
CREATE TABLE t1 (a INT PRIMARY KEY);
SET @gtid2= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (1);
SET @gtid3= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4);
SET @gtid4= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (5);
SET @gtid5= @@gtid_binlog_pos;
SET @gtid6= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (106);
INSERT INTO t1 VALUES (107);
Ok
1
Ok
1
Ok
1
Ok
1
Ok
1
Ok
1
FLUSH BINARY LOGS;
Ok
1
Ok
1
Ok
1
Ok
1
Ok
1
Ok
1
*** Test that purge deletes the gtid index files. ***
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (200);
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (201);
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (202);
PURGE BINARY LOGS TO 'FILE';
*** Test missed index lookup due to missing or corrupt index file.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
INSERT INTO t1 VALUES (301);
INSERT INTO t1 VALUES (302);
INSERT INTO t1 VALUES (303);
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (304);
INSERT INTO t1 VALUES (305);
FLUSH NO_WRITE_TO_BINLOG STATUS;
+++ Initial status:
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 0
Binlog_gtid_index_miss 0
+++ GTID Lookup in good index.
Gtid_Lookup_Ok
1
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 1
Binlog_gtid_index_miss 0
+++ GTID Lookup, index file is missing.
Gtid_Lookup_Ok
1
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 1
Binlog_gtid_index_miss 1
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
INSERT INTO t1 VALUES (306);
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (307);
INSERT INTO t1 VALUES (308);
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
+++ GTID Lookup, first page of index is corrupt.
Gtid_Lookup_Ok
1
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 1
Binlog_gtid_index_miss 2
SET @old_page_size= @@GLOBAL.binlog_gtid_index_page_size;
SET @old_span_min= @@GLOBAL.binlog_gtid_index_span_min;
SET GLOBAL binlog_gtid_index_page_size= 64;
SET GLOBAL binlog_gtid_index_span_min= 1;
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
INSERT INTO t1 VALUES (310);
INSERT INTO t1 VALUES (311);
INSERT INTO t1 VALUES (312);
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (313);
INSERT INTO t1 VALUES (314);
INSERT INTO t1 VALUES (315);
INSERT INTO t1 VALUES (316);
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
SET GLOBAL binlog_gtid_index_page_size= @old_page_size;
SET GLOBAL binlog_gtid_index_span_min= @old_span_min;
+++ GTID Lookup, root page of index is corrupt.
Gtid_Lookup_Ok
1
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 1
Binlog_gtid_index_miss 3
*** Test BINLOG_GTID_POS() with too-large offset.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
INSERT INTO t1 VALUES (401);
INSERT INTO t1 VALUES (402);
+++ Test the hot index.
SELECT BINLOG_GTID_POS('FILE', 100000000);
BINLOG_GTID_POS('FILE', 100000000)
NULL
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 2
Binlog_gtid_index_miss 3
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
+++ Test the cold index.
SELECT BINLOG_GTID_POS('FILE', 100000000);
BINLOG_GTID_POS('FILE', 100000000)
NULL
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 3
Binlog_gtid_index_miss 3
DROP TABLE t1;
*** Test that binlog GTID index is recovered after a crash.
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
Ok
1
Ok
1
Ok
1
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 3
Binlog_gtid_index_miss 0
*** Crash the server, check that GTID index can be used after restart.
SET debug_dbug="d,crash_shutdown";
shutdown;
ERROR HY000: Lost connection to server during query
FLUSH NO_WRITE_TO_BINLOG STATUS;
Ok
1
Ok
1
Ok
1
SHOW STATUS LIKE 'binlog_gtid_index_%';
Variable_name Value
Binlog_gtid_index_hit 3
Binlog_gtid_index_miss 0
DROP TABLE t1;
--source include/have_binlog_format_mixed.inc
SET GLOBAL binlog_gtid_index= 0;
SET GLOBAL binlog_gtid_index= 1;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
--let $pos1= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid1= @@gtid_binlog_pos;
CREATE TABLE t1 (a INT PRIMARY KEY);
--let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid2= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (1);
--let $pos3= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid3= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (2);
INSERT INTO t1 VALUES (3);
INSERT INTO t1 VALUES (4);
--let $pos4= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid4= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (5);
--let $pos5= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid5= @@gtid_binlog_pos;
--disable_query_log
--let $i=0
while ($i < 100) {
eval INSERT INTO t1 VALUES (6 + $i);
inc $i;
}
--enable_query_log
--let $pos6= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid6= @@gtid_binlog_pos;
INSERT INTO t1 VALUES (106);
INSERT INTO t1 VALUES (107);
# Test first the hot and then the cold index.
--let $i= 0
while ($i < 2) {
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos1) = @gtid1 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos2) = @gtid2 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos3) = @gtid3 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos4) = @gtid4 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos5) = @gtid5 AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos6) = @gtid6 AS Ok;
--enable_query_log
inc $i;
if ($i == 1) {
FLUSH BINARY LOGS;
}
}
--echo *** Test that purge deletes the gtid index files. ***
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (200);
--let $file2= query_get_value(SHOW MASTER STATUS, File, 1)
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (201);
--let $file3= query_get_value(SHOW MASTER STATUS, File, 1)
FLUSH BINARY LOGS;
INSERT INTO t1 VALUES (202);
--let $file4= query_get_value(SHOW MASTER STATUS, File, 1)
--replace_result $file3 FILE
eval PURGE BINARY LOGS TO '$file3';
--let $MYSQLD_DATADIR= `select @@datadir`
--error 1
--file_exists $MYSQLD_DATADIR/$file.idx
--error 1
--file_exists $MYSQLD_DATADIR/$file2.idx
--file_exists $MYSQLD_DATADIR/$file3.idx
--file_exists $MYSQLD_DATADIR/$file4.idx
--echo *** Test missed index lookup due to missing or corrupt index file.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (301);
INSERT INTO t1 VALUES (302);
INSERT INTO t1 VALUES (303);
--let $pos= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (304);
INSERT INTO t1 VALUES (305);
# BINLOG_GTID_POS() has a side effect: it increments binlog_gtid_index_hit
--disable_ps2_protocol
FLUSH NO_WRITE_TO_BINLOG STATUS;
--echo +++ Initial status:
SHOW STATUS LIKE 'binlog_gtid_index_%';
--echo +++ GTID Lookup in good index.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
--remove_file $MYSQLD_DATADIR/$file.idx
--echo +++ GTID Lookup, index file is missing.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (306);
--let $pos= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (307);
INSERT INTO t1 VALUES (308);
# Rotate again so we hit an on-disk index file, not the "hot" index.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
# Corrupt the flag byte of the first page with an unused bit.
--let FILE_TO_CORRUPT= $MYSQLD_DATADIR/$file.idx
--perl
use strict;
use warnings;
use Fcntl qw(:DEFAULT :seek);
sysopen F, $ENV{FILE_TO_CORRUPT}, O_RDWR
or die "Cannot open file $ENV{FILE_TO_CORRUPT}: $!\n";
# Corrupt the flag byte with an unused flag.
sysseek(F, 16, SEEK_SET)
or die "Cannot seek file: $!\n";
my $buf;
sysread(F, $buf, 1)
or die "Cannot read file: $!\n";
$buf= chr(ord($buf) | 0x80);
sysseek(F, 16, SEEK_SET)
or die "Cannot seek file: $!\n";
syswrite(F, $buf, 1) == 1
or die "Cannot write file: $!\n";
close F;
EOF
--echo +++ GTID Lookup, first page of index is corrupt.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
# Corrupt the last byte of the root page.
# Set a small page-size so we test corruption in something not the header page.
SET @old_page_size= @@GLOBAL.binlog_gtid_index_page_size;
SET @old_span_min= @@GLOBAL.binlog_gtid_index_span_min;
SET GLOBAL binlog_gtid_index_page_size= 64;
SET GLOBAL binlog_gtid_index_span_min= 1;
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (310);
INSERT INTO t1 VALUES (311);
INSERT INTO t1 VALUES (312);
--let $pos= query_get_value(SHOW MASTER STATUS, Position, 1)
SET @gtid_pos= @@GLOBAL.gtid_binlog_pos;
INSERT INTO t1 VALUES (313);
INSERT INTO t1 VALUES (314);
INSERT INTO t1 VALUES (315);
INSERT INTO t1 VALUES (316);
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
SET GLOBAL binlog_gtid_index_page_size= @old_page_size;
SET GLOBAL binlog_gtid_index_span_min= @old_span_min;
--let FILE_TO_CORRUPT= $MYSQLD_DATADIR/$file.idx
--perl
use strict;
use warnings;
use Fcntl qw(:DEFAULT :seek);
sysopen F, $ENV{FILE_TO_CORRUPT}, O_RDWR
or die "Cannot open file $ENV{FILE_TO_CORRUPT}: $!\n";
# Tricky: The index is written asynchroneously, it may still be incomplete.
# So wait for the file to be written completely with a root node at the end.
my $count= 0;
for (;;) {
my $end= sysseek(F, 0, SEEK_END);
if ($end > 0 && ($end % 64) == 0) {
# The index file is non-empty with a full page at the end, test if the
# root page has been fully written. This is seen as bit 2 (PAGE_FLAG_LAST)
# and bit 3 (PAGE_FLAG_ROOT) being set (0xc).
my $flag;
if (sysseek(F, -64, SEEK_CUR) &&
sysread(F, $flag, 1) &&
(ord($flag) & 0xc) == 0xc) {
last;
}
}
die "Timeout waiting for GTID index to be non-empty\n"
if ++$count >= 500;
# Simple way to do sub-second sleep.
select(undef, undef, undef, 0.050);
}
# Corrupt the flag byte with an unused flag.
sysseek(F, -2, SEEK_END)
or die "Cannot seek file: $!\n";
my $buf;
sysread(F, $buf, 1)
or die "Cannot read file: $!\n";
$buf= chr(ord($buf) ^ 0x4);
sysseek(F, -2, SEEK_END)
or die "Cannot seek file: $!\n";
syswrite(F, $buf, 1) == 1
or die "Cannot write file: $!\n";
close F;
EOF
--echo +++ GTID Lookup, root page of index is corrupt.
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos) = @gtid_pos AS Gtid_Lookup_Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
--echo *** Test BINLOG_GTID_POS() with too-large offset.
# New binlog to skip the now corrupted one.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
INSERT INTO t1 VALUES (401);
INSERT INTO t1 VALUES (402);
--echo +++ Test the hot index.
--replace_result $file FILE
eval SELECT BINLOG_GTID_POS('$file', 100000000);
SHOW STATUS LIKE 'binlog_gtid_index_%';
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
--echo +++ Test the cold index.
--replace_result $file FILE
eval SELECT BINLOG_GTID_POS('$file', 100000000);
SHOW STATUS LIKE 'binlog_gtid_index_%';
--enable_ps2_protocol
DROP TABLE t1;
--binlog-gtid-index-page-size=128 --binlog-gtid-index-span-min=1
--source include/have_innodb.inc
# Don't test this under valgrind, memory leaks will occur
--source include/not_valgrind.inc
# Avoid CrashReporter popup on Mac
--source include/not_crashrep.inc
# Binary must be compiled with debug for crash to occur
--source include/have_debug.inc
--source include/have_binlog_format_row.inc
# We have an .opt file that sets a small page size and disables sparseness,
# so we get something non-trivial in the GTID index even with a small amount
# of binlogged events.
--echo *** Test that binlog GTID index is recovered after a crash.
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
--disable_query_log
INSERT INTO t1 VALUES (0, 0);
INSERT INTO t1 VALUES (1, 0);
INSERT INTO t1 VALUES (2, 0);
--let $i= 10
while ($i < 20) {
eval INSERT INTO t1 VALUES ($i, 0);
inc $i;
}
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
--let $pos1= query_get_value(SHOW MASTER STATUS, Position, 1)
--let $gtid1= `SELECT @@gtid_binlog_pos`
while ($i < 30) {
eval INSERT INTO t1 VALUES ($i, 0);
inc $i;
}
--let $pos2= query_get_value(SHOW MASTER STATUS, Position, 1)
--let $gtid2= `SELECT @@gtid_binlog_pos`
while ($i < 40) {
eval INSERT INTO t1 VALUES ($i, 0);
inc $i;
}
--let $pos3= query_get_value(SHOW MASTER STATUS, Position, 1)
--let $gtid3= `SELECT @@gtid_binlog_pos`
INSERT INTO t1 VALUES (50, 0);
INSERT INTO t1 VALUES (51, 0);
--disable_ps2_protocol
FLUSH NO_WRITE_TO_BINLOG STATUS;
eval SELECT BINLOG_GTID_POS('$file', $pos1) = "$gtid1" AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos2) = "$gtid2" AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos3) = "$gtid3" AS Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
--enable_ps2_protocol
--echo *** Crash the server, check that GTID index can be used after restart.
--source include/crash_mysqld.inc
--disable_ps2_protocol
FLUSH NO_WRITE_TO_BINLOG STATUS;
--disable_query_log
eval SELECT BINLOG_GTID_POS('$file', $pos1) = "$gtid1" AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos2) = "$gtid2" AS Ok;
eval SELECT BINLOG_GTID_POS('$file', $pos3) = "$gtid3" AS Ok;
--enable_query_log
SHOW STATUS LIKE 'binlog_gtid_index_%';
--enable_ps2_protocol
DROP TABLE t1;
...@@ -6,6 +6,7 @@ connection server_2; ...@@ -6,6 +6,7 @@ connection server_2;
include/stop_slave.inc include/stop_slave.inc
CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS; CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS;
call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not set up decryption for binlog.'"); call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not set up decryption for binlog.'");
call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not decrypt binlog: encryption key error");
##################################################### #####################################################
# Part 1: unencrypted master # Part 1: unencrypted master
##################################################### #####################################################
...@@ -58,10 +59,11 @@ INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption; ...@@ -58,10 +59,11 @@ INSERT INTO table3_no_encryption SELECT NULL,NOW(),b FROM table3_no_encryption;
connection server_2; connection server_2;
start slave; start slave;
include/wait_for_slave_io_error.inc [errno=1236] include/wait_for_slave_io_error.inc [errno=1236]
# Ensuring slave was unable to replicate any transactions.. # Ensuring slave was unable to replicate any encrypted transactions..
# ..success # ..success
SHOW TABLES; SHOW TABLES;
Tables_in_test Tables_in_test
table1_no_encryption
include/stop_slave_sql.inc include/stop_slave_sql.inc
reset slave; reset slave;
########## ##########
...@@ -80,5 +82,7 @@ COUNT(*) ...@@ -80,5 +82,7 @@ COUNT(*)
4 4
DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption;
connection server_2; connection server_2;
RESET MASTER;
SET GLOBAL gtid_slave_pos= '';
include/start_slave.inc include/start_slave.inc
include/rpl_end.inc include/rpl_end.inc
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS; CHANGE MASTER TO MASTER_USE_GTID=SLAVE_POS;
--enable_connect_log --enable_connect_log
call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not set up decryption for binlog.'"); call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not set up decryption for binlog.'");
call mtr.add_suppression(" Got fatal error 1236 from master when reading data from binary log: 'Could not decrypt binlog: encryption key error");
--echo ##################################################### --echo #####################################################
--echo # Part 1: unencrypted master --echo # Part 1: unencrypted master
...@@ -55,6 +56,7 @@ FLUSH BINARY LOGS; ...@@ -55,6 +56,7 @@ FLUSH BINARY LOGS;
SET binlog_format=ROW; SET binlog_format=ROW;
INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption;
INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption; INSERT INTO table1_no_encryption SELECT NULL,NOW(),b FROM table1_no_encryption;
--let $last_unencrypted_gtid= `SELECT @@gtid_binlog_pos`
# Make sure that binary logs are not encrypted # Make sure that binary logs are not encrypted
...@@ -120,11 +122,11 @@ start slave; ...@@ -120,11 +122,11 @@ start slave;
--let $slave_io_errno= 1236 --let $slave_io_errno= 1236
--source include/wait_for_slave_io_error.inc --source include/wait_for_slave_io_error.inc
--echo # Ensuring slave was unable to replicate any transactions.. --echo # Ensuring slave was unable to replicate any encrypted transactions..
--let $gsp= `SELECT @@global.gtid_slave_pos` --let $gsp= `SELECT @@global.gtid_slave_pos`
if (`SELECT strcmp("$gsp","")`) if (`SELECT strcmp("$gsp","$last_unencrypted_gtid")`)
{ {
die Slave without encryption configured should fail to read encrypted binlog; die Slave without encryption configured should fail to read encrypted binlog (expected $last_unencrypted_gtid but got $gsp);
} }
--echo # ..success --echo # ..success
...@@ -151,5 +153,7 @@ DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption; ...@@ -151,5 +153,7 @@ DROP TABLE table1_no_encryption, table2_to_encrypt, table3_no_encryption;
--connection server_2 --connection server_2
--disable_connect_log --disable_connect_log
RESET MASTER;
SET GLOBAL gtid_slave_pos= '';
--source include/start_slave.inc --source include/start_slave.inc
--source include/rpl_end.inc --source include/rpl_end.inc
...@@ -14,6 +14,9 @@ CREATE TABLE t1(id int not null primary key) engine=innodb; ...@@ -14,6 +14,9 @@ CREATE TABLE t1(id int not null primary key) engine=innodb;
INSERT INTO t1 values (1); INSERT INTO t1 values (1);
show global variables like '%gtid%'; show global variables like '%gtid%';
Variable_name Value Variable_name Value
binlog_gtid_index ON
binlog_gtid_index_page_size 4096
binlog_gtid_index_span_min 65536
gtid_binlog_pos 1-11-2 gtid_binlog_pos 1-11-2
gtid_binlog_state 1-11-2 gtid_binlog_state 1-11-2
gtid_cleanup_batch_size 64 gtid_cleanup_batch_size 64
...@@ -29,6 +32,9 @@ connection node_2; ...@@ -29,6 +32,9 @@ connection node_2;
SET SESSION wsrep_sync_wait=15; SET SESSION wsrep_sync_wait=15;
show global variables like '%gtid%'; show global variables like '%gtid%';
Variable_name Value Variable_name Value
binlog_gtid_index ON
binlog_gtid_index_page_size 4096
binlog_gtid_index_span_min 65536
gtid_binlog_pos 0-12-1,1-11-2 gtid_binlog_pos 0-12-1,1-11-2
gtid_binlog_state 0-12-1,1-11-2 gtid_binlog_state 0-12-1,1-11-2
gtid_cleanup_batch_size 64 gtid_cleanup_batch_size 64
...@@ -55,6 +61,9 @@ Error 1231 Variable 'server_id' can't be set to the value of '200' ...@@ -55,6 +61,9 @@ Error 1231 Variable 'server_id' can't be set to the value of '200'
INSERT INTO t1 values(2); INSERT INTO t1 values(2);
show global variables like '%gtid%'; show global variables like '%gtid%';
Variable_name Value Variable_name Value
binlog_gtid_index ON
binlog_gtid_index_page_size 4096
binlog_gtid_index_span_min 65536
gtid_binlog_pos 0-12-1,1-11-3 gtid_binlog_pos 0-12-1,1-11-3
gtid_binlog_state 0-12-1,1-11-3 gtid_binlog_state 0-12-1,1-11-3
gtid_cleanup_batch_size 64 gtid_cleanup_batch_size 64
...@@ -69,6 +78,9 @@ wsrep_gtid_mode ON ...@@ -69,6 +78,9 @@ wsrep_gtid_mode ON
connection node_1; connection node_1;
show global variables like '%gtid%'; show global variables like '%gtid%';
Variable_name Value Variable_name Value
binlog_gtid_index ON
binlog_gtid_index_page_size 4096
binlog_gtid_index_span_min 65536
gtid_binlog_pos 1-11-3 gtid_binlog_pos 1-11-3
gtid_binlog_state 1-11-3 gtid_binlog_state 1-11-3
gtid_cleanup_batch_size 64 gtid_cleanup_batch_size 64
......
...@@ -8,12 +8,12 @@ wait/synch/mutex/sql/Ack_receiver::mutex YES YES ...@@ -8,12 +8,12 @@ wait/synch/mutex/sql/Ack_receiver::mutex YES YES
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_index_writer::gtid_index_mutex YES YES
wait/synch/mutex/sql/gtid_waiting::LOCK_gtid_waiting 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_after_binlog_sync YES YES wait/synch/mutex/sql/LOCK_after_binlog_sync YES YES
wait/synch/mutex/sql/LOCK_audit_mask 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 ( and name not in (
......
...@@ -23,6 +23,7 @@ from performance_schema.file_summary_by_instance ...@@ -23,6 +23,7 @@ from performance_schema.file_summary_by_instance
where file_name like "%master-%" order by file_name; where file_name like "%master-%" order by file_name;
FILE_NAME EVENT_NAME COUNT_READ COUNT_WRITE SUM_NUMBER_OF_BYTES_READ SUM_NUMBER_OF_BYTES_WRITE FILE_NAME EVENT_NAME COUNT_READ COUNT_WRITE SUM_NUMBER_OF_BYTES_READ SUM_NUMBER_OF_BYTES_WRITE
master-bin.000001 wait/io/file/sql/binlog MANY MANY MANY MANY master-bin.000001 wait/io/file/sql/binlog MANY MANY MANY MANY
master-bin.000001.idx wait/io/file/sql/gtid_index NONE MANY NONE MANY
master-bin.index wait/io/file/sql/binlog_index MANY MANY MANY MANY master-bin.index wait/io/file/sql/binlog_index MANY MANY MANY MANY
select * from performance_schema.file_summary_by_instance select * from performance_schema.file_summary_by_instance
where file_name like "%slave-%" order by file_name; where file_name like "%slave-%" order by file_name;
...@@ -112,6 +113,7 @@ where file_name like "%slave-%" ...@@ -112,6 +113,7 @@ where file_name like "%slave-%"
order by file_name; order by file_name;
FILE_NAME EVENT_NAME COUNT_READ COUNT_WRITE SUM_NUMBER_OF_BYTES_READ SUM_NUMBER_OF_BYTES_WRITE FILE_NAME EVENT_NAME COUNT_READ COUNT_WRITE SUM_NUMBER_OF_BYTES_READ SUM_NUMBER_OF_BYTES_WRITE
slave-bin.000001 wait/io/file/sql/binlog MANY MANY MANY MANY slave-bin.000001 wait/io/file/sql/binlog MANY MANY MANY MANY
slave-bin.000001.idx wait/io/file/sql/gtid_index NONE MANY NONE MANY
slave-bin.index wait/io/file/sql/binlog_index MANY MANY MANY MANY slave-bin.index wait/io/file/sql/binlog_index MANY MANY MANY MANY
slave-relay-bin.000001 wait/io/file/sql/relaylog MANY MANY MANY MANY slave-relay-bin.000001 wait/io/file/sql/relaylog MANY MANY MANY MANY
slave-relay-bin.000002 wait/io/file/sql/relaylog MANY MANY MANY MANY slave-relay-bin.000002 wait/io/file/sql/relaylog MANY MANY MANY MANY
......
# Include file for main test rpl.rpl_gtid_index.
# Test GTID indexes with given parameters.
#
# Parameters:
# $NUM_POS Number of GTIDs/binlog positions to create
# $NUM_DOMAIN Number of different domains to use
# $NUM_SERVER Number of different server_id to use
# $NUM_SLAVE_CONNECTS How many GTID slave connect positions to test
# $RND_SEED Random seed
--echo *** Testing $NUM_POS GTIDs with $NUM_SLAVE_CONNECTS test connects
--connection master
DELETE FROM t1 WHERE a >= 1000;
# Rotate binlogs to make new GTID index settings take effect.
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
# Prepare some random values, but deterministic between test runs.
CREATE TABLE rand_data(idx INT PRIMARY KEY, domain_id INT, server_id INT)
ENGINE=InnoDB;
INSERT INTO rand_data(idx, domain_id, server_id) VALUES (0, 0, 1);
eval
INSERT INTO rand_data(idx, domain_id, server_id)
SELECT seq,
@tmp:=floor($NUM_DOMAIN*POW(rand($RND_SEED),2)),
100 + $NUM_SERVER*@tmp + floor($NUM_SERVER*rand($RND_SEED))
FROM seq_1_to_$NUM_POS;
# Let's check that the test data is deterministic.
# If this changes due to some server changes, it's fine, the .result can just
# be updated. But we want it to be identical between test runs on same code,
# to facilitate debugging test failures.
SELECT COUNT(*), SUM(domain_id), SUM(server_id) FROM rand_data;
# Create some data for the binlog (and GTID index), recording the correct
# binlog positions and GTIDs.
CREATE TABLE gtid_data(
idx INT PRIMARY KEY,
gtid VARCHAR(44),
gtid_pos VARCHAR(255),
file VARCHAR(100),
pos INT,
row_count INT,
KEY(file, pos)) ENGINE=InnoDB;
--let $gtid= `SELECT @@last_gtid`
--source include/save_master_gtid.inc
--connection slave
--source include/sync_with_master_gtid.inc
--source include/stop_slave.inc
--connection master
SET @orig_domain_id= @@gtid_domain_id;
SET @orig_server_id= @@server_id;
--let $i= 0
--let $rotate_point= `SELECT floor($NUM_POS/2)`
--let $base_count= `SELECT COUNT(*) FROM t1`
--disable_query_log
while ($i < $NUM_POS) {
--let $file= query_get_value(SHOW MASTER STATUS, File, 1)
--let $pos= query_get_value(SHOW MASTER STATUS, Position, 1)
--let $gtid_pos= `SELECT @@gtid_binlog_pos`
--let $row_count= `SELECT $base_count + $i`
eval SET gtid_domain_id= (SELECT domain_id FROM rand_data WHERE idx=$i+1);
eval SET server_id= (SELECT server_id FROM rand_data WHERE idx=$i+1);
BEGIN;
eval INSERT INTO gtid_data(idx, gtid, gtid_pos, file, pos, row_count)
VALUES ($i, '$gtid', '$gtid_pos', '$file', $pos, $row_count);
eval INSERT INTO t1 VALUES ($i + 1000, 0);
COMMIT;
--let $gtid= `SELECT @@last_gtid`
inc $i;
if ($i==$rotate_point) {
FLUSH NO_WRITE_TO_BINLOG BINARY LOGS;
}
}
--enable_query_log
SET gtid_domain_id= @orig_domain_id;
SET server_id= @orig_server_id;
SELECT COUNT(*) FROM gtid_data;
# Test that BINLOG_GTID_POS returns correct positions for every GTID position.
--echo *** The result should be empty, otherwise some result is wrong:
SELECT idx, gtid_pos, BINLOG_GTID_POS(file, pos)
FROM gtid_data
WHERE NOT gtid_eq(CONVERT(gtid_pos USING utf8),BINLOG_GTID_POS(file, pos))
ORDER BY idx;
# Prepare to rewind the slave to this point to test again on same binlog.
--connection slave
SET @orig_pos= @@GLOBAL.gtid_slave_pos;
SET @orig_t1_limit= (SELECT MAX(a) FROM t1);
--echo *** Now connect the slave to each position in turn, and test that
--echo *** the right amount of data is replicated at each point.
--let $old_silent= $keep_include_silent
--let $keep_include_silent= 1
--let $i= 0
--disable_query_log
while ($i < $NUM_POS) {
--connection master
--let $gtid_pos= `SELECT gtid_pos FROM gtid_data WHERE idx=$i`
--let $master_count= `SELECT row_count FROM gtid_data WHERE idx=$i`
--connection slave
--disable_result_log
eval START SLAVE UNTIL master_gtid_pos='$gtid_pos';
--enable_result_log
--let $res= `SELECT MASTER_GTID_WAIT('$gtid_pos')`
if ($res != 0) {
--die "FAIL: MASTER_GTID_WAIT($gtid_pos) returned $res, should have been 0"
}
--source include/wait_for_slave_to_stop.inc
--let $slave_count = `SELECT COUNT(*) FROM t1`
if ($master_count != $slave_count) {
SELECT * FROM gtid_data ORDER BY file, pos;
SELECT * FROM t1 ORDER BY a;
--die "Not all rows replicated. $master_count on master but $slave_count on slave."
}
--let $i= `SELECT $i + ceil($NUM_POS / $NUM_SLAVE_CONNECTS)`
}
--enable_query_log
--echo *** Test slave connecting to some GTID positions where the position in
--echo *** the master's binlog is different between the different domains.
--echo *** Revind the slave and test on the same binlog data from the master as before.
--connection slave
SET sql_log_bin= 0;
TRUNCATE gtid_data;
DELETE FROM t1 WHERE a > @orig_t1_limit;
SET sql_log_bin= 1;
SET GLOBAL gtid_slave_pos= @orig_pos;
--let $i= 0
--disable_query_log
while ($i <= $NUM_DOMAIN) {
# Build a GTID position from GTIDs that are picked at different locations
# in the gtid_data table for each domain.
--connection master
let $until_pos=`
SELECT GROUP_CONCAT(gtid SEPARATOR ',')
FROM gtid_data
WHERE idx IN (
SELECT MAX(gtid_data.idx) AS pick
FROM gtid_data
INNER JOIN rand_data ON (rand_data.idx = gtid_data.idx)
WHERE gtid_data.idx*$NUM_DOMAIN <= (domain_id + $i)*$NUM_POS
GROUP BY domain_id
)`;
--connection slave
--disable_result_log
eval START SLAVE UNTIL master_gtid_pos='$until_pos';
--enable_result_log
--let $res= `SELECT MASTER_GTID_WAIT('$until_pos')`
if ($res != 0) {
--die "FAIL: MASTER_GTID_WAIT($until_pos) returned $res, should have been 0"
}
--source include/wait_for_slave_to_stop.inc
inc $i;
}
--enable_query_log
--let $keep_include_silent= $old_silent
# Check that everything was replicated (nothing skipped).
# We have one less row on the slave since the last UNTIL is the one before
# the master inserted the last row.
--connection master
--let $master_count= `SELECT COUNT(*)-1 FROM t1`
--connection slave
--let $slave_count= `SELECT COUNT(*) FROM t1`
if ($master_count != $slave_count) {
SELECT * FROM gtid_data ORDER BY file, pos;
SELECT * FROM t1 ORDER BY a;
--die "Not all rows replicated. $master_count on master but $slave_count on slave."
}
--connection master
DROP TABLE gtid_data, rand_data;
--source include/save_master_gtid.inc
--connection slave
--source include/start_slave.inc
--source include/sync_with_master_gtid.inc
--connection master
...@@ -28,7 +28,6 @@ include/show_events.inc ...@@ -28,7 +28,6 @@ include/show_events.inc
Log_name Pos Event_type Server_id End_log_pos Info Log_name Pos Event_type Server_id End_log_pos Info
slave-relay-bin.000002 # Rotate # # master-bin.000001;pos=POS slave-relay-bin.000002 # Rotate # # master-bin.000001;pos=POS
slave-relay-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION slave-relay-bin.000002 # Format_desc # # SERVER_VERSION, BINLOG_VERSION
slave-relay-bin.000002 # Gtid_list # # []
slave-relay-bin.000002 # Binlog_checkpoint # # master-bin.000001 slave-relay-bin.000002 # Binlog_checkpoint # # master-bin.000001
slave-relay-bin.000002 # Gtid # # GTID #-#-# slave-relay-bin.000002 # Gtid # # GTID #-#-#
slave-relay-bin.000002 # Gtid_list # # [#-#-#] slave-relay-bin.000002 # Gtid_list # # [#-#-#]
......
This diff is collapsed.
...@@ -24,6 +24,7 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos; ...@@ -24,6 +24,7 @@ CHANGE MASTER TO MASTER_USE_GTID=slave_pos;
--echo # --echo #
--echo # Initialize test data --echo # Initialize test data
--connection master --connection master
--source include/wait_for_binlog_checkpoint.inc
create table t1 (a int); create table t1 (a int);
SET @@session.server_id= 3; SET @@session.server_id= 3;
create table t2 (a int); create table t2 (a int);
......
--source include/have_sequence.inc
--source include/have_innodb.inc
--source include/master-slave.inc
--source include/have_binlog_format_mixed.inc
--connection slave
--source include/stop_slave.inc
CHANGE MASTER TO master_use_gtid= slave_pos;
--source include/start_slave.inc
--connection master
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
INSERT INTO t1 VALUES (0, 0);
--echo *** Test looking up a lot of different event positions and GTIDs.
# A function for comparing GTID positions.
# Handles that the domain_id order is different in the two strings.
# Works by repeatedly removing one GTID from each string. If the strings have
# the same length and nothing is left at the end, then they are identical.
delimiter //;
CREATE FUNCTION gtid_eq(a VARCHAR(255), b VARCHAR(255)) RETURNS BOOLEAN DETERMINISTIC
BEGIN
DECLARE g VARCHAR(255);
IF a IS NULL OR b IS NULL OR LENGTH(a) != LENGTH(b) THEN
RETURN FALSE;
END IF;
SET a= CONCAT(a, ',');
SET b= CONCAT(',', b, ',');
WHILE LENGTH(a) > 0 DO
SET g= REGEXP_SUBSTR(a, '^[^,]+,');
SET a= SUBSTRING(a, LENGTH(g)+1);
SET b= REPLACE(b, CONCAT(',', g), ',');
END WHILE;
RETURN b = ',';
END //
delimiter ;//
SET @old_page_size= @@GLOBAL.binlog_gtid_index_page_size;
SET @old_span_min= @@GLOBAL.binlog_gtid_index_span_min;
--echo *** A fair amount of work with default GTID index settings.
--let $NUM_POS= 200
--let $NUM_DOMAIN= 5
--let $NUM_SERVER= 5
--let $NUM_SLAVE_CONNECTS= 50
--let $RND_SEED= 42
--source suite/rpl/include/rpl_gtid_index.inc
--echo *** A lot of GTIDs with small btree pages to stress the Btree code.
--let $NUM_POS= 1000
--let $NUM_DOMAIN= 10
--let $RND_SEED= 150
SET GLOBAL binlog_gtid_index_page_size= 64;
SET GLOBAL binlog_gtid_index_span_min= 1;
--source suite/rpl/include/rpl_gtid_index.inc
--echo *** Small page size with sparse index.
--let $NUM_POS= 200
--let $RND_SEED= 666
SET GLOBAL binlog_gtid_index_page_size= 64;
SET GLOBAL binlog_gtid_index_span_min= 2048;
--source suite/rpl/include/rpl_gtid_index.inc
--echo *** Medium page size.
--let $NUM_POS= 200
--let $RND_SEED= 1024
SET GLOBAL binlog_gtid_index_page_size= 512;
SET GLOBAL binlog_gtid_index_span_min= 512;
--source suite/rpl/include/rpl_gtid_index.inc
--echo *** Large page size.
--let $NUM_POS= 200
--let $RND_SEED= 12345
SET GLOBAL binlog_gtid_index_page_size= 16384;
SET GLOBAL binlog_gtid_index_span_min= 1;
--source suite/rpl/include/rpl_gtid_index.inc
# Cleanup.
--connection master
SET GLOBAL binlog_gtid_index_page_size= @old_page_size;
SET GLOBAL binlog_gtid_index_span_min= @old_span_min;
DROP TABLE t1;
DROP FUNCTION gtid_eq;
--source include/rpl_end.inc
...@@ -432,6 +432,36 @@ NUMERIC_BLOCK_SIZE NULL ...@@ -432,6 +432,36 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST MIXED,STATEMENT,ROW ENUM_VALUE_LIST MIXED,STATEMENT,ROW
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME BINLOG_GTID_INDEX
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Enable the creation of a GTID index for every binlog file, and the use of such index for speeding up GTID lookup in the binlog.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME BINLOG_GTID_INDEX_PAGE_SIZE
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Page size to use for the binlog GTID index.
NUMERIC_MIN_VALUE 64
NUMERIC_MAX_VALUE 16777216
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME BINLOG_GTID_INDEX_SPAN_MIN
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Control sparseness of the binlog GTID index. If set to N, at most one index record will be added for every N bytes of binlog file written, to reduce the size of the index. Normally does not need tuning.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1073741824
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME BINLOG_OPTIMIZE_THREAD_SCHEDULING VARIABLE_NAME BINLOG_OPTIMIZE_THREAD_SCHEDULING
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN VARIABLE_TYPE BOOLEAN
......
...@@ -452,6 +452,36 @@ NUMERIC_BLOCK_SIZE NULL ...@@ -452,6 +452,36 @@ NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST MIXED,STATEMENT,ROW ENUM_VALUE_LIST MIXED,STATEMENT,ROW
READ_ONLY NO READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME BINLOG_GTID_INDEX
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE BOOLEAN
VARIABLE_COMMENT Enable the creation of a GTID index for every binlog file, and the use of such index for speeding up GTID lookup in the binlog.
NUMERIC_MIN_VALUE NULL
NUMERIC_MAX_VALUE NULL
NUMERIC_BLOCK_SIZE NULL
ENUM_VALUE_LIST OFF,ON
READ_ONLY NO
COMMAND_LINE_ARGUMENT OPTIONAL
VARIABLE_NAME BINLOG_GTID_INDEX_PAGE_SIZE
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Page size to use for the binlog GTID index.
NUMERIC_MIN_VALUE 64
NUMERIC_MAX_VALUE 16777216
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME BINLOG_GTID_INDEX_SPAN_MIN
VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE INT UNSIGNED
VARIABLE_COMMENT Control sparseness of the binlog GTID index. If set to N, at most one index record will be added for every N bytes of binlog file written, to reduce the size of the index. Normally does not need tuning.
NUMERIC_MIN_VALUE 1
NUMERIC_MAX_VALUE 1073741824
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO
COMMAND_LINE_ARGUMENT REQUIRED
VARIABLE_NAME BINLOG_IGNORE_DB VARIABLE_NAME BINLOG_IGNORE_DB
VARIABLE_SCOPE GLOBAL VARIABLE_SCOPE GLOBAL
VARIABLE_TYPE VARCHAR VARIABLE_TYPE VARCHAR
......
...@@ -165,7 +165,7 @@ SET (SQL_SOURCE ...@@ -165,7 +165,7 @@ SET (SQL_SOURCE
gcalc_slicescan.cc gcalc_tools.cc gcalc_slicescan.cc gcalc_tools.cc
my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc my_apc.cc mf_iocache_encr.cc item_jsonfunc.cc
my_json_writer.cc json_schema.cc json_schema_helper.cc my_json_writer.cc json_schema.cc json_schema_helper.cc
rpl_gtid.cc rpl_parallel.cc rpl_gtid.cc gtid_index.cc rpl_parallel.cc
semisync.cc semisync_master.cc semisync_slave.cc semisync.cc semisync_master.cc semisync_slave.cc
semisync_master_ack_receiver.cc semisync_master_ack_receiver.cc
sp_instr.cc sp_instr.cc
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -21,8 +21,10 @@ ...@@ -21,8 +21,10 @@
#include "rpl_constants.h" #include "rpl_constants.h"
class Relay_log_info; class Relay_log_info;
class Gtid_index_writer;
class Format_description_log_event; class Format_description_log_event;
class Gtid_log_event;
bool reopen_fstreams(const char *filename, FILE *outstream, FILE *errstream); bool reopen_fstreams(const char *filename, FILE *outstream, FILE *errstream);
void setup_log_handling(); void setup_log_handling();
...@@ -240,6 +242,7 @@ extern TC_LOG_DUMMY tc_log_dummy; ...@@ -240,6 +242,7 @@ extern TC_LOG_DUMMY tc_log_dummy;
#define LOG_CLOSE_TO_BE_OPENED 2 #define LOG_CLOSE_TO_BE_OPENED 2
#define LOG_CLOSE_STOP_EVENT 4 #define LOG_CLOSE_STOP_EVENT 4
#define LOG_CLOSE_DELAYED_CLOSE 8 #define LOG_CLOSE_DELAYED_CLOSE 8
#define LOG_CLOSE_SYNC_GTID_INDEX 16
/* /*
Maximum unique log filename extension. Maximum unique log filename extension.
...@@ -711,6 +714,9 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log ...@@ -711,6 +714,9 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
ulonglong group_commit_trigger_count, group_commit_trigger_timeout; ulonglong group_commit_trigger_count, group_commit_trigger_timeout;
ulonglong group_commit_trigger_lock_wait; ulonglong group_commit_trigger_lock_wait;
/* Binlog GTID index. */
Gtid_index_writer *gtid_index;
/* pointer to the sync period variable, for binlog this will be /* pointer to the sync period variable, for binlog this will be
sync_binlog_period, for relay log this will be sync_binlog_period, for relay log this will be
sync_relay_log_period sync_relay_log_period
...@@ -720,6 +726,13 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log ...@@ -720,6 +726,13 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
bool state_file_deleted; bool state_file_deleted;
bool binlog_state_recover_done; bool binlog_state_recover_done;
Gtid_index_writer *recover_gtid_index_start(const char *base_name,
my_off_t offset);
void recover_gtid_index_process(Gtid_index_writer *gi, my_off_t offset,
const rpl_gtid *gtid);
void recover_gtid_index_end(Gtid_index_writer *gi);
void recover_gtid_index_abort(Gtid_index_writer *gi);
inline uint get_sync_period() inline uint get_sync_period()
{ {
return *sync_period_ptr; return *sync_period_ptr;
...@@ -739,6 +752,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log ...@@ -739,6 +752,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
bool write_transaction_to_binlog_events(group_commit_entry *entry); bool write_transaction_to_binlog_events(group_commit_entry *entry);
void trx_group_commit_leader(group_commit_entry *leader); void trx_group_commit_leader(group_commit_entry *leader);
bool is_xidlist_idle_nolock(); bool is_xidlist_idle_nolock();
void update_gtid_index(uint32 offset, rpl_gtid gtid);
public: public:
int new_file_without_locking(); int new_file_without_locking();
/* /*
...@@ -759,11 +774,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log ...@@ -759,11 +774,8 @@ class MYSQL_BIN_LOG: public TC_LOG, private Event_log
ulong binlog_id; ulong binlog_id;
/* Total prepared XIDs and pending checkpoint requests in this binlog. */ /* Total prepared XIDs and pending checkpoint requests in this binlog. */
long xid_count; long xid_count;
long notify_count;
/* For linking in requests to the binlog background thread. */
xid_count_per_binlog *next_in_queue;
xid_count_per_binlog(char *log_file_name, uint log_file_name_len) xid_count_per_binlog(char *log_file_name, uint log_file_name_len)
:binlog_id(0), xid_count(0), notify_count(0) :binlog_id(0), xid_count(0)
{ {
binlog_name_len= log_file_name_len; binlog_name_len= log_file_name_len;
binlog_name= (char *) my_malloc(PSI_INSTRUMENT_ME, binlog_name_len, MYF(MY_ZEROFILL)); binlog_name= (char *) my_malloc(PSI_INSTRUMENT_ME, binlog_name_len, MYF(MY_ZEROFILL));
......
...@@ -83,6 +83,7 @@ ...@@ -83,6 +83,7 @@
#include "wsrep_server_state.h" #include "wsrep_server_state.h"
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
#include "proxy_protocol.h" #include "proxy_protocol.h"
#include "gtid_index.h"
#include "sql_callback.h" #include "sql_callback.h"
#include "threadpool.h" #include "threadpool.h"
...@@ -443,6 +444,9 @@ my_bool sp_automatic_privileges= 1; ...@@ -443,6 +444,9 @@ my_bool sp_automatic_privileges= 1;
ulong opt_binlog_rows_event_max_size; ulong opt_binlog_rows_event_max_size;
ulong binlog_row_metadata; ulong binlog_row_metadata;
my_bool opt_binlog_gtid_index= TRUE;
uint opt_binlog_gtid_index_page_size= 4096;
uint opt_binlog_gtid_index_span_min= 65536;
my_bool opt_master_verify_checksum= 0; my_bool opt_master_verify_checksum= 0;
my_bool opt_slave_sql_verify_checksum= 1; my_bool opt_slave_sql_verify_checksum= 1;
const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS}; const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS};
...@@ -491,6 +495,7 @@ ulong malloc_calls; ...@@ -491,6 +495,7 @@ ulong malloc_calls;
ulong specialflag=0; ulong specialflag=0;
ulong binlog_cache_use= 0, binlog_cache_disk_use= 0; ulong binlog_cache_use= 0, binlog_cache_disk_use= 0;
ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0; ulong binlog_stmt_cache_use= 0, binlog_stmt_cache_disk_use= 0;
ulong binlog_gtid_index_hit= 0, binlog_gtid_index_miss= 0;
ulong max_connections, max_connect_errors; ulong max_connections, max_connect_errors;
uint max_password_errors; uint max_password_errors;
ulong extra_max_connections; ulong extra_max_connections;
...@@ -896,7 +901,7 @@ PSI_file_key key_file_binlog, key_file_binlog_cache, key_file_binlog_index, ...@@ -896,7 +901,7 @@ PSI_file_key key_file_binlog, key_file_binlog_cache, key_file_binlog_index,
PSI_file_key key_file_query_log, key_file_slow_log; PSI_file_key key_file_query_log, key_file_slow_log;
PSI_file_key key_file_relaylog, key_file_relaylog_index, PSI_file_key key_file_relaylog, key_file_relaylog_index,
key_file_relaylog_cache, key_file_relaylog_index_cache; key_file_relaylog_cache, key_file_relaylog_index_cache;
PSI_file_key key_file_binlog_state; PSI_file_key key_file_binlog_state, key_file_gtid_index;
#ifdef HAVE_PSI_INTERFACE #ifdef HAVE_PSI_INTERFACE
#ifdef HAVE_MMAP #ifdef HAVE_MMAP
...@@ -921,6 +926,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, ...@@ -921,6 +926,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_LOCK_status, key_LOCK_temp_pool, key_LOCK_status, key_LOCK_temp_pool,
key_LOCK_system_variables_hash, key_LOCK_thd_data, key_LOCK_thd_kill, key_LOCK_system_variables_hash, key_LOCK_thd_data, key_LOCK_thd_kill,
key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log, key_LOCK_user_conn, key_LOCK_uuid_short_generator, key_LOG_LOCK_log,
key_gtid_index_lock,
key_master_info_data_lock, key_master_info_run_lock, key_master_info_data_lock, key_master_info_run_lock,
key_master_info_sleep_lock, key_master_info_start_stop_lock, key_master_info_sleep_lock, key_master_info_start_stop_lock,
key_master_info_start_alter_lock, key_master_info_start_alter_lock,
...@@ -1007,6 +1013,7 @@ static PSI_mutex_info all_server_mutexes[]= ...@@ -1007,6 +1013,7 @@ static PSI_mutex_info all_server_mutexes[]=
{ &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},
{ &key_LOG_LOCK_log, "LOG::LOCK_log", 0}, { &key_LOG_LOCK_log, "LOG::LOCK_log", 0},
{ &key_gtid_index_lock, "Gtid_index_writer::gtid_index_mutex", 0},
{ &key_master_info_data_lock, "Master_info::data_lock", 0}, { &key_master_info_data_lock, "Master_info::data_lock", 0},
{ &key_master_info_start_stop_lock, "Master_info::start_stop_lock", 0}, { &key_master_info_start_stop_lock, "Master_info::start_stop_lock", 0},
{ &key_master_info_run_lock, "Master_info::run_lock", 0}, { &key_master_info_run_lock, "Master_info::run_lock", 0},
...@@ -2011,6 +2018,7 @@ static void clean_up(bool print_message) ...@@ -2011,6 +2018,7 @@ static void clean_up(bool print_message)
injector::free_instance(); injector::free_instance();
mysql_bin_log.cleanup(); mysql_bin_log.cleanup();
Gtid_index_writer::gtid_index_cleanup();
my_tz_free(); my_tz_free();
my_dboptions_cache_free(); my_dboptions_cache_free();
...@@ -3962,6 +3970,7 @@ static int init_common_variables() ...@@ -3962,6 +3970,7 @@ static int init_common_variables()
inited before MY_INIT(). So we do it here. inited before MY_INIT(). So we do it here.
*/ */
mysql_bin_log.init_pthread_objects(); mysql_bin_log.init_pthread_objects();
Gtid_index_writer::gtid_index_init();
/* TODO: remove this when my_time_t is 64 bit compatible */ /* TODO: remove this when my_time_t is 64 bit compatible */
if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time)) if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time))
...@@ -7396,6 +7405,8 @@ SHOW_VAR status_vars[]= { ...@@ -7396,6 +7405,8 @@ SHOW_VAR status_vars[]= {
{"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS}, {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
{"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG}, {"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG},
{"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG}, {"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG},
{"Binlog_gtid_index_hit", (char*) &binlog_gtid_index_hit, SHOW_LONG},
{"Binlog_gtid_index_miss", (char*) &binlog_gtid_index_miss, SHOW_LONG},
{"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use, SHOW_LONG}, {"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use, SHOW_LONG},
{"Binlog_stmt_cache_use", (char*) &binlog_stmt_cache_use, SHOW_LONG}, {"Binlog_stmt_cache_use", (char*) &binlog_stmt_cache_use, SHOW_LONG},
{"Busy_time", (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS}, {"Busy_time", (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
...@@ -7821,6 +7832,7 @@ static int mysql_init_variables(void) ...@@ -7821,6 +7832,7 @@ static int mysql_init_variables(void)
delayed_insert_errors= thread_created= 0; delayed_insert_errors= thread_created= 0;
specialflag= 0; specialflag= 0;
binlog_cache_use= binlog_cache_disk_use= 0; binlog_cache_use= binlog_cache_disk_use= 0;
binlog_gtid_index_hit= binlog_gtid_index_miss= 0;
max_used_connections= slow_launch_threads = 0; max_used_connections= slow_launch_threads = 0;
max_used_connections_time= 0; max_used_connections_time= 0;
mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0; mysqld_user= mysqld_chroot= opt_init_file= opt_bin_logname = 0;
...@@ -9219,7 +9231,8 @@ static PSI_file_info all_server_files[]= ...@@ -9219,7 +9231,8 @@ static PSI_file_info all_server_files[]=
{ &key_file_trg, "trigger_name", 0}, { &key_file_trg, "trigger_name", 0},
{ &key_file_trn, "trigger", 0}, { &key_file_trn, "trigger", 0},
{ &key_file_init, "init", 0}, { &key_file_init, "init", 0},
{ &key_file_binlog_state, "binlog_state", 0} { &key_file_binlog_state, "binlog_state", 0},
{ &key_file_gtid_index, "gtid_index", 0}
}; };
#endif /* HAVE_PSI_INTERFACE */ #endif /* HAVE_PSI_INTERFACE */
...@@ -9413,6 +9426,7 @@ PSI_memory_key key_memory_acl_cache; ...@@ -9413,6 +9426,7 @@ PSI_memory_key key_memory_acl_cache;
PSI_memory_key key_memory_acl_mem; PSI_memory_key key_memory_acl_mem;
PSI_memory_key key_memory_acl_memex; PSI_memory_key key_memory_acl_memex;
PSI_memory_key key_memory_binlog_cache_mngr; PSI_memory_key key_memory_binlog_cache_mngr;
PSI_memory_key key_memory_binlog_gtid_index;
PSI_memory_key key_memory_binlog_pos; PSI_memory_key key_memory_binlog_pos;
PSI_memory_key key_memory_binlog_recover_exec; PSI_memory_key key_memory_binlog_recover_exec;
PSI_memory_key key_memory_binlog_statement_buffer; PSI_memory_key key_memory_binlog_statement_buffer;
...@@ -9652,6 +9666,7 @@ static PSI_memory_info all_server_memory[]= ...@@ -9652,6 +9666,7 @@ static PSI_memory_info all_server_memory[]=
// { &key_memory_Slave_job_group_group_relay_log_name, "Slave_job_group::group_relay_log_name", 0}, // { &key_memory_Slave_job_group_group_relay_log_name, "Slave_job_group::group_relay_log_name", 0},
{ &key_memory_Relay_log_info_group_relay_log_name, "Relay_log_info::group_relay_log_name", 0}, { &key_memory_Relay_log_info_group_relay_log_name, "Relay_log_info::group_relay_log_name", 0},
{ &key_memory_binlog_cache_mngr, "binlog_cache_mngr", 0}, { &key_memory_binlog_cache_mngr, "binlog_cache_mngr", 0},
{ &key_memory_binlog_gtid_index, "binlog_gtid_index", 0},
{ &key_memory_Row_data_memory_memory, "Row_data_memory::memory", 0}, { &key_memory_Row_data_memory_memory, "Row_data_memory::memory", 0},
// { &key_memory_Gtid_set_to_string, "Gtid_set::to_string", 0}, // { &key_memory_Gtid_set_to_string, "Gtid_set::to_string", 0},
// { &key_memory_Gtid_state_to_string, "Gtid_state::to_string", 0}, // { &key_memory_Gtid_state_to_string, "Gtid_state::to_string", 0},
......
...@@ -217,6 +217,7 @@ extern ulonglong thd_startup_options; ...@@ -217,6 +217,7 @@ extern ulonglong thd_startup_options;
extern my_thread_id global_thread_id; extern my_thread_id global_thread_id;
extern ulong binlog_cache_use, binlog_cache_disk_use; extern ulong binlog_cache_use, binlog_cache_disk_use;
extern ulong binlog_stmt_cache_use, binlog_stmt_cache_disk_use; extern ulong binlog_stmt_cache_use, binlog_stmt_cache_disk_use;
extern ulong binlog_gtid_index_hit, binlog_gtid_index_miss;
extern ulong aborted_threads, aborted_connects, aborted_connects_preauth; extern ulong aborted_threads, aborted_connects, aborted_connects_preauth;
extern ulong delayed_insert_timeout; extern ulong delayed_insert_timeout;
extern ulong delayed_insert_limit, delayed_queue_size; extern ulong delayed_insert_limit, delayed_queue_size;
...@@ -249,6 +250,9 @@ extern ulonglong slave_max_statement_time; ...@@ -249,6 +250,9 @@ extern ulonglong slave_max_statement_time;
extern double slave_max_statement_time_double; extern double slave_max_statement_time_double;
extern ulong opt_binlog_rows_event_max_size; extern ulong opt_binlog_rows_event_max_size;
extern ulong binlog_row_metadata; extern ulong binlog_row_metadata;
extern my_bool opt_binlog_gtid_index;
extern uint opt_binlog_gtid_index_page_size;
extern uint opt_binlog_gtid_index_span_min;
extern ulong thread_cache_size; extern ulong thread_cache_size;
extern ulong stored_program_cache_size; extern ulong stored_program_cache_size;
extern ulong opt_slave_parallel_threads; extern ulong opt_slave_parallel_threads;
...@@ -333,7 +337,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, ...@@ -333,7 +337,7 @@ extern PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list,
key_LOCK_rpl_status, key_LOCK_server_started, key_LOCK_rpl_status, key_LOCK_server_started,
key_LOCK_status, key_LOCK_optimizer_costs, key_LOCK_status, key_LOCK_optimizer_costs,
key_LOCK_thd_data, key_LOCK_thd_kill, key_LOCK_thd_data, key_LOCK_thd_kill,
key_LOCK_user_conn, key_LOG_LOCK_log, key_LOCK_user_conn, key_LOG_LOCK_log, key_gtid_index_lock,
key_master_info_data_lock, key_master_info_run_lock, key_master_info_data_lock, key_master_info_run_lock,
key_master_info_sleep_lock, key_master_info_start_stop_lock, key_master_info_sleep_lock, key_master_info_start_stop_lock,
key_master_info_start_alter_lock, key_master_info_start_alter_lock,
...@@ -411,7 +415,7 @@ extern PSI_file_key key_file_relaylog, key_file_relaylog_index, ...@@ -411,7 +415,7 @@ extern PSI_file_key key_file_relaylog, key_file_relaylog_index,
key_file_relaylog_cache, key_file_relaylog_index_cache; key_file_relaylog_cache, key_file_relaylog_index_cache;
extern PSI_socket_key key_socket_tcpip, key_socket_unix, extern PSI_socket_key key_socket_tcpip, key_socket_unix,
key_socket_client_connection; key_socket_client_connection;
extern PSI_file_key key_file_binlog_state; extern PSI_file_key key_file_binlog_state, key_file_gtid_index;
#ifdef HAVE_PSI_INTERFACE #ifdef HAVE_PSI_INTERFACE
void init_server_psi_keys(); void init_server_psi_keys();
...@@ -456,6 +460,7 @@ extern PSI_memory_key key_memory_user_var_entry_value; ...@@ -456,6 +460,7 @@ extern PSI_memory_key key_memory_user_var_entry_value;
extern PSI_memory_key key_memory_Slave_job_group_group_relay_log_name; extern PSI_memory_key key_memory_Slave_job_group_group_relay_log_name;
extern PSI_memory_key key_memory_Relay_log_info_group_relay_log_name; extern PSI_memory_key key_memory_Relay_log_info_group_relay_log_name;
extern PSI_memory_key key_memory_binlog_cache_mngr; extern PSI_memory_key key_memory_binlog_cache_mngr;
extern PSI_memory_key key_memory_binlog_gtid_index;
extern PSI_memory_key key_memory_Row_data_memory_memory; extern PSI_memory_key key_memory_Row_data_memory_memory;
extern PSI_memory_key key_memory_errmsgs; extern PSI_memory_key key_memory_errmsgs;
extern PSI_memory_key key_memory_Event_queue_element_for_exec_names; extern PSI_memory_key key_memory_Event_queue_element_for_exec_names;
......
...@@ -376,6 +376,15 @@ constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_ROW_METADATA= ...@@ -376,6 +376,15 @@ constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_ROW_METADATA=
constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_LEGACY_EVENT_POS= constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_LEGACY_EVENT_POS=
SUPER_ACL | BINLOG_ADMIN_ACL; SUPER_ACL | BINLOG_ADMIN_ACL;
constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX=
BINLOG_ADMIN_ACL;
constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX_PAGE_SIZE=
BINLOG_ADMIN_ACL;
constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX_SPAN_MIN=
BINLOG_ADMIN_ACL;
constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_EXPIRE_LOGS_DAYS= constexpr privilege_t PRIV_SET_SYSTEM_GLOBAL_VAR_EXPIRE_LOGS_DAYS=
BINLOG_ADMIN_ACL; BINLOG_ADMIN_ACL;
......
This diff is collapsed.
...@@ -26,6 +26,11 @@ ...@@ -26,6 +26,11 @@
extern const LEX_CSTRING rpl_gtid_slave_state_table_name; extern const LEX_CSTRING rpl_gtid_slave_state_table_name;
class String; class String;
#ifdef MYSQL_SERVER
struct TABLE;
#endif
struct slave_connection_state;
#define PARAM_GTID(G) G.domain_id, G.server_id, G.seq_no #define PARAM_GTID(G) G.domain_id, G.server_id, G.seq_no
#define GTID_MAX_STR_LENGTH (10+1+10+1+20) #define GTID_MAX_STR_LENGTH (10+1+10+1+20)
...@@ -296,8 +301,13 @@ struct rpl_slave_state ...@@ -296,8 +301,13 @@ struct rpl_slave_state
to know where to start when a master is changed to a slave. As a side to know where to start when a master is changed to a slave. As a side
effect, it also allows to skip a hash lookup in the very common case of effect, it also allows to skip a hash lookup in the very common case of
logging a new GTID with same server id as last GTID. logging a new GTID with same server id as last GTID.
The base class rpl_binlog_state_base contains just be basic data operations
to insert/update GTIDs, and is used eg. from Gtid_index_*. The main class
rpl_binlog_state builds server logic on top of that like mutex locking,
gtid_strict_mode handling, etc.
*/ */
struct rpl_binlog_state struct rpl_binlog_state_base
{ {
struct element { struct element {
uint32 domain_id; uint32 domain_id;
...@@ -309,29 +319,45 @@ struct rpl_binlog_state ...@@ -309,29 +319,45 @@ struct rpl_binlog_state
int update_element(const rpl_gtid *gtid); int update_element(const rpl_gtid *gtid);
}; };
/* Mapping from domain_id to collection of elements. */ /* Mapping from domain_id to collection of elements. */
HASH hash; HASH hash;
my_bool initialized;
rpl_binlog_state_base() : initialized(0) {}
~rpl_binlog_state_base();
void init();
void reset_nolock();
void free();
bool load_nolock(struct rpl_gtid *list, uint32 count);
bool load_nolock(rpl_binlog_state_base *orig_state);
int update_nolock(const struct rpl_gtid *gtid);
int alloc_element_nolock(const rpl_gtid *gtid);
uint32 count_nolock();
int get_gtid_list_nolock(rpl_gtid *gtid_list, uint32 list_size);
rpl_gtid *find_nolock(uint32 domain_id, uint32 server_id);
bool is_before_pos(slave_connection_state *pos);
};
struct rpl_binlog_state : public rpl_binlog_state_base
{
/* Mutex protecting access to the state. */ /* Mutex protecting access to the state. */
mysql_mutex_t LOCK_binlog_state; mysql_mutex_t LOCK_binlog_state;
my_bool initialized;
/* Auxiliary buffer to sort gtid list. */ /* Auxiliary buffer to sort gtid list. */
DYNAMIC_ARRAY gtid_sort_array; DYNAMIC_ARRAY gtid_sort_array;
rpl_binlog_state() :initialized(0) {} rpl_binlog_state() {}
~rpl_binlog_state(); ~rpl_binlog_state();
void init(); void init();
void reset_nolock();
void reset(); void reset();
void free(); void free();
bool load(struct rpl_gtid *list, uint32 count); bool load(struct rpl_gtid *list, uint32 count);
bool load(rpl_slave_state *slave_pos); bool load(rpl_slave_state *slave_pos);
int update_nolock(const struct rpl_gtid *gtid, bool strict);
int update(const struct rpl_gtid *gtid, bool strict); int update(const struct rpl_gtid *gtid, bool strict);
int update_with_next_gtid(uint32 domain_id, uint32 server_id, int update_with_next_gtid(uint32 domain_id, uint32 server_id,
rpl_gtid *gtid); rpl_gtid *gtid);
int alloc_element_nolock(const rpl_gtid *gtid);
bool check_strict_sequence(uint32 domain_id, uint32 server_id, uint64 seq_no, bool check_strict_sequence(uint32 domain_id, uint32 server_id, uint64 seq_no,
bool no_error= false); bool no_error= false);
int bump_seq_no_if_needed(uint32 domain_id, uint64 seq_no); int bump_seq_no_if_needed(uint32 domain_id, uint64 seq_no);
...@@ -342,7 +368,6 @@ struct rpl_binlog_state ...@@ -342,7 +368,6 @@ struct rpl_binlog_state
int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size); int get_most_recent_gtid_list(rpl_gtid **list, uint32 *size);
bool append_pos(String *str); bool append_pos(String *str);
bool append_state(String *str); bool append_state(String *str);
rpl_gtid *find_nolock(uint32 domain_id, uint32 server_id);
rpl_gtid *find(uint32 domain_id, uint32 server_id); rpl_gtid *find(uint32 domain_id, uint32 server_id);
rpl_gtid *find_most_recent(uint32 domain_id); rpl_gtid *find_most_recent(uint32 domain_id);
const char* drop_domain(DYNAMIC_ARRAY *ids, Gtid_list_log_event *glev, char*); const char* drop_domain(DYNAMIC_ARRAY *ids, Gtid_list_log_event *glev, char*);
......
...@@ -1547,7 +1547,7 @@ Relay_log_info::update_relay_log_state(rpl_gtid *gtid_list, uint32 count) ...@@ -1547,7 +1547,7 @@ Relay_log_info::update_relay_log_state(rpl_gtid *gtid_list, uint32 count)
int res= 0; int res= 0;
while (count) while (count)
{ {
if (relay_log_state.update_nolock(gtid_list, false)) if (relay_log_state.update_nolock(gtid_list))
res= 1; res= 1;
++gtid_list; ++gtid_list;
--count; --count;
......
This diff is collapsed.
...@@ -6844,6 +6844,36 @@ Sys_binlog_row_metadata( ...@@ -6844,6 +6844,36 @@ Sys_binlog_row_metadata(
ON_UPDATE(NULL)); ON_UPDATE(NULL));
static Sys_var_on_access_global<Sys_var_mybool,
PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX>
Sys_binlog_gtid_index(
"binlog_gtid_index",
"Enable the creation of a GTID index for every binlog file, and the use "
"of such index for speeding up GTID lookup in the binlog.",
GLOBAL_VAR(opt_binlog_gtid_index), CMD_LINE(OPT_ARG),
DEFAULT(TRUE));
static Sys_var_on_access_global<Sys_var_uint,
PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX_PAGE_SIZE>
Sys_binlog_gtid_index_page_size(
"binlog_gtid_index_page_size",
"Page size to use for the binlog GTID index.",
GLOBAL_VAR(opt_binlog_gtid_index_page_size), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(64, 1<<24), DEFAULT(4096), BLOCK_SIZE(1));
static Sys_var_on_access_global<Sys_var_uint,
PRIV_SET_SYSTEM_GLOBAL_VAR_BINLOG_GTID_INDEX_SPAN_MIN>
Sys_binlog_gtid_index_span_min(
"binlog_gtid_index_span_min",
"Control sparseness of the binlog GTID index. If set to N, at most one "
"index record will be added for every N bytes of binlog file written, "
"to reduce the size of the index. Normally does not need tuning.",
GLOBAL_VAR(opt_binlog_gtid_index_span_min), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1, 1024*1024L*1024L), DEFAULT(65536), BLOCK_SIZE(1));
static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var) static bool check_pseudo_slave_mode(sys_var *self, THD *thd, set_var *var)
{ {
longlong previous_val= thd->variables.pseudo_slave_mode; longlong previous_val= thd->variables.pseudo_slave_mode;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment