[Commits] 842ef80b029: MDEV-18464: Port kill_one_trx fixes from 10.4 to 10.1
revision-id: 842ef80b029c975b7f7f7ec25fe55817ec626f02 (mariadb-10.1.38-68-g842ef80b029) parent(s): 8be02be08bf6a7227e2ab6a5443b63f3a155e2a9 author: Jan Lindström committer: Jan Lindström timestamp: 2019-03-22 13:52:35 +0200 message: MDEV-18464: Port kill_one_trx fixes from 10.4 to 10.1 Pushed the decision for innodb transaction and system locking down to lock_trx_handle_wait() level. With this, we can avoid releasing these mutexes for executions where these mutexes were acquired upfront. This patch will also fix BF aborting of native threads, e.g. threads which have declared wsrep_on=OFF. Earlier, we have used, for innodb trx locks, was_chosen_as_deadlock_victim flag, for marking inodb transactions, which are victims for wsrep BF abort. With native threads (wsrep_on==OFF), re-using was_chosen_as_deadlock_victim flag may lead to inteference with real deadlock, and to deal with this, the patch has added new flag for marking wsrep BF aborts only: was_chosen_as_wsrep_victim Similar way if replication decides to abort one of the threads we mark victim by: was_chosen_as_replication_victim innobase_kill_query() Removed lock mutex and trx mutex code. wsrep_innobase_kill_one_trx() Here new was_chosen_as_wsrep_victim flag is set wsrep_kill_victim Remove unnecessary abort type lock_report_waiters_to_mysql Mark trx as a victim of replication abort lock_trx_handle_wait_low() New low lever function to handle lock waits. lock_trx_handle_wait() Taking lock mutex and trx mutex is pushed down to this function. row_search_for_mysql Remove lock mutex and trx mutex enter/exit trx_commit_in_memory trx_rollback_to_savepoint_for_mysql_low Initialize was_chosen_as_wsrep_victim --- storage/innobase/handler/ha_innodb.cc | 40 +++++++--------------------- storage/innobase/include/trx0trx.h | 21 +++++++-------- storage/innobase/lock/lock0lock.cc | 49 ++++++++++++++++++++++++----------- storage/innobase/row/row0sel.cc | 4 --- storage/innobase/trx/trx0roll.cc | 3 +++ storage/innobase/trx/trx0trx.cc | 6 ++--- storage/xtradb/handler/ha_innodb.cc | 38 ++++++--------------------- storage/xtradb/include/trx0trx.h | 21 +++++++-------- storage/xtradb/lock/lock0lock.cc | 49 ++++++++++++++++++++++++----------- storage/xtradb/row/row0sel.cc | 4 --- storage/xtradb/trx/trx0roll.cc | 6 +---- storage/xtradb/trx/trx0trx.cc | 6 ++--- 12 files changed, 113 insertions(+), 134 deletions(-) diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index c670839b5cd..6ccb1d6a05e 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4929,8 +4929,6 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) /* if victim has been signaled by BF thread and/or aborting is already progressing, following query aborting is not necessary any more. - Also, BF thread should own trx mutex for the victim, which would - conflict with trx_mutex_enter() below */ DBUG_VOID_RETURN; } @@ -4939,34 +4937,8 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) if (trx_t* trx = thd_to_trx(thd)) { ut_ad(trx->mysql_thd == thd); - switch (trx->abort_type) { -#ifdef WITH_WSREP - case TRX_WSREP_ABORT: - break; -#endif - case TRX_SERVER_ABORT: - if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { - lock_mutex_enter(); - } - /* fall through */ - case TRX_REPLICATION_ABORT: - trx_mutex_enter(trx); - } /* Cancel a pending lock request if there are any */ lock_trx_handle_wait(trx); - switch (trx->abort_type) { -#ifdef WITH_WSREP - case TRX_WSREP_ABORT: - break; -#endif - case TRX_SERVER_ABORT: - if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { - lock_mutex_exit(); - } - /* fall through */ - case TRX_REPLICATION_ABORT: - trx_mutex_exit(trx); - } } DBUG_VOID_RETURN; @@ -18683,6 +18655,14 @@ wsrep_innobase_kill_one_trx( wsrep_thd_ws_handle(thd)->trx_id); wsrep_thd_LOCK(thd); + + /* + * we mark with was_chosen_as_deadlock_victim transaction, + * which is already marked as BF victim + * lock_sys is held until this victim has aborted + */ + victim_trx->lock.was_chosen_as_wsrep_victim = true; + DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", { const char act[]= @@ -18866,7 +18846,7 @@ wsrep_abort_transaction( my_bool signal) { DBUG_ENTER("wsrep_innobase_abort_thd"); - + trx_t* victim_trx = thd_to_trx(victim_thd); trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; @@ -18878,12 +18858,10 @@ wsrep_abort_transaction( if (victim_trx) { lock_mutex_enter(); trx_mutex_enter(victim_trx); - victim_trx->abort_type = TRX_WSREP_ABORT; int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx, victim_trx, signal); trx_mutex_exit(victim_trx); lock_mutex_exit(); - victim_trx->abort_type = TRX_SERVER_ABORT; wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index fe16b8272b8..b83734b154a 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -613,6 +613,9 @@ struct trx_lock_t { transaction as a victim in deadlock resolution, it sets this to TRUE. Protected by trx->mutex. */ + bool was_chosen_as_replication_victim; + /* replication has marked this + trx to abort */ time_t wait_started; /*!< lock wait started at this time, protected only by lock_sys->mutex */ @@ -624,6 +627,12 @@ struct trx_lock_t { only be modified by the thread that is serving the running transaction. */ +#ifdef WITH_WSREP + bool was_chosen_as_wsrep_victim; + /*!< high priority wsrep thread has + marked this trx to abort */ +#endif /* WITH_WSREP */ + mem_heap_t* lock_heap; /*!< memory heap for trx_locks; protected by lock_sys->mutex */ @@ -695,14 +704,6 @@ lock_rec_convert_impl_to_expl()) will access transactions associated to other connections. The locks of transactions are protected by lock_sys->mutex and sometimes by trx->mutex. */ -enum trx_abort_t { - TRX_SERVER_ABORT = 0, -#ifdef WITH_WSREP - TRX_WSREP_ABORT, -#endif - TRX_REPLICATION_ABORT -}; - struct trx_t{ ulint magic_n; @@ -880,8 +881,6 @@ struct trx_t{ /*------------------------------*/ THD* mysql_thd; /*!< MySQL thread handle corresponding to this trx, or NULL */ - trx_abort_t abort_type; /*!< Transaction abort type*/ - const char* mysql_log_file_name; /*!< if MySQL binlog is used, this field contains a pointer to the latest file diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 3970a559a4c..984ac6cacbc 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2018, MariaDB Corporation. +Copyright (c) 2014, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1793,10 +1793,8 @@ wsrep_kill_victim( } } - lock->trx->abort_type = TRX_WSREP_ABORT; wsrep_innobase_kill_one_trx(trx->mysql_thd, (const trx_t*) trx, lock->trx, TRUE); - lock->trx->abort_type = TRX_SERVER_ABORT; } } } @@ -4785,9 +4783,8 @@ lock_report_waiters_to_mysql( innobase_kill_query. We mark this by setting current_lock_mutex_owner, so we can avoid trying to recursively take lock_sys->mutex. */ - w_trx->abort_type = TRX_REPLICATION_ABORT; + w_trx->lock.was_chosen_as_replication_victim = true; thd_report_wait_for(mysql_thd, w_trx->mysql_thd); - w_trx->abort_type = TRX_SERVER_ABORT; } ++i; } @@ -7967,16 +7964,7 @@ lock_trx_release_locks( lock_mutex_exit(); } -/*********************************************************************//** -Check whether the transaction has already been rolled back because it -was selected as a deadlock victim, or if it has to wait then cancel -the wait lock. -@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */ -UNIV_INTERN -dberr_t -lock_trx_handle_wait( -/*=================*/ - trx_t* trx) /*!< in/out: trx lock state */ +static inline dberr_t lock_trx_handle_wait_low(trx_t* trx) { ut_ad(lock_mutex_own()); ut_ad(trx_mutex_own(trx)); @@ -7993,6 +7981,37 @@ lock_trx_handle_wait( return DB_LOCK_WAIT; } +/*********************************************************************//** +Check whether the transaction has already been rolled back because it +was selected as a deadlock victim, or if it has to wait then cancel +the wait lock. +@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */ +UNIV_INTERN +dberr_t +lock_trx_handle_wait( +/*=================*/ + trx_t* trx) /*!< in/out: trx lock state */ +{ + bool lock_mutex_taken = false; +#ifdef WITH_WSREP + /* We already own mutexes */ + if (trx->lock.was_chosen_as_wsrep_victim) { + return lock_trx_handle_wait_low(trx); + } +#endif /* WITH_WSREP */ + if (!trx->lock.was_chosen_as_replication_victim) { + lock_mutex_enter(); + lock_mutex_taken = true; + } + trx_mutex_enter(trx); + dberr_t err = lock_trx_handle_wait_low(trx); + if (lock_mutex_taken) { + lock_mutex_exit(); + } + trx_mutex_exit(trx); + return err; +} + /*********************************************************************//** Get the number of locks on a table. @return number of locks */ diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 06bf4cc30c0..855266686e6 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -4746,11 +4746,7 @@ row_search_for_mysql( a deadlock and the transaction had to wait then release the lock it is waiting on. */ - lock_mutex_enter(); - trx_mutex_enter(trx); err = lock_trx_handle_wait(trx); - lock_mutex_exit(); - trx_mutex_exit(trx); switch (err) { case DB_SUCCESS: diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 3fd71aff23a..925fcf4f790 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -370,6 +370,9 @@ trx_rollback_to_savepoint_for_mysql_low( trx_mark_sql_stat_end(trx); trx->op_info = ""; +#ifdef WITH_WSREP + trx->lock.was_chosen_as_wsrep_victim = false; +#endif return(err); } diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index f36aabba8b4..396703250db 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1340,9 +1340,7 @@ trx_commit_in_memory( ut_ad(!trx->in_rw_trx_list); #ifdef WITH_WSREP - if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = false; #endif trx->dict_operation = TRX_DICT_OP_NONE; diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index d943a87ab78..6fd2ff62663 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5534,8 +5534,6 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) /* if victim has been signaled by BF thread and/or aborting is already progressing, following query aborting is not necessary any more. - Also, BF thread should own trx mutex for the victim, which would - conflict with trx_mutex_enter() below */ DBUG_VOID_RETURN; } @@ -5543,34 +5541,8 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels) if (trx_t* trx = thd_to_trx(thd)) { ut_ad(trx->mysql_thd == thd); - switch (trx->abort_type) { -#ifdef WITH_WSREP - case TRX_WSREP_ABORT: - break; -#endif - case TRX_SERVER_ABORT: - if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { - lock_mutex_enter(); - } - /* fall through */ - case TRX_REPLICATION_ABORT: - trx_mutex_enter(trx); - } /* Cancel a pending lock request if there are any */ lock_trx_handle_wait(trx); - switch (trx->abort_type) { -#ifdef WITH_WSREP - case TRX_WSREP_ABORT: - break; -#endif - case TRX_SERVER_ABORT: - if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { - lock_mutex_exit(); - } - /* fall through */ - case TRX_REPLICATION_ABORT: - trx_mutex_exit(trx); - } } DBUG_VOID_RETURN; @@ -19723,6 +19695,14 @@ wsrep_innobase_kill_one_trx( (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); wsrep_thd_LOCK(thd); + + /* + * we mark with was_chosen_as_deadlock_victim transaction, + * which is already marked as BF victim + * lock_sys is held until this victim has aborted + */ + victim_trx->lock.was_chosen_as_wsrep_victim = true; + DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock", { const char act[]= @@ -19911,12 +19891,10 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, if (victim_trx) { lock_mutex_enter(); trx_mutex_enter(victim_trx); - victim_trx->abort_type = TRX_WSREP_ABORT; int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx, victim_trx, signal); trx_mutex_exit(victim_trx); lock_mutex_exit(); - victim_trx->abort_type = TRX_SERVER_ABORT; wsrep_srv_conc_cancel_wait(victim_trx); DBUG_RETURN(rcode); } else { diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h index 77afde4c35c..9f6a3e756fd 100644 --- a/storage/xtradb/include/trx0trx.h +++ b/storage/xtradb/include/trx0trx.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -662,6 +662,9 @@ struct trx_lock_t { transaction as a victim in deadlock resolution, it sets this to TRUE. Protected by trx->mutex. */ + bool was_chosen_as_replication_victim; + /* replication has marked this + trx to abort */ time_t wait_started; /*!< lock wait started at this time, protected only by lock_sys->mutex */ @@ -673,6 +676,12 @@ struct trx_lock_t { only be modified by the thread that is serving the running transaction. */ +#ifdef WITH_WSREP + bool was_chosen_as_wsrep_victim; + /*!< high priority wsrep thread has + marked this trx to abort */ +#endif /* WITH_WSREP */ + mem_heap_t* lock_heap; /*!< memory heap for trx_locks; protected by lock_sys->mutex */ @@ -744,14 +753,6 @@ lock_rec_convert_impl_to_expl()) will access transactions associated to other connections. The locks of transactions are protected by lock_sys->mutex and sometimes by trx->mutex. */ -enum trx_abort_t { - TRX_SERVER_ABORT = 0, -#ifdef WITH_WSREP - TRX_WSREP_ABORT, -#endif - TRX_REPLICATION_ABORT -}; - struct trx_t{ ulint magic_n; @@ -930,8 +931,6 @@ struct trx_t{ /*------------------------------*/ THD* mysql_thd; /*!< MySQL thread handle corresponding to this trx, or NULL */ - trx_abort_t abort_type; /*!< Transaction abort type */ - const char* mysql_log_file_name; /*!< if MySQL binlog is used, this field contains a pointer to the latest file diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index 2183d281b78..8f92b9c9295 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2018, MariaDB Corporation. +Copyright (c) 2014, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1804,10 +1804,8 @@ wsrep_kill_victim( } } - lock->trx->abort_type = TRX_WSREP_ABORT; wsrep_innobase_kill_one_trx(trx->mysql_thd, (const trx_t*) trx, lock->trx, TRUE); - lock->trx->abort_type = TRX_SERVER_ABORT; } } } @@ -4824,9 +4822,8 @@ lock_report_waiters_to_mysql( innobase_kill_query. We mark this by setting current_lock_mutex_owner, so we can avoid trying to recursively take lock_sys->mutex. */ - w_trx->abort_type = TRX_REPLICATION_ABORT; + w_trx->lock.was_chosen_as_replication_victim = true; thd_report_wait_for(mysql_thd, w_trx->mysql_thd); - w_trx->abort_type = TRX_SERVER_ABORT; } ++i; } @@ -8077,16 +8074,7 @@ lock_trx_release_locks( lock_mutex_exit(); } -/*********************************************************************//** -Check whether the transaction has already been rolled back because it -was selected as a deadlock victim, or if it has to wait then cancel -the wait lock. -@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */ -UNIV_INTERN -dberr_t -lock_trx_handle_wait( -/*=================*/ - trx_t* trx) /*!< in/out: trx lock state */ +static inline dberr_t lock_trx_handle_wait_low(trx_t* trx) { ut_ad(lock_mutex_own()); ut_ad(trx_mutex_own(trx)); @@ -8103,6 +8091,37 @@ lock_trx_handle_wait( return DB_LOCK_WAIT; } +/*********************************************************************//** +Check whether the transaction has already been rolled back because it +was selected as a deadlock victim, or if it has to wait then cancel +the wait lock. +@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */ +UNIV_INTERN +dberr_t +lock_trx_handle_wait( +/*=================*/ + trx_t* trx) /*!< in/out: trx lock state */ +{ + bool lock_mutex_taken = false; +#ifdef WITH_WSREP + /* We already own mutexes */ + if (trx->lock.was_chosen_as_wsrep_victim) { + return lock_trx_handle_wait_low(trx); + } +#endif /* WITH_WSREP */ + if (!trx->lock.was_chosen_as_replication_victim) { + lock_mutex_enter(); + lock_mutex_taken = true; + } + trx_mutex_enter(trx); + dberr_t err = lock_trx_handle_wait_low(trx); + if (lock_mutex_taken) { + lock_mutex_exit(); + } + trx_mutex_exit(trx); + return err; +} + /*********************************************************************//** Get the number of locks on a table. @return number of locks */ diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index b6b5d107885..87bc2aa2875 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -4755,11 +4755,7 @@ row_search_for_mysql( a deadlock and the transaction had to wait then release the lock it is waiting on. */ - lock_mutex_enter(); - trx_mutex_enter(trx); err = lock_trx_handle_wait(trx); - lock_mutex_exit(); - trx_mutex_exit(trx); switch (err) { case DB_SUCCESS: diff --git a/storage/xtradb/trx/trx0roll.cc b/storage/xtradb/trx/trx0roll.cc index 56b7120fa34..85ab3de6308 100644 --- a/storage/xtradb/trx/trx0roll.cc +++ b/storage/xtradb/trx/trx0roll.cc @@ -375,12 +375,8 @@ trx_rollback_to_savepoint_for_mysql_low( trx_mark_sql_stat_end(trx); trx->op_info = ""; - #ifdef WITH_WSREP - if (wsrep_on(trx->mysql_thd) && - trx->lock.was_chosen_as_deadlock_victim) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = false; #endif return(err); diff --git a/storage/xtradb/trx/trx0trx.cc b/storage/xtradb/trx/trx0trx.cc index 17cba81daf3..ad5467e126c 100644 --- a/storage/xtradb/trx/trx0trx.cc +++ b/storage/xtradb/trx/trx0trx.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -1564,9 +1564,7 @@ trx_commit_in_memory( ut_ad(!trx->in_rw_trx_list); #ifdef WITH_WSREP - if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } + trx->lock.was_chosen_as_wsrep_victim = false; #endif trx->dict_operation = TRX_DICT_OP_NONE;
Hi Jan, On Fri, Mar 22, 2019 at 1:59 PM jan <jan.lindstrom@mariadb.com> wrote:
revision-id: 842ef80b029c975b7f7f7ec25fe55817ec626f02 (mariadb-10.1.38-68-g842ef80b029)
Was this pushed to buildbot as well? I did not find the commit ID. First, some general comments: * The functions trx_start_if_not_started_low() and trx_start_for_ddl_low() differ between XtraDB and InnoDB with regard to #ifdef WITH_WSREP. Why? Are the debug assignments truly necessary? I see that the difference was introduced 5 years ago in MDEV-6247. * The files storage/{innobase,xtradb}/trx/trx0roll.cc differ from each other after the change. It looks like the innobase version is better. Please remove the unnecessary lines from xtradb: --- storage/xtradb/trx/trx0roll.cc 2019-03-26 10:20:31.767971537 +0200 +++ storage/innobase/trx/trx0roll.cc 2019-03-26 10:20:31.759971465 +0200 @@ -33,8 +33,6 @@ #include "trx0roll.ic" #endif -#include <mysql/service_wsrep.h> - #include "fsp0fsp.h" #include "mach0data.h" #include "trx0rseg.h" @@ -51,9 +49,6 @@ #include "pars0pars.h" #include "srv0mon.h" #include "trx0sys.h" -#ifdef WITH_WSREP -#include "ha_prototypes.h" -#endif /* WITH_WSREP */ /** This many pages must be undone before a truncate is tried within rollback */ @@ -1075,12 +1070,6 @@ if (trx->update_undo) { trx_undo_truncate_end(trx, trx->update_undo, limit); } - -#ifdef WITH_WSREP_OUT - if (wsrep_on(trx->mysql_thd)) { - trx->lock.was_chosen_as_deadlock_victim = FALSE; - } -#endif /* WITH_WSREP */ } /***********************************************************************//** On to the detailed review:
diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index fe16b8272b8..b83734b154a 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -1,7 +1,7 @@ /*****************************************************************************
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2018, MariaDB Corporation. +Copyright (c) 2015, 2019, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software @@ -613,6 +613,9 @@ struct trx_lock_t { transaction as a victim in deadlock resolution, it sets this to TRUE. Protected by trx->mutex. */ + bool was_chosen_as_replication_victim; + /* replication has marked this + trx to abort */ time_t wait_started; /*!< lock wait started at this time, protected only by lock_sys->mutex */
@@ -624,6 +627,12 @@ struct trx_lock_t { only be modified by the thread that is serving the running transaction. */
+#ifdef WITH_WSREP + bool was_chosen_as_wsrep_victim; + /*!< high priority wsrep thread has + marked this trx to abort */ +#endif /* WITH_WSREP */ + mem_heap_t* lock_heap; /*!< memory heap for trx_locks; protected by lock_sys->mutex */
@@ -695,14 +704,6 @@ lock_rec_convert_impl_to_expl()) will access transactions associated to other connections. The locks of transactions are protected by lock_sys->mutex and sometimes by trx->mutex. */
-enum trx_abort_t { - TRX_SERVER_ABORT = 0, -#ifdef WITH_WSREP - TRX_WSREP_ABORT, -#endif - TRX_REPLICATION_ABORT -}; - struct trx_t{ ulint magic_n;
@@ -880,8 +881,6 @@ struct trx_t{ /*------------------------------*/ THD* mysql_thd; /*!< MySQL thread handle corresponding to this trx, or NULL */ - trx_abort_t abort_type; /*!< Transaction abort type*/ - const char* mysql_log_file_name; /*!< if MySQL binlog is used, this field contains a pointer to the latest file
Why are you replacing trx_t::abort_type with two fields in trx_lock_t that are located far apart from each other? To avoid changing the performance too much due to caching, I would suggest to introduce the two fields in trx_t, replacing the former location of abort_type. Do we really need such long names? Would trx_t::replication_victim and trx_t::wsrep_victim suffice? Please document how concurrent access to the fields is being protected. Apparently for the WSREP field it is both trx->mutex and lock_sys->mutex.
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index 3970a559a4c..984ac6cacbc 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -4785,9 +4783,8 @@ lock_report_waiters_to_mysql( innobase_kill_query. We mark this by setting current_lock_mutex_owner, so we can avoid trying to recursively take lock_sys->mutex. */ - w_trx->abort_type = TRX_REPLICATION_ABORT; + w_trx->lock.was_chosen_as_replication_victim = true; thd_report_wait_for(mysql_thd, w_trx->mysql_thd); - w_trx->abort_type = TRX_SERVER_ABORT; } ++i; }
Here, we seem to be only holding lock_sys->mutex, not w_trx->mutex.
@@ -7993,6 +7981,37 @@ lock_trx_handle_wait( return DB_LOCK_WAIT; }
+/*********************************************************************//** +Check whether the transaction has already been rolled back because it +was selected as a deadlock victim, or if it has to wait then cancel +the wait lock. +@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */ +UNIV_INTERN +dberr_t +lock_trx_handle_wait( +/*=================*/ + trx_t* trx) /*!< in/out: trx lock state */ +{ + bool lock_mutex_taken = false;
Do we really need this variable?
+#ifdef WITH_WSREP + /* We already own mutexes */ + if (trx->lock.was_chosen_as_wsrep_victim) { + return lock_trx_handle_wait_low(trx); + } +#endif /* WITH_WSREP */ + if (!trx->lock.was_chosen_as_replication_victim) { + lock_mutex_enter(); + lock_mutex_taken = true; + } + trx_mutex_enter(trx); + dberr_t err = lock_trx_handle_wait_low(trx); + if (lock_mutex_taken) { + lock_mutex_exit(); + } + trx_mutex_exit(trx); + return err; +}
I would expand the second part of the code and remove the condition before releasing the 2 mutexes: if (!trx->lock.was_chosen_as_replication_victim) { lock_mutex_enter(); trx_mutex_enter(trx); dberr_t err = lock_trx_handle_wait_low(trx); lock_mutex_exit(); trx_mutex_exit(trx); return err; } else { trx_mutex_enter(trx); dberr_t err = lock_trx_handle_wait_low(trx); trx_mutex_exit(trx); return err; } Also, I think that it would be better to declare lock_trx_handle_wait_low() only static but not inline, to reduce unnecessary code expansion. Best regards, Marko
participants (2)
-
jan
-
Marko Mäkelä