1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

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;
This commit is contained in:
unknown
2004-01-30 00:05:34 +01:00
parent 8746a25554
commit bbd2adf4ba
8 changed files with 136 additions and 18 deletions

View File

@ -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);