List:Commits« Previous MessageNext Message »
From:ingo Date:June 2 2006 2:57pm
Subject:bk commit into 5.1 tree (ingo:1.2177)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of mydev. When mydev 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://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet
  1.2177 06/06/02 14:57:27 ingo@stripped +5 -0
  Merge mysql.com:/home/mydev/mysql-5.1
  into  mysql.com:/home/mydev/mysql-5.1-amerge

  mysql-test/t/lock_multi.test
    1.16 06/06/02 14:57:22 ingo@stripped +0 -2
    Manual merge of team tree

  mysql-test/r/lock_multi.result
    1.18 06/06/02 14:57:22 ingo@stripped +0 -0
    Manual merge of team tree

  storage/myisam/myisamdef.h
    1.88 06/06/02 14:55:10 ingo@stripped +0 -0
    Auto merged

  storage/myisam/mi_check.c
    1.147 06/06/02 14:55:10 ingo@stripped +0 -0
    Auto merged

  sql/sql_db.cc
    1.135 06/06/02 14:55:10 ingo@stripped +0 -0
    Auto merged

# 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:	ingo
# Host:	chilla.local
# Root:	/home/mydev/mysql-5.1-amerge/RESYNC

--- 1.146/storage/myisam/mi_check.c	2006-05-30 20:06:14 +02:00
+++ 1.147/storage/myisam/mi_check.c	2006-06-02 14:55:10 +02:00
@@ -453,25 +453,24 @@ int chk_key(MI_CHECK *param, register MI
     if ((uint) share->base.auto_key -1 == key)
     {
       /* Check that auto_increment key is bigger than max key value */
-      ulonglong save_auto_value=info->s->state.auto_increment;
-      info->s->state.auto_increment=0;
+      ulonglong auto_increment;
       info->lastinx=key;
       _mi_read_key_record(info, 0L, info->rec_buff);
-      update_auto_increment(info, info->rec_buff);
-      if (info->s->state.auto_increment > save_auto_value)
+      auto_increment= retrieve_auto_increment(info, info->rec_buff);
+      if (auto_increment > info->s->state.auto_increment)
       {
-	mi_check_print_warning(param,
-			       "Auto-increment value: %s is smaller than max used value: %s",
-			       llstr(save_auto_value,buff2),
-			       llstr(info->s->state.auto_increment, buff));
+        mi_check_print_warning(param, "Auto-increment value: %s is smaller "
+                               "than max used value: %s",
+                               llstr(info->s->state.auto_increment,buff2),
+                               llstr(auto_increment, buff));
       }
       if (param->testflag & T_AUTO_INC)
       {
-	set_if_bigger(info->s->state.auto_increment,
-		      param->auto_increment_value);
+        set_if_bigger(info->s->state.auto_increment,
+                      auto_increment);
+        set_if_bigger(info->s->state.auto_increment,
+                      param->auto_increment_value);
       }
-      else
-	info->s->state.auto_increment=save_auto_value;
 
       /* Check that there isn't a row with auto_increment = 0 in the table */
       mi_extra(info,HA_EXTRA_KEYREAD,0);
@@ -481,8 +480,8 @@ int chk_key(MI_CHECK *param, register MI
       {
 	/* Don't count this as a real warning, as myisamchk can't correct it */
 	uint save=param->warning_printed;
-	mi_check_print_warning(param,
-			       "Found row where the auto_increment column has the value 0");
+        mi_check_print_warning(param, "Found row where the auto_increment "
+                               "column has the value 0");
 	param->warning_printed=save;
       }
       mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
@@ -4124,11 +4123,10 @@ void update_auto_increment_key(MI_CHECK 
   }
   else
   {
-    ulonglong auto_increment= (repair_only ? info->s->state.auto_increment :
-			       param->auto_increment_value);
-    info->s->state.auto_increment=0;
-    update_auto_increment(info, record);
+    ulonglong auto_increment= retrieve_auto_increment(info, record);
     set_if_bigger(info->s->state.auto_increment,auto_increment);
+    if (!repair_only)
+      set_if_bigger(info->s->state.auto_increment, param->auto_increment_value);
   }
   mi_extra(info,HA_EXTRA_NO_KEYREAD,0);
   my_free((char*) record, MYF(0));

--- 1.87/storage/myisam/myisamdef.h	2006-05-30 18:14:53 +02:00
+++ 1.88/storage/myisam/myisamdef.h	2006-06-02 14:55:10 +02:00
@@ -593,7 +593,7 @@ extern uint _mi_pack_key(MI_INFO *info,u
 extern int _mi_read_key_record(MI_INFO *info,my_off_t filepos,byte *buf);
 extern int _mi_read_cache(IO_CACHE *info,byte *buff,my_off_t pos,
 			  uint length,int re_read_if_possibly);
-extern void update_auto_increment(MI_INFO *info,const byte *record);
+extern ulonglong retrieve_auto_increment(MI_INFO *info,const byte *record);
 
 extern byte *mi_alloc_rec_buff(MI_INFO *,ulong, byte**);
 #define mi_get_rec_buff_ptr(info,buf)                              \

--- 1.134/sql/sql_db.cc	2006-05-22 20:45:58 +02:00
+++ 1.135/sql/sql_db.cc	2006-06-02 14:55:10 +02:00
@@ -538,16 +538,27 @@ bool mysql_create_db(THD *thd, char *db,
     my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
     DBUG_RETURN(-1);
   }
-  
-  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
 
-  /* do not create database if another thread is holding read lock */
+  /*
+    Do not create database if another thread is holding read lock.
+    Wait for global read lock before acquiring LOCK_mysql_create_db.
+    After wait_if_global_read_lock() we have protection against another
+    global read lock. If we would acquire LOCK_mysql_create_db first,
+    another thread could step in and get the global read lock before we
+    reach wait_if_global_read_lock(). If this thread tries the same as we
+    (admin a db), it would then go and wait on LOCK_mysql_create_db...
+    Furthermore wait_if_global_read_lock() checks if the current thread
+    has the global read lock and refuses the operation with
+    ER_CANT_UPDATE_WITH_READLOCK if applicable.
+  */
   if (wait_if_global_read_lock(thd, 0, 1))
   {
     error= -1;
     goto exit2;
   }
 
+  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
+
   /* Check directory */
   path_len= build_table_filename(path, sizeof(path), db, "", "");
   path[path_len-1]= 0;                    // Remove last '/' from path
@@ -655,9 +666,9 @@ bool mysql_create_db(THD *thd, char *db,
   }
 
 exit:
+  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
   start_waiting_global_read_lock(thd);
 exit2:
-  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
   DBUG_RETURN(error);
 }
 
@@ -671,12 +682,23 @@ bool mysql_alter_db(THD *thd, const char
   int error= 0;
   DBUG_ENTER("mysql_alter_db");
 
-  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
-
-  /* do not alter database if another thread is holding read lock */
+  /*
+    Do not alter database if another thread is holding read lock.
+    Wait for global read lock before acquiring LOCK_mysql_create_db.
+    After wait_if_global_read_lock() we have protection against another
+    global read lock. If we would acquire LOCK_mysql_create_db first,
+    another thread could step in and get the global read lock before we
+    reach wait_if_global_read_lock(). If this thread tries the same as we
+    (admin a db), it would then go and wait on LOCK_mysql_create_db...
+    Furthermore wait_if_global_read_lock() checks if the current thread
+    has the global read lock and refuses the operation with
+    ER_CANT_UPDATE_WITH_READLOCK if applicable.
+  */
   if ((error=wait_if_global_read_lock(thd,0,1)))
     goto exit2;
 
+  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
+
   /* 
      Recreate db options file: /dbpath/.db.opt
      We pass MY_DB_OPT_FILE as "extension" to avoid
@@ -721,9 +743,9 @@ bool mysql_alter_db(THD *thd, const char
   send_ok(thd, result);
 
 exit:
+  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
   start_waiting_global_read_lock(thd);
 exit2:
-  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
   DBUG_RETURN(error);
 }
 
@@ -755,15 +777,26 @@ bool mysql_rm_db(THD *thd,char *db,bool 
   TABLE_LIST* dropped_tables= 0;
   DBUG_ENTER("mysql_rm_db");
 
-  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
-
-  /* do not drop database if another thread is holding read lock */
+  /*
+    Do not drop database if another thread is holding read lock.
+    Wait for global read lock before acquiring LOCK_mysql_create_db.
+    After wait_if_global_read_lock() we have protection against another
+    global read lock. If we would acquire LOCK_mysql_create_db first,
+    another thread could step in and get the global read lock before we
+    reach wait_if_global_read_lock(). If this thread tries the same as we
+    (admin a db), it would then go and wait on LOCK_mysql_create_db...
+    Furthermore wait_if_global_read_lock() checks if the current thread
+    has the global read lock and refuses the operation with
+    ER_CANT_UPDATE_WITH_READLOCK if applicable.
+  */
   if (wait_if_global_read_lock(thd, 0, 1))
   {
     error= -1;
     goto exit2;
   }
 
+  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
+
   length= build_table_filename(path, sizeof(path), db, "", "");
   strmov(path+length, MY_DB_OPT_FILE);		// Append db option file name
   del_dbopt(path);				// Remove dboption hash entry
@@ -872,7 +905,6 @@ bool mysql_rm_db(THD *thd,char *db,bool 
 exit:
   (void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now  */
   error= Events::drop_schema_events(thd, db);
-  start_waiting_global_read_lock(thd);
   /*
     If this database was the client's selected database, we silently change the
     client's selected database to nothing (to have an empty SELECT DATABASE()
@@ -901,9 +933,9 @@ exit:
     thd->db= 0;
     thd->db_length= 0;
   }
-exit2:
   VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
-
+  start_waiting_global_read_lock(thd);
+exit2:
   DBUG_RETURN(error);
 }
 

--- 1.17/mysql-test/r/lock_multi.result	2006-05-29 15:27:19 +02:00
+++ 1.18/mysql-test/r/lock_multi.result	2006-06-02 14:57:22 +02:00
@@ -58,3 +58,19 @@ ERROR HY000: Can't execute the query bec
 UNLOCK TABLES;
 DROP DATABASE mysqltest_1;
 ERROR HY000: Can't drop database 'mysqltest_1'; database doesn't exist
+use mysql;
+LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
+FLUSH TABLES;
+use mysql;
+ SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
+OPTIMIZE TABLES columns_priv, db, host, user;
+Table	Op	Msg_type	Msg_text
+mysql.columns_priv	optimize	status	OK
+mysql.db	optimize	status	OK
+mysql.host	optimize	status	OK
+mysql.user	optimize	status	OK
+UNLOCK TABLES;
+Select_priv
+N
+use test;
+use test;

--- 1.15/mysql-test/t/lock_multi.test	2006-05-29 15:27:20 +02:00
+++ 1.16/mysql-test/t/lock_multi.test	2006-06-02 14:57:22 +02:00
@@ -161,3 +161,33 @@ disconnect con2;
 --error ER_DB_DROP_EXISTS
 DROP DATABASE mysqltest_1;
 
+# Bug#16986 - Deadlock condition with MyISAM tables
+#
+connection locker;
+use mysql;
+LOCK TABLES columns_priv WRITE, db WRITE, host WRITE, user WRITE;
+FLUSH TABLES;
+--sleep 1
+#
+connection reader;
+use mysql;
+#NOTE:  This must be a multi-table select, otherwise the deadlock will not occur
+send SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
+--sleep 1
+#
+connection locker;
+# Make test case independent from earlier grants.
+--replace_result "Table is already up to date" "OK"
+OPTIMIZE TABLES columns_priv, db, host, user;
+UNLOCK TABLES;
+#
+connection reader;
+reap;
+use test;
+#
+connection locker;
+use test;
+#
+connection default;
+
+# End of 5.0 tests
Thread
bk commit into 5.1 tree (ingo:1.2177)ingo2 Jun