@@ -644,71 +644,81 @@ lock_rec_get_insert_intention(
644
644
return (lock->type_mode & LOCK_INSERT_INTENTION);
645
645
}
646
646
647
+ #ifdef UNIV_DEBUG
647
648
#ifdef WITH_WSREP
648
- /* * Check if both conflicting lock and other record lock are brute force
649
- (BF). This case is a bug so report lock information and wsrep state.
650
- @param[in] lock_rec1 conflicting waiting record lock or NULL
651
- @param[in] lock_rec2 other waiting record lock
652
- @param[in] trx1 lock_rec1 can be NULL, trx
649
+ /* * Check if both conflicting lock transaction and other transaction
650
+ requesting record lock are brute force (BF). If they are check is
651
+ this BF-BF wait correct and if not report BF wait and assert.
652
+
653
+ @param[in] lock_rec other waiting record lock
654
+ @param[in] trx trx requesting conflicting record lock
653
655
*/
654
- static void wsrep_assert_no_bf_bf_wait (
655
- const lock_t * lock_rec1,
656
- const lock_t * lock_rec2,
657
- const trx_t * trx1)
656
+ static void wsrep_assert_no_bf_bf_wait (const lock_t *lock, const trx_t *trx)
658
657
{
659
- ut_ad (!lock_rec1 || lock_get_type_low (lock_rec1) == LOCK_REC);
660
- ut_ad (lock_get_type_low (lock_rec2) == LOCK_REC);
658
+ ut_ad (lock_get_type_low (lock) == LOCK_REC);
661
659
ut_ad (lock_mutex_own ());
660
+ trx_t * lock_trx= lock->trx ;
662
661
663
662
/* Note that we are holding lock_sys->mutex, thus we should
664
663
not acquire THD::LOCK_thd_data mutex below to avoid mutexing
665
664
order violation. */
666
665
667
- if (!trx1 ->is_wsrep () || !lock_rec2-> trx ->is_wsrep ())
666
+ if (!trx ->is_wsrep () || !lock_trx ->is_wsrep ())
668
667
return ;
669
- if (UNIV_LIKELY (!wsrep_thd_is_BF (trx1->mysql_thd , FALSE )))
670
- return ;
671
- if (UNIV_LIKELY (!wsrep_thd_is_BF (lock_rec2->trx ->mysql_thd , FALSE )))
668
+ if (UNIV_LIKELY (!wsrep_thd_is_BF (trx->mysql_thd , FALSE ))
669
+ || UNIV_LIKELY (!wsrep_thd_is_BF (lock_trx->mysql_thd , FALSE )))
672
670
return ;
673
671
674
- /* if BF - BF order is honored, we can keep trx1 waiting for the lock */
675
- if (wsrep_trx_order_before (trx1->mysql_thd , lock_rec2->trx ->mysql_thd ))
672
+ ut_ad (trx->state == TRX_STATE_ACTIVE);
673
+
674
+ trx_mutex_enter (lock_trx);
675
+ const trx_state_t trx2_state= lock_trx->state ;
676
+ trx_mutex_exit (lock_trx);
677
+
678
+ /* If transaction is already committed in memory or
679
+ prepared we should wait. When transaction is committed in
680
+ memory we held trx mutex, but not lock_sys->mutex. Therefore,
681
+ we could end here before transaction has time to do
682
+ lock_release() that is protected with lock_sys->mutex. */
683
+ switch (trx2_state) {
684
+ case TRX_STATE_COMMITTED_IN_MEMORY:
685
+ case TRX_STATE_PREPARED:
676
686
return ;
687
+ case TRX_STATE_ACTIVE:
688
+ break ;
689
+ default :
690
+ ut_ad (" invalid state" == 0 );
691
+ }
677
692
678
- /* avoiding BF-BF conflict assert, if victim is already aborting
679
- or rolling back for replaying
680
- */
681
- if (wsrep_trx_is_aborting (lock_rec2->trx ->mysql_thd ))
693
+ /* If BF - BF order is honored, i.e. trx already holding
694
+ record lock should be ordered before this new lock request
695
+ we can keep trx waiting for the lock. If conflicting
696
+ transaction is already aborting or rolling back for replaying
697
+ we can also let new transaction waiting. */
698
+ if (wsrep_trx_order_before (lock_trx->mysql_thd , trx->mysql_thd )
699
+ || wsrep_trx_is_aborting (lock_trx->mysql_thd ))
682
700
return ;
683
701
684
702
mtr_t mtr;
685
703
686
- if (lock_rec1) {
687
- ib::error () << " Waiting lock on table: "
688
- << lock_rec1->index ->table ->name
689
- << " index: "
690
- << lock_rec1->index ->name ()
691
- << " that has conflicting lock " ;
692
- lock_rec_print (stderr, lock_rec1, mtr);
693
- }
694
-
695
704
ib::error () << " Conflicting lock on table: "
696
- << lock_rec2 ->index ->table ->name
705
+ << lock ->index ->table ->name
697
706
<< " index: "
698
- << lock_rec2 ->index ->name ()
707
+ << lock ->index ->name ()
699
708
<< " that has lock " ;
700
- lock_rec_print (stderr, lock_rec2 , mtr);
709
+ lock_rec_print (stderr, lock , mtr);
701
710
702
711
ib::error () << " WSREP state: " ;
703
712
704
- wsrep_report_bf_lock_wait (trx1 ->mysql_thd ,
705
- trx1 ->id );
706
- wsrep_report_bf_lock_wait (lock_rec2-> trx ->mysql_thd ,
707
- lock_rec2-> trx ->id );
713
+ wsrep_report_bf_lock_wait (trx ->mysql_thd ,
714
+ trx ->id );
715
+ wsrep_report_bf_lock_wait (lock_trx ->mysql_thd ,
716
+ lock_trx ->id );
708
717
/* BF-BF wait is a bug */
709
718
ut_error;
710
719
}
711
720
#endif /* WITH_WSREP */
721
+ #endif /* UNIV_DEBUG */
712
722
713
723
/* ********************************************************************/ /* *
714
724
Checks if a lock request for a new lock has to wait for request lock2.
@@ -832,9 +842,11 @@ lock_rec_has_to_wait(
832
842
return (FALSE );
833
843
}
834
844
835
- /* There should not be two conflicting locks that are
836
- brute force. If there is it is a bug. */
837
- wsrep_assert_no_bf_bf_wait (NULL , lock2, trx);
845
+ /* We very well can let bf to wait normally as other
846
+ BF will be replayed in case of conflict. For debug
847
+ builds we will do additional sanity checks to catch
848
+ unsupported bf wait if any. */
849
+ ut_d (wsrep_assert_no_bf_bf_wait (lock2, trx));
838
850
#endif /* WITH_WSREP */
839
851
840
852
return (TRUE );
@@ -1111,66 +1123,35 @@ lock_rec_other_has_expl_req(
1111
1123
#endif /* UNIV_DEBUG */
1112
1124
1113
1125
#ifdef WITH_WSREP
1114
- static
1115
- void
1116
- wsrep_kill_victim (
1117
- /* ==============*/
1118
- const trx_t * const trx,
1119
- const lock_t *lock)
1126
+ static void wsrep_kill_victim (const trx_t * const trx, const lock_t *lock)
1120
1127
{
1121
1128
ut_ad (lock_mutex_own ());
1122
- ut_ad (trx_mutex_own (lock->trx ));
1129
+ ut_ad (trx->is_wsrep ());
1130
+ trx_t * lock_trx = lock->trx ;
1131
+ ut_ad (trx_mutex_own (lock_trx));
1132
+ ut_ad (lock_trx != trx);
1123
1133
1124
- /* quit for native mysql */
1125
- if (!trx-> is_wsrep ()) return ;
1134
+ if (! wsrep_thd_is_BF (trx-> mysql_thd , FALSE ))
1135
+ return ;
1126
1136
1127
- my_bool bf_this = wsrep_thd_is_BF (trx-> mysql_thd , FALSE );
1128
- my_bool bf_other = wsrep_thd_is_BF (lock-> trx -> mysql_thd , FALSE );
1129
- mtr_t mtr ;
1137
+ if (lock_trx-> state == TRX_STATE_COMMITTED_IN_MEMORY
1138
+ || lock_trx-> lock . was_chosen_as_deadlock_victim )
1139
+ return ;
1130
1140
1131
- if ((bf_this && !bf_other) ||
1132
- (bf_this && bf_other && wsrep_trx_order_before (
1133
- trx->mysql_thd , lock->trx ->mysql_thd ))) {
1141
+ my_bool bf_other = wsrep_thd_is_BF (lock_trx->mysql_thd , FALSE );
1134
1142
1135
- if (lock->trx ->lock .que_state == TRX_QUE_LOCK_WAIT) {
1136
- if (UNIV_UNLIKELY (wsrep_debug)) {
1137
- ib::info () << " WSREP: BF victim waiting\n " ;
1138
- }
1143
+ if (!bf_other
1144
+ || wsrep_trx_order_before (trx->mysql_thd ,
1145
+ lock_trx->mysql_thd )) {
1146
+
1147
+ if (lock_trx->lock .que_state == TRX_QUE_LOCK_WAIT) {
1148
+ if (UNIV_UNLIKELY (wsrep_debug))
1149
+ WSREP_INFO (" BF victim waiting" );
1139
1150
/* cannot release lock, until our lock
1140
1151
is in the queue*/
1141
- } else if (lock->trx != trx) {
1142
- if (wsrep_log_conflicts) {
1143
- if (bf_this) {
1144
- ib::info () << " *** Priority TRANSACTION:" ;
1145
- } else {
1146
- ib::info () << " *** Victim TRANSACTION:" ;
1147
- }
1148
-
1149
- wsrep_trx_print_locking (stderr, trx, 3000 );
1150
-
1151
- if (bf_other) {
1152
- ib::info () << " *** Priority TRANSACTION:" ;
1153
- } else {
1154
- ib::info () << " *** Victim TRANSACTION:" ;
1155
- }
1156
- wsrep_trx_print_locking (stderr, lock->trx , 3000 );
1157
-
1158
- ib::info () << " *** WAITING FOR THIS LOCK TO BE GRANTED:" ;
1159
-
1160
- if (lock_get_type (lock) == LOCK_REC) {
1161
- lock_rec_print (stderr, lock, mtr);
1162
- } else {
1163
- lock_table_print (stderr, lock);
1164
- }
1165
-
1166
- ib::info () << " SQL1: "
1167
- << wsrep_thd_query (trx->mysql_thd );
1168
- ib::info () << " SQL2: "
1169
- << wsrep_thd_query (lock->trx ->mysql_thd );
1170
- }
1171
-
1172
- wsrep_innobase_kill_one_trx (trx->mysql_thd ,
1173
- trx, lock->trx , TRUE );
1152
+ } else {
1153
+ wsrep_innobase_kill_one_trx (trx->mysql_thd , trx,
1154
+ lock_trx, true );
1174
1155
}
1175
1156
}
1176
1157
}
@@ -2410,10 +2391,6 @@ static void lock_rec_dequeue_from_page(lock_t* in_lock)
2410
2391
/* Grant the lock */
2411
2392
ut_ad (lock->trx != in_lock->trx );
2412
2393
lock_grant (lock);
2413
- #ifdef WITH_WSREP
2414
- } else {
2415
- wsrep_assert_no_bf_bf_wait (c, lock, c->trx );
2416
- #endif /* WITH_WSREP */
2417
2394
}
2418
2395
}
2419
2396
} else {
@@ -4342,10 +4319,6 @@ lock_rec_unlock(
4342
4319
/* Grant the lock */
4343
4320
ut_ad (trx != lock->trx );
4344
4321
lock_grant (lock);
4345
- #ifdef WITH_WSREP
4346
- } else {
4347
- wsrep_assert_no_bf_bf_wait (c, lock, c->trx );
4348
- #endif /* WITH_WSREP */
4349
4322
}
4350
4323
}
4351
4324
} else {
0 commit comments