diff options
author | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-06-14 15:47:39 +0300 |
---|---|---|
committer | Jan Lindström <jan.lindstrom@mariadb.com> | 2018-06-15 09:04:26 +0300 |
commit | c69357d8d4592b746a2dd7074c8fb6a437098b2a (patch) | |
tree | 8bbcb53dd48cca7fda5c496094bf56bb71842262 /storage | |
parent | f4387288ab54837aa84ce728b2ce61e52850e4ec (diff) | |
download | mariadb-git-c69357d8d4592b746a2dd7074c8fb6a437098b2a.tar.gz |
MDEV-15611 Due to the failure of foreign key detection, Galera slave node killed himself.
Merge following change from 10.2
revision-id: d52cff9f10aeea208a1058f7b5527e602125584c (mariadb-10.2.14-25-gd52cff9)
parent(s): bc2501453c3ab9a2cf3516bc3557de8665bc2776
author: Sachin Setiya
committer: Sachin Setiya
timestamp: 2018-04-04 12:26:06 +0530
message:
MDEV-15611 Due to the failure of foreign key detection, Galera...
slave node killed himself.
Problem:- If we try to delete table with foreign key and table whom it is
referring with wsrep_slave_threads>1 then galera tries to execute both
Delete_rows_log-event in parallel, which should not happen.
Solution:- This is happening because we do not have foreign key info in
write set. Upto version 10.2.7 it used to work fine. Actually it happening
because of issue in commit 2f342c4. wsrep_must_process_fk should be used
with negation.
Diffstat (limited to 'storage')
-rw-r--r-- | storage/innobase/row/row0upd.cc | 141 | ||||
-rw-r--r-- | storage/xtradb/row/row0upd.cc | 141 |
2 files changed, 150 insertions, 132 deletions
diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index e2de47bf86a..33f46882651 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1803,6 +1803,23 @@ row_upd_store_row( } } +#ifdef WITH_WSREP +/** Determine if a FOREIGN KEY constraint needs to be processed. +@param[in] node query node +@param[in] trx transaction +@return whether the node cannot be ignored */ + +inline bool wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) +{ + if (!wsrep_on_trx(trx)) { + return false; + } + return que_node_get_type(node->common.parent) != QUE_NODE_UPDATE + || static_cast<upd_node_t*>(node->common.parent)->cascade_node + != node; +} +#endif /* WITH_WSREP */ + /***********************************************************//** Updates a secondary index entry of a row. @return DB_SUCCESS if operation successfully completed, else error @@ -1833,7 +1850,7 @@ row_upd_sec_index_entry( referenced = row_upd_index_is_referenced(index, trx); #ifdef WITH_WSREP - ibool foreign = wsrep_row_upd_index_is_foreign(index, trx); + bool foreign = wsrep_row_upd_index_is_foreign(index, trx); #endif /* WITH_WSREP */ heap = mem_heap_create(1024); @@ -1962,61 +1979,61 @@ row_upd_sec_index_entry( row_ins_sec_index_entry() below */ if (!rec_get_deleted_flag( rec, dict_table_is_comp(index->table))) { -#ifdef WITH_WSREP - que_node_t *parent = que_node_get_parent(node); -#endif /* WITH_WSREP */ err = btr_cur_del_mark_set_sec_rec( 0, btr_cur, TRUE, thr, &mtr); - if (err == DB_SUCCESS && referenced) { - - ulint* offsets; - - offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, - &heap); - - /* NOTE that the following call loses - the position of pcur ! */ - err = row_upd_check_references_constraints( - node, &pcur, index->table, - index, offsets, thr, &mtr); + if (err != DB_SUCCESS) { + break; } + #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced && - wsrep_on_trx(trx) && - !wsrep_thd_is_BF(trx->mysql_thd, FALSE) && - !(parent && que_node_get_type(parent) == - QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - foreign - ) { - ulint* offsets = - rec_get_offsets( + if (!referenced && foreign + && wsrep_must_process_fk(node, trx) + && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + ulint* offsets = rec_get_offsets( rec, index, NULL, ULINT_UNDEFINED, &heap); + err = wsrep_row_upd_check_foreign_constraints( node, &pcur, index->table, index, offsets, thr, &mtr); + switch (err) { case DB_SUCCESS: case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) fprintf (stderr, - "WSREP: sec index FK check fail for deadlock"); + if (wsrep_debug) { + ib_logf(IB_LOG_LEVEL_WARN, + "WSREP: sec index FK check fail for deadlock: " + " index %s table %s", index->name, index->table->name); + } break; default: - fprintf (stderr, - "WSREP: referenced FK check fail: %d", - (int)err); + ib_logf(IB_LOG_LEVEL_ERROR, + "WSREP: referenced FK check fail: %s index %s table %s", + ut_strerr(err), index->name, index->table->name); break; } } #endif /* WITH_WSREP */ } - break; + + if (referenced) { + + ulint* offsets; + + offsets = rec_get_offsets( + rec, index, NULL, ULINT_UNDEFINED, + &heap); + + /* NOTE that the following call loses + the position of pcur ! */ + err = row_upd_check_references_constraints( + node, &pcur, index->table, + index, offsets, thr, &mtr); + } } btr_pcur_close(&pcur); @@ -2185,9 +2202,6 @@ row_upd_clust_rec_by_insert( rec_t* rec; ulint* offsets = NULL; -#ifdef WITH_WSREP - que_node_t *parent = que_node_get_parent(node); -#endif /* WITH_WSREP */ ut_ad(node); ut_ad(dict_index_is_clust(index)); @@ -2269,35 +2283,31 @@ err_exit: if (err != DB_SUCCESS) { goto err_exit; } - } #ifdef WITH_WSREP - if (!referenced && wsrep_on_trx(trx) && - !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - foreign - ) { + } else if ((foreign && wsrep_must_process_fk(node, trx))) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); + switch (err) { case DB_SUCCESS: case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) fprintf (stderr, - "WSREP: insert FK check fail for deadlock"); + if (wsrep_debug) { + ib_logf(IB_LOG_LEVEL_WARN, + "WSREP: sec index FK check fail for deadlock: " + " index %s table %s", index->name, index->table->name); + } break; default: - fprintf (stderr, - "WSREP: referenced FK check fail: %d", - (int)err); + ib_logf(IB_LOG_LEVEL_ERROR, + "WSREP: referenced FK check fail: %s index %s table %s", + ut_strerr(err), index->name, index->table->name); break; } - if (err != DB_SUCCESS) { - goto err_exit; - } - } #endif /* WITH_WSREP */ + } } mtr_commit(mtr); @@ -2500,7 +2510,7 @@ row_upd_del_mark_clust_rec( dberr_t err; #ifdef WITH_WSREP rec_t* rec; - que_node_t *parent = que_node_get_parent(node); + trx_t* trx = thr_get_trx(thr) ; #endif /* WITH_WSREP */ ut_ad(node); @@ -2529,38 +2539,37 @@ row_upd_del_mark_clust_rec( btr_cur_get_block(btr_cur), btr_cur_get_rec(btr_cur), #endif /* WITH_WSREP */ index, offsets, thr, mtr); - if (err == DB_SUCCESS && referenced) { + if (err != DB_SUCCESS) { + } else if (referenced) { /* NOTE that the following call loses the position of pcur ! */ err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); - } #ifdef WITH_WSREP - trx_t* trx = thr_get_trx(thr) ; - if (err == DB_SUCCESS && !referenced && wsrep_on_trx(trx) && - !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - foreign - ) { + } else if (foreign && wsrep_must_process_fk(node, trx)) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); + switch (err) { case DB_SUCCESS: case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) fprintf (stderr, - "WSREP: clust rec FK check fail for deadlock"); + if (wsrep_debug) { + ib_logf(IB_LOG_LEVEL_WARN, + "WSREP: sec index FK check fail for deadlock: " + " index %s table %s", index->name, index->table->name); + } break; default: - fprintf (stderr, - "WSREP: clust rec referenced FK check fail: %d", - (int)err); + ib_logf(IB_LOG_LEVEL_ERROR, + "WSREP: referenced FK check fail: %s index %s table %s", + ut_strerr(err), index->name, index->table->name); break; } - } #endif /* WITH_WSREP */ + } mtr_commit(mtr); diff --git a/storage/xtradb/row/row0upd.cc b/storage/xtradb/row/row0upd.cc index 9ac72f8d068..93ccc07c9af 100644 --- a/storage/xtradb/row/row0upd.cc +++ b/storage/xtradb/row/row0upd.cc @@ -1806,6 +1806,23 @@ row_upd_store_row( } } +#ifdef WITH_WSREP +/** Determine if a FOREIGN KEY constraint needs to be processed. +@param[in] node query node +@param[in] trx transaction +@return whether the node cannot be ignored */ + +inline bool wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) +{ + if (!wsrep_on_trx(trx)) { + return false; + } + return que_node_get_type(node->common.parent) != QUE_NODE_UPDATE + || static_cast<upd_node_t*>(node->common.parent)->cascade_node + != node; +} +#endif /* WITH_WSREP */ + /***********************************************************//** Updates a secondary index entry of a row. @return DB_SUCCESS if operation successfully completed, else error @@ -1836,7 +1853,7 @@ row_upd_sec_index_entry( referenced = row_upd_index_is_referenced(index, trx); #ifdef WITH_WSREP - ibool foreign = wsrep_row_upd_index_is_foreign(index, trx); + bool foreign = wsrep_row_upd_index_is_foreign(index, trx); #endif /* WITH_WSREP */ heap = mem_heap_create(1024); @@ -1968,61 +1985,61 @@ row_upd_sec_index_entry( row_ins_sec_index_entry() below */ if (!rec_get_deleted_flag( rec, dict_table_is_comp(index->table))) { -#ifdef WITH_WSREP - que_node_t *parent = que_node_get_parent(node); -#endif /* WITH_WSREP */ err = btr_cur_del_mark_set_sec_rec( 0, btr_cur, TRUE, thr, &mtr); - if (err == DB_SUCCESS && referenced) { - - ulint* offsets; - - offsets = rec_get_offsets( - rec, index, NULL, ULINT_UNDEFINED, - &heap); - - /* NOTE that the following call loses - the position of pcur ! */ - err = row_upd_check_references_constraints( - node, &pcur, index->table, - index, offsets, thr, &mtr); + if (err != DB_SUCCESS) { + break; } + #ifdef WITH_WSREP - if (err == DB_SUCCESS && !referenced && - wsrep_on_trx(trx) && - !wsrep_thd_is_BF(trx->mysql_thd, FALSE) && - !(parent && que_node_get_type(parent) == - QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - foreign - ) { - ulint* offsets = - rec_get_offsets( + if (!referenced && foreign + && wsrep_must_process_fk(node, trx) + && !wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + ulint* offsets = rec_get_offsets( rec, index, NULL, ULINT_UNDEFINED, &heap); + err = wsrep_row_upd_check_foreign_constraints( node, &pcur, index->table, index, offsets, thr, &mtr); + switch (err) { case DB_SUCCESS: case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) fprintf (stderr, - "WSREP: sec index FK check fail for deadlock"); + if (wsrep_debug) { + ib_logf(IB_LOG_LEVEL_WARN, + "WSREP: sec index FK check fail for deadlock: " + " index %s table %s", index->name, index->table->name); + } break; default: - fprintf (stderr, - "WSREP: referenced FK check fail: %d", - (int)err); + ib_logf(IB_LOG_LEVEL_ERROR, + "WSREP: referenced FK check fail: %s index %s table %s", + ut_strerr(err), index->name, index->table->name); break; } } #endif /* WITH_WSREP */ } - break; + + if (referenced) { + + ulint* offsets; + + offsets = rec_get_offsets( + rec, index, NULL, ULINT_UNDEFINED, + &heap); + + /* NOTE that the following call loses + the position of pcur ! */ + err = row_upd_check_references_constraints( + node, &pcur, index->table, + index, offsets, thr, &mtr); + } } btr_pcur_close(&pcur); @@ -2191,9 +2208,6 @@ row_upd_clust_rec_by_insert( rec_t* rec; ulint* offsets = NULL; -#ifdef WITH_WSREP - que_node_t *parent = que_node_get_parent(node); -#endif /* WITH_WSREP */ ut_ad(node); ut_ad(dict_index_is_clust(index)); @@ -2278,35 +2292,31 @@ err_exit: if (err != DB_SUCCESS) { goto err_exit; } - } #ifdef WITH_WSREP - if (!referenced && wsrep_on_trx(trx) && - !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - foreign - ) { + } else if ((foreign && wsrep_must_process_fk(node, trx))) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, table, index, offsets, thr, mtr); + switch (err) { case DB_SUCCESS: case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) fprintf (stderr, - "WSREP: insert FK check fail for deadlock"); + if (wsrep_debug) { + ib_logf(IB_LOG_LEVEL_WARN, + "WSREP: sec index FK check fail for deadlock: " + " index %s table %s", index->name, index->table->name); + } break; default: - fprintf (stderr, - "WSREP: referenced FK check fail: %d", - (int)err); + ib_logf(IB_LOG_LEVEL_ERROR, + "WSREP: referenced FK check fail: %s index %s table %s", + ut_strerr(err), index->name, index->table->name); break; } - if (err != DB_SUCCESS) { - goto err_exit; - } - } #endif /* WITH_WSREP */ + } } mtr_commit(mtr); @@ -2512,7 +2522,7 @@ row_upd_del_mark_clust_rec( dberr_t err; #ifdef WITH_WSREP rec_t* rec; - que_node_t *parent = que_node_get_parent(node); + trx_t* trx = thr_get_trx(thr) ; #endif /* WITH_WSREP */ ut_ad(node); @@ -2541,38 +2551,37 @@ row_upd_del_mark_clust_rec( btr_cur_get_block(btr_cur), btr_cur_get_rec(btr_cur), #endif /* WITH_WSREP */ index, offsets, thr, mtr); - if (err == DB_SUCCESS && referenced) { + if (err != DB_SUCCESS) { + } else if (referenced) { /* NOTE that the following call loses the position of pcur ! */ err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); - } #ifdef WITH_WSREP - trx_t* trx = thr_get_trx(thr) ; - if (err == DB_SUCCESS && !referenced && wsrep_on_trx(trx) && - !(parent && que_node_get_type(parent) == QUE_NODE_UPDATE && - ((upd_node_t*)parent)->cascade_node == node) && - foreign - ) { + } else if (foreign && wsrep_must_process_fk(node, trx)) { err = wsrep_row_upd_check_foreign_constraints( node, pcur, index->table, index, offsets, thr, mtr); + switch (err) { case DB_SUCCESS: case DB_NO_REFERENCED_ROW: err = DB_SUCCESS; break; case DB_DEADLOCK: - if (wsrep_debug) fprintf (stderr, - "WSREP: clust rec FK check fail for deadlock"); + if (wsrep_debug) { + ib_logf(IB_LOG_LEVEL_WARN, + "WSREP: sec index FK check fail for deadlock: " + " index %s table %s", index->name, index->table->name); + } break; default: - fprintf (stderr, - "WSREP: clust rec referenced FK check fail: %d", - (int)err); + ib_logf(IB_LOG_LEVEL_ERROR, + "WSREP: referenced FK check fail: %s index %s table %s", + ut_strerr(err), index->name, index->table->name); break; } - } #endif /* WITH_WSREP */ + } mtr_commit(mtr); |