Hi Sachin, My comments below. On Sun, Jan 22, 2017 at 7:18 AM, SachinSetiya <sachin.setiya@mariadb.com> wrote:
revision-id: d1124c98cbede6366e4b4d27a23dcf5b9d207cf0 (mariadb-10.1.21-2-gd1124c9) parent(s): a14638581b4c8ef175e68dccff07967d819b3b7e author: Sachin Setiya committer: Sachin Setiya timestamp: 2017-01-22 17:47:29 +0530 message:
MDEV-10812 WSREP causes responses being sent to protocol commands that must not send a response
Problem:- When using wsrep (w/ galera) and issuing commands that can cause deadlocks, deadlock exception errors are sent in responses to commands such as close prepared statement () which, by spec, must not send a
s/close prepared statement ()/close prepared statement and close connection/ response.
Solution:- We will not jump to dispatch_end: when there is deadlock and query is either COM_QUIT or COM_STMT_CLOSE.
Or, I would say, in dispatch_command, we handle COM_QUIT and COM_STMT_CLOSE commands even in case of error.
Patch Credit:- Jaka Močnik
--- .../galera/r/galera_prepared_statement.result | 18 ++++++++++++++++ .../suite/galera/t/galera_prepared_statement.test | 25 ++++++++++++++++++++++ sql/sql_parse.cc | 6 +++++- 3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/mysql-test/suite/galera/r/galera_prepared_statement.result b/mysql-test/suite/galera/r/galera_prepared_statement.result index de5ac9c..3425648 100644 --- a/mysql-test/suite/galera/r/galera_prepared_statement.result +++ b/mysql-test/suite/galera/r/galera_prepared_statement.result @@ -27,7 +27,25 @@ ALTER TABLE t1 ADD COLUMN f2 INTEGER; ALTER TABLE t1 DROP COLUMN f1; EXECUTE st1; ERROR 22007: Incorrect integer value: 'abc' for column 'f2' at row 1 +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +CREATE TABLE t5(a int primary key); +INSERT INTO t5 VALUES(1),(2),(3); +START TRANSACTION ; +PREPARE st5 FROM 'SELECT * FROM t5'; +EXECUTE st5; +a +1 +2 +3 +update t5 set a=a+100; +EXECUTE st5; +a +101 +102 +103 +update t5 set a=a+100; DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; DROP TABLE t4; +DROP TABLE t5;
diff --git a/mysql-test/suite/galera/t/galera_prepared_statement.test
b/mysql-test/suite/galera/t/galera_prepared_statement.test index 3bee097..debc00e 100644 --- a/mysql-test/suite/galera/t/galera_prepared_statement.test +++ b/mysql-test/suite/galera/t/galera_prepared_statement.test @@ -38,8 +38,33 @@ ALTER TABLE t1 DROP COLUMN f1; --error ER_TRUNCATED_WRONG_VALUE_FOR_FIELD EXECUTE st1;
+# MDEV-10812 +# On Closing Prepare Stamemnt, When wsrep_conflict_state is ABORTED +# It causes wrong response to be sent on Clients. + +# First Create a Deadlock --connection node_1 +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +CREATE TABLE t5(a int primary key); +INSERT INTO t5 VALUES(1),(2),(3); +START TRANSACTION ; +PREPARE st5 FROM 'SELECT * FROM t5'; +EXECUTE st5; +update t5 set a=a+100; +EXECUTE st5; + +--sleep 2 +--connection node_2 +update t5 set a=a+100; + +--sleep 2 +--connection node_1 +# here we have deadlock +--disconnect node_1 + +--connection node_2 DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; DROP TABLE t4; +DROP TABLE t5;
The test always hits command != COM_QUIT assert if I revert : + if (thd->wsrep_conflict_state == ABORTED && + command != COM_STMT_CLOSE && command != COM_QUIT) So, I modified your test a bit (simplified) to not use PS. --echo # --echo # MDEV-10812: On closing prepare stamemnt, when wsrep_conflict_state --echo # is ABORTED, it causes wrong response to be sent to the client --echo # # First create a deadlock --connect node_1a, 127.0.0.1, root, , test, $NODE_MYPORT_1 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; CREATE TABLE t1(a INT PRIMARY KEY); INSERT INTO t1 VALUES(1),(2),(3); START TRANSACTION ; UPDATE t1 SET a=a+100; --sleep 2 --connection node_2 UPDATE t1 SET a=a+100; --sleep 2 --connection node_1a # here we get deadlock error --disconnect node_1a --connection node_2 DROP TABLE t1; I think it should be ok.
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 033e88a..d45b196 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -1265,7 +1265,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, { wsrep_client_rollback(thd); } - if (thd->wsrep_conflict_state== ABORTED) + /* we let COM_QUIT and STMT_CLOSE execute even if wsrep aborted */
We let COM_QUIT and COM_STMT_CLOSE to execute even if wsrep aborted. + if (thd->wsrep_conflict_state == ABORTED &&
+ command != COM_STMT_CLOSE && command != COM_QUIT) { my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); WSREP_DEBUG("Deadlock error for: %s", thd->query()); @@ -1918,6 +1920,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (WSREP(thd)) { + DBUG_ASSERT((command != COM_QUIT && command != COM_STMT_CLOSE) + || thd->get_stmt_da()->is_disabled());
Please add a comment explaining this assert. Thanks, Nirbhay
/* wsrep BF abort in query exec phase */ mysql_mutex_lock(&thd->LOCK_wsrep_thd); do_end_of_statement= thd->wsrep_conflict_state != REPLAYING && _______________________________________________ commits mailing list commits@mariadb.org https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits