diff options
author | guilhem@mysql.com <> | 2004-01-30 00:05:34 +0100 |
---|---|---|
committer | guilhem@mysql.com <> | 2004-01-30 00:05:34 +0100 |
commit | e71325caf95afbaaacac3581f38b0eafd2116620 (patch) | |
tree | 86a549cfea46d66ac122b39922323a8bd8a9e317 /sql | |
parent | 5ce227e78a2bc0530c3cab2cbebdd4672a0c40c1 (diff) | |
download | mariadb-git-e71325caf95afbaaacac3581f38b0eafd2116620.tar.gz |
Fix for BUG#2477 "Slave stop with error after master reboot if use HEAP tables":
when we open the HEAP table for the first time since server restart,
in hp_open(), we set a flag to propagate this info to the handler level
which then writes a DELETE FROM this_heap_table to the binlog.
It is not a perfect solution for the bug, because between the server start and
the first open of the table, the slave still had old data in his table so
a SELECT on the slave may show wrong content. But if there is a --init-file
to populate the HEAP table on master as startup, then this is a safe fix
(I'll put a note about init-file in the HEAP section of the manual).
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_heap.cc | 1 | ||||
-rw-r--r-- | sql/handler.h | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 54 |
3 files changed, 47 insertions, 11 deletions
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 2edc3b1478e..eb4bf517374 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -222,6 +222,7 @@ void ha_heap::info(uint flag) index_file_length=info.index_length; max_data_file_length= info.max_records* info.reclength; delete_length= info.deleted * info.reclength; + implicit_emptied= info.implicit_emptied; } int ha_heap::extra(enum ha_extra_function operation) diff --git a/sql/handler.h b/sql/handler.h index 8e72267c337..60edf539e2c 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -213,6 +213,7 @@ public: uint raid_type,raid_chunks; FT_INFO *ft_handler; bool auto_increment_column_changed; + bool implicit_emptied; /* Can be !=0 only if HEAP */ handler(TABLE *table_arg) :table(table_arg), ref(0), data_file_length(0), max_data_file_length(0), index_file_length(0), @@ -221,7 +222,7 @@ public: create_time(0), check_time(0), update_time(0), key_used_on_scan(MAX_KEY), active_index(MAX_REF_PARTS), ref_length(sizeof(my_off_t)), block_size(0), - raid_type(0), ft_handler(0) + raid_type(0), ft_handler(0), implicit_emptied(0) {} virtual ~handler(void) {} int ha_open(const char *name, int mode, int test_if_locked); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 9937336fb4a..40153ad847e 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -550,6 +550,11 @@ void close_temporary_tables(THD *thd) query_buf_size= 50; // Enough for DROP ... TABLE for (table=thd->temporary_tables ; table ; table=table->next) + /* + We are going to add 4 ` around the db/table names, so 1 does not look + enough; indeed it is enough, because table->key_length is greater (by 8, + because of server_id and thread_id) than db||table. + */ query_buf_size+= table->key_length+1; if ((query = alloc_root(&thd->mem_root, query_buf_size))) @@ -566,8 +571,8 @@ void close_temporary_tables(THD *thd) Here we assume table_cache_key always starts with \0 terminated db name */ - end = strxmov(end,"`",table->table_cache_key,"`", - ".`",table->real_name,"`,", NullS); + end = strxmov(end,"`",table->table_cache_key,"`.`", + table->real_name,"`,", NullS); } next=table->next; close_temporary(table); @@ -1331,8 +1336,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, } } pthread_mutex_unlock(&LOCK_open); - thd->net.last_error[0]=0; // Clear error message - thd->net.last_errno=0; + thd->clear_error(); error=0; if (openfrm(path,alias, (uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE | HA_GET_INDEX | @@ -1343,8 +1347,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, (entry->file->is_crashed() && entry->file->check_and_repair(thd))) { /* Give right error message */ - thd->net.last_error[0]=0; - thd->net.last_errno=0; + thd->clear_error(); my_error(ER_NOT_KEYFILE, MYF(0), name, my_errno); sql_print_error("Error: Couldn't repair table: %s.%s",db,name); if (entry->file) @@ -1352,16 +1355,47 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db, error=1; } else - { - thd->net.last_error[0]=0; // Clear error message - thd->net.last_errno=0; - } + thd->clear_error(); pthread_mutex_lock(&LOCK_open); unlock_table_name(thd,&table_list); if (error) goto err; } + /* + If we are here, there was no fatal error (but error may be still + unitialized). + */ + if (unlikely(entry->file->implicit_emptied)) + { + entry->file->implicit_emptied= 0; + if (mysql_bin_log.is_open()) + { + char *query, *end; + uint query_buf_size= 20 + 2*NAME_LEN + 1; + if ((query= (char*)my_malloc(query_buf_size,MYF(MY_WME)))) + { + end = strxmov(strmov(query, "DELETE FROM `"), + db,"`.`",name,"`", NullS); + Query_log_event qinfo(thd, query, (ulong)(end-query), 0); + mysql_bin_log.write(&qinfo); + my_free(query, MYF(0)); + } + else + { + /* + As replication is maybe going to be corrupted, we need to warn the + DBA on top of warning the client (which will automatically be done + because of MYF(MY_WME) in my_malloc() above). + */ + sql_print_error("Error: when opening HEAP table, could not allocate \ +memory to write 'DELETE FROM `%s`.`%s`' to the binary log",db,name); + if (entry->file) + closefrm(entry); + goto err; + } + } + } DBUG_RETURN(0); err: DBUG_RETURN(1); |