diff options
author | Luis Soares <luis.soares@oracle.com> | 2012-02-24 16:07:43 +0000 |
---|---|---|
committer | Luis Soares <luis.soares@oracle.com> | 2012-02-24 16:07:43 +0000 |
commit | 02f44fe92ba250f1123321313c1c5202cc5c263a (patch) | |
tree | f4388eb761cc036d29ab5b7128ae62647026ceb2 /sql/rpl_rli.cc | |
parent | 89b6cb72c9ca8bac35dcfdee414e2eb4cc87971b (diff) | |
download | mariadb-git-02f44fe92ba250f1123321313c1c5202cc5c263a.tar.gz |
Bug#13693012: SLAVE CRASHING ON INSERT STATEMENT WITH MERGE TABLE
PROBLEM: After WL 4144, when using MyISAM Merge tables, the routine
open_and_lock_tables will append to the list of tables to lock, the
base tables that make up the MERGE table. This has two side-effects in
replication:
1. On the master side, we log additional table maps for the base
tables, since they appear in the list of locked tables, even
though we don't really use them at the slave.
2. On the slave side, when opening a MERGE table while applying a
ROW event, additional tables are appended to the list of tables
to lock.
Side-effect #1 is not harmful. It's just that when using MyISAM Merge
tables a few table maps more may be logged.
Side-effect #2, is harmful, because the list rli->tables_to_lock is an
extended structure from TABLE_LIST in which the extra fields are
filled from the table maps that are processed. Since
open_and_lock_tables appends tables to the list after all table map
events have been processed we end up with entries without
replication/table map data on them. Thus when trying to access that
info for these extra tables, the server will crash.
SOLUTION: We fix side-effect #2 by making sure that we access the
replication part of the structure for those in the list that were
accounted for when processing the correspondent table map events. All
in all, we never go beyond rli->tables_to_lock_count.
We also deploy an assertion when clearing rli->tables_to_lock, making
sure that the base tables are not in the list anymore (were closed in
close_thread_tables).
Diffstat (limited to 'sql/rpl_rli.cc')
-rw-r--r-- | sql/rpl_rli.cc | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 351ff5843dd..542ae58efae 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1264,6 +1264,23 @@ void Relay_log_info::cleanup_context(THD *thd, bool error) void Relay_log_info::clear_tables_to_lock() { + DBUG_ENTER("Relay_log_info::clear_tables_to_lock()"); +#ifndef DBUG_OFF + /** + When replicating in RBR and MyISAM Merge tables are involved + open_and_lock_tables (called in do_apply_event) appends the + base tables to the list of tables_to_lock. Then these are + removed from the list in close_thread_tables (which is called + before we reach this point). + + This assertion just confirms that we get no surprises at this + point. + */ + uint i=0; + for (TABLE_LIST *ptr= tables_to_lock ; ptr ; ptr= ptr->next_global, i++) ; + DBUG_ASSERT(i == tables_to_lock_count); +#endif + while (tables_to_lock) { uchar* to_free= reinterpret_cast<uchar*>(tables_to_lock); @@ -1288,10 +1305,12 @@ void Relay_log_info::clear_tables_to_lock() my_free(to_free); } DBUG_ASSERT(tables_to_lock == NULL && tables_to_lock_count == 0); + DBUG_VOID_RETURN; } void Relay_log_info::slave_close_thread_tables(THD *thd) { + DBUG_ENTER("Relay_log_info::slave_close_thread_tables(THD *thd)"); thd->stmt_da->can_overwrite_status= TRUE; thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd); thd->stmt_da->can_overwrite_status= FALSE; @@ -1313,5 +1332,6 @@ void Relay_log_info::slave_close_thread_tables(THD *thd) thd->mdl_context.release_statement_locks(); clear_tables_to_lock(); + DBUG_VOID_RETURN; } #endif |