diff --git a/Docs/manual.texi b/Docs/manual.texi
index e59e97a1b29b2f345470309a86b6dbf2b75b4158..5d86eb7192d44660e672ea371a672cf9bb4557ed 100644
--- a/Docs/manual.texi
+++ b/Docs/manual.texi
@@ -46244,6 +46244,7 @@ users use this code as the rest of the code and because of this we are
 not yet 100% confident in this code.
 
 @menu
+* News-3.23.46::                
 * News-3.23.45::                Changes in release 3.23.45
 * News-3.23.44::                Changes in release 3.23.44
 * News-3.23.43::                Changes in release 3.23.43
@@ -46293,7 +46294,20 @@ not yet 100% confident in this code.
 * News-3.23.0::                 Changes in release 3.23.0
 @end menu
 
-@node News-3.23.45, News-3.23.44, News-3.23.x, News-3.23.x
+@node News-3.23.46, News-3.23.45, News-3.23.x, News-3.23.x
+@appendixsubsec Changes in release 3.23.46
+@itemize @bullet
+@item
+Fixed bug where one got an empty set instead of a DEADLOCK error when using
+BDB tables.
+@item
+One can now kill @code{ANALYZE},@code{REPAIR} and @code{OPTIMIZE TABLE} when
+the thread is waiting to get a lock on the table.
+@item
+Fixed race condition in @code{ANALYZE TABLE}.
+@end itemize
+
+@node News-3.23.45, News-3.23.44, News-3.23.46, News-3.23.x
 @appendixsubsec Changes in release 3.23.45
 @itemize @bullet
 @item
diff --git a/mysql-test/r/bdb-deadlock.result b/mysql-test/r/bdb-deadlock.result
new file mode 100644
index 0000000000000000000000000000000000000000..89077d169805cc14f2c56a529cdc123001f24d29
--- /dev/null
+++ b/mysql-test/r/bdb-deadlock.result
@@ -0,0 +1,10 @@
+x
+1
+id	x
+0	1
+id	x
+0	1
+id	x
+0	1
+id	x
+0	1
diff --git a/mysql-test/t/backup.test b/mysql-test/t/backup.test
index c622522c87013c58d3c1777ee173bedd783bc328..ad332cde6461b3ae3ab716482cd0990dc3cec53e 100644
--- a/mysql-test/t/backup.test
+++ b/mysql-test/t/backup.test
@@ -39,3 +39,4 @@ reap;
 unlock tables;
 connection con1;
 reap;
+drop table t1;
diff --git a/mysql-test/t/bdb-crash.test b/mysql-test/t/bdb-crash.test
index e2d2cd42be2e4c3d9684b6b5b15c0fe330afc5ee..cdbc2dbe0e49f26afed8eb8013ffc322cb8a8367 100644
--- a/mysql-test/t/bdb-crash.test
+++ b/mysql-test/t/bdb-crash.test
@@ -1,8 +1,8 @@
 -- source include/have_bdb.inc
 # test for bug reported by Mark Steele
 
-drop table if exists tblChange;
-CREATE TABLE tblCharge (
+drop table if exists t1;
+CREATE TABLE t1 (
   ChargeID int(10) unsigned DEFAULT '0' NOT NULL auto_increment,
   ServiceID int(10) unsigned DEFAULT '0' NOT NULL,
   ChargeDate date DEFAULT '0000-00-00' NOT NULL,
@@ -20,16 +20,16 @@ DEFAULT 'New' NOT NULL,
 ) type=BDB;
 
 BEGIN;
-INSERT INTO tblCharge
+INSERT INTO t1
 VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
 COMMIT;
 
 BEGIN;
-UPDATE tblCharge SET ChargeAuthorizationMessage = 'blablabla' WHERE
+UPDATE t1 SET ChargeAuthorizationMessage = 'blablabla' WHERE
 ChargeID = 1;
 COMMIT;
 
-INSERT INTO tblCharge
+INSERT INTO t1
 VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
-select * from tblCharge;
-drop table tblCharge;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/bdb-deadlock.test b/mysql-test/t/bdb-deadlock.test
new file mode 100644
index 0000000000000000000000000000000000000000..b32b50c715b7fd5b42043ddd75bee49374af8475
--- /dev/null
+++ b/mysql-test/t/bdb-deadlock.test
@@ -0,0 +1,48 @@
+# This test doesn't work with the embedded version as this code
+# assumes that one query is running while we are doing queries on
+# a second connection.
+# This would work if mysqltest run would be threaded and handle each
+# connection in a separate thread.
+#
+
+#-- source include/not_embedded.inc
+-- source include/have_bdb.inc
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+drop table if exists t1,t2;
+connection con1;
+create table t1 (id integer, x integer) type=BDB;
+create table t2 (id integer, x integer) type=BDB;
+insert into t1 values(0, 0);
+insert into t2 values(0, 0);
+set autocommit=0;
+update t1 set x = 1 where id = 0;
+
+connection con2;
+set autocommit=0;
+update t2 set x = 1 where id = 0;
+
+# The following query should hang because con1 is locking the page
+--send
+select x from t1 where id = 0;
+
+connection con1;
+# This should generate a deadlock as we are trying to access a locked row
+--error 1213
+select x from t2 where id = 0;
+commit;
+
+connection con2;
+reap;
+commit;
+select * from t1;
+select * from t2;
+commit;
+
+connection con1;
+select * from t1;
+select * from t2;
+commit;
+drop table t1,t2;
diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c
index 10c803378dfe82feae9c80e74261498f8a5c1c4d..aa50877072dd65568bd7dfea5fb2723c4b7a36c3 100644
--- a/mysys/thr_lock.c
+++ b/mysys/thr_lock.c
@@ -913,7 +913,8 @@ void thr_multi_unlock(THR_LOCK_DATA **data,uint count)
   DBUG_VOID_RETURN;
 }
 
-/* Abort all threads waiting for a lock. The lock will be upgraded to a
+/*
+  Abort all threads waiting for a lock. The lock will be upgraded to
   TL_WRITE_ONLY to abort any new accesses to the lock
 */
 
diff --git a/sql/records.cc b/sql/records.cc
index 5edbd6896b56a7c714718a9412fe62cb123a7653..37f79e54cf6571b61c9c57756aaa21170889f483 100644
--- a/sql/records.cc
+++ b/sql/records.cc
@@ -132,8 +132,13 @@ static int rr_quick(READ_RECORD *info)
   {
     if (tmp == HA_ERR_END_OF_FILE)
       tmp= -1;
-    else if (info->print_error)
-      info->file->print_error(tmp,MYF(0));
+    else
+    {
+      if (info->print_error)
+	info->file->print_error(tmp,MYF(0));
+      if (tmp < 0)				// Fix negative BDB errno
+	tmp=1;
+    }
   }
   return tmp;
 }
@@ -153,8 +158,13 @@ static int rr_sequential(READ_RECORD *info)
     {
       if (tmp == HA_ERR_END_OF_FILE)
 	tmp= -1;
-      else if (info->print_error)
-	info->table->file->print_error(tmp,MYF(0));
+      else
+      {
+	if (info->print_error)
+	  info->table->file->print_error(tmp,MYF(0));
+	if (tmp < 0)				// Fix negative BDB errno
+	  tmp=1;
+      }
       break;
     }
   }
@@ -168,21 +178,27 @@ static int rr_from_tempfile(READ_RECORD *info)
 tryNext:
   if (my_b_read(info->io_cache,info->ref_pos,info->ref_length))
     return -1;					/* End of file */
-  tmp=info->file->rnd_pos(info->record,info->ref_pos);
-  if (tmp)
+  if ((tmp=info->file->rnd_pos(info->record,info->ref_pos)))
   {
     if (tmp == HA_ERR_END_OF_FILE)
       tmp= -1;
     else if (tmp == HA_ERR_RECORD_DELETED)
       goto tryNext;
-    else if (info->print_error)
-      info->file->print_error(tmp,MYF(0));
+    else
+    {
+      if (info->print_error)
+	info->file->print_error(tmp,MYF(0));
+      if (tmp < 0)				// Fix negative BDB errno
+	tmp=1;
+    }
   }
   return tmp;
 } /* rr_from_tempfile */
 
+
 static int rr_from_pointers(READ_RECORD *info)
 {
+  int tmp;
   byte *cache_pos;
 tryNext:
   if (info->cache_pos == info->cache_end)
@@ -190,15 +206,19 @@ tryNext:
   cache_pos=info->cache_pos;
   info->cache_pos+=info->ref_length;
 
-  int tmp=info->file->rnd_pos(info->record,cache_pos);
-  if (tmp)
+  if ((tmp=info->file->rnd_pos(info->record,cache_pos)))
   {
     if (tmp == HA_ERR_END_OF_FILE)
       tmp= -1;
     else if (tmp == HA_ERR_RECORD_DELETED)
       goto tryNext;
-    else if (info->print_error)
-      info->file->print_error(tmp,MYF(0));
+    else
+    {
+      if (info->print_error)
+	info->file->print_error(tmp,MYF(0));
+      if (tmp < 0)				// Fix negative BDB errno
+	tmp=1;
+    }
   }
   return tmp;
 }
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index b0e319288d9979fb563392fa4522c9eddd46fb50..049fb1c182c3b50658ce5489a060a1999aeaae83 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -954,9 +954,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
     }
 
     /* Close all instances of the table to allow repair to rename files */
-    if (open_for_modify && table->table->version)
+    if (lock_type == TL_WRITE && table->table->version)
     {
       pthread_mutex_lock(&LOCK_open);
+      const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
+					      "Waiting to get writelock");
       mysql_lock_abort(thd,table->table);
       while (remove_table_from_cache(thd, table->table->table_cache_key,
 				     table->table->real_name) &&
@@ -966,9 +968,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
 	(void) pthread_cond_wait(&COND_refresh,&LOCK_open);
 	dropping_tables--;
       }
+      thd->exit_cond(old_message);
       pthread_mutex_unlock(&LOCK_open);
       if (thd->killed)
 	goto err;
+      open_for_modify=0;
     }
 
     int result_code = (table->table->file->*operator_func)(thd, check_opt);
@@ -1016,6 +1020,9 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
     }
     if (fatal_error)
       table->table->version=0;			// Force close of table
+    else if (open_for_modify)
+      remove_table_from_cache(thd, table->table->table_cache_key,
+			      table->table->real_name);
     close_thread_tables(thd);
     if (my_net_write(&thd->net, (char*) packet->ptr(),
 		     packet->length()))