summaryrefslogtreecommitdiff
path: root/sql/sql_insert.cc
diff options
context:
space:
mode:
authorJon Olav Hauglid <jon.hauglid@sun.com>2009-11-18 10:02:21 +0100
committerJon Olav Hauglid <jon.hauglid@sun.com>2009-11-18 10:02:21 +0100
commit41ba42928628fc555cb2f222fbacefa178f63f0a (patch)
tree8689772a48655a043aaef7096f97b84492b2d529 /sql/sql_insert.cc
parenteb7bfcac405045541a4fc156e9c34a448d4dd128 (diff)
downloadmariadb-git-41ba42928628fc555cb2f222fbacefa178f63f0a.tar.gz
Bug #47682 strange behaviour of INSERT DELAYED
The problem was a "self-deadlock" if the connection issuing INSERT DELAYED had both the global read lock (FLUSH TABLES WITH READ LOCK) and LOCK TABLES mode active. The table being inserted into had to be different from the table(s) locked by LOCK TABLES. For INSERT DELAYED, the connection thread waits until the handler thread has opened and locked its table before returning. But since the global read lock was active, the handler thread would be unable to lock and would wait for the global read lock to go away. So the handler thread would be waiting for the connection thread to release the global read lock while the connection thread was waiting for the handler thread to lock the table. This gave a "self-deadlock" (same connection, different threads). The deadlock would only happen if we also had LOCK TABLES mode since the INSERT otherwise will try to get protection against global read lock before starting the handler thread. It will then notice that the global read lock is owned by the same connection and report ER_CANT_UPDATE_WITH_READLOCK. This patch removes the deadlock by reporting ER_CANT_UPDATE_WITH_READLOCK also if we are inside LOCK TABLES mode. Test case added to delayed.test.
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r--sql/sql_insert.cc16
1 files changed, 16 insertions, 0 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 6e2b3903b52..e9a36629c66 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -500,6 +500,22 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list)
DBUG_ENTER("open_and_lock_for_insert_delayed");
#ifndef EMBEDDED_LIBRARY
+ if (thd->locked_tables && thd->global_read_lock)
+ {
+ /*
+ If this connection has the global read lock, the handler thread
+ will not be able to lock the table. It will wait for the global
+ read lock to go away, but this will never happen since the
+ connection thread will be stuck waiting for the handler thread
+ to open and lock the table.
+ If we are not in locked tables mode, INSERT will seek protection
+ against the global read lock (and fail), thus we will only get
+ to this point in locked tables mode.
+ */
+ my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+
if (delayed_get_table(thd, table_list))
DBUG_RETURN(TRUE);