From: Date: September 4 2008 9:52am Subject: bzr push into mysql-5.1 branch (mats:2678 to 2680) Bug#32709 List-Archive: http://lists.mysql.com/commits/53228 X-Bug: 32709 Message-Id: <20080904075223.8076E5BE4D@mats-laptop> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 2680 Mats Kindahl 2008-09-03 BUG#32709: Assertion failed: trx_data->empty(), file log.cc Incremental fixes: updating a comment and fixing a result file. modified: mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result sql/sql_class.h 2679 Mats Kindahl 2008-09-03 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. modified: mysql-test/extra/rpl_tests/rpl_row_basic.test mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result sql/log.cc sql/log.h sql/sql_class.cc sql/sql_class.h 2678 Andrei Elkin 2008-09-03 [merge] merging with 5.1.29. modified: mysql-test/r/default.result mysql-test/t/default.test sql/item.cc === modified file 'mysql-test/extra/rpl_tests/rpl_row_basic.test' --- a/mysql-test/extra/rpl_tests/rpl_row_basic.test 2008-08-14 08:27:28 +0000 +++ b/mysql-test/extra/rpl_tests/rpl_row_basic.test 2008-09-03 20:04:07 +0000 @@ -451,3 +451,23 @@ connection master; drop table t1, t2, t3, t4, t5, t6, t7; 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; === modified file 'mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result' --- a/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2008-08-12 09:09:36 +0000 +++ b/mysql-test/suite/rpl/r/rpl_row_basic_2myisam.result 2008-09-03 20:04:07 +0000 @@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1); INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2); Comparing tables master:test.t7 and slave:test.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; === modified file 'mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result' --- a/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2008-08-12 09:09:36 +0000 +++ b/mysql-test/suite/rpl/r/rpl_row_basic_3innodb.result 2008-09-03 20:04:07 +0000 @@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1); INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2); Comparing tables master:test.t7 and slave:test.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; === modified file 'mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result' --- a/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result 2008-08-12 09:09:36 +0000 +++ b/mysql-test/suite/rpl_ndb/r/rpl_row_basic_7ndb.result 2008-09-03 20:52:54 +0000 @@ -520,3 +520,10 @@ INSERT INTO t7 VALUES (1, "", 1); INSERT INTO t7 VALUES (2, repeat(_utf8'a', 255), 2); Comparing tables master:test.t7 and slave:test.t7 drop table t1, t2, t3, t4, t5, t6, t7; +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE='NDB' ; +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; === modified file 'sql/log.cc' --- a/sql/log.cc 2008-07-22 10:41:55 +0000 +++ b/sql/log.cc 2008-09-03 20:04:07 +0000 @@ -1421,6 +1421,7 @@ binlog_end_trans(THD *thd, binlog_trx_da If rolling back a statement in a transaction, we truncate the transaction cache to remove the statement. */ + thd->binlog_remove_pending_rows_event(TRUE); if (all || !(thd->options & (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT))) trx_data->reset(); else // ...statement @@ -3769,6 +3770,31 @@ THD::binlog_set_pending_rows_event(Rows_ } +/** + 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 (either cached binlog if transaction, or disk binlog). Sets a new pending === modified file 'sql/log.h' --- a/sql/log.h 2007-10-30 08:03:34 +0000 +++ b/sql/log.h 2008-09-03 20:04:07 +0000 @@ -307,6 +307,7 @@ public: void update_table_map_version() { ++m_table_map_version; } int flush_and_set_pending_rows_event(THD *thd, Rows_log_event* event); + int remove_pending_rows_event(THD *thd); #endif /* !defined(MYSQL_CLIENT) */ void reset_bytes_written() === modified file 'sql/sql_class.cc' --- a/sql/sql_class.cc 2008-08-26 10:07:56 +0000 +++ b/sql/sql_class.cc 2008-09-03 20:04:07 +0000 @@ -3502,6 +3502,21 @@ int THD::binlog_delete_row(TABLE* table, } +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) { DBUG_ENTER("THD::binlog_flush_pending_rows_event"); === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2008-08-26 10:01:49 +0000 +++ b/sql/sql_class.h 2008-09-03 20:52:54 +0000 @@ -1360,9 +1360,14 @@ public: Rows_log_event* binlog_get_pending_rows_event() const; void binlog_set_pending_rows_event(Rows_log_event* ev); int binlog_flush_pending_rows_event(bool stmt_end); + int binlog_remove_pending_rows_event(bool clear_maps); private: - uint binlog_table_maps; // Number of table maps currently in the binlog + /* + Number of outstanding table maps, i.e., table maps in the + transaction cache. + */ + uint binlog_table_maps; enum enum_binlog_flag { BINLOG_FLAG_UNSAFE_STMT_PRINTED,