Skip to content

Commit 21b2fad

Browse files
author
Jan Lindström
committed
MDEV-18464: Port kill_one_trx fixes from 10.4 to 10.1
Pushed the decision for innodb transaction and system locking down to lock0lock.cc 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: victim=true Similar way if replication decides to abort one of the threads we mark victim by: victim=true innobase_kill_query Remove lock sys and trx mutex handling. wsrep_innobase_kill_one_trx Mark victim trx with victim=true trx0trx.h Remove trx_abort_t type and abort type variable from trx struct. Add victim variable to trx. wsrep_kill_victim Remove abort_type lock_report_waiters_to_mysql Take also trx mutex and mark trx as a victim for replication abort. lock_trx_handle_wait_low New low level function to 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. lock_trx_handle_wait If transaction is not marked as victim take lock sys and trx mutex before calling lock_trx_handle_wait_low and release them after that. row_search_for_mysql Remove lock sys and trx mutex taking and releasing. trx_rollback_to_savepoint_for_mysql_low trx_commit_in_memory Clean up victim variable.
1 parent deff3f7 commit 21b2fad

File tree

12 files changed

+99
-170
lines changed

12 files changed

+99
-170
lines changed

storage/innobase/handler/ha_innodb.cc

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4929,8 +4929,6 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels)
49294929
/* if victim has been signaled by BF thread and/or aborting
49304930
is already progressing, following query aborting is not necessary
49314931
any more.
4932-
Also, BF thread should own trx mutex for the victim, which would
4933-
conflict with trx_mutex_enter() below
49344932
*/
49354933
DBUG_VOID_RETURN;
49364934
}
@@ -4939,34 +4937,8 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels)
49394937
if (trx_t* trx = thd_to_trx(thd)) {
49404938
ut_ad(trx->mysql_thd == thd);
49414939

4942-
switch (trx->abort_type) {
4943-
#ifdef WITH_WSREP
4944-
case TRX_WSREP_ABORT:
4945-
break;
4946-
#endif
4947-
case TRX_SERVER_ABORT:
4948-
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
4949-
lock_mutex_enter();
4950-
}
4951-
/* fall through */
4952-
case TRX_REPLICATION_ABORT:
4953-
trx_mutex_enter(trx);
4954-
}
49554940
/* Cancel a pending lock request if there are any */
49564941
lock_trx_handle_wait(trx);
4957-
switch (trx->abort_type) {
4958-
#ifdef WITH_WSREP
4959-
case TRX_WSREP_ABORT:
4960-
break;
4961-
#endif
4962-
case TRX_SERVER_ABORT:
4963-
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
4964-
lock_mutex_exit();
4965-
}
4966-
/* fall through */
4967-
case TRX_REPLICATION_ABORT:
4968-
trx_mutex_exit(trx);
4969-
}
49704942
}
49714943

49724944
DBUG_VOID_RETURN;
@@ -18683,6 +18655,12 @@ wsrep_innobase_kill_one_trx(
1868318655
wsrep_thd_ws_handle(thd)->trx_id);
1868418656

1868518657
wsrep_thd_LOCK(thd);
18658+
18659+
/* We mark this as victim transaction, which is already marked
18660+
as BF victim. Both trx mutex and lock_sys mutex is held until
18661+
this victim has aborted. */
18662+
victim_trx->victim = true;
18663+
1868618664
DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock",
1868718665
{
1868818666
const char act[]=
@@ -18866,7 +18844,7 @@ wsrep_abort_transaction(
1886618844
my_bool signal)
1886718845
{
1886818846
DBUG_ENTER("wsrep_innobase_abort_thd");
18869-
18847+
1887018848
trx_t* victim_trx = thd_to_trx(victim_thd);
1887118849
trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL;
1887218850

@@ -18878,12 +18856,10 @@ wsrep_abort_transaction(
1887818856
if (victim_trx) {
1887918857
lock_mutex_enter();
1888018858
trx_mutex_enter(victim_trx);
18881-
victim_trx->abort_type = TRX_WSREP_ABORT;
1888218859
int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
1888318860
victim_trx, signal);
1888418861
trx_mutex_exit(victim_trx);
1888518862
lock_mutex_exit();
18886-
victim_trx->abort_type = TRX_SERVER_ABORT;
1888718863
wsrep_srv_conc_cancel_wait(victim_trx);
1888818864
DBUG_RETURN(rcode);
1888918865
} else {

storage/innobase/include/trx0trx.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2015, 2018, MariaDB Corporation.
4+
Copyright (c) 2015, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -623,7 +623,6 @@ struct trx_lock_t {
623623
lock_sys->mutex. Otherwise, this may
624624
only be modified by the thread that is
625625
serving the running transaction. */
626-
627626
mem_heap_t* lock_heap; /*!< memory heap for trx_locks;
628627
protected by lock_sys->mutex */
629628

@@ -695,14 +694,6 @@ lock_rec_convert_impl_to_expl()) will access transactions associated
695694
to other connections. The locks of transactions are protected by
696695
lock_sys->mutex and sometimes by trx->mutex. */
697696

698-
enum trx_abort_t {
699-
TRX_SERVER_ABORT = 0,
700-
#ifdef WITH_WSREP
701-
TRX_WSREP_ABORT,
702-
#endif
703-
TRX_REPLICATION_ABORT
704-
};
705-
706697
struct trx_t{
707698
ulint magic_n;
708699

@@ -880,8 +871,12 @@ struct trx_t{
880871
/*------------------------------*/
881872
THD* mysql_thd; /*!< MySQL thread handle corresponding
882873
to this trx, or NULL */
883-
trx_abort_t abort_type; /*!< Transaction abort type*/
884-
874+
bool victim; /*!< This transaction is
875+
selected as victim for abort
876+
either by replication or
877+
high priority wsrep thread. This
878+
field is protected by trx and
879+
lock sys mutex. */
885880
const char* mysql_log_file_name;
886881
/*!< if MySQL binlog is used, this field
887882
contains a pointer to the latest file

storage/innobase/lock/lock0lock.cc

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2014, 2018, MariaDB Corporation.
4+
Copyright (c) 2014, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -1793,10 +1793,8 @@ wsrep_kill_victim(
17931793
}
17941794
}
17951795

1796-
lock->trx->abort_type = TRX_WSREP_ABORT;
17971796
wsrep_innobase_kill_one_trx(trx->mysql_thd,
17981797
(const trx_t*) trx, lock->trx, TRUE);
1799-
lock->trx->abort_type = TRX_SERVER_ABORT;
18001798
}
18011799
}
18021800
}
@@ -4782,12 +4780,11 @@ lock_report_waiters_to_mysql(
47824780
if (w_trx->id != victim_trx_id) {
47834781
/* If thd_report_wait_for() decides to kill the
47844782
transaction, then we will get a call back into
4785-
innobase_kill_query. We mark this by setting
4786-
current_lock_mutex_owner, so we can avoid trying
4787-
to recursively take lock_sys->mutex. */
4788-
w_trx->abort_type = TRX_REPLICATION_ABORT;
4783+
innobase_kill_query.*/
4784+
trx_mutex_enter(w_trx);
4785+
w_trx->victim = true;
47894786
thd_report_wait_for(mysql_thd, w_trx->mysql_thd);
4790-
w_trx->abort_type = TRX_SERVER_ABORT;
4787+
trx_mutex_exit(w_trx);
47914788
}
47924789
++i;
47934790
}
@@ -7967,16 +7964,7 @@ lock_trx_release_locks(
79677964
lock_mutex_exit();
79687965
}
79697966

7970-
/*********************************************************************//**
7971-
Check whether the transaction has already been rolled back because it
7972-
was selected as a deadlock victim, or if it has to wait then cancel
7973-
the wait lock.
7974-
@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */
7975-
UNIV_INTERN
7976-
dberr_t
7977-
lock_trx_handle_wait(
7978-
/*=================*/
7979-
trx_t* trx) /*!< in/out: trx lock state */
7967+
inline dberr_t lock_trx_handle_wait_low(trx_t* trx)
79807968
{
79817969
ut_ad(lock_mutex_own());
79827970
ut_ad(trx_mutex_own(trx));
@@ -7993,6 +7981,32 @@ lock_trx_handle_wait(
79937981
return DB_LOCK_WAIT;
79947982
}
79957983

7984+
/*********************************************************************//**
7985+
Check whether the transaction has already been rolled back because it
7986+
was selected as a deadlock victim, or if it has to wait then cancel
7987+
the wait lock.
7988+
@return DB_DEADLOCK, DB_LOCK_WAIT or DB_SUCCESS */
7989+
UNIV_INTERN
7990+
dberr_t
7991+
lock_trx_handle_wait(
7992+
/*=================*/
7993+
trx_t* trx) /*!< in/out: trx lock state */
7994+
{
7995+
if (!trx->victim) {
7996+
lock_mutex_enter();
7997+
trx_mutex_enter(trx);
7998+
}
7999+
8000+
dberr_t err = lock_trx_handle_wait_low(trx);
8001+
8002+
if (!trx->victim) {
8003+
lock_mutex_exit();
8004+
trx_mutex_exit(trx);
8005+
}
8006+
8007+
return err;
8008+
}
8009+
79968010
/*********************************************************************//**
79978011
Get the number of locks on a table.
79988012
@return number of locks */

storage/innobase/row/row0sel.cc

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4746,11 +4746,7 @@ row_search_for_mysql(
47464746
a deadlock and the transaction had to wait then
47474747
release the lock it is waiting on. */
47484748

4749-
lock_mutex_enter();
4750-
trx_mutex_enter(trx);
47514749
err = lock_trx_handle_wait(trx);
4752-
lock_mutex_exit();
4753-
trx_mutex_exit(trx);
47544750

47554751
switch (err) {
47564752
case DB_SUCCESS:

storage/innobase/trx/trx0roll.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2016, 2018, MariaDB Corporation.
4+
Copyright (c) 2016, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -370,6 +370,7 @@ trx_rollback_to_savepoint_for_mysql_low(
370370
trx_mark_sql_stat_end(trx);
371371

372372
trx->op_info = "";
373+
trx->victim = false;
373374

374375
return(err);
375376
}

storage/innobase/trx/trx0trx.cc

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2015, 2018, MariaDB Corporation.
4+
Copyright (c) 2015, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -1339,11 +1339,7 @@ trx_commit_in_memory(
13391339
ut_ad(!trx->in_ro_trx_list);
13401340
ut_ad(!trx->in_rw_trx_list);
13411341

1342-
#ifdef WITH_WSREP
1343-
if (trx->mysql_thd && wsrep_on(trx->mysql_thd)) {
1344-
trx->lock.was_chosen_as_deadlock_victim = FALSE;
1345-
}
1346-
#endif
1342+
trx->victim = false;
13471343
trx->dict_operation = TRX_DICT_OP_NONE;
13481344

13491345
trx->error_state = DB_SUCCESS;

storage/xtradb/handler/ha_innodb.cc

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5534,43 +5534,15 @@ static void innobase_kill_query(handlerton*, THD* thd, enum thd_kill_levels)
55345534
/* if victim has been signaled by BF thread and/or aborting
55355535
is already progressing, following query aborting is not necessary
55365536
any more.
5537-
Also, BF thread should own trx mutex for the victim, which would
5538-
conflict with trx_mutex_enter() below
55395537
*/
55405538
DBUG_VOID_RETURN;
55415539
}
55425540
#endif /* WITH_WSREP */
55435541
if (trx_t* trx = thd_to_trx(thd)) {
55445542
ut_ad(trx->mysql_thd == thd);
55455543

5546-
switch (trx->abort_type) {
5547-
#ifdef WITH_WSREP
5548-
case TRX_WSREP_ABORT:
5549-
break;
5550-
#endif
5551-
case TRX_SERVER_ABORT:
5552-
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
5553-
lock_mutex_enter();
5554-
}
5555-
/* fall through */
5556-
case TRX_REPLICATION_ABORT:
5557-
trx_mutex_enter(trx);
5558-
}
55595544
/* Cancel a pending lock request if there are any */
55605545
lock_trx_handle_wait(trx);
5561-
switch (trx->abort_type) {
5562-
#ifdef WITH_WSREP
5563-
case TRX_WSREP_ABORT:
5564-
break;
5565-
#endif
5566-
case TRX_SERVER_ABORT:
5567-
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
5568-
lock_mutex_exit();
5569-
}
5570-
/* fall through */
5571-
case TRX_REPLICATION_ABORT:
5572-
trx_mutex_exit(trx);
5573-
}
55745546
}
55755547

55765548
DBUG_VOID_RETURN;
@@ -19723,6 +19695,12 @@ wsrep_innobase_kill_one_trx(
1972319695
(thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void");
1972419696

1972519697
wsrep_thd_LOCK(thd);
19698+
19699+
/* We mark this as victim transaction, which is already marked
19700+
as BF victim. Both trx mutex and lock_sys mutex is held until
19701+
this victim has aborted. */
19702+
victim_trx->victim = true;
19703+
1972619704
DBUG_EXECUTE_IF("sync.wsrep_after_BF_victim_lock",
1972719705
{
1972819706
const char act[]=
@@ -19911,12 +19889,10 @@ wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd,
1991119889
if (victim_trx) {
1991219890
lock_mutex_enter();
1991319891
trx_mutex_enter(victim_trx);
19914-
victim_trx->abort_type = TRX_WSREP_ABORT;
1991519892
int rcode = wsrep_innobase_kill_one_trx(bf_thd, bf_trx,
1991619893
victim_trx, signal);
1991719894
trx_mutex_exit(victim_trx);
1991819895
lock_mutex_exit();
19919-
victim_trx->abort_type = TRX_SERVER_ABORT;
1992019896
wsrep_srv_conc_cancel_wait(victim_trx);
1992119897
DBUG_RETURN(rcode);
1992219898
} else {

storage/xtradb/include/trx0trx.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*****************************************************************************
22
33
Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved.
4-
Copyright (c) 2015, 2018, MariaDB Corporation.
4+
Copyright (c) 2015, 2019, MariaDB Corporation.
55
66
This program is free software; you can redistribute it and/or modify it under
77
the terms of the GNU General Public License as published by the Free Software
@@ -672,7 +672,6 @@ struct trx_lock_t {
672672
lock_sys->mutex. Otherwise, this may
673673
only be modified by the thread that is
674674
serving the running transaction. */
675-
676675
mem_heap_t* lock_heap; /*!< memory heap for trx_locks;
677676
protected by lock_sys->mutex */
678677

@@ -744,14 +743,6 @@ lock_rec_convert_impl_to_expl()) will access transactions associated
744743
to other connections. The locks of transactions are protected by
745744
lock_sys->mutex and sometimes by trx->mutex. */
746745

747-
enum trx_abort_t {
748-
TRX_SERVER_ABORT = 0,
749-
#ifdef WITH_WSREP
750-
TRX_WSREP_ABORT,
751-
#endif
752-
TRX_REPLICATION_ABORT
753-
};
754-
755746
struct trx_t{
756747
ulint magic_n;
757748

@@ -930,8 +921,12 @@ struct trx_t{
930921
/*------------------------------*/
931922
THD* mysql_thd; /*!< MySQL thread handle corresponding
932923
to this trx, or NULL */
933-
trx_abort_t abort_type; /*!< Transaction abort type */
934-
924+
bool victim; /*!< This transaction is
925+
selected as victim for abort
926+
either by replication or
927+
high priority wsrep thread. This
928+
field is protected by trx and
929+
lock sys mutex. */
935930
const char* mysql_log_file_name;
936931
/*!< if MySQL binlog is used, this field
937932
contains a pointer to the latest file

0 commit comments

Comments
 (0)