mirror of
https://github.com/MariaDB/server.git
synced 2025-09-02 09:41:40 +03:00
auto-merge mysql-5.1-bugteam (local) --> mysql-5.1-bugteam
This commit is contained in:
119
mysql-test/suite/rpl/r/rpl_concurrency_error.result
Normal file
119
mysql-test/suite/rpl/r/rpl_concurrency_error.result
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
stop slave;
|
||||||
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
|
reset master;
|
||||||
|
reset slave;
|
||||||
|
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||||
|
start slave;
|
||||||
|
########################################################################
|
||||||
|
# Environment
|
||||||
|
########################################################################
|
||||||
|
CREATE TABLE t (i INT, PRIMARY KEY(i), f CHAR(8)) engine = Innodb;
|
||||||
|
CREATE TABLE n (d DATETIME, f CHAR(32)) engine = MyIsam;
|
||||||
|
CREATE TRIGGER tr AFTER UPDATE ON t FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO n VALUES ( now(), concat( 'updated t: ', old.f, ' -> ', new.f ) );
|
||||||
|
END |
|
||||||
|
INSERT INTO t VALUES (4,'black'), (2,'red'), (3,'yelow'), (1,'cyan');
|
||||||
|
########################################################################
|
||||||
|
# Testing ER_LOCK_WAIT_TIMEOUT
|
||||||
|
########################################################################
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
UPDATE t SET f = 'yellow 2' WHERE i = 3;
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
UPDATE t SET f = 'magenta 2' WHERE f = 'red';
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
INSERT INTO t VALUES (5 + (2 * 10),"brown");
|
||||||
|
INSERT INTO n VALUES (now(),"brown");
|
||||||
|
COMMIT;
|
||||||
|
ROLLBACK;
|
||||||
|
Warnings:
|
||||||
|
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||||
|
show binlog events from <binlog_start>;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'magenta 2' WHERE f = 'red'
|
||||||
|
master-bin.000001 # Query # # ROLLBACK
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'yellow 2' WHERE i = 3
|
||||||
|
master-bin.000001 # Xid # # COMMIT /* XID */
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO t VALUES (5 + (2 * 10),"brown")
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO n VALUES (now(),"brown")
|
||||||
|
master-bin.000001 # Query # # ROLLBACK
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
UPDATE t SET f = 'gray 2' WHERE i = 3;
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
UPDATE t SET f = 'dark blue 2' WHERE f = 'red';
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
INSERT INTO t VALUES (6 + (2 * 10),"brown");
|
||||||
|
INSERT INTO n VALUES (now(),"brown");
|
||||||
|
COMMIT;
|
||||||
|
COMMIT;
|
||||||
|
show binlog events from <binlog_start>;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'dark blue 2' WHERE f = 'red'
|
||||||
|
master-bin.000001 # Query # # ROLLBACK
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'gray 2' WHERE i = 3
|
||||||
|
master-bin.000001 # Xid # # COMMIT /* XID */
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO t VALUES (6 + (2 * 10),"brown")
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO n VALUES (now(),"brown")
|
||||||
|
master-bin.000001 # Xid # # COMMIT /* XID */
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
UPDATE t SET f = 'yellow 1' WHERE i = 3;
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
UPDATE t SET f = 'magenta 1' WHERE f = 'red';
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
INSERT INTO t VALUES (5 + (1 * 10),"brown");
|
||||||
|
INSERT INTO n VALUES (now(),"brown");
|
||||||
|
COMMIT;
|
||||||
|
ROLLBACK;
|
||||||
|
Warnings:
|
||||||
|
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||||
|
show binlog events from <binlog_start>;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'magenta 1' WHERE f = 'red'
|
||||||
|
master-bin.000001 # Query # # ROLLBACK
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'yellow 1' WHERE i = 3
|
||||||
|
master-bin.000001 # Xid # # COMMIT /* XID */
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO t VALUES (5 + (1 * 10),"brown")
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO n VALUES (now(),"brown")
|
||||||
|
master-bin.000001 # Query # # ROLLBACK
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
UPDATE t SET f = 'gray 1' WHERE i = 3;
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
UPDATE t SET f = 'dark blue 1' WHERE f = 'red';
|
||||||
|
ERROR HY000: Lock wait timeout exceeded; try restarting transaction
|
||||||
|
INSERT INTO t VALUES (6 + (1 * 10),"brown");
|
||||||
|
INSERT INTO n VALUES (now(),"brown");
|
||||||
|
COMMIT;
|
||||||
|
COMMIT;
|
||||||
|
show binlog events from <binlog_start>;
|
||||||
|
Log_name Pos Event_type Server_id End_log_pos Info
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'dark blue 1' WHERE f = 'red'
|
||||||
|
master-bin.000001 # Query # # ROLLBACK
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; UPDATE t SET f = 'gray 1' WHERE i = 3
|
||||||
|
master-bin.000001 # Xid # # COMMIT /* XID */
|
||||||
|
master-bin.000001 # Query # # BEGIN
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO t VALUES (6 + (1 * 10),"brown")
|
||||||
|
master-bin.000001 # Query # # use `test`; INSERT INTO n VALUES (now(),"brown")
|
||||||
|
master-bin.000001 # Xid # # COMMIT /* XID */
|
||||||
|
source include/diff_master_slave.inc;
|
||||||
|
source include/diff_master_slave.inc;
|
||||||
|
########################################################################
|
||||||
|
# Cleanup
|
||||||
|
########################################################################
|
||||||
|
DROP TRIGGER tr;
|
||||||
|
DROP TABLE t;
|
||||||
|
DROP TABLE n;
|
1
mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt
Normal file
1
mysql-test/suite/rpl/t/rpl_concurrency_error-master.opt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
--innodb-lock-wait-timeout=1
|
149
mysql-test/suite/rpl/t/rpl_concurrency_error.test
Normal file
149
mysql-test/suite/rpl/t/rpl_concurrency_error.test
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
###############################################################################
|
||||||
|
#BUG#44581 Slave stops when transaction with non-transactional table gets
|
||||||
|
#lock wait timeout
|
||||||
|
#
|
||||||
|
# In STMT and MIXED modes, a statement that changes both non-transactional and
|
||||||
|
# transactional tables must be written to the binary log whenever there are
|
||||||
|
# changes to non-transactional tables. This means that the statement gets into
|
||||||
|
# the # binary log even when the changes to the transactional tables fail. In
|
||||||
|
# particular, in the presence of a failure such statement is annotated with the
|
||||||
|
# error number and wrapped in a begin/rollback. On the slave, while applying
|
||||||
|
# the statement, it is expected the same failure and the rollback prevents the
|
||||||
|
# transactional changes to be persisted.
|
||||||
|
|
||||||
|
# This test aims to verify if a statement that updates both transactional and
|
||||||
|
# non-transacitonal tables and fails due to concurrency problems is correctly
|
||||||
|
# processed by the slave in the sense that the statements get into the binary
|
||||||
|
# log, the error is ignored and only the non-transactional tables are changed.
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
--source include/master-slave.inc
|
||||||
|
--source include/have_innodb.inc
|
||||||
|
--source include/have_binlog_format_statement.inc
|
||||||
|
|
||||||
|
--echo ########################################################################
|
||||||
|
--echo # Environment
|
||||||
|
--echo ########################################################################
|
||||||
|
connection master;
|
||||||
|
|
||||||
|
CREATE TABLE t (i INT, PRIMARY KEY(i), f CHAR(8)) engine = Innodb;
|
||||||
|
CREATE TABLE n (d DATETIME, f CHAR(32)) engine = MyIsam;
|
||||||
|
|
||||||
|
DELIMITER |;
|
||||||
|
CREATE TRIGGER tr AFTER UPDATE ON t FOR EACH ROW
|
||||||
|
BEGIN
|
||||||
|
INSERT INTO n VALUES ( now(), concat( 'updated t: ', old.f, ' -> ', new.f ) );
|
||||||
|
END |
|
||||||
|
DELIMITER ;|
|
||||||
|
|
||||||
|
INSERT INTO t VALUES (4,'black'), (2,'red'), (3,'yelow'), (1,'cyan');
|
||||||
|
|
||||||
|
connect (conn1, 127.0.0.1,root,,);
|
||||||
|
connect (conn2, 127.0.0.1,root,,);
|
||||||
|
|
||||||
|
--echo ########################################################################
|
||||||
|
--echo # Testing ER_LOCK_WAIT_TIMEOUT
|
||||||
|
--echo ########################################################################
|
||||||
|
|
||||||
|
let $type=2;
|
||||||
|
|
||||||
|
while ($type)
|
||||||
|
{
|
||||||
|
let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
|
||||||
|
connection conn1;
|
||||||
|
if (`select $type = 2`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
}
|
||||||
|
if (`select $type = 1`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
}
|
||||||
|
eval UPDATE t SET f = 'yellow $type' WHERE i = 3;
|
||||||
|
|
||||||
|
connection conn2;
|
||||||
|
if (`select $type = 2`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
}
|
||||||
|
if (`select $type = 1`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
}
|
||||||
|
--error ER_LOCK_WAIT_TIMEOUT
|
||||||
|
eval UPDATE t SET f = 'magenta $type' WHERE f = 'red';
|
||||||
|
eval INSERT INTO t VALUES (5 + ($type * 10),"brown");
|
||||||
|
INSERT INTO n VALUES (now(),"brown");
|
||||||
|
|
||||||
|
connection conn1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection conn2;
|
||||||
|
ROLLBACK;
|
||||||
|
--source include/show_binlog_events.inc
|
||||||
|
|
||||||
|
let $binlog_start= query_get_value("SHOW MASTER STATUS", Position, 1);
|
||||||
|
connection conn1;
|
||||||
|
if (`select $type = 2`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
}
|
||||||
|
if (`select $type = 1`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
}
|
||||||
|
eval UPDATE t SET f = 'gray $type' WHERE i = 3;
|
||||||
|
|
||||||
|
connection conn2;
|
||||||
|
if (`select $type = 2`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 1;
|
||||||
|
BEGIN;
|
||||||
|
}
|
||||||
|
if (`select $type = 1`)
|
||||||
|
{
|
||||||
|
SET AUTOCOMMIT = 0;
|
||||||
|
}
|
||||||
|
--error ER_LOCK_WAIT_TIMEOUT
|
||||||
|
eval UPDATE t SET f = 'dark blue $type' WHERE f = 'red';
|
||||||
|
eval INSERT INTO t VALUES (6 + ($type * 10),"brown");
|
||||||
|
INSERT INTO n VALUES (now(),"brown");
|
||||||
|
|
||||||
|
connection conn1;
|
||||||
|
COMMIT;
|
||||||
|
|
||||||
|
connection conn2;
|
||||||
|
COMMIT;
|
||||||
|
--source include/show_binlog_events.inc
|
||||||
|
|
||||||
|
dec $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
let $diff_statement= SELECT * FROM t order by i;
|
||||||
|
source include/diff_master_slave.inc;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
let $diff_statement= SELECT * FROM n order by d, f;
|
||||||
|
source include/diff_master_slave.inc;
|
||||||
|
|
||||||
|
--echo ########################################################################
|
||||||
|
--echo # Cleanup
|
||||||
|
--echo ########################################################################
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
DROP TRIGGER tr;
|
||||||
|
DROP TABLE t;
|
||||||
|
DROP TABLE n;
|
||||||
|
|
||||||
|
sync_slave_with_master;
|
||||||
|
|
||||||
|
connection master;
|
||||||
|
disconnect conn1;
|
||||||
|
disconnect conn2;
|
@@ -369,6 +369,34 @@ int convert_handler_error(int error, THD* thd, TABLE *table)
|
|||||||
return (actual_error);
|
return (actual_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool concurrency_error_code(int error)
|
||||||
|
{
|
||||||
|
switch (error)
|
||||||
|
{
|
||||||
|
case ER_LOCK_WAIT_TIMEOUT:
|
||||||
|
case ER_LOCK_DEADLOCK:
|
||||||
|
case ER_XA_RBDEADLOCK:
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool unexpected_error_code(int unexpected_error)
|
||||||
|
{
|
||||||
|
switch (unexpected_error)
|
||||||
|
{
|
||||||
|
case ER_NET_READ_ERROR:
|
||||||
|
case ER_NET_ERROR_ON_WRITE:
|
||||||
|
case ER_QUERY_INTERRUPTED:
|
||||||
|
case ER_SERVER_SHUTDOWN:
|
||||||
|
case ER_NEW_ABORTING_CONNECTION:
|
||||||
|
return(TRUE);
|
||||||
|
default:
|
||||||
|
return(FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pretty_print_str()
|
pretty_print_str()
|
||||||
*/
|
*/
|
||||||
@@ -3006,7 +3034,7 @@ int Query_log_event::do_apply_event(Relay_log_info const *rli,
|
|||||||
DBUG_PRINT("query",("%s",thd->query));
|
DBUG_PRINT("query",("%s",thd->query));
|
||||||
|
|
||||||
if (ignored_error_code((expected_error= error_code)) ||
|
if (ignored_error_code((expected_error= error_code)) ||
|
||||||
!check_expected_error(thd,rli,expected_error))
|
!unexpected_error_code(expected_error))
|
||||||
{
|
{
|
||||||
if (flags2_inited)
|
if (flags2_inited)
|
||||||
/*
|
/*
|
||||||
@@ -3138,8 +3166,8 @@ compare_errors:
|
|||||||
actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
|
actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
|
||||||
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
|
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
|
||||||
expected_error, actual_error));
|
expected_error, actual_error));
|
||||||
if ((expected_error != actual_error) &&
|
if ((expected_error && expected_error != actual_error &&
|
||||||
expected_error &&
|
!concurrency_error_code(expected_error)) &&
|
||||||
!ignored_error_code(actual_error) &&
|
!ignored_error_code(actual_error) &&
|
||||||
!ignored_error_code(expected_error))
|
!ignored_error_code(expected_error))
|
||||||
{
|
{
|
||||||
@@ -3158,7 +3186,8 @@ Default database: '%s'. Query: '%s'",
|
|||||||
/*
|
/*
|
||||||
If we get the same error code as expected, or they should be ignored.
|
If we get the same error code as expected, or they should be ignored.
|
||||||
*/
|
*/
|
||||||
else if (expected_error == actual_error ||
|
else if ((expected_error == actual_error &&
|
||||||
|
!concurrency_error_code(expected_error)) ||
|
||||||
ignored_error_code(actual_error))
|
ignored_error_code(actual_error))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info",("error ignored"));
|
DBUG_PRINT("info",("error ignored"));
|
||||||
|
19
sql/slave.cc
19
sql/slave.cc
@@ -1884,25 +1884,6 @@ static ulong read_event(MYSQL* mysql, Master_info *mi, bool* suppress_warnings)
|
|||||||
DBUG_RETURN(len - 1);
|
DBUG_RETURN(len - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int check_expected_error(THD* thd, Relay_log_info const *rli,
|
|
||||||
int expected_error)
|
|
||||||
{
|
|
||||||
DBUG_ENTER("check_expected_error");
|
|
||||||
|
|
||||||
switch (expected_error) {
|
|
||||||
case ER_NET_READ_ERROR:
|
|
||||||
case ER_NET_ERROR_ON_WRITE:
|
|
||||||
case ER_QUERY_INTERRUPTED:
|
|
||||||
case ER_SERVER_SHUTDOWN:
|
|
||||||
case ER_NEW_ABORTING_CONNECTION:
|
|
||||||
DBUG_RETURN(1);
|
|
||||||
default:
|
|
||||||
DBUG_RETURN(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Check if the current error is of temporary nature of not.
|
Check if the current error is of temporary nature of not.
|
||||||
Some errors are temporary in nature, such as
|
Some errors are temporary in nature, such as
|
||||||
|
@@ -171,7 +171,6 @@ bool rpl_master_has_bug(const Relay_log_info *rli, uint bug_id, bool report,
|
|||||||
bool rpl_master_erroneous_autoinc(THD* thd);
|
bool rpl_master_erroneous_autoinc(THD* thd);
|
||||||
|
|
||||||
const char *print_slave_db_safe(const char *db);
|
const char *print_slave_db_safe(const char *db);
|
||||||
int check_expected_error(THD* thd, Relay_log_info const *rli, int error_code);
|
|
||||||
void skip_load_data_infile(NET* net);
|
void skip_load_data_infile(NET* net);
|
||||||
|
|
||||||
void end_slave(); /* release slave threads */
|
void end_slave(); /* release slave threads */
|
||||||
|
Reference in New Issue
Block a user