Commit e9b8feef authored by Jon Olav Hauglid's avatar Jon Olav Hauglid

Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED

This assert could be triggered during two phase commit if binary
log was used as transaction coordinator log. The triggered assert
checks that the same number of transaction IDs are processed in
the prepare and commit phases.

The reason it was triggered, was that the transaction consisted
of an INSERT/UPDATE IGNORE that had an ignorable error. Since it
had an error, no row log events were made and therefore
prepared_xids was 0. However, since it was an IGNORE statement,
the statement started a read/write statement transaction, committed
it and completed successfully.

This patch fixes the problem by adjusting the assert to take
this possibility into account.

Test case added to binlog.binlog_innodb_row.test.
parent b677cadd
......@@ -59,3 +59,20 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 # Query # # use `test`; DROP TEMPORARY TABLE IF EXISTS `t1` /* generated by server */
###############################################
#
# Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED
#
DROP TABLE IF EXISTS t1, t2;
CREATE TABLE t1(a INT PRIMARY KEY) engine=innodb;
CREATE TABLE t2(a INT) engine=myisam;
INSERT INTO t1 VALUES (1);
START TRANSACTION;
INSERT INTO t2 VALUES (1);
INSERT IGNORE INTO t1 VALUES (1);
COMMIT;
INSERT INTO t1 VALUES (2);
START TRANSACTION;
INSERT INTO t2 VALUES (2);
UPDATE IGNORE t1 SET a=1 WHERE a=2;
COMMIT;
DROP TABLE t1, t2;
......@@ -77,3 +77,29 @@ DROP TEMPORARY TABLE t1;
-- echo ###############################################
-- source include/show_binlog_events.inc
-- echo ###############################################
--echo #
--echo # Bug#12346411 SQL/LOG.CC:6509: ASSERTION `PREPARED_XIDS > 0' FAILED
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1, t2;
--enable_warnings
CREATE TABLE t1(a INT PRIMARY KEY) engine=innodb;
CREATE TABLE t2(a INT) engine=myisam;
INSERT INTO t1 VALUES (1);
START TRANSACTION;
INSERT INTO t2 VALUES (1);
INSERT IGNORE INTO t1 VALUES (1);
COMMIT;
INSERT INTO t1 VALUES (2);
START TRANSACTION;
INSERT INTO t2 VALUES (2);
UPDATE IGNORE t1 SET a=1 WHERE a=2;
COMMIT;
DROP TABLE t1, t2;
......@@ -6506,8 +6506,11 @@ int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
{
DBUG_ENTER("TC_LOG_BINLOG::unlog");
mysql_mutex_lock(&LOCK_prep_xids);
DBUG_ASSERT(prepared_xids > 0);
if (--prepared_xids == 0) {
// prepared_xids can be 0 if the transaction had ignorable errors.
DBUG_ASSERT(prepared_xids >= 0);
if (prepared_xids > 0)
prepared_xids--;
if (prepared_xids == 0) {
DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids));
mysql_cond_signal(&COND_prep_xids);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment