summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorguilhem@mysql.com <>2004-01-30 00:05:34 +0100
committerguilhem@mysql.com <>2004-01-30 00:05:34 +0100
commite71325caf95afbaaacac3581f38b0eafd2116620 (patch)
tree86a549cfea46d66ac122b39922323a8bd8a9e317 /sql
parent5ce227e78a2bc0530c3cab2cbebdd4672a0c40c1 (diff)
downloadmariadb-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.cc1
-rw-r--r--sql/handler.h3
-rw-r--r--sql/sql_base.cc54
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);