summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_sys.h1
-rw-r--r--mysql-test/suite/rpl/r/rpl_parallel_optimistic.result23
-rw-r--r--mysql-test/suite/rpl/t/rpl_parallel_optimistic.test64
-rw-r--r--sql/handler.cc5
-rw-r--r--sql/mysqld.cc10
-rw-r--r--sql/sql_class.cc7
-rw-r--r--sql/sql_class.h6
7 files changed, 114 insertions, 2 deletions
diff --git a/include/my_sys.h b/include/my_sys.h
index 110a2ee9af3..1c5649812d1 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -112,6 +112,7 @@ typedef struct my_aio_result {
#define ME_JUST_INFO 1024 /**< not error but just info */
#define ME_JUST_WARNING 2048 /**< not error but just warning */
#define ME_FATALERROR 4096 /* Fatal statement error */
+#define ME_LOG_AS_WARN 8192 /* is error but error-logged as warning */
/* Bits in last argument to fn_format */
#define MY_REPLACE_DIR 1 /* replace dir in name with 'dir' */
diff --git a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result
index 0177e65b10f..a6da3399fab 100644
--- a/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result
+++ b/mysql-test/suite/rpl/r/rpl_parallel_optimistic.result
@@ -1,4 +1,6 @@
include/rpl_init.inc [topology=1->2]
+call mtr.add_suppression("Warning.*Deadlock found when trying to get lock; try restarting transaction");
+call mtr.add_suppression("Warning.*mysqld: Can't find record in 't2'");
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
SET @old_parallel_threads=@@GLOBAL.slave_parallel_threads;
@@ -543,6 +545,27 @@ a b
57 7
58 8
59 9
+DELETE FROM t1;
+DELETE FROM t2;
+include/save_master_gtid.inc
+include/sync_with_master_gtid.inc
+BEGIN;
+INSERT INTO t1 SET a=1;
+SET @save.binlog_format=@@session.binlog_format;
+SET @@SESSION.binlog_format=row;
+BEGIN;
+INSERT INTO t1 SET a=1;
+INSERT INTO t2 SET a=1;
+COMMIT;
+BEGIN;
+DELETE FROM t2;
+COMMIT;
+ROLLBACK;
+SET @@SESSION.binlog_format= @save.binlog_format;
+DELETE FROM t1;
+DELETE FROM t2;
+include/save_master_gtid.inc
+include/sync_with_master_gtid.inc
include/stop_slave.inc
SET GLOBAL slave_parallel_mode=@old_parallel_mode;
SET GLOBAL slave_parallel_threads=@old_parallel_threads;
diff --git a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test
index 41fb6ebb72e..28bf4a77fd4 100644
--- a/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test
+++ b/mysql-test/suite/rpl/t/rpl_parallel_optimistic.test
@@ -4,6 +4,11 @@
--let $rpl_topology=1->2
--source include/rpl_init.inc
+--connection server_2
+call mtr.add_suppression("Warning.*Deadlock found when trying to get lock; try restarting transaction");
+# The following instruction is a part of the proof of MDEV-13577 fixes, below.
+call mtr.add_suppression("Warning.*mysqld: Can't find record in 't2'");
+
--connection server_1
ALTER TABLE mysql.gtid_slave_pos ENGINE=InnoDB;
CREATE TABLE t1 (a int PRIMARY KEY, b INT) ENGINE=InnoDB;
@@ -480,8 +485,65 @@ SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
SELECT * FROM t1 WHERE a >= 40 ORDER BY a;
SELECT * FROM t2 WHERE a >= 40 ORDER BY a;
-# Clean up.
+# partial cleanup to reuse the tables by following tests
+--connection server_1
+DELETE FROM t1;
+DELETE FROM t2;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+#
+# MDEV-13577 optimistic parallel slave errors out to error log unnecessary
+#
+
+# The 1st of the following two trx:s a blocker on slave
+--connection server_2
+BEGIN;
+INSERT INTO t1 SET a=1;
+
+--connection server_1
+SET @save.binlog_format=@@session.binlog_format;
+SET @@SESSION.binlog_format=row;
+
+BEGIN;
+ INSERT INTO t1 SET a=1;
+ INSERT INTO t2 SET a=1;
+COMMIT;
+
+# This transaction is going to win optimistical race with above INSERT
+# on slave while being depend on it. That means it will face a kind of temporary error
+# and then will retry to succeed.
+BEGIN;
+ DELETE FROM t2;
+COMMIT;
+
+# First make sure DELETE raced indeed to get stuck at retrying stage
+# where it runs "realistically" now. There is nomore optimistic error
+# in the errorlog, which is downgraded to the warning level (when
+# --log-warnings > 1), see above suppression.
+--connection server_2
+--let $wait_condition= SELECT COUNT(*) = 1 FROM information_schema.processlist WHERE state = "Waiting for prior transaction to commit"
+--source include/wait_condition.inc
+
+# Next release the 1st trx to commit.
+--connection server_2
+ROLLBACK;
+
+# MDEV-13577 local cleanup:
+--connection server_1
+SET @@SESSION.binlog_format= @save.binlog_format;
+DELETE FROM t1;
+DELETE FROM t2;
+--source include/save_master_gtid.inc
+
+--connection server_2
+--source include/sync_with_master_gtid.inc
+
+#
+# Clean up.
+#
--connection server_2
--source include/stop_slave.inc
SET GLOBAL slave_parallel_mode=@old_parallel_mode;
diff --git a/sql/handler.cc b/sql/handler.cc
index 397891ceec5..87f0926ad9a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -3639,12 +3639,15 @@ void handler::print_error(int error, myf errflag)
if ((debug_assert_if_crashed_table ||
global_system_variables.log_warnings > 1))
{
+ THD *thd= ha_thd();
/*
Log error to log before we crash or if extended warnings are requested
*/
errflag|= ME_NOREFRESH;
+ if (thd && thd->is_optimistic_slave_worker())
+ errflag|= ME_LOG_AS_WARN;
}
- }
+ }
/* if we got an OS error from a file-based engine, specify a path of error */
if (error < HA_ERR_FIRST && bas_ext()[0])
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 5f954f7576d..5bf5e3f73fc 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -3517,6 +3517,16 @@ void my_message_sql(uint error, const char *str, myf MyFlags)
level= Sql_condition::WARN_LEVEL_WARN;
func= sql_print_warning;
}
+ else if (MyFlags & ME_LOG_AS_WARN)
+ {
+ /*
+ Typical use case is optimistic parallel slave where DA needs to hold
+ an error condition caused by the current error, but the error-log
+ level is relaxed to the warning one.
+ */
+ level= Sql_condition::WARN_LEVEL_ERROR;
+ func= sql_print_warning;
+ }
else
{
level= Sql_condition::WARN_LEVEL_ERROR;
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 24140246b96..37f29115171 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -7100,6 +7100,13 @@ bool THD::rgi_have_temporary_tables()
return rgi_slave->rli->save_temporary_tables != 0;
}
+bool THD::is_optimistic_slave_worker()
+{
+ DBUG_ASSERT(system_thread != SYSTEM_THREAD_SLAVE_SQL || rgi_slave);
+
+ return system_thread == SYSTEM_THREAD_SLAVE_SQL && rgi_slave &&
+ rgi_slave->speculation == rpl_group_info::SPECULATE_OPTIMISTIC;
+}
void
wait_for_commit::reinit()
diff --git a/sql/sql_class.h b/sql/sql_class.h
index ca6155ec93f..0ced84791a0 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -4167,6 +4167,12 @@ public:
(THD_TRANS::DID_WAIT | THD_TRANS::CREATED_TEMP_TABLE |
THD_TRANS::DROPPED_TEMP_TABLE | THD_TRANS::DID_DDL));
}
+
+ /*
+ Returns true when the thread handle belongs to a slave worker thread
+ running in the optimistic execution mode.
+ */
+ bool is_optimistic_slave_worker();
};