1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Bug #32709: Assertion failed: trx_data->empty(), file log.cc

The assertion indicates that some data was left in the transaction
cache when the server was shut down, which means that a previous
statement did not commit or rollback correctly.

What happened was that a bug in the rollback of a transactional
table caused the transaction cache to be emptied, but not reset.
The error can be triggered by having a failing UPDATE or INSERT,
on a transactional table, causing an implicit rollback.

Fixed by always flushing the pending event to reset the state
properly.
This commit is contained in:
Mats Kindahl
2008-09-03 22:04:07 +02:00
parent 83ce448cfe
commit 9755f07279
7 changed files with 77 additions and 0 deletions

View File

@ -451,3 +451,23 @@ connection master;
drop table t1, t2, t3, t4, t5, t6, t7; drop table t1, t2, t3, t4, t5, t6, t7;
sync_slave_with_master; sync_slave_with_master;
#
# BUG#32709: Assertion failed: trx_data->empty(), file .\log.cc, line 1293
#
connection master;
eval CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=$type;
INSERT INTO t1 VALUES (1), (2), (3);
--error ER_DUP_ENTRY
UPDATE t1 SET a = 10;
INSERT INTO t1 VALUES (4);
sync_slave_with_master;
let $diff_table_1=master:test.t1;
let $diff_table_2=slave:test.t1;
source include/diff_tables.inc;
connection master;
drop table t1;
sync_slave_with_master;

View File

@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1);
INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2); INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2);
Comparing tables master:test.t7 and slave:test.t7 Comparing tables master:test.t7 and slave:test.t7
drop table t1, t2, t3, t4, t5, t6, t7; drop table t1, t2, t3, t4, t5, t6, t7;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='MYISAM' ;
INSERT INTO t1 VALUES (1), (2), (3);
UPDATE t1 SET a = 10;
ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
INSERT INTO t1 VALUES (4);
Comparing tables master:test.t1 and slave:test.t1
drop table t1;

View File

@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1);
INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2); INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2);
Comparing tables master:test.t7 and slave:test.t7 Comparing tables master:test.t7 and slave:test.t7
drop table t1, t2, t3, t4, t5, t6, t7; drop table t1, t2, t3, t4, t5, t6, t7;
CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='INNODB' ;
INSERT INTO t1 VALUES (1), (2), (3);
UPDATE t1 SET a = 10;
ERROR 23000: Duplicate entry '10' for key 'PRIMARY'
INSERT INTO t1 VALUES (4);
Comparing tables master:test.t1 and slave:test.t1
drop table t1;

View File

@ -1421,6 +1421,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data,
If rolling back a statement in a transaction, we truncate the If rolling back a statement in a transaction, we truncate the
transaction cache to remove the statement. transaction cache to remove the statement.
*/ */
thd->binlog_remove_pending_rows_event(TRUE);
if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT)))
trx_data->reset(); trx_data->reset();
else // ...statement else // ...statement
@ -3769,6 +3770,31 @@ THD::binlog_set_pending_rows_event(Rows_log_event* ev)
} }
/**
Remove the pending rows event, discarding any outstanding rows.
If there is no pending rows event available, this is effectively a
no-op.
*/
int
MYSQL_BIN_LOG::remove_pending_rows_event(THD *thd)
{
DBUG_ENTER(__FUNCTION__);
binlog_trx_data *const trx_data=
(binlog_trx_data*) thd_get_ha_data(thd, binlog_hton);
DBUG_ASSERT(trx_data);
if (Rows_log_event* pending= trx_data->pending())
{
delete pending;
trx_data->set_pending(NULL);
}
DBUG_RETURN(0);
}
/* /*
Moves the last bunch of rows from the pending Rows event to the binlog Moves the last bunch of rows from the pending Rows event to the binlog
(either cached binlog if transaction, or disk binlog). Sets a new pending (either cached binlog if transaction, or disk binlog). Sets a new pending

View File

@ -307,6 +307,7 @@ public:
void update_table_map_version() { ++m_table_map_version; } void update_table_map_version() { ++m_table_map_version; }
int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event); int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event);
int remove_pending_rows_event(THD *thd);
#endif /* !defined(MYSQL_CLIENT) */ #endif /* !defined(MYSQL_CLIENT) */
void reset_bytes_written() void reset_bytes_written()

View File

@ -3502,6 +3502,21 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans,
} }
int THD::binlog_remove_pending_rows_event(bool clear_maps)
{
DBUG_ENTER(__FUNCTION__);
if (!mysql_bin_log.is_open())
DBUG_RETURN(0);
mysql_bin_log.remove_pending_rows_event(this);
if (clear_maps)
binlog_table_maps= 0;
DBUG_RETURN(0);
}
int THD::binlog_flush_pending_rows_event(bool stmt_end) int THD::binlog_flush_pending_rows_event(bool stmt_end)
{ {
DBUG_ENTER("THD::binlog_flush_pending_rows_event"); DBUG_ENTER("THD::binlog_flush_pending_rows_event");

View File

@ -1360,6 +1360,7 @@ public:
Rows_log_event* binlog_get_pending_rows_event() const; Rows_log_event* binlog_get_pending_rows_event() const;
void binlog_set_pending_rows_event(Rows_log_event* ev); void binlog_set_pending_rows_event(Rows_log_event* ev);
int binlog_flush_pending_rows_event(bool stmt_end); int binlog_flush_pending_rows_event(bool stmt_end);
int binlog_remove_pending_rows_event(bool clear_maps);
private: private:
uint binlog_table_maps; // Number of table maps currently in the binlog uint binlog_table_maps; // Number of table maps currently in the binlog