diff --git a/Docs/manual.texi b/Docs/manual.texi
index 41baa1b6f648808cb1b229962613af755ea07480..3bacaf1a834ece00560b776d38effe6bd5ba3aca 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -813,7 +813,7 @@ MySQL change history
 
 Changes in release 3.23.x  (Recommended; beta)
 
-* News-3.23.27::                
+* News-3.23.27::                Changes in release 3.23.27
 * News-3.23.26::                Changes in release 3.23.26
 * News-3.23.25::                Changes in release 3.23.25
 * News-3.23.24::                Changes in release 3.23.24
@@ -21494,6 +21494,22 @@ If the repair fails, retry once more with the old repair option method
 type of error with little disk requirements..
 @end itemize
 
+If the recover wouldn't be able to recover all rows from a previous
+completed statement and you didn't specify @code{FORCE} as an option to
+@code{myisam-recover}, then the automatic repair will abort with an error
+message in the error file:
+
+@example
+Error: Couldn't repair table: test.g00pages
+@end example
+
+If you in this case had used the @code{FORCE} option you would instead have got
+a warning in the error file:
+
+@example
+Warning: Found 344 of 354 rows when repairing ./test/g00pages
+@end example
+
 Note that if you run automatic recover with the @code{BACKUP} option,
 you should have a cron script that automaticly moves file with names
 like @file{tablename-datetime.BAK} from the database directories to a
@@ -38138,7 +38154,10 @@ though, so 3.23 is not released as a stable version yet.
 @appendixsubsec Changes in release 3.23.27
 @itemize @bullet
 @item
-You can now have sockets even with @code{mit-pthreads}
+Fixed bug where the automatic repair of MyISAM tables failed sometimes
+when the data file was corrupt.
+@item
+You can now use Unix sockets with @code{mit-pthreads}
 @item
 Small portability fixes
 @end itemize
diff --git a/configure.in b/configure.in
index 48d04852cdfa002b5856de8d23a43d1baa6ba3e3..32041850efcb5da020a92ef4e104c9bf7848d634 100644
--- a/configure.in
+++ b/configure.in
@@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script.
 AC_INIT(sql/mysqld.cc)
 AC_CANONICAL_SYSTEM
 # The Docs Makefile.am parses this line!
-AM_INIT_AUTOMAKE(mysql, 3.23.26-beta)
+AM_INIT_AUTOMAKE(mysql, 3.23.27-beta)
 AM_CONFIG_HEADER(config.h)
 
 PROTOCOL_VERSION=10
@@ -1860,11 +1860,11 @@ AC_SUBST(sql_server_dirs)
 AC_SUBST(thread_dirs)
 AC_SUBST(server_scripts)
 
-if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes"
-then
+#if test "$with_posix_threads" = "no" -o "$with_mit_threads" = "yes"
+#then
   # MIT pthreads does now support connecting with unix sockets
   # AC_DEFINE(HAVE_THREADS_WITHOUT_SOCKETS)
-fi
+#fi
 
 # Some usefull subst
 AC_SUBST(CC)
diff --git a/include/m_string.h b/include/m_string.h
index c17e928ea374e0bb4a870aba926a1371e207198a..6b7719d44f56419e04030013d5240837637bbfad 100644
--- a/include/m_string.h
+++ b/include/m_string.h
@@ -62,7 +62,7 @@
 #if !defined(HAVE_MEMCPY) && !defined(HAVE_MEMMOVE)
 # define memcpy(d, s, n)	bcopy ((s), (d), (n))
 # define memset(A,C,B)		bfill((A),(B),(C))
-# define memmove(d, s, n)	bmove ((s), (d), (n))
+# define memmove(d, s, n)	bmove ((d), (s), (n))
 #elif defined(HAVE_MEMMOVE)
 # define bmove(d, s, n)		memmove((d), (s), (n))
 #else
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 351c2d469dacdd236b92abcba8f6b2e6ed6f6d31..2e3df08083d7cc4be0aba75a185c7a01234fdbd6 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -1048,6 +1048,7 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
   mi_check_print_error(param,"got error: %d when reading datafile",my_errno);
  err2:
   my_afree((gptr) record);
+  param->retry_without_quick=1;
   DBUG_RETURN(1);
 } /* chk_data_link */
 
@@ -2052,6 +2053,7 @@ static int sort_get_next_record(SORT_INFO *sort_info)
       {
 	if (param->read_cache.error)
 	  param->out_flag |= O_DATA_LOST;
+	param->retry_repair=param->retry_without_quick=1;
 	DBUG_RETURN(-1);
       }
       sort_info->start_recpos=sort_info->pos;
@@ -2076,7 +2078,10 @@ static int sort_get_next_record(SORT_INFO *sort_info)
       found_record=block_info.second_read= 0;
       left_length=1;
       if (searching)
+      {
 	pos=MY_ALIGN(pos,MI_DYN_ALIGN_SIZE);
+	param->retry_without_quick=1;
+      }
       do
       {
 	if (pos > sort_info->max_pos)
@@ -2084,11 +2089,10 @@ static int sort_get_next_record(SORT_INFO *sort_info)
 	if (pos & (MI_DYN_ALIGN_SIZE-1))
 	{
 	  if ((param->testflag & T_VERBOSE) || searching == 0)
-	  {
 	    mi_check_print_info(param,"Wrong aligned block at %s",
 				llstr(pos,llbuff));
+	  if (searching)
 	    goto try_next;
-	  }
 	}
 	if (found_record && pos == param->search_after_block)
 	  mi_check_print_info(param,"Block: %s used by record at %s",
@@ -2110,6 +2114,7 @@ static int sort_get_next_record(SORT_INFO *sort_info)
 	if (searching && ! sort_info->fix_datafile)
 	{
 	  param->error_printed=1;
+	  param->retry_repair=param->retry_without_quick=1;
 	  DBUG_RETURN(1);	/* Something wrong with data */
 	}
 	if (((b_type=_mi_get_block_info(&block_info,-1,pos)) &
@@ -2230,7 +2235,7 @@ static int sort_get_next_record(SORT_INFO *sort_info)
 	    {
 	      mi_check_print_error(param,"Not enough memory for blob at %s",
 			  llstr(sort_info->start_recpos,llbuff));
-	      DBUG_RETURN(-1);
+	      DBUG_RETURN(1);
 	    }
 	  }
 	  else
@@ -2305,6 +2310,7 @@ static int sort_get_next_record(SORT_INFO *sort_info)
       if (searching && ! sort_info->fix_datafile)
       {
 	param->error_printed=1;
+	param->retry_repair=param->retry_without_quick=1;
 	DBUG_RETURN(1);		/* Something wrong with data */
       }
       sort_info->start_recpos=sort_info->pos;
@@ -2958,6 +2964,7 @@ int update_state_info(MI_CHECK *param, MI_INFO *info,uint update)
     }
     if (mi_state_info_write(share->kfile,&share->state,1+2))
       goto err;
+    share->changed=0;
   }
   {						/* Force update of status */
     int error;
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index 7d9ba9b7c282f337096db2fdeffae30d464cc0a3..29259d15c1a6fb696c3af47a88f58a74f357ebf4 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -196,7 +196,7 @@ static struct option long_options[] =
 
 static void print_version(void)
 {
-  printf("%s  Ver 1.35 for %s at %s\n",my_progname,SYSTEM_TYPE,
+  printf("%s  Ver 1.36 for %s at %s\n",my_progname,SYSTEM_TYPE,
 	 MACHINE_TYPE);
 }
 
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 639c2dc04a60c064c1a666e605d8447f8559d311..7b1d274922dd840e9fa0288f5e356bfcfcd2d315 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -368,14 +368,14 @@ int ha_myisam::restore(THD* thd, HA_CHECK_OPT *check_opt)
   
  err:
   {
-      MI_CHECK param;
-      myisamchk_init(&param);
-      param.thd = thd;
-      param.op_name = (char*)"restore";
-      param.table_name = table->table_name;
-      param.testflag = 0;
-      mi_check_print_error(&param,errmsg, errno );
-      return error; 
+    MI_CHECK param;
+    myisamchk_init(&param);
+    param.thd = thd;
+    param.op_name = (char*)"restore";
+    param.table_name = table->table_name;
+    param.testflag = 0;
+    mi_check_print_error(&param,errmsg, errno );
+    return error; 
   }
 }
 
@@ -409,10 +409,11 @@ int ha_myisam::backup(THD* thd, HA_CHECK_OPT *check_opt)
 int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
 {
   int error;
-  if (!file) return HA_ADMIN_INTERNAL_ERROR;
   MI_CHECK param;
   ha_rows start_records;
 
+  if (!file) return HA_ADMIN_INTERNAL_ERROR;
+
   myisamchk_init(&param);
   param.thd = thd;
   param.op_name = (char*) "repair";
@@ -428,14 +429,15 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
     if (param.retry_without_quick && param.opt_rep_quick)
     {
       param.opt_rep_quick=0;
-      sql_print_error("Warning: Retrying recover of:  %s without quick",
+      sql_print_error("Warning: Retrying repair of:  '%s' without quick",
 		      table->path);
       continue;
     }
+    param.opt_rep_quick=0;			// Safety
     if ((param.testflag & T_REP_BY_SORT))
     {
       param.testflag= (param.testflag & ~T_REP_BY_SORT) | T_REP;
-      sql_print_error("Warning: Retrying recover of:  %s with keycache",
+      sql_print_error("Warning: Retrying repair of:  '%s' with keycache",
 		      table->path);
       continue;
     }
@@ -444,7 +446,7 @@ int ha_myisam::repair(THD* thd, HA_CHECK_OPT *check_opt)
   if (!error && start_records != file->state->records)
   {
     char llbuff[22],llbuff2[22];
-    sql_print_error("Warning:  Found %s of %s rows from %s",
+    sql_print_error("Warning: Found %s of %s rows when repairing '%s'",
 		    llstr(file->state->records, llbuff),
 		    llstr(start_records, llbuff2),
 		    table->path);
@@ -472,6 +474,7 @@ int ha_myisam::optimize(THD* thd, HA_CHECK_OPT *check_opt)
 int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
 {
   int error=0;
+  uint extra_testflag=0;
   bool optimize_done= !optimize, statistics_done=0;
   char fixed_name[FN_REFLEN];
   const char *old_proc_info=thd->proc_info;
@@ -487,6 +490,12 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
   VOID(fn_format(fixed_name,file->filename,"",MI_NAME_IEXT,
 		     4+ (param.opt_follow_links ? 16 : 0)));
 
+  if (mi_lock_database(file,F_WRLCK))
+  {
+    mi_check_print_error(&param,ER(ER_CANT_LOCK),my_errno);
+    DBUG_RETURN(HA_ADMIN_FAILED);
+  }
+
   if (!optimize || 
       ((file->state->del || share->state.split != file->state->records) &&
        (!param.opt_rep_quick ||
@@ -496,10 +505,13 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
     if (mi_test_if_sort_rep(file,file->state->records,0) &&
 	(param.testflag & T_REP_BY_SORT))
     {
+      uint testflag=param.testflag;
+      extra_testflag=  T_STATISTICS;
       param.testflag|= T_STATISTICS;		// We get this for free
       thd->proc_info="Repair by sorting";
       statistics_done=1;
       error = mi_repair_by_sort(&param, file, fixed_name, param.opt_rep_quick);
+      param.testflag=testflag;
     }
     else
     {
@@ -539,17 +551,19 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
       update_auto_increment_key(&param, file, 1);
     error = update_state_info(&param, file,
 			      UPDATE_TIME | UPDATE_OPEN_COUNT |
-			      (param.testflag & T_STATISTICS ?
-			       UPDATE_STAT : 0));
+			      ((param.testflag | extra_testflag) &
+			       T_STATISTICS ? UPDATE_STAT : 0));
     info(HA_STATUS_NO_LOCK | HA_STATUS_TIME | HA_STATUS_VARIABLE |
 	 HA_STATUS_CONST);
   }
-  else if (!mi_is_crashed(file))
+  else
   {
-    mi_mark_crashed(file);
+    mi_mark_crashed_on_repair(file);
     file->update |= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED;
+    update_state_info(&param, file, 0);
   }
   thd->proc_info=old_proc_info;
+  mi_lock_database(file,F_UNLCK);
   DBUG_RETURN(error ? HA_ADMIN_FAILED :
 	      !optimize_done ? HA_ADMIN_ALREADY_DONE : HA_ADMIN_OK);
 }
@@ -593,6 +607,7 @@ bool ha_myisam::activate_all_index(THD *thd)
 bool ha_myisam::check_and_repair(THD *thd)
 {
   int error=0;
+  int marked_crashed;
   HA_CHECK_OPT check_opt;
   DBUG_ENTER("ha_myisam::auto_check_and_repair");
 
@@ -601,11 +616,11 @@ bool ha_myisam::check_and_repair(THD *thd)
   // Don't use quick if deleted rows
   if (!file->state->del && (myisam_recover_options & HA_RECOVER_QUICK))
     check_opt.quick=1;
-  sql_print_error("Warning: Checking table:  %s",table->path);
-  if (mi_is_crashed(file) || check(thd, &check_opt))
+  sql_print_error("Warning: Checking table:   '%s'",table->path);
+  if ((marked_crashed=mi_is_crashed(file)) || check(thd, &check_opt))
   {
-    sql_print_error("Warning: Recovering table: %s",table->path);
-    check_opt.quick= !check_opt.retry_without_quick;
+    sql_print_error("Warning: Recovering table: '%s'",table->path);
+    check_opt.quick= !check_opt.retry_without_quick && !marked_crashed;
     check_opt.flags=(((myisam_recover_options & HA_RECOVER_BACKUP) ? 
 		      T_BACKUP_DATA : 0) |
 		     (!(myisam_recover_options & HA_RECOVER_FORCE) ? 
diff --git a/sql/handler.cc b/sql/handler.cc
index c7353a864ff874176282b7e53ece8d53b749ccb2..df44df4a8c1739b64fc844b31b6fc341168fbd2d 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -542,6 +542,7 @@ void handler::print_error(int error, myf errflag)
     textno=ER_CHECKREAD;
     break;
   case HA_ERR_CRASHED:
+  case HA_ERR_CRASHED_ON_REPAIR:
     textno=ER_NOT_KEYFILE;
     break;
   case HA_ERR_OUT_OF_MEM:
diff --git a/sql/mysqlbinlog.cc b/sql/mysqlbinlog.cc
index 5c94d5d5a5745d7d38c1b33d5e1d0e1343568929..179bc717093910d92350b54cb541da9876046748 100644
--- a/sql/mysqlbinlog.cc
+++ b/sql/mysqlbinlog.cc
@@ -327,8 +327,8 @@ static void dump_local_log_entries(const char* logname)
  if(!position)
    {
      char magic[4];
-     if(my_fread(file, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME)))
-	die("I/O error reading binlog magic number");
+     if (my_fread(file, (byte*) magic, sizeof(magic), MYF(MY_NABP|MY_WME)))
+       die("I/O error reading binlog magic number");
      if(memcmp(magic, BINLOG_MAGIC, 4))
        die("Bad magic number");
   }
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index b32e5393404ab521ab223f926299e5366cff7d9c..9fc47cd4dfc89e60dedbc40067c595cd1e93102b 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -567,6 +567,9 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
 	pthread_mutex_unlock(&LOCK_delayed_create);
 	DBUG_RETURN(0);
       }
+      pthread_mutex_lock(&LOCK_thread_count);
+      thread_count++;
+      pthread_mutex_unlock(&LOCK_thread_count);
       if (!(tmp->thd.db=my_strdup(table_list->db,MYF(MY_WME))) ||
 	  !(tmp->thd.query=my_strdup(table_list->real_name,MYF(MY_FAE))))
       {
@@ -578,9 +581,6 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
       }
       tmp->table_list=table_list;			// Needed to open table
       tmp->lock();
-      pthread_mutex_lock(&LOCK_thread_count);
-      thread_count++;
-      pthread_mutex_unlock(&LOCK_thread_count);
       pthread_mutex_lock(&tmp->mutex);
       if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib,
 				handle_delayed_insert,(void*) tmp)))
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 83355d08925865c6e52f7b10fc84855aa03a00c6..359ed495a83cf1d0712d750dd54953809a240ba9 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -817,6 +817,7 @@ bool do_command(THD *thd)
       mysql_slow_log.write(thd, thd->query, thd->query_length, start_of_query);
     }
   }
+  thd->proc_info="cleaning up2";
   VOID(pthread_mutex_lock(&LOCK_thread_count)); // For process list
   thd->proc_info=0;
   thd->command=COM_SLEEP;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 35949c41b3c93adffa8575df6e94eb3a6c53ccca..4cdfc992e191717e4a665f85ab8eb40be24b6777 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3721,6 +3721,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
     table->db_stat=0;
     goto err;
   }
+  statistic_increment(created_tmp_disk_tables, &LOCK_status);
   table->db_record_offset=1;
   DBUG_RETURN(0);
  err:
@@ -3781,7 +3782,6 @@ bool create_myisam_from_heap(TABLE *table, TMP_TABLE_PARAM *param, int error,
   save_proc_info=thd->proc_info;
   thd->proc_info="converting HEAP to MyISAM";
 
-  statistic_increment(created_tmp_disk_tables, &LOCK_status);
   if (create_myisam_tmp_table(&new_table,param,
 			      thd->lex.options | thd->options))
     goto err2;
@@ -4196,7 +4196,7 @@ join_read_const(JOIN_TAB *tab)
       if (error != HA_ERR_KEY_NOT_FOUND)
       {
 	sql_print_error("read_const: Got error %d when reading table %s",
-			error, table->real_name);
+			error, table->path);
 	table->file->print_error(error,MYF(0));
 	return 1;
       }
@@ -4231,7 +4231,7 @@ join_read_key(JOIN_TAB *tab)
     if (error && error != HA_ERR_KEY_NOT_FOUND)
     {
       sql_print_error("read_key: Got error %d when reading table '%s'",error,
-		      table->real_name);
+		      table->path);
       table->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4255,7 +4255,7 @@ join_read_always_key(JOIN_TAB *tab)
     if (error != HA_ERR_KEY_NOT_FOUND)
     {
       sql_print_error("read_const: Got error %d when reading table %s",error,
-		      table->real_name);
+		      table->path);
       table->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4287,7 +4287,7 @@ join_read_next(READ_RECORD *info)
     if (error != HA_ERR_END_OF_FILE)
     {
       sql_print_error("read_next: Got error %d when reading table %s",error,
-		      table->real_name);
+		      table->path);
       table->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4365,7 +4365,7 @@ join_init_read_next_with_key(READ_RECORD *info)
     if (error != HA_ERR_END_OF_FILE)
     {
       sql_print_error("read_next_with_key: Got error %d when reading table %s",
-		      error, info->table->real_name);
+		      error, info->table->path);
       info->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4397,7 +4397,7 @@ join_init_read_last_with_key(JOIN_TAB *tab)
     if (error != HA_ERR_END_OF_FILE)
     {
       sql_print_error("read_first_with_key: Got error %d when reading table",
-		      error, table->real_name);
+		      error, table->path);
       table->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4415,7 +4415,7 @@ join_init_read_prev_with_key(READ_RECORD *info)
     if (error != HA_ERR_END_OF_FILE)
     {
       sql_print_error("read_prev_with_key: Got error %d when reading table: %s",
-		      error,info->table->real_name);
+		      error,info->table->path);
       info->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4441,7 +4441,7 @@ join_ft_read_first(JOIN_TAB *tab)
     if (error != HA_ERR_KEY_NOT_FOUND)
     {
       sql_print_error("ft_read_first/init: Got error %d when reading table %s",error,
-                      table->real_name);
+                      table->path);
       table->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4454,7 +4454,7 @@ join_ft_read_first(JOIN_TAB *tab)
     if (error != HA_ERR_END_OF_FILE)
     {
       sql_print_error("ft_read_first/read: Got error %d when reading table %s",
-                      error, table->real_name);
+                      error, table->path);
       table->file->print_error(error,MYF(0));
       return 1;
     }
@@ -4472,7 +4472,7 @@ join_ft_read_next(READ_RECORD *info)
     if (error != HA_ERR_END_OF_FILE)
     {
       sql_print_error("ft_read_next: Got error %d when reading table %s",
-                      error, info->table->real_name);
+                      error, info->table->path);
       info->file->print_error(error,MYF(0));
       return 1;
     }