summaryrefslogtreecommitdiff
path: root/innobase/row
diff options
context:
space:
mode:
Diffstat (limited to 'innobase/row')
-rw-r--r--innobase/row/row0ins.c81
-rw-r--r--innobase/row/row0mysql.c21
2 files changed, 83 insertions, 19 deletions
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index 7f1852c70f2..0da749212d2 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -370,6 +370,32 @@ row_ins_cascade_ancestor_updates_table(
return(FALSE);
}
+/*************************************************************************
+Returns the number of ancestor UPDATE or DELETE nodes of a
+cascaded update/delete node. */
+static
+ulint
+row_ins_cascade_n_ancestors(
+/*========================*/
+ /* out: number of ancestors */
+ que_node_t* node) /* in: node in a query graph */
+{
+ que_node_t* parent;
+ ulint n_ancestors = 0;
+
+ parent = que_node_get_parent(node);
+
+ while (que_node_get_type(parent) == QUE_NODE_UPDATE) {
+ n_ancestors++;
+
+ parent = que_node_get_parent(parent);
+
+ ut_a(parent);
+ }
+
+ return(n_ancestors);
+}
+
/**********************************************************************
Calculates the update vector node->cascade->update for a child table in
a cascaded update. */
@@ -616,6 +642,34 @@ row_ins_foreign_report_add_err(
}
/*************************************************************************
+Invalidate the query cache for the given table. */
+static
+void
+row_ins_invalidate_query_cache(
+/*===========================*/
+ que_thr_t* thr, /* in: query thread whose run_node
+ is an update node */
+ const char* name) /* in: table name prefixed with
+ database name and a '/' character */
+{
+ char* buf;
+ char* ptr;
+ ulint len = strlen(name) + 1;
+
+ buf = mem_strdupl(name, len);
+
+ ptr = strchr(buf, '/');
+ ut_a(ptr);
+ *ptr = '\0';
+
+ /* We call a function in ha_innodb.cc */
+#ifndef UNIV_HOTBACKUP
+ innobase_invalidate_query_cache(thr_get_trx(thr), buf, len);
+#endif
+ mem_free(buf);
+}
+
+/*************************************************************************
Perform referential actions or checks when a parent row is deleted or updated
and the constraint had an ON DELETE or ON UPDATE condition which was not
RESTRICT. */
@@ -650,26 +704,15 @@ row_ins_foreign_check_on_constraint(
ulint n_to_update;
ulint err;
ulint i;
- char* ptr;
- char* table_name_buf;
+
+
ut_a(thr && foreign && pcur && mtr);
/* Since we are going to delete or update a row, we have to invalidate
the MySQL query cache for table */
- table_name_buf = mem_strdup(table->name);
-
- ptr = strchr(table_name_buf, '/');
- ut_a(ptr);
- *ptr = '\0';
-
-#ifndef UNIV_HOTBACKUP
- /* We call a function in ha_innodb.cc */
- innobase_invalidate_query_cache(thr_get_trx(thr), table_name_buf,
- strlen(table->name) + 1);
-#endif
- mem_free(table_name_buf);
+ row_ins_invalidate_query_cache(thr, table->name);
node = thr->run_node;
@@ -757,6 +800,16 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
+ if (row_ins_cascade_n_ancestors(cascade) >= 15) {
+ err = DB_ROW_IS_REFERENCED;
+
+ row_ins_foreign_report_err(
+(char*)"Trying a too deep cascaded delete or update\n",
+ thr, foreign, btr_pcur_get_rec(pcur), entry);
+
+ goto nonstandard_exit_func;
+ }
+
index = btr_pcur_get_btr_cur(pcur)->index;
ut_a(index == foreign->foreign_index);
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index c4408de2a85..556c80c948d 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -741,14 +741,15 @@ run_again:
}
/*************************************************************************
-Unlocks a table lock possibly reserved by trx. */
+Unlocks all table locks explicitly requested by trx (with LOCK TABLES,
+lock type LOCK_TABLE_EXP). */
void
-row_unlock_table_for_mysql(
-/*=======================*/
+row_unlock_tables_for_mysql(
+/*========================*/
trx_t* trx) /* in: transaction */
{
- if (!trx->n_tables_locked) {
+ if (!trx->n_lock_table_exp) {
return;
}
@@ -3175,7 +3176,12 @@ row_check_table_for_mysql(
REPEATABLE READ here */
prebuilt->trx->isolation_level = TRX_ISO_REPEATABLE_READ;
-
+
+ /* Enlarge the fatal lock wait timeout during CHECK TABLE. */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
index = dict_table_get_first_index(table);
while (index != NULL) {
@@ -3223,6 +3229,11 @@ row_check_table_for_mysql(
ret = DB_ERROR;
}
+ /* Restore the fatal lock wait timeout after CHECK TABLE. */
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
prebuilt->trx->op_info = "";
return(ret);