summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <heikki@hundin.mysql.fi>2003-03-03 19:31:01 +0200
committerunknown <heikki@hundin.mysql.fi>2003-03-03 19:31:01 +0200
commite70b22e55c5756a8318c07ab337a1c31acf1aa86 (patch)
treec9c5aff16956b040c42f44d96cb69c6c44097284 /sql
parent9ca8f13734d103a44f1653ef7bf1a3ae2747e750 (diff)
downloadmariadb-git-e70b22e55c5756a8318c07ab337a1c31acf1aa86.tar.gz
ha_innodb.h, ha_innodb.cc, handler.h, handler.cc, sql_class.cc:
Fix a hang on the adaptive hash S-latch if an application program uses mysql_use_result() and performs queries on two connections at the same time sql/sql_class.cc: Fix a hang on the adaptive hash S-latch if an application program uses mysql_use_result() and performs queries on two connections at the same time sql/handler.cc: Fix a hang on the adaptive hash S-latch if an application program uses mysql_use_result() and performs queries on two connections at the same time sql/handler.h: Fix a hang on the adaptive hash S-latch if an application program uses mysql_use_result() and performs queries on two connections at the same time sql/ha_innodb.cc: Fix a hang on the adaptive hash S-latch if an application program uses mysql_use_result() and performs queries on two connections at the same time sql/ha_innodb.h: Fix a hang on the adaptive hash S-latch if an application program uses mysql_use_result() and performs queries on two connections at the same time
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_innodb.cc13
-rw-r--r--sql/ha_innodb.h1
-rw-r--r--sql/handler.cc30
-rw-r--r--sql/handler.h1
-rw-r--r--sql/sql_class.cc16
5 files changed, 61 insertions, 0 deletions
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index b5962526d9e..1c6de24ed75 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -151,6 +151,19 @@ innobase_release_stat_resources(
}
/************************************************************************
+Call this function when mysqld passes control to the client. That is to
+avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
+documentation, see handler.cc. */
+
+void
+innobase_release_temporary_latches(
+/*===============================*/
+ void* innobase_tid)
+{
+ innobase_release_stat_resources((trx_t*)innobase_tid);
+}
+
+/************************************************************************
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
time calls srv_active_wake_master_thread. This function should be used
when a single database operation may introduce a small need for
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index d2639f39c5b..8031fa0aa29 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -208,3 +208,4 @@ int innodb_show_status(THD* thd);
my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
uint full_name_len);
+void innobase_release_temporary_latches(void* innobase_tid);
diff --git a/sql/handler.cc b/sql/handler.cc
index fb33888e91e..3fae7c3bd72 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -238,8 +238,10 @@ int ha_autocommit_or_rollback(THD *thd, int error)
handler must be the same as in the binlog.
arguments:
+ thd: the thread handle of the current connection
log_file_name: latest binlog file name
end_offset: the offset in the binlog file up to which we wrote
+ return value: 0 if success, 1 if error
*/
int ha_report_binlog_offset_and_commit(THD *thd,
@@ -266,6 +268,34 @@ int ha_report_binlog_offset_and_commit(THD *thd,
return error;
}
+/*
+ This function should be called when MySQL sends rows of a SELECT result set
+ or the EOF mark to the client. It releases a possible adaptive hash index
+ S-latch held by thd in InnoDB and also releases a possible InnoDB query
+ FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
+ keep them over several calls of the InnoDB handler interface when a join
+ is executed. But when we let the control to pass to the client they have
+ to be released because if the application program uses mysql_use_result(),
+ it may deadlock on the S-latch if the application on another connection
+ performs another SQL query. In MySQL-4.1 this is even more important because
+ there a connection can have several SELECT queries open at the same time.
+
+ arguments:
+ thd: the thread handle of the current connection
+ return value: always 0
+*/
+
+int ha_release_temporary_latches(THD *thd)
+{
+#ifdef HAVE_INNOBASE_DB
+ THD_TRANS *trans;
+ trans = &thd->transaction.all;
+ if (trans->innobase_tid)
+ innobase_release_temporary_latches(trans->innobase_tid);
+#endif
+ return 0;
+}
+
int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
int error=0;
diff --git a/sql/handler.h b/sql/handler.h
index b9209d087a0..8f1d00f64b5 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -371,6 +371,7 @@ void ha_resize_key_cache(void);
int ha_start_stmt(THD *thd);
int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
my_off_t end_offset);
+int ha_release_temporary_latches(THD *thd);
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_autocommit_or_rollback(THD *thd, int error);
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index e5ba58a0543..a99d17b0ec4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -463,6 +463,14 @@ bool select_send::send_data(List<Item> &items)
String *packet= &thd->packet;
DBUG_ENTER("send_data");
+#ifdef HAVE_INNOBASE_DB
+ /* We may be passing the control from mysqld to the client: release the
+ InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
+ by thd */
+ if (thd->transaction.all.innobase_tid)
+ ha_release_temporary_latches(thd);
+#endif
+
if (thd->offset_limit)
{ // using limit offset,count
thd->offset_limit--;
@@ -486,6 +494,14 @@ bool select_send::send_data(List<Item> &items)
bool select_send::send_eof()
{
+#ifdef HAVE_INNOBASE_DB
+ /* We may be passing the control from mysqld to the client: release the
+ InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
+ by thd */
+ if (thd->transaction.all.innobase_tid)
+ ha_release_temporary_latches(thd);
+#endif
+
/* Unlock tables before sending packet to gain some speed */
if (thd->lock)
{