diff options
Diffstat (limited to 'innobase/row')
-rw-r--r-- | innobase/row/row0ins.c | 81 | ||||
-rw-r--r-- | innobase/row/row0mysql.c | 21 |
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); |