[prev in list] [next in list] [prev in thread] [next in thread] 

List:       mysql-internals
Subject:    bk commit into 4.0 tree (guilhem:1.1692)
From:       guilhem () mysql ! com
Date:       2004-01-29 23:05:40
Message-ID: 20040129230540.D69F07A6E4 () gbichot2 ! local
[Download RAW message or body]

Below is the list of changes that have just been committed into a local
4.0 repository of guilhem. When guilhem does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://www.mysql.com/doc/I/n/Installing_source_tree.html

ChangeSet
  1.1692 04/01/30 00:05:34 guilhem@mysql.com +8 -0
  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).

  mysql-test/t/rpl_heap.test
    1.1 04/01/30 00:05:31 guilhem@mysql.com +47 -0

  mysql-test/r/rpl_heap.result
    1.1 04/01/30 00:05:31 guilhem@mysql.com +29 -0

  sql/sql_base.cc
    1.171 04/01/30 00:05:31 guilhem@mysql.com +44 -10
    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;

  sql/handler.h
    1.90 04/01/30 00:05:31 guilhem@mysql.com +2 -1
    new info 'implicit_emptied' in the handler level; only HEAP uses it.

  sql/ha_heap.cc
    1.22 04/01/30 00:05:31 guilhem@mysql.com +1 -0
    report info to upper level

  mysql-test/t/rpl_heap.test
    1.0 04/01/30 00:05:31 guilhem@mysql.com +0 -0
    BitKeeper file /home/mysql_src/mysql-4.0/mysql-test/t/rpl_heap.test

  mysql-test/r/rpl_heap.result
    1.0 04/01/30 00:05:31 guilhem@mysql.com +0 -0
    BitKeeper file /home/mysql_src/mysql-4.0/mysql-test/r/rpl_heap.result

  include/heap.h
    1.9 04/01/30 00:05:31 guilhem@mysql.com +2 -0
    new variables implicit_emptied
    (we need one in HEAPINFO for the hp_info() call).

  heap/hp_open.c
    1.12 04/01/30 00:05:31 guilhem@mysql.com +3 -0
    If this is the first open of the HEAP table, it means it is empty,
    so we mark it.

  heap/hp_info.c
    1.6 04/01/30 00:05:30 guilhem@mysql.com +8 -7
    new info variable implicit_emptied

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	guilhem
# Host:	gbichot2.local
# Root:	/home/mysql_src/mysql-4.0

--- 1.5/heap/hp_info.c	Thu Dec  6 13:10:37 2001
+++ 1.6/heap/hp_info.c	Fri Jan 30 00:05:30 2004
@@ -48,12 +48,13 @@
 	      int flag __attribute__((unused)))
 {
   DBUG_ENTER("heap_info");
-  x->records	 = info->s->records;
-  x->deleted	 = info->s->deleted;
-  x->reclength	 = info->s->reclength;
-  x->data_length = info->s->data_length;
-  x->index_length= info->s->index_length;
-  x->max_records = info->s->max_records;
-  x->errkey	 = info->errkey;
+  x->records         = info->s->records;
+  x->deleted         = info->s->deleted;
+  x->reclength       = info->s->reclength;
+  x->data_length     = info->s->data_length;
+  x->index_length    = info->s->index_length;
+  x->max_records     = info->s->max_records;
+  x->errkey          = info->errkey;
+  x->implicit_emptied= info->implicit_emptied;
   DBUG_RETURN(0);
 } /* heap_info */

--- 1.11/heap/hp_open.c	Thu Jul  3 15:21:46 2003
+++ 1.12/heap/hp_open.c	Fri Jan 30 00:05:31 2004
@@ -30,6 +30,7 @@
 		   uint reclength, ulong max_records, ulong min_records)
 {
   uint i,j,key_segs,max_length,length;
+  my_bool implicit_emptied= 0;
   HP_INFO *info;
   HP_SHARE *share;
   HP_KEYSEG *keyseg;
@@ -39,6 +40,7 @@
   if (!(share=_hp_find_named_heap(name)))
   {
     DBUG_PRINT("info",("Initializing new table"));
+    implicit_emptied= 1;
     for (i=key_segs=max_length=0 ; i < keys ; i++)
     {
       key_segs+= keydef[i].keysegs;
@@ -127,6 +129,7 @@
 #ifndef DBUG_OFF
   info->opt_flag=READ_CHECK_USED;		/* Check when changing */
 #endif
+  info->implicit_emptied= implicit_emptied;
   DBUG_PRINT("exit",("heap: %lx  reclength: %d  records_in_block: %d",
 		     info,share->reclength,share->block.records_in_block));
   DBUG_RETURN(info);

--- 1.8/include/heap.h	Sat Jan 12 14:42:52 2002
+++ 1.9/include/heap.h	Fri Jan 30 00:05:31 2004
@@ -47,6 +47,7 @@
   ulong index_length;
   uint reclength;			/* Length of one record */
   int errkey;
+  my_bool implicit_emptied;
 } HEAPINFO;
 
 
@@ -126,6 +127,7 @@
   int  mode;				/* Mode of file (READONLY..) */
   uint opt_flag,update;
   byte *lastkey;			/* Last used key with rkey */
+  my_bool implicit_emptied;
 #ifdef THREAD
   THR_LOCK_DATA lock;
 #endif

--- 1.21/sql/ha_heap.cc	Thu Nov 14 11:21:27 2002
+++ 1.22/sql/ha_heap.cc	Fri Jan 30 00:05:31 2004
@@ -222,6 +222,7 @@
   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)

--- 1.89/sql/handler.h	Tue Dec 30 12:14:18 2003
+++ 1.90/sql/handler.h	Fri Jan 30 00:05:31 2004
@@ -213,6 +213,7 @@
   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 @@
     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);

--- 1.170/sql/sql_base.cc	Tue Dec 16 11:12:26 2003
+++ 1.171/sql/sql_base.cc	Fri Jan 30 00:05:31 2004
@@ -550,6 +550,11 @@
   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 @@
         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 @@
       }
     }
     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 @@
 	(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,15 +1355,46 @@
       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:
--- New file ---
+++ mysql-test/r/rpl_heap.result	04/01/30 00:05:31
reset master;
drop table if exists t1;
create table t1 (a int) type=HEAP;
insert into t1 values(10);
show binlog events from 79;
Log_name	Pos	Event_type	Server_id	Orig_log_pos	Info
master-bin.001	79	Query	1	79	use `test`; create table t1 (a int) type=HEAP
master-bin.001	147	Query	1	147	use `test`; DELETE FROM `test`.`t1`
master-bin.001	205	Query	1	205	use `test`; insert into t1 values(10)
reset slave;
start slave;
show create table t1;
Table	Create Table
t1	CREATE TABLE `t1` (
  `a` int(11) default NULL
) TYPE=HEAP
select * from t1;
a
10
select * from t1;
a
select * from t1 limit 10;
a
show binlog events in 'master-bin.002' from 79;
Log_name	Pos	Event_type	Server_id	Orig_log_pos	Info
master-bin.002	79	Query	1	79	use `test`; DELETE FROM `test`.`t1`
select * from t1;
a
drop table t1;

--- New file ---
+++ mysql-test/t/rpl_heap.test	04/01/30 00:05:31
# You must run this test with --manager.

require_manager;

# Don't know why, but using TCP/IP connections makes this test fail
# with "Lost connection to MySQL server during query" when we
# issue a query after the server restart.
# Maybe this is something awkward in mysqltest or in the manager?
# So we use sockets.
connect (master,localhost,root,,test,0,master.sock);
connect (slave,localhost,root,,test,0,slave.sock);

connection master;
reset master;
drop table if exists t1;
create table t1 (a int) type=HEAP;
insert into t1 values(10);
save_master_pos;
show binlog events from 79;
connection slave;
reset slave;
start slave;
sync_with_master;
show create table t1;
select * from t1; # should be one row

server_stop master;
server_start master;

connection master;
select * from t1;
# to check that DELETE is not written twice
# (the LIMIT is to not use the query cache)
select * from t1 limit 10;
save_master_pos;
show binlog events in 'master-bin.002' from 79;

connection slave;
sync_with_master;
select * from t1; # should be empty

# clean up
connection master;
drop table t1;
save_master_pos;
connection slave;
sync_with_master;


-- 
MySQL Internals Mailing List
For list archives: http://lists.mysql.com/internals
To unsubscribe:    http://lists.mysql.com/internals?unsub=mysql-internals@progressive-comp.com

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic