diff options
author | Andrei Elkin <aelkin@mysql.com> | 2008-12-02 19:32:07 +0200 |
---|---|---|
committer | Andrei Elkin <aelkin@mysql.com> | 2008-12-02 19:32:07 +0200 |
commit | 40889f9ea6643620509f6978316a40d209b92b18 (patch) | |
tree | b683cc87cc1675f4a2ca9044490d895be9255e2a /sql/log.cc | |
parent | 9e91c8d6c2bd94b87ae53a9be828f2b78d29cc83 (diff) | |
download | mariadb-git-40889f9ea6643620509f6978316a40d209b92b18.tar.gz |
Bug #40221 Replication failure on RBR + UPDATE the primary key
A transaction could result in having an extra event after a query that
errored e.g because of a dup key. Such a query is rolled back in
innodb, as specified, but has not been in binlog.
It appeares that the binlog engine did not always register for a query
(statement) because the previous query had not reset at its statement
commit time. Because of that fact there was no roll-back to the
trx_data->before_stmt_pos position and a the pending event of the
errorred query could become flushed to the binlog file.
Fixed with deploying the reset of trx_data->before_stmt_pos at the end
of the query processing.
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/sql/log.cc b/sql/log.cc index fb8669a5731..8169ff08590 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -207,6 +207,7 @@ public: truncate(0); before_stmt_pos= MY_OFF_T_UNDEF; trans_log.end_of_file= max_binlog_cache_size; + DBUG_ASSERT(empty()); } Rows_log_event *pending() const @@ -1377,8 +1378,6 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, FLAGSTR(thd->options, OPTION_NOT_AUTOCOMMIT), FLAGSTR(thd->options, OPTION_BEGIN))); - thd->binlog_flush_pending_rows_event(TRUE); - /* NULL denotes ROLLBACK with nothing to replicate: i.e., rollback of only transactional tables. If the transaction contain changes to @@ -1387,6 +1386,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, */ if (end_ev != NULL) { + thd->binlog_flush_pending_rows_event(TRUE); /* Doing a commit or a rollback including non-transactional tables, i.e., ending a transaction where we might write the transaction @@ -1435,6 +1435,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, mysql_bin_log.update_table_map_version(); } + DBUG_ASSERT(thd->binlog_get_pending_rows_event() == NULL); DBUG_RETURN(error); } @@ -1466,6 +1467,7 @@ static int binlog_prepare(handlerton *hton, THD *thd, bool all) */ static int binlog_commit(handlerton *hton, THD *thd, bool all) { + int error= 0; DBUG_ENTER("binlog_commit"); binlog_trx_data *const trx_data= (binlog_trx_data*) thd_get_ha_data(thd, binlog_hton); @@ -1552,10 +1554,14 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) { Query_log_event qev(thd, STRING_WITH_LEN("COMMIT"), TRUE, FALSE); qev.error_code= 0; // see comment in MYSQL_LOG::write(THD, IO_CACHE) - int error= binlog_end_trans(thd, trx_data, &qev, all); - DBUG_RETURN(error); + error= binlog_end_trans(thd, trx_data, &qev, all); + goto end; } - DBUG_RETURN(0); + +end: + if (!all) + trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt commit + DBUG_RETURN(error); } /** @@ -1615,6 +1621,8 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) */ error= binlog_end_trans(thd, trx_data, 0, all); } + if (!all) + trx_data->before_stmt_pos = MY_OFF_T_UNDEF; // part of the stmt rollback DBUG_RETURN(error); } |