1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Merge 10.5 into 10.6

This commit is contained in:
Marko Mäkelä
2025-01-20 09:57:37 +02:00
142 changed files with 3642 additions and 828 deletions

View File

@@ -1,23 +1,115 @@
# MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-datetime
set timestamp=1000000000;
CREATE TABLE t1(word VARCHAR(20));
set timestamp=1000000010;
INSERT INTO t1 VALUES ("abirvalg");
set timestamp=1000000020;
INSERT INTO t1 SELECT * FROM t1;
flush logs;
Case: Default, must not see warning.
# MYSQL_BINLOG --short-form MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
Case: Stop datetime before EOF, must not see warning.
# MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:50' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
Case: Stop datetime between records, must not see warning.
# MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
Case: Stop datetime at EOF, must not see warning.
# MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
Case: Stop datetime after EOF, must see warning.
# MYSQL_BINLOG --short-form --stop-datetime='2035-01-19 03:14:05' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
WARNING: Did not reach stop datetime '2035-01-19 03:14:05' before end of input
DROP TABLE t1;
SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-01 10:20:30.123456');
#
# Clear the existing binary log state, and start fresh using
# the timestamp variable set above
#
RESET MASTER;
create table t1 (a int);
insert into t1 values (1);
SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-02 10:20:30.123456');
insert into t1 values (2);
SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-03 10:20:30.123456');
flush binary logs;
SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-04 10:20:30.123456');
insert into t1 values (3);
insert into t1 values (4);
SET TIMESTAMP= UNIX_TIMESTAMP('2024-12-05 10:20:30.123456');
insert into t1 values (5);
insert into t1 values (6);
insert into t1 values (7);
SET TIMESTAMP=UNIX_TIMESTAMP('2024-12-06 10:20:30.123456');
flush binary logs;
drop table t1;
# Ensuring binary log order is correct
#
#
# Test using --read-from-remote-server
#
connection default;
#
# --stop-datetime tests
# Note: MDEV-35528 reported that mysqlbinlog would fail on tests cases
# 2.a, 2.b, and 2.c.
#
# Case 1.a) With one binlog file, a --stop-datetime before the end of
# the file should not result in a warning
# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-02 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1
#
# Case 1.b) With one binlog file, a --stop-datetime at the end of the
# file should not result in a warning
# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-03 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1
#
# Case 1.c) With one binlog file, a --stop-datetime beyond the end of
# the file should(!) result in a warning
# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1
WARNING: Did not reach stop datetime '2024-12-04 10:20:30.123456' before end of input
#
# Case 2.a) With two binlog files, a --stop-datetime within the
# timespan of binlog 2 should:
# 1) not provide any warnings
# 2) not prevent binlog 1 or 2 from outputting the desired events
# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1
include/assert_grep.inc [Ensure all intended GTIDs are present]
include/assert_grep.inc [Ensure the next GTID binlogged is _not_ present]
#
# Case 2.b) With two binlog files, a --stop-datetime at the end of
# binlog 2 should:
# 1) not provide any warnings
# 2) not prevent binlog 1 or 2 from outputting all events
# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-06 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1
include/assert_grep.inc [Ensure a GTID exists for each transaction]
#
# Case 2.c) With two binlog files, a --stop-datetime beyond the end of
# binlog 2 should:
# 1) provide a warning that the stop datetime was not reached
# 2) not prevent binlog 1 or 2 from outputting all events
# MYSQL_BINLOG --read-from-remote-server --stop-datetime='2024-12-07 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1
WARNING: Did not reach stop datetime '2024-12-07 10:20:30.123456' before end of input
include/assert_grep.inc [Ensure a GTID exists for each transaction]
#
#
# Test using local binlog files
#
connection default;
#
# --stop-datetime tests
# Note: MDEV-35528 reported that mysqlbinlog would fail on tests cases
# 2.a, 2.b, and 2.c.
#
# Case 1.a) With one binlog file, a --stop-datetime before the end of
# the file should not result in a warning
# MYSQL_BINLOG --stop-datetime='2024-12-02 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1
#
# Case 1.b) With one binlog file, a --stop-datetime at the end of the
# file should not result in a warning
# MYSQL_BINLOG --stop-datetime='2024-12-03 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1
#
# Case 1.c) With one binlog file, a --stop-datetime beyond the end of
# the file should(!) result in a warning
# MYSQL_BINLOG --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full --result-file=tmp/warn_datetime_test_file.out 2>&1
WARNING: Did not reach stop datetime '2024-12-04 10:20:30.123456' before end of input
#
# Case 2.a) With two binlog files, a --stop-datetime within the
# timespan of binlog 2 should:
# 1) not provide any warnings
# 2) not prevent binlog 1 or 2 from outputting the desired events
# MYSQL_BINLOG --stop-datetime='2024-12-04 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1
include/assert_grep.inc [Ensure all intended GTIDs are present]
include/assert_grep.inc [Ensure the next GTID binlogged is _not_ present]
#
# Case 2.b) With two binlog files, a --stop-datetime at the end of
# binlog 2 should:
# 1) not provide any warnings
# 2) not prevent binlog 1 or 2 from outputting all events
# MYSQL_BINLOG --stop-datetime='2024-12-06 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1
include/assert_grep.inc [Ensure a GTID exists for each transaction]
#
# Case 2.c) With two binlog files, a --stop-datetime beyond the end of
# binlog 2 should:
# 1) provide a warning that the stop datetime was not reached
# 2) not prevent binlog 1 or 2 from outputting all events
# MYSQL_BINLOG --stop-datetime='2024-12-07 10:20:30.123456' binlog_f1_full binlog_f2_full --result-file=tmp/warn_datetime_test_file.out 2>&1
WARNING: Did not reach stop datetime '2024-12-07 10:20:30.123456' before end of input
include/assert_grep.inc [Ensure a GTID exists for each transaction]
#
# End of binlog_mysqlbinlog_warn_stop_datetime.test

View File

@@ -1,13 +1,65 @@
# MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-condition
Case: Default stop position, WARNING must not appear
# MYSQL_BINLOG --short-form --start-position=4 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
Case: Stop position before EOF, WARNING must not appear
# MYSQL_BINLOG --short-form --start-position=4 --stop-position=97 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
Case: Stop position at EOF, WARNING must not appear
# MYSQL_BINLOG --short-form --start-position=4 --stop-position=98 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
Case: Stop position after EOF, WARNING must appear
# MYSQL_BINLOG --short-form --start-position=4 --stop-position=99 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
WARNING: Did not reach stop position 99 before end of input
#
# Clear the existing binary log state.
#
RESET MASTER;
create table t1 (a int);
insert into t1 values (1);
insert into t1 values (2);
flush binary logs;
insert into t1 values (3);
# Tag binlog_f2_mid
insert into t1 values (4);
insert into t1 values (5);
insert into t1 values (6);
insert into t1 values (7);
flush binary logs;
drop table t1;
# Ensuring binary log order is correct
# Ensuring file offset of binlog_f2_mid < binlog_f1_end
#
#
# Test using local binlog files
#
connection default;
#
# --stop-position tests
#
# Case 1.a) With one binlog file, a --stop-position before the end of
# the file should not result in a warning
# MYSQL_BINLOG --stop-position=binlog_f1_pre_rotate binlog_f1_full --result-file=tmp/warn_position_test_file.out 2>&1
#
# Case 1.b) With one binlog file, a --stop-position at the exact end of
# the file should not result in a warning
# MYSQL_BINLOG --stop-position=binlog_f1_end binlog_f1_full --result-file=tmp/warn_position_test_file.out 2>&1
#
# Case 1.c) With one binlog file, a --stop-position past the end of the
# file should(!) result in a warning
# MYSQL_BINLOG --short-form --stop-position=binlog_f1_over_eof binlog_f1_full --result-file=tmp/warn_position_test_file.out 2>&1
WARNING: Did not reach stop position <BINLOG_F1_OVER_EOF> before end of input
#
# Case 2.a) With two binlog files, a --stop-position targeting b2 which
# exists in the size of b1 should:
# 1) not provide any warnings
# 2) not prevent b2 from outputting its desired events before the
# stop position
# MYSQL_BINLOG --stop-position=binlog_f2_mid binlog_f1_full binlog_f2_full --result-file=tmp/warn_position_test_file.out 2>&1
include/assert_grep.inc [Ensure all intended GTIDs are present]
include/assert_grep.inc [Ensure the next GTID binlogged is _not_ present]
#
# Case 2.b) With two binlog files, a --stop-position targeting the end
# of binlog 2 should:
# 1) not provide any warnings
# 2) not prevent b2 from outputting its entire binary log
# MYSQL_BINLOG --stop-position=binlog_f2_end binlog_f1_full binlog_f2_full --result-file=tmp/warn_position_test_file.out 2>&1
include/assert_grep.inc [Ensure a GTID exists for each transaction]
include/assert_grep.inc [Ensure the last GTID binlogged is present]
#
# Case 2.c) With two binlog files, a --stop-position targeting beyond
# the eof of binlog 2 should:
# 1) provide a warning that the stop position was not reached
# 2) not prevent b2 from outputting its entire binary log
# MYSQL_BINLOG --stop-position=binlog_f2_over_eof binlog_f1_full binlog_f2_full --result-file=tmp/warn_position_test_file.out 2>&1
WARNING: Did not reach stop position <BINLOG_F2_OVER_EOF> before end of input
include/assert_grep.inc [Ensure a GTID exists for each transaction]
#
# End of binlog_mysqlbinlog_warn_stop_position.test

View File

@@ -0,0 +1,106 @@
#
# Helper file that ensures mysqlbinlog --stop-datetime behavior for local
# files or a remote server
#
# Parameters:
# read_from_remote_server (bool): A boolean that changes which source to use
# for mysqlbinlog. When true, reads remotely; when false, uses local files.
#
--connection default
--let $MYSQLD_DATADIR= `select @@datadir`
# PARAM_READ_FROM_REMOTE is used as a parameter to mysqlbinlog (_OUT suffix is
# output in echo commands). If using local files, they are blank; if reading
# from remote server, it is overridden to the correct values.
--let $PARAM_READ_FROM_REMOTE=
# Used in echo statements to remove potentially changing values
--let $PARAM_READ_FROM_REMOTE_OUT=
if ($read_from_remote_server)
{
--let $PARAM_READ_FROM_REMOTE= --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT
--let $PARAM_READ_FROM_REMOTE_OUT= --read-from-remote-server
# binlog files in --read-from-remote-server don't use file system path
--let $binlog_f1_full= $binlog_f1
--let $binlog_f2_full= $binlog_f2
}
if (!$read_from_remote_server)
{
# If using local files, file system path to the binlog files is needed
--let $binlog_f1_full= $MYSQLD_DATADIR/$binlog_f1
--let $binlog_f2_full= $MYSQLD_DATADIR/$binlog_f2
}
--echo #
--echo # --stop-datetime tests
--echo # Note: MDEV-35528 reported that mysqlbinlog would fail on tests cases
--echo # 2.a, 2.b, and 2.c.
--echo #
--echo # Case 1.a) With one binlog file, a --stop-datetime before the end of
--echo # the file should not result in a warning
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b1_timestamp2' binlog_f1_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b1_timestamp2' $binlog_f1_full --result-file=$binlog_out 2>&1
--echo #
--echo # Case 1.b) With one binlog file, a --stop-datetime at the end of the
--echo # file should not result in a warning
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b1_timestamp3' binlog_f1_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b1_timestamp3' $binlog_f1_full --result-file=$binlog_out 2>&1
--echo #
--echo # Case 1.c) With one binlog file, a --stop-datetime beyond the end of
--echo # the file should(!) result in a warning
--let $future_timestamp= 2035-12-06 10:20:30.123456
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp1' binlog_f1_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp1' $binlog_f1_full --result-file=$binlog_out 2>&1
--echo #
--echo # Case 2.a) With two binlog files, a --stop-datetime within the
--echo # timespan of binlog 2 should:
--echo # 1) not provide any warnings
--echo # 2) not prevent binlog 1 or 2 from outputting the desired events
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp1' binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp1' $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1
--let $server_id= `SELECT @@GLOBAL.server_id`
--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id`
--let $assert_file= $binlog_out
--let $assert_text= Ensure all intended GTIDs are present
--let $assert_select= GTID $domain_id-$server_id-
--let $assert_count= 3
--source include/assert_grep.inc
--let $assert_text= Ensure the next GTID binlogged is _not_ present
--let $assert_select= GTID $binlog_f2_gtid_after_midpoint
--let $assert_count= 0
--source include/assert_grep.inc
--echo #
--echo # Case 2.b) With two binlog files, a --stop-datetime at the end of
--echo # binlog 2 should:
--echo # 1) not provide any warnings
--echo # 2) not prevent binlog 1 or 2 from outputting all events
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp3' binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp3' $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1
--let $assert_text= Ensure a GTID exists for each transaction
--let $assert_select= GTID $domain_id-$server_id-
--let $assert_count= 8
--source include/assert_grep.inc
--echo #
--echo # Case 2.c) With two binlog files, a --stop-datetime beyond the end of
--echo # binlog 2 should:
--echo # 1) provide a warning that the stop datetime was not reached
--echo # 2) not prevent binlog 1 or 2 from outputting all events
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-datetime='$b2_timestamp_not_reached' binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-datetime='$b2_timestamp_not_reached' $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1
--let $assert_text= Ensure a GTID exists for each transaction
--let $assert_select= GTID $domain_id-$server_id-
--let $assert_count= 8
--source include/assert_grep.inc

View File

@@ -1,42 +1,86 @@
--echo
--echo # MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-datetime
--echo
#
# Test ensures that --stop-datetime work correctly for mysqlbinlog. This high
# level test sets up the binary log (and tags certain locations for comparison),
# and the helper file binlog_mysqlbinlog_warn_stop_datetime.inc performs the
# actual tests.
#
# References:
# MDEV-27037: mysqlbinlog emits a warning when reaching EOF before
# stop-condition
# MDEV-35528: mariadb-binlog cannot process more than 1 logfiles when
# --stop-datetime is specified
#
--source include/have_log_bin.inc
--source include/have_binlog_format_statement.inc
--let $binlog_out_relpath= tmp/warn_datetime_test_file.out
--let $binlog_out= $MYSQLTEST_VARDIR/$binlog_out_relpath
--let ignored_output_file= $MYSQLTEST_VARDIR/tmp/warn_pos_test_file.out
--let $b1_timestamp1= 2024-12-01 10:20:30.123456
--let $b1_timestamp2= 2024-12-02 10:20:30.123456
--let $b1_timestamp3= 2024-12-03 10:20:30.123456
--let $b2_timestamp1= 2024-12-04 10:20:30.123456
--let $b2_timestamp2= 2024-12-05 10:20:30.123456
--let $b2_timestamp3= 2024-12-06 10:20:30.123456
--let $b2_timestamp_not_reached= 2024-12-07 10:20:30.123456
set timestamp=1000000000;
CREATE TABLE t1(word VARCHAR(20));
set timestamp=1000000010;
INSERT INTO t1 VALUES ("abirvalg");
set timestamp=1000000020;
INSERT INTO t1 SELECT * FROM t1;
--let MYSQLD_DATADIR= `select @@datadir;`
flush logs;
--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b1_timestamp1')
--echo Case: Default, must not see warning.
--echo # MYSQL_BINLOG --short-form MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
--exec $MYSQL_BINLOG --short-form $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1
--echo #
--echo # Clear the existing binary log state, and start fresh using
--echo # the timestamp variable set above
--echo #
RESET MASTER;
--echo Case: Stop datetime before EOF, must not see warning.
--echo # MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:50' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
--exec $MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:50' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1
--let $binlog_f1= query_get_value(SHOW MASTER STATUS, File, 1)
create table t1 (a int);
insert into t1 values (1);
--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b1_timestamp2')
insert into t1 values (2);
--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b1_timestamp3')
flush binary logs;
--let $binlog_f2= query_get_value(SHOW MASTER STATUS, File, 1)
--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b2_timestamp1')
insert into t1 values (3);
insert into t1 values (4);
--eval SET TIMESTAMP= UNIX_TIMESTAMP('$b2_timestamp2')
--let $binlog_f2_gtid_after_midpoint= `SELECT @@GLOBAL.gtid_binlog_pos`
insert into t1 values (5);
insert into t1 values (6);
insert into t1 values (7);
--let $binlog_f2_last_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
--eval SET TIMESTAMP=UNIX_TIMESTAMP('$b2_timestamp3')
flush binary logs;
drop table t1;
--echo Case: Stop datetime between records, must not see warning.
--echo # MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
--exec $MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1
--echo # Ensuring binary log order is correct
--let $binlog_f1_show= query_get_value(SHOW BINARY LOGS, Log_name, 1)
if (`SELECT strcmp('$binlog_f1','$binlog_f1_show') != 0`)
{
--echo # Real binlog_f1: $binlog_f1
--echo # First binlog in SHOW BINLOG FILES: $binlog_f1_show
--die Wrong order of binary log files in SHOW BINARY LOGS
}
--let $binlog_f2_show= query_get_value(SHOW BINARY LOGS, Log_name, 2)
if (`SELECT strcmp('$binlog_f2','$binlog_f2_show') != 0`)
{
--echo # Real binlog_f2: $binlog_f2
--echo # First binlog in SHOW BINLOG FILES: $binlog_f2_show
--die Wrong order of binary log files in SHOW BINARY LOGS
}
--echo Case: Stop datetime at EOF, must not see warning.
--echo # MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
--exec $MYSQL_BINLOG --short-form --stop-datetime='2001-09-08 21:46:55' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1
--echo #
--echo #
--echo # Test using --read-from-remote-server
--echo #
--let $read_from_remote_server= 1
--source binlog_mysqlbinlog_warn_stop_datetime.inc
--echo Case: Stop datetime after EOF, must see warning.
--echo # MYSQL_BINLOG --short-form --stop-datetime='2035-01-19 03:14:05' MYSQLD_DATADIR/master-bin.000001 --result-file=ignored_output_file
--exec $MYSQL_BINLOG --short-form --stop-datetime='2035-01-19 03:14:05' $MYSQLD_DATADIR/master-bin.000001 --result-file=$ignored_output_file 2>&1
DROP TABLE t1;
--remove_file $ignored_output_file
--echo #
--echo #
--echo # Test using local binlog files
--echo #
--let $read_from_remote_server= 0
--source binlog_mysqlbinlog_warn_stop_datetime.inc
--echo #
--echo # End of binlog_mysqlbinlog_warn_stop_datetime.test

View File

@@ -0,0 +1,115 @@
#
# Helper file that ensures mysqlbinlog --stop-position behavior for local
# files or a remote server
#
# Parameters:
# read_from_remote_server (bool): A boolean that changes which source to use
# for mysqlbinlog. When true, reads remotely; when false, uses local files.
#
--connection default
--let $MYSQLD_DATADIR= `select @@datadir`
# PARAM_READ_FROM_REMOTE is used as a parameter to mysqlbinlog (_OUT suffix is
# output in echo commands). If using local files, they are blank; if reading
# from remote server, it is overridden to the correct values.
--let $PARAM_READ_FROM_REMOTE=
# Used in echo statements to remove potentially changing values
--let $PARAM_READ_FROM_REMOTE_OUT=
if ($read_from_remote_server)
{
--let $PARAM_READ_FROM_REMOTE= --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT
--let $PARAM_READ_FROM_REMOTE_OUT= --read-from-remote-server
# binlog files in --read-from-remote-server don't use file system path
--let $binlog_f1_full= $binlog_f1
--let $binlog_f2_full= $binlog_f2
}
if (!$read_from_remote_server)
{
# If using local files, file system path to the binlog files is needed
--let $binlog_f1_full= $MYSQLD_DATADIR/$binlog_f1
--let $binlog_f2_full= $MYSQLD_DATADIR/$binlog_f2
}
--echo #
--echo # --stop-position tests
--echo #
--echo # Case 1.a) With one binlog file, a --stop-position before the end of
--echo # the file should not result in a warning
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f1_pre_rotate binlog_f1_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f1_pre_rotate $binlog_f1_full --result-file=$binlog_out 2>&1
--echo #
--echo # Case 1.b) With one binlog file, a --stop-position at the exact end of
--echo # the file should not result in a warning
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f1_end binlog_f1_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f1_end $binlog_f1_full --result-file=$binlog_out 2>&1
--echo #
--echo # Case 1.c) With one binlog file, a --stop-position past the end of the
--echo # file should(!) result in a warning
--let $binlog_f1_over_eof= `SELECT $binlog_f1_end + 1`
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --short-form --stop-position=binlog_f1_over_eof binlog_f1_full --result-file=$binlog_out_relpath 2>&1
--replace_result $binlog_f1_over_eof <BINLOG_F1_OVER_EOF>
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --short-form --stop-position=$binlog_f1_over_eof $binlog_f1_full --result-file=$binlog_out 2>&1
--echo #
--echo # Case 2.a) With two binlog files, a --stop-position targeting b2 which
--echo # exists in the size of b1 should:
--echo # 1) not provide any warnings
--echo # 2) not prevent b2 from outputting its desired events before the
--echo # stop position
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f2_mid binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f2_mid $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1
--let $server_id= `SELECT @@GLOBAL.server_id`
--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id`
--let $assert_file= $binlog_out
--let $assert_text= Ensure all intended GTIDs are present
--let $assert_select= GTID $domain_id-$server_id-
--let $assert_count= 4
--source include/assert_grep.inc
--let $assert_text= Ensure the next GTID binlogged is _not_ present
--let $assert_select= GTID $binlog_f2_gtid_after_midpoint
--let $assert_count= 0
--source include/assert_grep.inc
--echo #
--echo # Case 2.b) With two binlog files, a --stop-position targeting the end
--echo # of binlog 2 should:
--echo # 1) not provide any warnings
--echo # 2) not prevent b2 from outputting its entire binary log
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f2_end binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f2_end $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1
--let $server_id= `SELECT @@GLOBAL.server_id`
--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id`
--let $assert_text= Ensure a GTID exists for each transaction
--let $assert_select= GTID $domain_id-$server_id-
--let $assert_count= 8
--source include/assert_grep.inc
--let $assert_text= Ensure the last GTID binlogged is present
--let $assert_select= GTID $binlog_f2_last_gtid
--let $assert_count= 1
--source include/assert_grep.inc
--echo #
--echo # Case 2.c) With two binlog files, a --stop-position targeting beyond
--echo # the eof of binlog 2 should:
--echo # 1) provide a warning that the stop position was not reached
--echo # 2) not prevent b2 from outputting its entire binary log
--let $binlog_f2_over_eof= `SELECT $binlog_f2_end + 1`
--echo # MYSQL_BINLOG $PARAM_READ_FROM_REMOTE_OUT --stop-position=binlog_f2_over_eof binlog_f1_full binlog_f2_full --result-file=$binlog_out_relpath 2>&1
--replace_result $binlog_f2_over_eof <BINLOG_F2_OVER_EOF>
--exec $MYSQL_BINLOG $PARAM_READ_FROM_REMOTE --stop-position=$binlog_f2_over_eof $binlog_f1_full $binlog_f2_full --result-file=$binlog_out 2>&1
--let $server_id= `SELECT @@GLOBAL.server_id`
--let $domain_id= `SELECT @@GLOBAL.gtid_domain_id`
--let $assert_text= Ensure a GTID exists for each transaction
--let $assert_select= GTID $domain_id-$server_id-
--let $assert_count= 8
--source include/assert_grep.inc

View File

@@ -1,26 +1,83 @@
--echo
--echo # MDEV-27037 mysqlbinlog emits a warning when reaching EOF before stop-condition
--echo
#
# Test ensures that --stop-position work correctly for mysqlbinlog. This high
# level test sets up the binary log (and tags certain locations for comparison),
# and the helper file binlog_mysqlbinlog_warn_stop_position.inc performs the
# actual tests.
#
# References:
# MDEV-27037: mysqlbinlog emits a warning when reaching EOF before
# stop-condition
#
--source include/have_log_bin.inc
--let assert_file= $MYSQLTEST_VARDIR/tmp/warn_pos_test_file.out
--let data_file= $MYSQLTEST_VARDIR/std_data/master-bin.000001
--let $binlog_out_relpath= tmp/warn_position_test_file.out
--let $binlog_out= $MYSQLTEST_VARDIR/$binlog_out_relpath
--echo Case: Default stop position, WARNING must not appear
--echo # MYSQL_BINLOG --short-form --start-position=4 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
--exec $MYSQL_BINLOG --short-form --start-position=4 $data_file --result-file=$assert_file 2>&1
--echo #
--echo # Clear the existing binary log state.
--echo #
RESET MASTER;
--echo Case: Stop position before EOF, WARNING must not appear
--echo # MYSQL_BINLOG --short-form --start-position=4 --stop-position=97 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
--exec $MYSQL_BINLOG --short-form --start-position=4 --stop-position=97 $data_file --result-file=$assert_file 2>&1
--let $binlog_f1= query_get_value(SHOW MASTER STATUS, File, 1)
create table t1 (a int);
insert into t1 values (1);
insert into t1 values (2);
--let $binlog_f1_pre_rotate= query_get_value(SHOW MASTER STATUS, Position, 1)
flush binary logs;
--let $binlog_f2= query_get_value(SHOW MASTER STATUS, File, 1)
insert into t1 values (3);
--echo # Tag binlog_f2_mid
--let $binlog_f2_mid= query_get_value(SHOW MASTER STATUS, Position, 1)
insert into t1 values (4);
--let $binlog_f2_gtid_after_midpoint= `SELECT @@GLOBAL.gtid_binlog_pos`
insert into t1 values (5);
insert into t1 values (6);
insert into t1 values (7);
--let $binlog_f2_last_gtid= `SELECT @@GLOBAL.gtid_binlog_pos`
--let $binlog_f2_pre_rot= query_get_value(SHOW MASTER STATUS, Position, 1)
flush binary logs;
drop table t1;
--echo Case: Stop position at EOF, WARNING must not appear
--echo # MYSQL_BINLOG --short-form --start-position=4 --stop-position=98 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
--exec $MYSQL_BINLOG --short-form --start-position=4 --stop-position=98 $data_file --result-file=$assert_file 2>&1
--echo # Ensuring binary log order is correct
--let $binlog_f1_show= query_get_value(SHOW BINARY LOGS, Log_name, 1)
--let $binlog_f1_end= query_get_value(SHOW BINARY LOGS, File_size, 1)
if (`SELECT strcmp('$binlog_f1','$binlog_f1_show') != 0`)
{
--echo # Real binlog_f1: $binlog_f1
--echo # First binlog in SHOW BINLOG FILES: $binlog_f1_show
--die Wrong order of binary log files in SHOW BINARY LOGS
}
--let $binlog_f2_show= query_get_value(SHOW BINARY LOGS, Log_name, 2)
--let $binlog_f2_end= query_get_value(SHOW BINARY LOGS, File_size, 2)
if (`SELECT strcmp('$binlog_f2','$binlog_f2_show') != 0`)
{
--echo # Real binlog_f2: $binlog_f2
--echo # First binlog in SHOW BINLOG FILES: $binlog_f2_show
--die Wrong order of binary log files in SHOW BINARY LOGS
}
--echo Case: Stop position after EOF, WARNING must appear
--echo # MYSQL_BINLOG --short-form --start-position=4 --stop-position=99 mysql-test/std_data/master-bin.000001 --result-file=warn_pos_test_file.out 2>&1
--exec $MYSQL_BINLOG --short-form --start-position=4 --stop-position=99 $data_file --result-file=$assert_file 2>&1
--echo # Ensuring file offset of binlog_f2_mid < binlog_f1_end
if ($binlog_f2_mid > $binlog_f1_end)
{
--echo # Binlog 1 end: $binlog_f1:$binlog_f1_end
--echo # Binlog 2 stop point: $binlog_f2:$binlog_f2_mid
--die Mid point chosen to end in binlog 2 does not exist in earlier binlog
}
--remove_file $assert_file
#--echo #
#--echo #
#--echo # Test using --read-from-remote-server
#--echo #
#--let $read_from_remote_server= 1
#--emit warning is not supported by --read-from-remote-server now
#--source binlog_mysqlbinlog_warn_stop_position.inc
--echo #
--echo #
--echo # Test using local binlog files
--echo #
--let $read_from_remote_server= 0
--source binlog_mysqlbinlog_warn_stop_position.inc
--echo #
--echo # End of binlog_mysqlbinlog_warn_stop_position.test

View File

@@ -26,7 +26,7 @@ LTRIM(now()) AS a0,
LPAD(now(),10) AS b0;
/*M!999999\- enable the sandbox mode */
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`a0` varchar(64) NOT NULL DEFAULT ltrim(current_timestamp()),
`a1` varchar(64) GENERATED ALWAYS AS (ltrim(`a0`)) STORED,
@@ -35,7 +35,7 @@ CREATE TABLE `t1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t2` (
`a0` varchar(64) NOT NULL DEFAULT ltrim_oracle(current_timestamp()),
`a1` varchar(64) GENERATED ALWAYS AS (ltrim_oracle(`a0`)) STORED,
@@ -44,13 +44,13 @@ CREATE TABLE `t2` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1 COLLATE=latin1_swedish_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `v1` AS SELECT
1 AS `a0`,
1 AS `b0` */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `v2` AS SELECT
1 AS `a0`,
1 AS `b0` */;

View File

@@ -2245,7 +2245,7 @@ CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/test/t1';
# Dump table t1 using mysqldump tool
/*M!999999\- enable the sandbox mode */
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`id` varchar(20) NOT NULL,
PRIMARY KEY (`id`)

View File

@@ -0,0 +1,70 @@
#
# This .cnf file creates a setup with 2 standard MariaDB servers, followed by a 2-node Galera cluster
#
# Use default setting for mysqld processes
!include include/default_mysqld.cnf
[mysqld]
loose-innodb
log-bin=mysqld-bin
log-slave-updates
binlog-format=row
innodb-autoinc-lock-mode=2
default-storage-engine=innodb
# enforce read-committed characteristics across the cluster
# wsrep-causal-reads=ON
wsrep-sync-wait=15
[mysqld.1]
wsrep-on=1
server-id=1
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep_provider=@ENV.WSREP_PROVIDER
wsrep_cluster_address=gcomm://
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.1.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M'
wsrep_node_address='127.0.0.1:@mysqld.1.#galera_port'
wsrep_node_incoming_address=127.0.0.1:@mysqld.1.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.1.#sst_port'
[mysqld.2]
wsrep-on=1
server-id=2
#galera_port=@OPT.port
#ist_port=@OPT.port
#sst_port=@OPT.port
wsrep_provider=@ENV.WSREP_PROVIDER
wsrep_cluster_address='gcomm://127.0.0.1:@mysqld.1.#galera_port'
wsrep_provider_options='repl.causal_read_timeout=PT90S;base_port=@mysqld.2.#galera_port;evs.suspect_timeout=PT10S;evs.inactive_timeout=PT30S;evs.install_timeout=PT15S;gcache.size=10M'
wsrep_node_address='127.0.0.1:@mysqld.2.#galera_port'
wsrep_node_incoming_address=127.0.0.1:@mysqld.2.port
wsrep_sst_receive_address='127.0.0.1:@mysqld.2.#sst_port'
[mysqld.3]
wsrep-on=OFF
server-id=3
gtid_domain_id=3
[mysqld.4]
wsrep-on=OFF
server-id=4
gtid_domain_id=4
[sst]
sst-log-archive-dir=@ENV.MYSQLTEST_VARDIR/log
[ENV]
NODE_MYPORT_1= @mysqld.1.port
NODE_MYSOCK_1= @mysqld.1.socket
NODE_MYPORT_2= @mysqld.2.port
NODE_MYSOCK_2= @mysqld.2.socket
NODE_MYPORT_3= @mysqld.3.port
NODE_MYSOCK_3= @mysqld.3.socket
NODE_MYPORT_4= @mysqld.4.port
NODE_MYSOCK_4= @mysqld.4.socket

View File

@@ -0,0 +1,95 @@
connection node_2;
connection node_1;
connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_4;
connection primary1;
# Primary1 creating user for replication
create user repl@'%' identified by 'repl';
grant all on *.* to repl@'%';
connection primary2;
# Primary2 creating user for replication
create user repl2@'%' identified by 'repl2';
grant all on *.* to repl2@'%';
connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connection replica;
connection node_2;
connection replica;
# Galera replica changing master to primary1
SET @@default_master_connection='stream2';
# Primary node changing master to primary2
START ALL SLAVES;
Warnings:
Note 1937 SLAVE 'stream1' started
Note 1937 SLAVE 'stream2' started
connection primary1;
# Primary 1: Creating table and populating it with data
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection primary2;
# Primary 2: Creating table and populating it with data
CREATE TABLE t2 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_1000 FROM t2;
EXPECT_1000
1000
connection replica;
# Waiting for data to replicate to node_1
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
SELECT COUNT(*) AS EXPECT_1000 FROM t2;
EXPECT_1000
1000
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
3-3-1003,4-4-1003 3-3-1003,4-4-1003 3-3-1003,4-4-1003
connection node_2;
# Waiting for data to replicate to node_2
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
SELECT COUNT(*) AS EXPECT_1000 FROM t2;
EXPECT_1000
1000
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
3-3-1003,4-4-1003 3-3-1003,4-4-1003 3-3-1003,4-4-1003
connection primary1;
drop table t1;
connection primary2;
drop table t2;
# Wait until drop table is replicated on Galera
connection replica;
connection node_2;
connection replica;
STOP ALL SLAVES;
Warnings:
Note 1938 SLAVE 'stream1' stopped
Note 1938 SLAVE 'stream2' stopped
RESET SLAVE ALL;
connection primary1;
RESET MASTER;
connection primary2;
RESET MASTER;
connection node_1;
disconnect primary1;
disconnect primary2;
disconnect replica;
disconnect node_2;
disconnect node_1;
# End of test

View File

@@ -0,0 +1,138 @@
connection node_2;
connection node_1;
connect replica1, 127.0.0.1, root, , test, $NODE_MYPORT_1;
connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_4;
connect replica2, 127.0.0.1, root, , test, $NODE_MYPORT_4;
connection primary1;
# Primary1 node creating user for replication
create user repl@'%' identified by 'repl';
grant all on *.* to repl@'%';
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
connection replica1;
connection node_2;
connection primary2;
connection replica1;
# Galera replica changing master to primary1
START SLAVE;
connection primary2;
# Primary2 creating user for replication
create user repl2@'%' identified by 'repl2';
grant all on *.* to repl2@'%';
connection replica2;
# replica2 changing master to primary2
START SLAVE;
connection primary1;
# Primary1: Creating table and populating it with data
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection replica1;
# Waiting for data to replicate to replica
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
# Writing more data to table
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
EXPECT_2000
2000
connection node_2;
# Waiting for data to replicate to Galera node_2
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
EXPECT_2000
2000
# Writing more data to table
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_3000 FROM t1;
EXPECT_3000
3000
connection primary2;
# Waiting for data to replicate to primary2
SELECT COUNT(*) AS EXPECT_3000 FROM t1;
EXPECT_3000
3000
# Writing more data to table
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
EXPECT_4000
4000
connection primary1;
# Waiting for data to replicate to primary1
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
EXPECT_4000
4000
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-4-1004,16-15-3002 0-4-1004,16-15-3002 0-4-1004,16-15-3002
connection replica1;
# Waiting for data to replicate to replica
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
EXPECT_4000
4000
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-4-1004,16-15-3002 0-4-1004,16-15-3002 0-4-1004,16-15-3002
connection node_2;
# Waiting for data to replicate to node_2
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
EXPECT_4000
4000
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-4-1004 0-4-1004,16-15-3002 0-4-1004,16-15-3002
connection primary2;
# Waiting for data to replicate to node_3
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
EXPECT_4000
4000
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-4-1004 0-4-1004,16-15-3002 0-4-1004,16-15-3002
connection primary1;
drop table t1;
# Wait until drop table is replicated on Galera
connection replica1;
connection node_2;
connection primary2;
connection replica1;
STOP SLAVE;
RESET SLAVE ALL;
connection replica2;
STOP SLAVE;
RESET SLAVE ALL;
RESET MASTER;
connection node_1;
disconnect primary1;
disconnect replica1;
disconnect primary2;
disconnect replica2;
disconnect node_2;
disconnect node_1;
# End of test

View File

@@ -1,122 +1,169 @@
connection node_2;
connection node_1;
connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3;
connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_2;
connect primary, 127.0.0.1, root, , test, $NODE_MYPORT_3;
create user repl@'%' identified by 'repl';
grant all on *.* to repl@'%';
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
connection node_1;
connection node_2;
connection node_2;
connection replica;
connection replica;
START SLAVE;
connection node_3;
CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
connection node_2;
connection primary;
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection replica;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-1004 0-3-1004 0-3-1004
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection node_1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
connection node_2;
# Verify that graceful shutdown succeeds.
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-1004 0-3-1004 0-3-1004
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection replica;
# Verify that graceful shutdown succeeds in replica.
# Force SST
connection node_1;
# Waiting until node_2 is not part of cluster anymore
connection node_2;
# Start node_2 again
¤ Wait until node_2 is back on cluster
connection node_2;
# Waiting until replica is not part of cluster anymore
connection replica;
# Start replica again
# Wait until replica is back on cluster
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-1004 0-3-1004 0-3-1004
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection node_1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
connection node_3;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
connection node_3;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-1004 0-3-1004 0-3-1004
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection primary;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
drop table t1;
connection node_2;
connection replica;
connection node_1;
connection node_3;
CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
connection node_2;
connection primary;
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection replica;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-2006 0-3-2006 0-3-2006
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
EXPECT_1000
1000
connection node_1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
EXPECT_10000
10000
connection node_2;
# Verify that graceful shutdown succeeds.
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-2006 0-3-2006 0-3-2006
connection replica;
# Verify that graceful shutdown succeeds in replica.
# Force SST
connection node_1;
# Waiting until node_2 is not part of cluster anymore
connection node_3;
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
EXPECT_20000
20000
connection node_2;
# Start node_2 again
¤ Wait until node_2 is back on cluster
connection node_2;
# Waiting until replica is not part of cluster anymore
# Add writes to primary
connection primary;
# Intentionally generate 1k GTID-events
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
EXPECT_2000
2000
connection replica;
# Start replica again
# Wait until replica is back on cluster
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
EXPECT_20000
20000
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-3006 0-3-3006 0-3-3006
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
EXPECT_2000
2000
connection node_1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
EXPECT_20000
20000
connection node_3;
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
EXPECT_20000
20000
connection node_3;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
EXPECT_1
1
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
@@gtid_slave_pos @@gtid_binlog_pos @@gtid_current_pos
0-3-3006 0-3-3006 0-3-3006
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
EXPECT_2000
2000
connection primary;
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
EXPECT_2000
2000
drop table t1;
connection node_2;
connection replica;
connection node_1;
connection node_2;
connection replica;
STOP SLAVE;
RESET SLAVE ALL;
connection node_3;
connection primary;
RESET MASTER;
connection node_1;
disconnect node_3;
disconnect primary;
disconnect replica;
disconnect node_2;
disconnect node_1;
# End of test

View File

@@ -0,0 +1,22 @@
!include ../galera_2nodes_as_replica_2primary.cnf
[mysqld]
wsrep-debug=1
[mysqld.1]
server_id=15
wsrep_gtid_mode=1
wsrep_gtid_domain_id=16
gtid_domain_id=11
gtid_strict_mode=1
wsrep-slave-threads=4
slave-parallel-threads=2
[mysqld.2]
skip-slave-start=OFF
server_id=15
wsrep_gtid_mode=1
wsrep_gtid_domain_id=16
gtid_domain_id=11
gtid_strict_mode=1
wsrep-slave-threads=4

View File

@@ -0,0 +1,170 @@
#
# Test two primary nodes async replication to Galera cluster
#
# primary1 primary2
# #3 #4
# | |
# | async replication v
# +-------------------+ +----------------+
# | |
# v v
# galera replica <------galera replication-------->galera node_2
# #1 #2
#
# Test outline
#
# - Create user for async replication and table with rows in both primaries
# - Verify that tables and rows are replicated to all Galera nodes
# - Verify that gtid position is same in all Galera nodes
#
# The galera/galera_2nodes_as_replica_2primary.cnf describes the setup of the nodes
#
--source include/force_restart.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
# As node #3 and #4 are not a Galera node, and galera_cluster.inc does not open connetion to it
# we open the connections here
--connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_3
--connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_4
--connection primary1
--echo # Primary1 creating user for replication
create user repl@'%' identified by 'repl';
grant all on *.* to repl@'%';
--connection primary2
--echo # Primary2 creating user for replication
create user repl2@'%' identified by 'repl2';
grant all on *.* to repl2@'%';
--connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_1
--let $node_1 = replica
--let $node_2 = node_2
--source include/auto_increment_offset_save.inc
--connection replica
--echo # Galera replica changing master to primary1
--disable_query_log
SET @@default_master_connection='stream1';
--eval CHANGE MASTER 'stream1' TO master_host='127.0.0.1', master_user='repl', master_password='repl', master_port=$NODE_MYPORT_3, master_use_gtid=slave_pos;
--enable_query_log
SET @@default_master_connection='stream2';
--echo # Primary node changing master to primary2
--disable_query_log
--eval CHANGE MASTER 'stream2' TO master_host='127.0.0.1', master_user='repl2', master_password='repl2', master_port=$NODE_MYPORT_4, master_use_gtid=slave_pos;
--enable_query_log
START ALL SLAVES;
--connection primary1
--echo # Primary 1: Creating table and populating it with data
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
--disable_query_log
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection primary2
--echo # Primary 2: Creating table and populating it with data
CREATE TABLE t2 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
while($count < $inserts)
{
--eval insert into t2 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_1000 FROM t2;
--connection replica
--echo # Waiting for data to replicate to node_1
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--let $wait_condition_on_error_output = SHOW ALL SLAVES STATUS;
--source include/wait_condition_with_debug.inc
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
--let $wait_condition_on_error_output = SHOW ALL SLAVES STATUS;
--source include/wait_condition_with_debug.inc
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t2;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
SELECT COUNT(*) AS EXPECT_1000 FROM t2;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
--connection node_2
--echo # Waiting for data to replicate to node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t2;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
SELECT COUNT(*) AS EXPECT_1000 FROM t2;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
#
# Cleanup
#
--connection primary1
drop table t1;
--connection primary2
drop table t2;
--echo # Wait until drop table is replicated on Galera
--connection replica
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
--source include/wait_condition.inc
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't2';
--source include/wait_condition.inc
--connection replica
STOP ALL SLAVES;
RESET SLAVE ALL;
--connection primary1
RESET MASTER;
--connection primary2
RESET MASTER;
--source include/auto_increment_offset_restore.inc
--connection node_1
--disconnect primary1
--disconnect primary2
--disconnect replica
--source include/galera_end.inc
--echo # End of test

View File

@@ -0,0 +1,25 @@
!include ../galera_3nodes_as_slave.cnf
[mysqld]
wsrep-debug=1
[mysqld.1]
server_id=15
wsrep_gtid_mode=1
wsrep_gtid_domain_id=16
gtid_domain_id=11
gtid_strict_mode=1
[mysqld.2]
server_id=15
wsrep_gtid_mode=1
wsrep_gtid_domain_id=16
gtid_domain_id=11
gtid_strict_mode=1
[mysqld.3]
server_id=15
wsrep_gtid_mode=1
wsrep_gtid_domain_id=16
gtid_domain_id=11
gtid_strict_mode=1

View File

@@ -0,0 +1,234 @@
#
# Test circular replication where galera cluster is async replica and master
#
# mariadb #4 galera galera
# primary1
# replica2
# ---async replication-->replica1 #1 <--galera replication--> node_2 #2
# ^ ^
# | | galera replication
# | v
# +<------------------async replication----------------------primary2 (galera) #3
#
# Test outline:
#
# - Create user for async replication in primary1
# - Create user for async replication in primary2
# - Create table and some data in primary1
# - Verify that table and data is replicated to galera nodes
# - Verify that mysql.gtid_slave_pos has some rows in all Galera nodes
# - Verify that gtid_slave_pos, gtid_binlog_pos and gtid_current_pos are
# same in all Galera nodes and primary1
# - Verify that writes on Galera nodes are replicated to all nodes
# and to primary1
#
# The galera/galera_3nodes_as_slave.cnf describes the setup of the nodes
#
--source include/force_restart.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
--connect replica1, 127.0.0.1, root, , test, $NODE_MYPORT_1
--connect primary2, 127.0.0.1, root, , test, $NODE_MYPORT_3
# As node #4 is not a Galera node, and galera_cluster.inc does not open connetion to it
# because it is both primary and replica we open both connections here
--connect primary1, 127.0.0.1, root, , test, $NODE_MYPORT_4
--connect replica2, 127.0.0.1, root, , test, $NODE_MYPORT_4
--connection primary1
--echo # Primary1 node creating user for replication
create user repl@'%' identified by 'repl';
grant all on *.* to repl@'%';
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
--let $node_1 = replica1
--let $node_2 = node_2
--let $node_3 = primary2
--source include/auto_increment_offset_save.inc
--connection replica1
--echo # Galera replica changing master to primary1
--disable_query_log
--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='repl', master_password='repl', master_port=$NODE_MYPORT_4, master_use_gtid=slave_pos;
--enable_query_log
START SLAVE;
--connection primary2
--echo # Primary2 creating user for replication
create user repl2@'%' identified by 'repl2';
grant all on *.* to repl2@'%';
--connection replica2
--echo # replica2 changing master to primary2
--disable_query_log
--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='repl2', master_password='repl2', master_port=$NODE_MYPORT_3, master_use_gtid=slave_pos;
--enable_query_log
START SLAVE;
--connection primary1
--echo # Primary1: Creating table and populating it with data
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection replica1
--echo # Waiting for data to replicate to replica
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--echo # Writing more data to table
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
--connection node_2
--echo # Waiting for data to replicate to Galera node_2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 2000 FROM t1;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
--echo # Writing more data to table
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_3000 FROM t1;
--connection primary2
--echo # Waiting for data to replicate to primary2
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 3000 FROM t1;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_3000 FROM t1;
--echo # Writing more data to table
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
--connection primary1
--echo # Waiting for data to replicate to primary1
--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1;
--let $wait_condition_on_error_output = SHOW SLAVE STATUS;
--source include/wait_condition_with_debug.inc
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
--connection replica1
--echo # Waiting for data to replicate to replica
--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
--connection node_2
--echo # Waiting for data to replicate to node_2
--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
--connection primary2
--echo # Waiting for data to replicate to node_3
--let $wait_condition = SELECT COUNT(*) = 4000 FROM t1;
--source include/wait_condition.inc
SELECT COUNT(*) AS EXPECT_4000 FROM t1;
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
#
# Cleanup
#
--connection primary1
drop table t1;
--echo # Wait until drop table is replicated on Galera
--connection replica1
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--connection primary2
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--connection replica1
STOP SLAVE;
RESET SLAVE ALL;
--connection replica2
STOP SLAVE;
RESET SLAVE ALL;
RESET MASTER;
--source include/auto_increment_offset_restore.inc
--connection node_1
--disconnect primary1
--disconnect replica1
--disconnect primary2
--disconnect replica2
--source include/galera_end.inc
--echo # End of test

View File

@@ -1,77 +1,115 @@
#
# Test Galera as a replica to a MySQL async replication
# Test Galera as a replica to a MariaDB async replication
#
# MariaDB
# primary ---async replication--->galera node_2 (replica)<----galera replication---> galera node1
#
# Test outline:
#
# - Create user for async replication
# - Create table and some data in primary
# - Verify that table and data is replicated to galera nodes
# - Verify that mysql.gtid_slave_pos has some rows in all Galera nodes
# - Verify that gtid_slave_pos, gtid_binlog_pos and gtid_current_pos are
# same in all Galera nodes
# - Verify that we can shutdown and restart Galera replica (node #2)
# - Verify that gtid_slave_pos, gtid_binlog_pos and gtid_current_pos are
# same in all Galera nodes
# - Verify that mysql.gtid_slave_pos table has limited amount of rows
# - Veruft that ddl works (drop table)
#
# Similar test is done so that new rows are added to table in
# primary while async replica (node #2) is down.
#
# The galera/galera_2node_slave.cnf describes the setup of the nodes
#
--source include/force_restart.inc
--source include/galera_cluster.inc
--source include/have_innodb.inc
--source include/have_sequence.inc
# In this test we mark node #2 as replica
--connect replica, 127.0.0.1, root, , test, $NODE_MYPORT_2
# As node #3 is not a Galera node, and galera_cluster.inc does not open connetion to it
# we open the node_3 connection here
--connect node_3, 127.0.0.1, root, , test, $NODE_MYPORT_3
# we open the primary connection her
--connect primary, 127.0.0.1, root, , test, $NODE_MYPORT_3
create user repl@'%' identified by 'repl';
grant all on *.* to repl@'%';
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
--let $node_1 = node_1
--let $node_2 = node_2
--let $node_2 = replica
--source include/auto_increment_offset_save.inc
--connection node_2
--connection replica
--disable_query_log
--eval CHANGE MASTER TO master_host='127.0.0.1', master_user='repl', master_password='repl', master_port=$NODE_MYPORT_3, master_use_gtid=slave_pos;
--enable_query_log
START SLAVE;
--connection node_3
--connection primary
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb;
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
INSERT INTO t1 SELECT seq, 'test' from seq_1_to_10000;
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
--connection node_2
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection replica
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1;
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection node_1
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1;
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection node_2
--echo # Verify that graceful shutdown succeeds.
--connection replica
--echo # Verify that graceful shutdown succeeds in replica.
--source include/shutdown_mysqld.inc
--echo # Force SST
--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat
--connection node_1
--echo # Waiting until node_2 is not part of cluster anymore
--echo # Waiting until replica is not part of cluster anymore
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
--connection node_2
--echo # Start node_2 again
--connection replica
--echo # Start replica again
--source include/start_mysqld.inc
--echo ¤ Wait until node_2 is back on cluster
--echo # Wait until replica is back on cluster
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
@@ -79,24 +117,30 @@ SELECT COUNT(*) AS EXPECT_10000 FROM t1;
--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc
--connection node_2
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection node_1
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection node_3
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
--connection primary
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
#
# Cleanup
#
--connection node_3
drop table t1;
--connection node_2
--connection replica
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
@@ -108,59 +152,80 @@ drop table t1;
# Case 2 : While slave is down add writes to master
#
--connection node_3
CREATE TABLE t1 (id bigint primary key, msg varchar(100)) engine=innodb;
--connection primary
CREATE TABLE t1 (id bigint auto_increment primary key, msg varchar(100)) engine=innodb;
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
INSERT INTO t1 SELECT seq, 'test' from seq_1_to_10000;
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection node_2
--connection replica
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1;
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
SELECT COUNT(*) AS EXPECT_1000 FROM t1;
--connection node_1
--let $wait_condition = SELECT COUNT(*) = 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) = 10000 FROM t1;
--let $wait_condition = SELECT COUNT(*) = 1000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_10000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
--connection node_2
--echo # Verify that graceful shutdown succeeds.
--connection replica
--echo # Verify that graceful shutdown succeeds in replica.
--source include/shutdown_mysqld.inc
--echo # Force SST
--remove_file $MYSQLTEST_VARDIR/mysqld.2/data/grastate.dat
--connection node_1
--echo # Waiting until node_2 is not part of cluster anymore
--echo # Waiting until replica is not part of cluster anymore
--let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
--source include/wait_condition.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
# Add writes to master
--connection node_3
--echo # Add writes to primary
--connection primary
--echo # Intentionally generate 1k GTID-events
--let $inserts=1000
--let $count=0
--disable_query_log
INSERT INTO t1 SELECT seq, 'test' from seq_20001_to_30000;
while($count < $inserts)
{
--eval insert into t1 values (NULL,'test1')
--inc $count
}
--enable_query_log
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
--connection node_2
--echo # Start node_2 again
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
--connection replica
--echo # Start replica again
--source include/start_mysqld.inc
--echo ¤ Wait until node_2 is back on cluster
--echo # Wait until replica is back on cluster
--let $wait_condition = SELECT VARIABLE_VALUE = 'Primary' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_status';
--source include/wait_condition.inc
--let $wait_condition = SELECT VARIABLE_VALUE = 2 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size';
@@ -168,28 +233,34 @@ SELECT COUNT(*) AS EXPECT_20000 FROM t1;
--let $wait_condition = SELECT VARIABLE_VALUE = 'ON' FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_ready';
--source include/wait_condition.inc
--connection node_2
--let $wait_condition = SELECT COUNT(*) = 20000 FROM t1;
--let $wait_condition = SELECT COUNT(*) = 2000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
--connection node_1
--let $wait_condition = SELECT COUNT(*) = 20000 FROM t1;
--let $wait_condition = SELECT COUNT(*) = 2000 FROM t1;
--source include/wait_condition.inc
--let $wait_condition = SELECT COUNT(*) < 1000 FROM mysql.gtid_slave_pos;
--source include/wait_condition.inc
SELECT COUNT(*) > 0 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
SELECT COUNT(*) < 1000 AS EXPECT_1 FROM mysql.gtid_slave_pos;
SELECT @@gtid_slave_pos,@@gtid_binlog_pos,@@gtid_current_pos;
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
--connection node_3
SELECT COUNT(*) AS EXPECT_20000 FROM t1;
--connection primary
SELECT COUNT(*) AS EXPECT_2000 FROM t1;
#
# Cleanup
#
--connection node_3
drop table t1;
--connection node_2
--connection replica
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
@@ -197,16 +268,18 @@ drop table t1;
--let $wait_condition = SELECT COUNT(*) = 0 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1';
--source include/wait_condition.inc
--connection node_2
--connection replica
STOP SLAVE;
RESET SLAVE ALL;
--connection node_3
--connection primary
RESET MASTER;
--connection node_1
--disconnect node_3
--source include/auto_increment_offset_restore.inc
--connection node_1
--disconnect primary
--disconnect replica
--source include/galera_end.inc
--echo # End of test

View File

@@ -825,3 +825,22 @@ DELETE FROM t1 WHERE ts = 1 AND color = 'GREEN';
SELECT * from t1 WHERE ts = 1 AND color = 'GREEN';
id color ts
DROP TABLE t1;
#
# MDEV-22695 Server crashes in heap_rnext upon DELETE from a HEAP table
#
CREATE TABLE t1 (a VARCHAR(128), b VARCHAR(32), KEY(a) USING BTREE, KEY(b) USING BTREE) ENGINE=HEAP;
INSERT INTO t1 VALUES ('foo',NULL),('m','b'),(6,'j'),('bar','qux'),(NULL,NULL);
DELETE FROM t1 WHERE a <=> 'm' OR b <=> NULL;
DROP TABLE t1;
#
# MDEV-28130 MariaDB SEGV issue at tree_search_next
#
CREATE TABLE v(t1 INT, pk INT, KEY(t1), KEY pk using btree (pk), KEY v using btree(t1, pk)) engine=memory;
HANDLER v OPEN;
HANDLER v READ t1=(2) limit 3;
t1 pk
HANDLER v READ pk PREV;
t1 pk
HANDLER v READ pk PREV;
t1 pk
drop table v;

View File

@@ -607,3 +607,22 @@ INSERT INTO t1 VALUES("7","GREEN", 2);
DELETE FROM t1 WHERE ts = 1 AND color = 'GREEN';
SELECT * from t1 WHERE ts = 1 AND color = 'GREEN';
DROP TABLE t1;
--echo #
--echo # MDEV-22695 Server crashes in heap_rnext upon DELETE from a HEAP table
--echo #
CREATE TABLE t1 (a VARCHAR(128), b VARCHAR(32), KEY(a) USING BTREE, KEY(b) USING BTREE) ENGINE=HEAP;
INSERT INTO t1 VALUES ('foo',NULL),('m','b'),(6,'j'),('bar','qux'),(NULL,NULL);
DELETE FROM t1 WHERE a <=> 'm' OR b <=> NULL;
# Cleanup
DROP TABLE t1;
--echo #
--echo # MDEV-28130 MariaDB SEGV issue at tree_search_next
--echo #
CREATE TABLE v(t1 INT, pk INT, KEY(t1), KEY pk using btree (pk), KEY v using btree(t1, pk)) engine=memory;
HANDLER v OPEN;
HANDLER v READ t1=(2) limit 3;
HANDLER v READ pk PREV;
HANDLER v READ pk PREV;
drop table v;

View File

@@ -3347,3 +3347,9 @@ Table Op Msg_type Msg_text
test.t1 check status OK
ALTER TABLE t1 FORCE;
DROP TABLE t1;
#
# MDEV-35723: applying zero offset to null pointer on INSERT
#
CREATE TABLE t1(c TEXT(1) NOT NULL, INDEX (c)) ENGINE=InnoDB;
INSERT INTO t1 SET c='';
DROP TABLE t1;

View File

@@ -2615,3 +2615,10 @@ CHECK TABLE t1;
ALTER TABLE t1 FORCE;
# Cleanup
DROP TABLE t1;
--echo #
--echo # MDEV-35723: applying zero offset to null pointer on INSERT
--echo #
CREATE TABLE t1(c TEXT(1) NOT NULL, INDEX (c)) ENGINE=InnoDB;
INSERT INTO t1 SET c='';
DROP TABLE t1;

View File

@@ -0,0 +1,4 @@
[clear]
--innodb-encrypt-log=OFF
[crypt]
--innodb-encrypt-log=ON

View File

@@ -0,0 +1,6 @@
--innodb-undo-tablespaces=2
--plugin-load-add=$FILE_KEY_MANAGEMENT_SO
--loose-file-key-management
--loose-file-key-management-filekey=FILE:$MTR_SUITE_DIR/filekeys-data.key
--loose-file-key-management-filename=$MTR_SUITE_DIR/filekeys-data.enc
--loose-file-key-management-encryption-algorithm=aes_cbc

View File

@@ -0,0 +1,39 @@
SET GLOBAL innodb_undo_log_truncate = 0;
create table t1 (keyc int primary key default 0, c char(6)) engine=innodb;
create table t2 (keyc int primary key default 0, c char(6)) engine=innodb;
CREATE PROCEDURE p(t VARCHAR(64))
BEGIN
DECLARE i TEXT DEFAULT 'insert into t1 select seq,repeat(chr(48),6)
from seq_1_to_20000';
DECLARE u1 TEXT DEFAULT 'update t1 set c=repeat(chr(32),6)';
DECLARE u2 TEXT DEFAULT 'update t1 set c=repeat(chr(64),6)';
EXECUTE IMMEDIATE REPLACE(i,'t1', t);
EXECUTE IMMEDIATE REPLACE(u1,'t1', t);
EXECUTE IMMEDIATE REPLACE(u2,'t1', t);
END;
$$
connect con1,localhost,root,,;
begin;
call p('t1');
connection default;
call p('t2');
connection con1;
commit;
disconnect con1;
connection default;
DROP PROCEDURE p;
SET GLOBAL innodb_undo_log_truncate = 1;
SET GLOBAL innodb_max_undo_log_size=DEFAULT;
SET GLOBAL innodb_max_purge_lag_wait=0;
# Prepare full backup
# shutdown server
# remove datadir
# xtrabackup move back
# restart
select count(*) from t1;
count(*)
20000
select count(*) from t2;
count(*)
20000
DROP TABLE t1,t2;

View File

@@ -0,0 +1,59 @@
--source include/have_innodb.inc
--source include/not_embedded.inc
--source include/have_sequence.inc
--source include/have_file_key_management.inc
SET GLOBAL innodb_undo_log_truncate = 0;
#
# Perform DML action using multiple clients and multiple undo tablespace.
#
create table t1 (keyc int primary key default 0, c char(6)) engine=innodb;
create table t2 (keyc int primary key default 0, c char(6)) engine=innodb;
DELIMITER $$;
CREATE PROCEDURE p(t VARCHAR(64))
BEGIN
DECLARE i TEXT DEFAULT 'insert into t1 select seq,repeat(chr(48),6)
from seq_1_to_20000';
DECLARE u1 TEXT DEFAULT 'update t1 set c=repeat(chr(32),6)';
DECLARE u2 TEXT DEFAULT 'update t1 set c=repeat(chr(64),6)';
EXECUTE IMMEDIATE REPLACE(i,'t1', t);
EXECUTE IMMEDIATE REPLACE(u1,'t1', t);
EXECUTE IMMEDIATE REPLACE(u2,'t1', t);
END;
$$
DELIMITER ;$$
connect (con1,localhost,root,,);
begin;
send call p('t1');
connection default;
call p('t2');
connection con1;
reap;
commit;
disconnect con1;
connection default;
DROP PROCEDURE p;
SET GLOBAL innodb_undo_log_truncate = 1;
SET GLOBAL innodb_max_undo_log_size=DEFAULT;
SET GLOBAL innodb_max_purge_lag_wait=0;
let $targetdir=$MYSQLTEST_VARDIR/tmp/backup;
--disable_result_log
exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --parallel=10 --target-dir=$targetdir --throttle=1000;
--echo # Prepare full backup
exec $XTRABACKUP --prepare --target-dir=$targetdir;
--enable_result_log
source include/restart_and_restore.inc;
select count(*) from t1;
select count(*) from t2;
# Cleanup
rmdir $targetdir;
DROP TABLE t1,t2;

View File

@@ -280,32 +280,32 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET l
USE `test`;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `v1` AS SELECT
1 AS `a+b`,
1 AS `c` */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `v2` AS SELECT
1 AS `a+b`,
1 AS `c`,
1 AS `current_role()` */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `v3` AS SELECT
1 AS `a+b`,
1 AS `c` */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `v4` AS SELECT
1 AS `a+b`,
1 AS `c` */;
SET character_set_client = @saved_cs_client;
SET @saved_cs_client = @@character_set_client;
SET character_set_client = utf8;
SET character_set_client = utf8mb4;
/*!50001 CREATE VIEW `v5` AS SELECT
1 AS `a+b`,
1 AS `c` */;
@@ -315,7 +315,7 @@ CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqltest1` /*!40100 DEFAULT CHARACTER
USE `mysqltest1`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,
@@ -324,7 +324,7 @@ CREATE TABLE `t1` (
/*!40101 SET character_set_client = @saved_cs_client */;
INSERT INTO `t1` VALUES (1,10,100),(2,20,200);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL,

View File

@@ -0,0 +1,71 @@
include/master-slave.inc
[connection master]
#
# Initialize system-versioned and partitioned table and its data
connection master;
SET timestamp=UNIX_TIMESTAMP('2025-01-01 01:00:00.000000');
RESET MASTER;
create table t1 (x int) engine=InnoDB with system versioning partition by system_time limit 3 partitions 5;
insert into t1 values(1);
insert into t1 values(2);
insert into t1 values(3);
insert into t1 values(4);
insert into t1 values(5);
# Verifying master partitions are correct after data insertion..
# .. done
connection slave;
connection slave;
# Verifying partitions of master and slave match on data setup..
# .. done
#
# "Delete" each row -- these are the BINLOG commands generated by
# mysqlbinlog from `delete from t1 where x=<n>` statments. Because the
# table uses system versioning and system_time partition, the actual
# events are updates, with added fields for the `row_start` and `row_end`
# columns.
connection master;
# BINLOG for Format Description event
BINLOG '
APZ0Zw8BAAAA/AAAAAABAAAAAAQAMTAuNi4yMS1NYXJpYURCLWRlYnVnLWxvZwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA9nRnEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA
CgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEEwQADQgICAoKCgHgiCNP
';
# BINLOG for delete from t1 where x=1;
BINLOG '
APZ0ZxMBAAAAMQAAAAQHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBvaHPfA==
APZ0ZxgBAAAASAAAAEwHAAAAACEAAAAAAAEAAwcH+AEAAABndPYAAAAAf////w9CP/gBAAAAZ3T2
AAAAAGd09gAAAADnhA23
';
# BINLOG for delete from t1 where x=2;
BINLOG '
APZ0ZxMBAAAAMQAAAPUHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBwNtQNQ==
APZ0ZxgBAAAASAAAAD0IAAAAACEAAAAAAAEAAwcH+AIAAABndPYAAAAAf////w9CP/gCAAAAZ3T2
AAAAAGd09gAAAABPYZUX
';
# BINLOG for delete from t1 where x=3;
BINLOG '
APZ0ZxMBAAAAMQAAAOYIAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBKWGevg==
APZ0ZxgBAAAASAAAAC4JAAAAACEAAAAAAAEAAwcH+AMAAABndPYAAAAAf////w9CP/gDAAAAZ3T2
AAAAAGd09gAAAAD0hz5S
';
# BINLOG for delete from t1 where x=4;
BINLOG '
APZ0ZxMBAAAAMQAAANcJAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBaT9IZg==
APZ0ZxgBAAAASAAAAB8KAAAAACEAAAAAAAEAAwcH+AQAAABndPYAAAAAf////w9CP/gEAAAAZ3T2
AAAAAGd09gAAAADA4Tdx
';
# BINLOG for delete from t1 where x=5;
BINLOG '
APZ0ZxMBAAAAMQAAAMgKAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBMk64Mw==
APZ0ZxgBAAAASAAAABALAAAAACEAAAAAAAEAAwcH+AUAAABndPYAAAAAf////w9CP/gFAAAAZ3T2
AAAAAGd09gAAAAA5blY6
';
# Verifying master partitions are correct after deletion BINLOG stmts..
# .. done
connection slave;
connection slave;
connection master;
drop table t1;
include/rpl_end.inc

View File

@@ -0,0 +1,4 @@
!include ../my.cnf
[mysqld]
default_time_zone="-7:00"

View File

@@ -0,0 +1,248 @@
#
# Ensure that executing row-injected events (i.e. via BINLOG statments and
# row-based binlog events) uses historical partitions. That is, for tables
# which use system versioning and system_time partitions, MDEV-35096 reported
# that row-injected events would not be stored into the correct historical
# partition. This test considers both use cases of row-injected events.
#
# The test setup creates a system-versioned table with system_time-based
# partitioning and fills the table up with enough records that bypass the size
# limit of each historical partition.
#
# To test BINLOG statements, a series of BINLOG statements are used to delete
# all the records in the test tables, and the resulting partitions are analyzed
# to ensure that they match the partition specification. The BINLOG events
# were collected by running an original set of delete statements on the table
# data, and taking their binlog data from mysqlbinlog. Note these binary log
# events are actually Update events, because system versioning just archives
# the rows, rather than deleting them.
#
# To test row-based event replication, a slave replicates the master's
# events, and the partitions are compared between the slave and master for
# consistency.
#
# Note that the TIMESTAMP of this test is fixed so the BINLOG statements can
# identify the correct rows to delete (system versioning adds implicit fields
# `row_start` and `row_end`, which are automatically populated using the current
# timestamp).
#
#
# References:
# MDEV-35096: History is stored in different partitions on different nodes
# when using SYSTEM VERSION
#
--source include/have_binlog_format_row.inc
--source include/master-slave.inc
--source include/have_innodb.inc
--source include/have_partition.inc
--echo #
--echo # Initialize system-versioned and partitioned table and its data
--connection master
# Fix the timestamp for the system versioned row_start and row_end fields, so
# the later hard-coded BINLOG base64 data can find the rows.
SET timestamp=UNIX_TIMESTAMP('2025-01-01 01:00:00.000000');
RESET MASTER;
create table t1 (x int) engine=InnoDB with system versioning partition by system_time limit 3 partitions 5;
insert into t1 values(1);
insert into t1 values(2);
insert into t1 values(3);
insert into t1 values(4);
insert into t1 values(5);
--let $master_total_size= `select count(*) from t1`
--let $master_p0_size= `select count(*) from t1 partition (p0)`
--let $master_p1_size= `select count(*) from t1 partition (p1)`
--let $master_p2_size= `select count(*) from t1 partition (p2)`
--echo # Verifying master partitions are correct after data insertion..
if ($master_total_size != 5)
{
--echo # Master t1 count: $master_total_size
--die Master table t1 should have 5 entries
}
if ($master_p0_size)
{
--echo # Master t1,p0 count: $master_p0_size
--die Master t1 partition p0 should be empty
}
if ($master_p1_size)
{
--echo # Master t1,p1 count: $master_p1_size
--die Master t1 partition p1 should be empty
}
if ($master_p2_size)
{
--echo # Master t1,p2 count: $master_p2_size
--die Master t1 partition p2 should be empty
}
--echo # .. done
--sync_slave_with_master
--connection slave
--let $slave_total_size= `select count(*) from t1`
--let $slave_p0_size= `select count(*) from t1 partition (p0)`
--let $slave_p1_size= `select count(*) from t1 partition (p1)`
--let $slave_p2_size= `select count(*) from t1 partition (p2)`
--echo # Verifying partitions of master and slave match on data setup..
if ($slave_total_size != $master_total_size)
{
--connection master
select count(*) from t0;
--connection slave
select count(*) from t1;
--die Size of t1 differs between master and slave
}
if ($slave_p0_size != $master_p0_size)
{
--connection master
select count(*) from t1 partition (p0);
--connection slave
select count(*) from t1 partition (p0);
--die Size of t1 partition p0 differs between master and slave
}
if ($slave_p1_size != $master_p1_size)
{
--connection master
select count(*) from t1 partition (p1);
--connection slave
select count(*) from t1 partition (p1);
--die Size of t1 partition p1 differs between master and slave
}
if ($slave_p2_size != $master_p2_size)
{
--connection master
select count(*) from t1 partition (p2);
--connection slave
select count(*) from t1 partition (p2);
--die Size of t1 partition p2 differs between master and slave
}
--echo # .. done
--echo #
--echo # "Delete" each row -- these are the BINLOG commands generated by
--echo # mysqlbinlog from `delete from t1 where x=<n>` statments. Because the
--echo # table uses system versioning and system_time partition, the actual
--echo # events are updates, with added fields for the `row_start` and `row_end`
--echo # columns.
--connection master
--echo # BINLOG for Format Description event
BINLOG '
APZ0Zw8BAAAA/AAAAAABAAAAAAQAMTAuNi4yMS1NYXJpYURCLWRlYnVnLWxvZwAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAA9nRnEzgNAAgAEgAEBAQEEgAA5AAEGggAAAAICAgCAAAACgoKAAAAAAAA
CgoKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAEEwQADQgICAoKCgHgiCNP
';
--echo # BINLOG for delete from t1 where x=1;
BINLOG '
APZ0ZxMBAAAAMQAAAAQHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBvaHPfA==
APZ0ZxgBAAAASAAAAEwHAAAAACEAAAAAAAEAAwcH+AEAAABndPYAAAAAf////w9CP/gBAAAAZ3T2
AAAAAGd09gAAAADnhA23
';
--echo # BINLOG for delete from t1 where x=2;
BINLOG '
APZ0ZxMBAAAAMQAAAPUHAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBwNtQNQ==
APZ0ZxgBAAAASAAAAD0IAAAAACEAAAAAAAEAAwcH+AIAAABndPYAAAAAf////w9CP/gCAAAAZ3T2
AAAAAGd09gAAAABPYZUX
';
--echo # BINLOG for delete from t1 where x=3;
BINLOG '
APZ0ZxMBAAAAMQAAAOYIAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBKWGevg==
APZ0ZxgBAAAASAAAAC4JAAAAACEAAAAAAAEAAwcH+AMAAABndPYAAAAAf////w9CP/gDAAAAZ3T2
AAAAAGd09gAAAAD0hz5S
';
--echo # BINLOG for delete from t1 where x=4;
BINLOG '
APZ0ZxMBAAAAMQAAANcJAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBaT9IZg==
APZ0ZxgBAAAASAAAAB8KAAAAACEAAAAAAAEAAwcH+AQAAABndPYAAAAAf////w9CP/gEAAAAZ3T2
AAAAAGd09gAAAADA4Tdx
';
--echo # BINLOG for delete from t1 where x=5;
BINLOG '
APZ0ZxMBAAAAMQAAAMgKAAAAACEAAAAAAAEABHRlc3QAAnQxAAMDERECBgYBMk64Mw==
APZ0ZxgBAAAASAAAABALAAAAACEAAAAAAAEAAwcH+AUAAABndPYAAAAAf////w9CP/gFAAAAZ3T2
AAAAAGd09gAAAAA5blY6
';
--let $master_total_size= `select count(*) from t1`
--let $master_p0_size= `select count(*) from t1 partition (p0)`
--let $master_p1_size= `select count(*) from t1 partition (p1)`
--let $master_p2_size= `select count(*) from t1 partition (p2)`
--echo # Verifying master partitions are correct after deletion BINLOG stmts..
if ($master_total_size > 0)
{
--echo # Master t1 count: $master_total_size
--die Master table t1 should have 0 count
}
if ($master_p0_size != 3)
{
--echo # Master t1,p0 count: $master_p0_size
--die Master t1 partition p0 should have 3 entries
}
if ($master_p1_size != 2)
{
--echo # Master t1,p1 count: $master_p1_size
--die Master t1 partition p1 should have 2 entries
}
if ($master_p2_size)
{
--echo # Master t1,p2 count: $master_p2_size
--die Master t1 partition p2 should be empty
}
--echo # .. done
--sync_slave_with_master
--connection slave
--let $slave_total_size= `select count(*) from t1`
--let $slave_p0_size= `select count(*) from t1 partition (p0)`
--let $slave_p1_size= `select count(*) from t1 partition (p1)`
--let $slave_p2_size= `select count(*) from t1 partition (p2)`
if ($slave_total_size != $master_total_size)
{
--connection master
select count(*) from t1;
--connection slave
select count(*) from t1;
--die Size of t1 differs between master and slave
}
if ($slave_p0_size != $master_p0_size)
{
--connection master
select count(*) from t1 partition (p0);
--connection slave
select count(*) from t1 partition (p0);
--die Size of t1 partition p0 differs between master and slave
}
if ($slave_p1_size != $master_p1_size)
{
--connection master
select count(*) from t1 partition (p1);
--connection slave
select count(*) from t1 partition (p1);
--die Size of t1 partition p1 differs between master and slave
}
if ($slave_p2_size != $master_p2_size)
{
--connection master
select count(*) from t1 partition (p2);
--connection slave
select count(*) from t1 partition (p2);
--die Size of t1 partition p2 differs between master and slave
}
--connection master
drop table t1;
--source include/rpl_end.inc

View File

@@ -18,7 +18,7 @@ alter table t1 engine=S3;
###
/*M!999999\- enable the sandbox mode */
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`pk` int(11) NOT NULL,
`a` int(11) DEFAULT NULL,

View File

@@ -9,7 +9,7 @@ DO SETVAL(`a1`, 1, 0);
CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
DO SETVAL(`x1`, 1, 0);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
KEY `a` (`a`)
@@ -23,7 +23,7 @@ DO SETVAL(`a1`, 1, 0);
CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
DO SETVAL(`x1`, 1, 0);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
KEY `a` (`a`)
@@ -37,7 +37,7 @@ DO SETVAL(`a1`, 1, 0);
CREATE SEQUENCE `x1` start with 1 minvalue 1 maxvalue 9223372036854775806 increment by 1 cache 1000 nocycle ENGINE=InnoDB;
DO SETVAL(`x1`, 1, 0);
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
KEY `a` (`a`)
@@ -47,7 +47,7 @@ INSERT INTO `t1` VALUES (1),(2);
# dump by tables only tables
/*M!999999\- enable the sandbox mode */
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
/*!40101 SET character_set_client = utf8mb4 */;
CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
KEY `a` (`a`)

View File

@@ -2927,7 +2927,7 @@ VARIABLE_SCOPE SESSION ONLY
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT This variable is for internal server use
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 18446744073709551615
NUMERIC_MAX_VALUE 4294967295
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO

View File

@@ -3087,7 +3087,7 @@ VARIABLE_SCOPE SESSION ONLY
VARIABLE_TYPE BIGINT UNSIGNED
VARIABLE_COMMENT This variable is for internal server use
NUMERIC_MIN_VALUE 0
NUMERIC_MAX_VALUE 18446744073709551615
NUMERIC_MAX_VALUE 4294967295
NUMERIC_BLOCK_SIZE 1
ENUM_VALUE_LIST NULL
READ_ONLY NO

View File

@@ -577,3 +577,17 @@ drop table t;
#
# End of 10.4 tests
#
#
# MDEV-26891 Segfault in Field::register_field_in_read_map upon INSERT DELAYED with virtual columns
#
CREATE TABLE t (
id INT AUTO_INCREMENT,
a varchar(16) NOT NULL DEFAULT '',
b varchar(16) GENERATED ALWAYS AS (a) VIRTUAL,
KEY `col_year` (b(8),id)
) ENGINE=MyISAM;
INSERT DELAYED INTO t (a) VALUES ('foo'),('bar');
DROP TABLE t;
#
# End of 10.5 tests
#

View File

@@ -541,3 +541,22 @@ drop table t;
--echo #
--echo # End of 10.4 tests
--echo #
--echo #
--echo # MDEV-26891 Segfault in Field::register_field_in_read_map upon INSERT DELAYED with virtual columns
--echo #
CREATE TABLE t (
id INT AUTO_INCREMENT,
a varchar(16) NOT NULL DEFAULT '',
b varchar(16) GENERATED ALWAYS AS (a) VIRTUAL,
KEY `col_year` (b(8),id)
) ENGINE=MyISAM;
INSERT DELAYED INTO t (a) VALUES ('foo'),('bar');
# Cleanup
DROP TABLE t;
--echo #
--echo # End of 10.5 tests
--echo #

View File

@@ -27,7 +27,9 @@ id x current
1 2 0
1 3 1
drop table t;
#
# MDEV-15645 Assertion `table->insert_values' failed in write_record upon REPLACE into a view with underlying versioned table
#
create or replace table t1 (a int, b int, primary key (a), unique(b)) with system versioning;
insert into t1 values (1,1);
create or replace table t2 (c int);
@@ -48,7 +50,9 @@ INSERT INTO t1 () VALUES (),(),(),(),(),();
UPDATE IGNORE t1 SET f = 1;
REPLACE t1 SELECT * FROM t1;
DROP TABLE t1;
#
# MDEV-22540 ER_DUP_ENTRY upon REPLACE or Assertion failed
#
set timestamp=1589245268.41934;
create table t1 (a int primary key) with system versioning;
insert into t1 values (1),(2);
@@ -72,3 +76,15 @@ Warnings:
Warning 1062 Duplicate entry '1' for key 'a'
load data infile '15330.data' replace into table t1 (a,b,c);
drop table t1;
#
# MDEV-35343 unexpected replace behaviour when long unique index on system versioned table
#
create table t1 (data char(10));
insert into t1 values ('o');
alter ignore table t1 add unique index (data);
alter ignore table t1 add unique index (data);
Warnings:
Note 1831 Duplicate index `data_2`. This is deprecated and will be disallowed in a future release
alter table t1 add system versioning;
replace into t1 values ('o'), ('o');
drop table t1;

View File

@@ -35,7 +35,9 @@ replace t values (1, 3);
select *, current_row(row_end) as current from t for system_time all order by x;
drop table t;
--echo #
--echo # MDEV-15645 Assertion `table->insert_values' failed in write_record upon REPLACE into a view with underlying versioned table
--echo #
create or replace table t1 (a int, b int, primary key (a), unique(b)) with system versioning;
insert into t1 values (1,1);
create or replace table t2 (c int);
@@ -59,7 +61,9 @@ UPDATE IGNORE t1 SET f = 1;
REPLACE t1 SELECT * FROM t1;
DROP TABLE t1;
--echo #
--echo # MDEV-22540 ER_DUP_ENTRY upon REPLACE or Assertion failed
--echo #
set timestamp=1589245268.41934;
create table t1 (a int primary key) with system versioning;
insert into t1 values (1),(2);
@@ -105,4 +109,15 @@ drop table t1;
eval set default_storage_engine= $default_engine;
--enable_query_log
--echo #
--echo # MDEV-35343 unexpected replace behaviour when long unique index on system versioned table
--echo #
create table t1 (data char(10));
insert into t1 values ('o');
alter ignore table t1 add unique index (data);
alter ignore table t1 add unique index (data);
alter table t1 add system versioning;
replace into t1 values ('o'), ('o');
drop table t1;
--source suite/versioning/common_finish.inc