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

Merge 10.1 into 10.2

This commit is contained in:
Marko Mäkelä
2019-08-12 18:23:42 +03:00
22 changed files with 452 additions and 92 deletions

View File

@@ -567,7 +567,8 @@ is_page_corrupted(
page_size); page_size);
if (is_corrupted && log_file) { if (is_corrupted && log_file) {
fprintf(log_file, fprintf(log_file,
"Page " ULINTPF ":%llu may be corrupted;" "[page id: space=" ULINTPF
", page_number=%llu] may be corrupted;"
" key_version=%u\n", " key_version=%u\n",
space_id, cur_page_num, space_id, cur_page_num,
mach_read_from_4( mach_read_from_4(

View File

@@ -55,12 +55,19 @@ https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning */
#endif /* HAVE_VALGRIND_MEMCHECK_H */ #endif /* HAVE_VALGRIND_MEMCHECK_H */
#ifndef DBUG_OFF #ifndef DBUG_OFF
/* NOTE: Do not invoke TRASH_FILL directly! Use TRASH_ALLOC or TRASH_FREE.
The MEM_UNDEFINED() call before memset() is for canceling the effect
of any previous MEM_NOACCESS(). We must invoke MEM_UNDEFINED() after
writing the dummy pattern, unless MEM_NOACCESS() is going to be invoked.
On AddressSanitizer, the MEM_UNDEFINED() in TRASH_ALLOC() has no effect. */
#define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_UNDEFINED(A, trash_tmp); memset(A, C, trash_tmp); } while (0) #define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_UNDEFINED(A, trash_tmp); memset(A, C, trash_tmp); } while (0)
#else #else
#define TRASH_FILL(A,B,C) do { MEM_UNDEFINED((A), (B)); } while (0) #define TRASH_FILL(A,B,C) do { MEM_UNDEFINED((A), (B)); } while (0)
#endif #endif
/** Note that some memory became allocated or uninitialized. */
#define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0) #define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0)
/** Note that some memory became freed. (Prohibit further access to it.) */
#define TRASH_FREE(A,B) do { TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0) #define TRASH_FREE(A,B) do { TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0)
#endif /* MY_VALGRIND_INCLUDED */ #endif /* MY_VALGRIND_INCLUDED */

View File

@@ -81,7 +81,7 @@ comments, you can create the result file in one of the following ways:
# mysqltest --record --database test --result-file=r/test_case_name.result < t/test_case_name.test # mysqltest --record --database test --result-file=r/test_case_name.result < t/test_case_name.test
When this is done, take a look at r/test_case_name.result . When this is done, take a look at r/test_case_name.result.
If the result is incorrect, you have found a bug. In this case, you should If the result is incorrect, you have found a bug. In this case, you should
edit the test result to the correct results so that we can verify that edit the test result to the correct results so that we can verify that
the bug is corrected in future releases. the bug is corrected in future releases.

View File

@@ -2710,6 +2710,8 @@ Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. CREATE... REPLACE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. CREATE... REPLACE SELECT is unsafe because the order in which rows are retrieved by the SELECT determines which (if any) rows are replaced. This order cannot be predicted and may differ on master and the slave
INSERT INTO insert_2_keys VALUES (1, 2) INSERT INTO insert_2_keys VALUES (1, 2)
ON DUPLICATE KEY UPDATE a=VALUES(a)+10, b=VALUES(b)+10; ON DUPLICATE KEY UPDATE a=VALUES(a)+10, b=VALUES(b)+10;
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
DROP TABLE filler_table; DROP TABLE filler_table;
DROP TABLE insert_table; DROP TABLE insert_table;
DROP TABLE update_table; DROP TABLE update_table;

View File

@@ -15,3 +15,4 @@ rpl_get_master_version_and_clock : Bug#11766137 Jan 05 2011 joro Valgrind warnin
rpl_partition_archive : MDEV-5077 2013-09-27 svoj Cannot exchange partition with archive table rpl_partition_archive : MDEV-5077 2013-09-27 svoj Cannot exchange partition with archive table
rpl_row_binlog_max_cache_size : MDEV-11092 rpl_row_binlog_max_cache_size : MDEV-11092
rpl_row_index_choice : MDEV-11666 rpl_row_index_choice : MDEV-11666
rpl_mdev_17614 : MDEV-17614/MDEV-17073 Unexpected lock conflict

View File

@@ -0,0 +1,20 @@
include/master-slave.inc
[connection master]
CREATE TEMPORARY TABLE t1 (a INT NOT NULL);
LOAD DATA INFILE 'x' INTO TABLE x;
ERROR 42S02: Table 'test.x' doesn't exist
CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x);
ERROR HY000: Cannot create temporary table with partitions
"************** DROP TEMPORARY TABLE Should be present in Binary log **************"
include/show_binlog_events.inc
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE TEMPORARY TABLE t1 (a INT NOT NULL)
master-bin.000001 # Gtid # # GTID #-#-#
master-bin.000001 # Query # # use `test`; CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x)
CREATE TABLE t1 (b INT);
INSERT INTO t1 VALUES (NULL);
connection slave;
connection master;
DROP TABLE t1;
include/rpl_end.inc

View File

@@ -1,31 +1,5 @@
call mtr.add_suppression("Unsafe statement written to the binary log using statement format"); call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
include/master-slave.inc include/master-slave.inc
[connection master]
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
UNIQUE(b));
connection slave;
connection master;
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
SELECT * FROM t1;
a b
1 10
2 2
connection slave;
call mtr.add_suppression("Slave SQL.*suffer.*http:..bugs.mysql.com.bug.php.id=24432");
include/wait_for_slave_sql_error.inc [errno=1105]
Last_SQL_Error = 'Error 'master may suffer from http://bugs.mysql.com/bug.php?id=24432 so slave stops; check error log on slave for more info' on query. Default database: 'test'. Query: 'INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10''
SELECT * FROM t1;
a b
stop slave;
include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
include/wait_for_slave_to_start.inc
connection master; connection master;
CREATE TABLE t1 ( CREATE TABLE t1 (
id bigint(20) unsigned NOT NULL auto_increment, id bigint(20) unsigned NOT NULL auto_increment,

View File

@@ -0,0 +1,98 @@
include/master-slave.inc
[connection master]
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT,
UNIQUE(b), c int) engine=innodb;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
COMMIT;
SELECT * FROM t1;
a b c
1 1 2
2 2 3
include/wait_for_slave_sql_error.inc [errno=1062]
Last_SQL_Error = 'Error 'Duplicate entry '1' for key 'b'' on query. Default database: 'test'. Query: 'INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c)''
#Different value from server
SELECT * FROM t1;
a b c
1 1 1
2 2 3
stop slave;
include/wait_for_slave_to_stop.inc
reset slave;
reset master;
drop table t1;
start slave;
include/wait_for_slave_to_start.inc
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
INSERT INTO t1 VALUES (default, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (default, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
INSERT INTO t1 VALUES(default, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
COMMIT;
SELECT * FROM t1;
a b c
1 1 2
3 2 3
#same data as master
SELECT * FROM t1;
a b c
1 1 2
3 2 3
drop table t1;
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT,
UNIQUE(b), c int, d int ) engine=innodb;
INSERT INTO t1 VALUES (1, 1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
COMMIT;
SELECT * FROM t1;
a b c d
1 1 1 1
2 NULL 2 2
3 NULL 2 3
#same data as master
SELECT * FROM t1;
a b c d
1 1 1 1
2 NULL 2 2
3 NULL 2 3
drop table t1;
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
COMMIT;
SELECT * FROM t1;
a b c
1 1 2
2 2 3
include/wait_for_slave_sql_error.inc [errno=1062]
Last_SQL_Error = 'Error 'Duplicate entry '1' for key 'b'' on query. Default database: 'test'. Query: 'INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c)''
#Different value from server
SELECT * FROM t1;
a b c
1 1 1
2 2 3
stop slave;
include/wait_for_slave_to_stop.inc
reset slave;
reset master;
drop table t1;
start slave;
include/wait_for_slave_to_start.inc
include/rpl_end.inc

View File

@@ -0,0 +1,18 @@
include/master-slave.inc
[connection master]
connection slave;
SET @old_innodb_thread_concurrency := @@innodb_thread_concurrency;
SET @old_innodb_thread_sleep_delay := @@innodb_thread_sleep_delay;
SET GLOBAL innodb_thread_concurrency = 100;
connection master;
CREATE TABLE t(f INT) ENGINE=INNODB;
INSERT INTO t VALUES (10);
connection slave;
include/diff_tables.inc [master:t, slave:t]
"===== Clean up======="
connection master;
DROP TABLE t;
connection slave;
SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
SET GLOBAL innodb_thread_sleep_delay = @old_innodb_thread_sleep_delay;
include/rpl_end.inc

View File

@@ -1,5 +1,6 @@
include/master-slave.inc include/master-slave.inc
[connection master] [connection master]
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TABLE t1(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB; CREATE TABLE t2(id INT AUTO_INCREMENT, i INT, PRIMARY KEY (id)) ENGINE=INNODB;
CREATE TRIGGER trig1 AFTER INSERT ON t1 CREATE TRIGGER trig1 AFTER INSERT ON t1
@@ -49,9 +50,13 @@ connection master;
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB; CREATE TABLE t1(i INT, j INT, UNIQUE KEY(i), UNIQUE KEY(j)) ENGINE=INNODB;
INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
START TRANSACTION; START TRANSACTION;
LOCK TABLES t1 WRITE; LOCK TABLES t1 WRITE;
INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1; INSERT INTO t1 (i,j) VALUES (1,2) ON DUPLICATE KEY UPDATE j=j+1;
Warnings:
Note 1592 Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. INSERT... ON DUPLICATE KEY UPDATE on a table with more than one UNIQUE KEY is unsafe
UNLOCK TABLES; UNLOCK TABLES;
COMMIT; COMMIT;
connection slave; connection slave;

View File

@@ -0,0 +1,56 @@
# ==== Purpose ====
#
# Test verifies that failed CREATE OR REPLACE TEMPORARY TABLE statement which
# dropped the table but failed at a later stage of creation of temporary table
# is written to binarylog in row based replication.
#
# ==== Implementation ====
#
# Steps:
# 0 - Have mixed based replication mode.
# 1 - Create a temporary table. It will be replicated as mixed replication
# mode is in use.
# 2 - Execute an unsafe statement which will switch current statement
# binlog format to 'ROW'. i.e If binlog_format=MIXED, there are open
# temporary tables, and an unsafe statement is executed, then subsequent
# statements are logged in row format.
# 3 - Execute a CREATE OR REPLACE TEMPORARY TABLE statement which tries to
# create partitions on temporary table. Since it is not supported it will
# fail.
# 4 - Check the binary log output to ensure that the failed statement is
# written to the binary log.
# 5 - Slave should be up and running and in sync with master.
#
# ==== References ====
#
# MDEV-18930: Failed CREATE OR REPLACE TEMPORARY not written into binary log
# makes data on master and slave diverge
#
--source include/have_partition.inc
--source include/have_binlog_format_mixed.inc
--source include/master-slave.inc
CREATE TEMPORARY TABLE t1 (a INT NOT NULL);
# Execute an unsafe statement which switches replication mode internally from
# "STATEMENT" to "ROW".
--error ER_NO_SUCH_TABLE
LOAD DATA INFILE 'x' INTO TABLE x;
--error ER_PARTITION_NO_TEMPORARY
CREATE OR REPLACE TEMPORARY TABLE t1 (x INT) PARTITION BY HASH(x);
--echo "************** DROP TEMPORARY TABLE Should be present in Binary log **************"
--source include/show_binlog_events.inc
CREATE TABLE t1 (b INT);
INSERT INTO t1 VALUES (NULL);
--sync_slave_with_master
# Cleanup
--connection master
DROP TABLE t1;
--source include/rpl_end.inc

View File

@@ -14,45 +14,6 @@ source include/have_binlog_checksum_off.inc;
source include/master-slave.inc; source include/master-slave.inc;
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT.");
#
# This is to test that slave properly detects if
# master may suffer from:
# BUG#24432 "INSERT... ON DUPLICATE KEY UPDATE skips auto_increment values"
# (i.e. on master, INSERT ON DUPLICATE KEY UPDATE is used and manipulates
# an auto_increment column, and is binlogged statement-based).
#
# testcase with INSERT VALUES
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY AUTO_INCREMENT, b INT,
UNIQUE(b));
sync_slave_with_master;
connection master;
INSERT INTO t1(b) VALUES(1),(1),(2) ON DUPLICATE KEY UPDATE t1.b=10;
SELECT * FROM t1;
connection slave;
# show the error message
#1105 = ER_UNKNOWN_ERROR
--let $slave_sql_errno= 1105
--let $show_slave_sql_error= 1
call mtr.add_suppression("Slave SQL.*suffer.*http:..bugs.mysql.com.bug.php.id=24432");
--source include/wait_for_slave_sql_error.inc
# show that it was not replicated
SELECT * FROM t1;
# restart replication for the next testcase
stop slave;
--source include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
--source include/wait_for_slave_to_start.inc
# testcase with INSERT SELECT # testcase with INSERT SELECT
connection master; connection master;
CREATE TABLE t1 ( CREATE TABLE t1 (

View File

@@ -0,0 +1,121 @@
source include/have_debug.inc;
source include/have_innodb.inc;
-- source include/have_binlog_format_statement.inc
source include/master-slave.inc;
# MDEV-17614
# INSERT on dup key update is replication unsafe
# There can be three case
# 1. 2 unique key, Replication is unsafe.
# 2. 2 unique key , with one auto increment key, Safe to replicate because Innodb will acquire gap lock
# 3. n no of unique keys (n>1) but insert is only in 1 unique key
# 4. 2 unique key , with one auto increment key(but user gives auto inc value), unsafe to replicate
# Case 1
call mtr.add_suppression("Unsafe statement written to the binary log using statement format");
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY , b INT,
UNIQUE(b), c int) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--connection slave
# show the error message
--let $slave_sql_errno= 1062
--let $show_slave_sql_error= 1
--source include/wait_for_slave_sql_error.inc
--echo #Different value from server
SELECT * FROM t1;
# restart replication for the next testcase
stop slave;
--source include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
--source include/wait_for_slave_to_start.inc
# Case 2
--connection master
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (default, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (default, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(default, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--sync_slave_with_master
--echo #same data as master
SELECT * FROM t1;
connection master;
drop table t1;
--sync_slave_with_master
# Case 3
--connection master
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY, b INT,
UNIQUE(b), c int, d int ) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (1, 1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, NULL, 2, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(3, NULL, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--sync_slave_with_master
--echo #same data as master
SELECT * FROM t1;
connection master;
drop table t1;
--sync_slave_with_master
# Case 4
--connection master
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY auto_increment, b INT,
UNIQUE(b), c int) engine=innodb;
sync_slave_with_master;
connection master;
INSERT INTO t1 VALUES (1, 1, 1);
BEGIN;
INSERT INTO t1 VALUES (2, 1, 2) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master1
INSERT INTO t1 VALUES(2, 2, 3) ON DUPLICATE KEY UPDATE b=VALUES(b), c=VALUES(c);
--connection master
COMMIT;
SELECT * FROM t1;
--connection slave
# show the error message
--let $slave_sql_errno= 1062
--let $show_slave_sql_error= 1
--source include/wait_for_slave_sql_error.inc
--echo #Different value from server
SELECT * FROM t1;
# restart replication for the next testcase
stop slave;
--source include/wait_for_slave_to_stop.inc
reset slave;
connection master;
reset master;
drop table t1;
connection slave;
start slave;
--source include/wait_for_slave_to_start.inc
--source include/rpl_end.inc

View File

@@ -0,0 +1,41 @@
# ==== Purpose ====
#
# Test verifies that replication shouldn't hang when number of active threads
# on the slave server are less than the allowed innodb_thread_concurrency value.
#
# ==== Implementation ====
#
# Steps:
# 0 - Have master slave replication setup with engine being Innodb.
# 1 - Configure innodb_thread_concurrency = 100.
# 2 - Do some DML on master and sync the slave with master.
# 3 - Ensure replication doesn't hang.
#
# ==== References ====
#
# MDEV-20247: Replication hangs with "preparing" and never starts
#
--source include/master-slave.inc
--source include/have_innodb.inc
--connection slave
SET @old_innodb_thread_concurrency := @@innodb_thread_concurrency;
SET @old_innodb_thread_sleep_delay := @@innodb_thread_sleep_delay;
SET GLOBAL innodb_thread_concurrency = 100;
--connection master
CREATE TABLE t(f INT) ENGINE=INNODB;
INSERT INTO t VALUES (10);
--sync_slave_with_master
--let $diff_tables=master:t, slave:t
--source include/diff_tables.inc
--echo "===== Clean up======="
--connection master
DROP TABLE t;
--sync_slave_with_master
SET GLOBAL innodb_thread_concurrency = @old_innodb_thread_concurrency;
SET GLOBAL innodb_thread_sleep_delay = @old_innodb_thread_sleep_delay;
--source include/rpl_end.inc

View File

@@ -24,7 +24,7 @@
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_binlog_format_mixed.inc --source include/have_binlog_format_mixed.inc
--source include/master-slave.inc --source include/master-slave.inc
call mtr.add_suppression("Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT");
# Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS # Case-1: BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS
# Statement is unsafe because it invokes a trigger or a # Statement is unsafe because it invokes a trigger or a
# stored function that inserts into an AUTO_INCREMENT column. # stored function that inserts into an AUTO_INCREMENT column.

View File

@@ -6120,6 +6120,48 @@ int THD::decide_logging_format(TABLE_LIST *tables)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
int THD::decide_logging_format_low(TABLE *table)
{
/*
INSERT...ON DUPLICATE KEY UPDATE on a table with more than one unique keys
can be unsafe.
*/
if(wsrep_binlog_format() <= BINLOG_FORMAT_STMT &&
!is_current_stmt_binlog_format_row() &&
!lex->is_stmt_unsafe() &&
lex->sql_command == SQLCOM_INSERT &&
lex->duplicates == DUP_UPDATE)
{
uint unique_keys= 0;
uint keys= table->s->keys, i= 0;
Field *field;
for (KEY* keyinfo= table->s->key_info;
i < keys && unique_keys <= 1; i++, keyinfo++)
if (keyinfo->flags & HA_NOSAME &&
!(keyinfo->key_part->field->flags & AUTO_INCREMENT_FLAG &&
//User given auto inc can be unsafe
!keyinfo->key_part->field->val_int()))
{
for (uint j= 0; j < keyinfo->user_defined_key_parts; j++)
{
field= keyinfo->key_part[j].field;
if(!bitmap_is_set(table->write_set,field->field_index))
goto exit;
}
unique_keys++;
exit:;
}
if (unique_keys > 1)
{
lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_INSERT_TWO_KEYS);
binlog_unsafe_warning_flags|= lex->get_stmt_unsafe_flags();
set_current_stmt_binlog_format_row_if_mixed();
return 1;
}
}
return 0;
}
/* /*
Implementation of interface to write rows to the binary log through the Implementation of interface to write rows to the binary log through the

View File

@@ -2399,6 +2399,20 @@ public:
/* container for handler's private per-connection data */ /* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA]; Ha_data ha_data[MAX_HA];
/**
Bit field for the state of binlog warnings.
The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
unsafeness that the current statement has.
This must be a member of THD and not of LEX, because warnings are
detected and issued in different places (@c
decide_logging_format() and @c binlog_query(), respectively).
Between these calls, the THD->lex object may change; e.g., if a
stored routine is invoked. Only THD persists between the calls.
*/
uint32 binlog_unsafe_warning_flags;
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
binlog_cache_mngr * binlog_setup_trx_data(); binlog_cache_mngr * binlog_setup_trx_data();
@@ -2508,20 +2522,6 @@ private:
*/ */
enum_binlog_format current_stmt_binlog_format; enum_binlog_format current_stmt_binlog_format;
/**
Bit field for the state of binlog warnings.
The first Lex::BINLOG_STMT_UNSAFE_COUNT bits list all types of
unsafeness that the current statement has.
This must be a member of THD and not of LEX, because warnings are
detected and issued in different places (@c
decide_logging_format() and @c binlog_query(), respectively).
Between these calls, the THD->lex object may change; e.g., if a
stored routine is invoked. Only THD persists between the calls.
*/
uint32 binlog_unsafe_warning_flags;
/* /*
Number of outstanding table maps, i.e., table maps in the Number of outstanding table maps, i.e., table maps in the
transaction cache. transaction cache.
@@ -4165,6 +4165,18 @@ public:
} }
void leave_locked_tables_mode(); void leave_locked_tables_mode();
int decide_logging_format(TABLE_LIST *tables); int decide_logging_format(TABLE_LIST *tables);
/*
In Some cases when decide_logging_format is called it does not have all
information to decide the logging format. So that cases we call decide_logging_format_2
at later stages in execution.
One example would be binlog format for IODKU but column with unique key is not inserted.
We dont have inserted columns info when we call decide_logging_format so on later stage we call
decide_logging_format_low
@returns 0 if no format is changed
1 if there is change in binlog format
*/
int decide_logging_format_low(TABLE *table);
enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE}; enum need_invoker { INVOKER_NONE=0, INVOKER_USER, INVOKER_ROLE};
void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; } void binlog_invoker(bool role) { m_binlog_invoker= role ? INVOKER_ROLE : INVOKER_USER; }

View File

@@ -1051,6 +1051,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
break; break;
} }
thd->decide_logging_format_low(table);
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
{ {

View File

@@ -5115,7 +5115,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
err: err:
/* In RBR we don't need to log CREATE TEMPORARY TABLE */ /* In RBR we don't need to log CREATE TEMPORARY TABLE */
if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table()) if (!result && thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
DBUG_RETURN(result); DBUG_RETURN(result);
if (create_info->tmp_table()) if (create_info->tmp_table())

View File

@@ -1753,9 +1753,9 @@ innobase_srv_conc_enter_innodb(
&& thd_is_replication_slave_thread(trx->mysql_thd)) { && thd_is_replication_slave_thread(trx->mysql_thd)) {
const ulonglong end = my_interval_timer() const ulonglong end = my_interval_timer()
+ ulonglong(srv_replication_delay) * 1000000; + ulonglong(srv_replication_delay) * 1000000;
while (srv_conc_get_active_threads() while ((srv_conc_get_active_threads()
>= srv_thread_concurrency >= srv_thread_concurrency)
|| my_interval_timer() >= end) { && my_interval_timer() < end) {
os_thread_sleep(2000 /* 2 ms */); os_thread_sleep(2000 /* 2 ms */);
} }
} else { } else {

View File

@@ -1,7 +1,7 @@
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2017, 2018, MariaDB Corporation. Copyright (c) 2017, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software

View File

@@ -1954,9 +1954,9 @@ innobase_srv_conc_enter_innodb(
&& thd_is_replication_slave_thread(trx->mysql_thd)) { && thd_is_replication_slave_thread(trx->mysql_thd)) {
const ulonglong end = my_interval_timer() const ulonglong end = my_interval_timer()
+ ulonglong(srv_replication_delay) * 1000000; + ulonglong(srv_replication_delay) * 1000000;
while (srv_conc_get_active_threads() while ((srv_conc_get_active_threads()
>= srv_thread_concurrency >= srv_thread_concurrency)
|| my_interval_timer() >= end) { && my_interval_timer() < end) {
os_thread_sleep(2000 /* 2 ms */); os_thread_sleep(2000 /* 2 ms */);
} }
} else { } else {