In this blog, we’ll look at the differences in how a PREPARE statement handles errors in binary and text protocols.
Since Percona XtraDB Cluster is a multi-master solution, when an application executes conflicting workloads one of the workloads gets rolled back with a DEADLOCK error. While the same holds true even if you fire the workload through a PREPARE statement, there are differences between using the MySQL connector API (with binary protocol) and the MySQL client (with text protocol). Let’s look at these differences with the help of an example.
|
1 |
use test;<br>create table t (i int, k int, primary key pk(i)) engine=innodb;<br>insert into t values (1, 10), (2, 20), (3, 30);<br>select * from t; |
|
1 |
prepare st1 from 'update t set k = k + 100 where i > 1';<br>execute st1; |
|
1 |
prepare st1 from 'update t set k = k + 100 where i > 1';<br>execute st1; |
|
1 |
(1, 10), (2, 220), (3, 230); |
|
1 |
mysql> execute st1;<br><strong>ERROR 1213 (40001): WSREP detected deadlock/conflict and aborted the transaction. Try restarting the transaction<br></strong>mysql> select * from t;<br>+---+------+<br>| i | k |<br>+---+------+<br>| 1 | 10 |<br>| 2 | 120 |<br>| 3 | 130 |<br>+---+------+<br>3 rows in set (0.00 sec) |
Now let’s try to execute these workloads through Connector API. Connector API uses a binary protocol, which means it directly invokes the PREPARE statement and executes the statement using dedicated command codes ( COM_STMT_PREPARE and COM_STMT_EXECUTE).
While the conflicting transaction internal abort remains same, the COM_QUERY command code (text protocol) handling corrects the “query interrupted error” and resets it to “deadlock error” based on the wsrep_conflict_state value. It also has logic to retry the auto-commit enable statement.
This error handling and retry logic is not present when the COM_STMT_PREPARE and COM_STMT_EXECUTE command codes are used. This means the user sees a different error (non-masked error) when we try the same workload through an application using the MySQL Connector API:
|
1 |
<strong>Output of application from node-2:</strong><br><br>Statement init OK!<br>Statement prepare OK!<br>Statement execution failed: Query execution was interrupted<br><br>exact error-code to be specific:<b><span style="color: #38761d;"> <span style="color: #000000;">ER_QUERY_INTERRUPT<wbr />ED - 1317 - "Query execution was interrupted"</span></span></b> |
As you can see above, the statement/workload execution fails with “Query execution was interrupted” error vs. “deadlock” error (as seen with the normal MySQL client).
While the core execution remains same, error handling is different with text and binary protocol. This issue/limitation was always present, but it’s more prominent since sysbench-1.0 started using the PREPARE statement as a default.
What does this means to end-user/application?
Resources
RELATED POSTS