diff options
author | unknown <guilhem@mysql.com> | 2004-01-30 00:05:34 +0100 |
---|---|---|
committer | unknown <guilhem@mysql.com> | 2004-01-30 00:05:34 +0100 |
commit | bbd2adf4ba6ec2086a5e8eeaa89f56f1abee02f6 (patch) | |
tree | 86a549cfea46d66ac122b39922323a8bd8a9e317 /sql/sql_base.cc | |
parent | 8746a25554d18f03fc32ca5d338850f9308bee88 (diff) | |
download | mariadb-git-bbd2adf4ba6ec2086a5e8eeaa89f56f1abee02f6.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).
heap/hp_info.c:
new info variable implicit_emptied
heap/hp_open.c:
If this is the first open of the HEAP table, it means it is empty,
so we mark it.
include/heap.h:
new variables implicit_emptied
(we need one in HEAPINFO for the hp_info() call).
sql/ha_heap.cc:
report info to upper level
sql/handler.h:
new info 'implicit_emptied' in the handler level; only HEAP uses it.
sql/sql_base.cc:
When a HEAP table is opened for the first time, write a DELETE FROM to the binlog,
for replication and mysqlbinlog|mysql.
Monty: I added the
entry->file->implicit_emptied= 0;
Diffstat (limited to 'sql/sql_base.cc')
-rw-r--r-- | sql/sql_base.cc | 54 |
1 files changed, 44 insertions, 10 deletions
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); |