Skip to content

Commit e66bb57

Browse files
committed
MDEV-12837: WSREP: BF lock wait long
This is 10.1 version where no merge error exists. wsrep_on_check New check function. Galera can't be enabled if innodb-lock-schedule-algorithm=VATS. innobase_kill_query In Galera async kill we could own lock mutex. innobase_init If Variance-Aware-Transaction-Sheduling Algorithm (VATS) is used on Galera we refuse to start InnoDB. Changed innodb-lock-schedule-algorithm as read-only parameter as it was designed to be. lock_rec_other_has_expl_req, lock_rec_other_has_conflicting, lock_rec_lock_slow lock_table_other_has_incompatible lock_rec_insert_check_and_lock Change pointer to conflicting lock to normal pointer as this pointer contents could be changed later.
1 parent 1374f95 commit e66bb57

File tree

11 files changed

+215
-107
lines changed

11 files changed

+215
-107
lines changed

mysql-test/suite/sys_vars/r/sysvars_innodb.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1347,7 +1347,7 @@ NUMERIC_MIN_VALUE NULL
13471347
NUMERIC_MAX_VALUE NULL
13481348
NUMERIC_BLOCK_SIZE NULL
13491349
ENUM_VALUE_LIST fcfs,vats
1350-
READ_ONLYNO
1350+
READ_ONLYYES
13511351
COMMAND_LINE_ARGUMENT REQUIRED
13521352
VARIABLE_NAME INNODB_LOCK_WAIT_TIMEOUT
13531353
SESSION_VALUE 50
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
--innodb-lock-schedule-algorithm=FCFS

sql/sys_vars.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4895,7 +4895,8 @@ static Sys_var_mybool Sys_wsrep_on (
48954895
"wsrep_on", "To enable wsrep replication ",
48964896
SESSION_VAR(wsrep_on),
48974897
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
4898-
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
4898+
NO_MUTEX_GUARD, NOT_IN_BINLOG,
4899+
ON_CHECK(wsrep_on_check),
48994900
ON_UPDATE(wsrep_on_update));
49004901

49014902
static Sys_var_charptr Sys_wsrep_start_position (

sql/wsrep_var.cc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,28 @@ int wsrep_init_vars()
5252
return 0;
5353
}
5454

55+
extern ulong innodb_lock_schedule_algorithm;
56+
5557
bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
5658
{
5759
if (var_type == OPT_GLOBAL) {
5860
// FIXME: this variable probably should be changed only per session
5961
thd->variables.wsrep_on = global_system_variables.wsrep_on;
6062
}
63+
64+
return false;
65+
}
66+
67+
bool wsrep_on_check(sys_var *self, THD* thd, set_var* var)
68+
{
69+
bool new_wsrep_on= (bool)var->save_result.ulonglong_value;
70+
71+
if (new_wsrep_on && innodb_lock_schedule_algorithm != 0) {
72+
my_message(ER_WRONG_ARGUMENTS, " WSREP (galera) can't be enabled "
73+
"if innodb_lock_schedule_algorithm=VATS. Please configure"
74+
" innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0));
75+
return true;
76+
}
6177
return false;
6278
}
6379

sql/wsrep_var.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ int wsrep_init_vars();
4141
#define DEFAULT_ARGS (THD* thd, enum_var_type var_type)
4242
#define INIT_ARGS (const char* opt)
4343

44-
extern bool wsrep_causal_reads_update UPDATE_ARGS;
44+
extern bool wsrep_causal_reads_update UPDATE_ARGS;
45+
extern bool wsrep_on_check CHECK_ARGS;
4546
extern bool wsrep_on_update UPDATE_ARGS;
4647
extern bool wsrep_sync_wait_update UPDATE_ARGS;
4748
extern bool wsrep_start_position_check CHECK_ARGS;

storage/innobase/handler/ha_innodb.cc

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3478,6 +3478,17 @@ innobase_init(
34783478
goto error;
34793479
}
34803480

3481+
#ifdef WITH_WSREP
3482+
/* Currently, Galera does not support VATS lock schedule algorithm. */
3483+
if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
3484+
&& global_system_variables.wsrep_on) {
3485+
/* Do not allow InnoDB startup with VATS and Galera */
3486+
sql_print_error("In Galera environment Variance-Aware-Transaction-Sheduling Algorithm"
3487+
" is not supported.");
3488+
goto error;
3489+
}
3490+
#endif /* WITH_WSREP */
3491+
34813492
#ifndef HAVE_LZ4
34823493
if (innodb_compression_algorithm == PAGE_LZ4_ALGORITHM) {
34833494
sql_print_error("InnoDB: innodb_compression_algorithm = %lu unsupported.\n"
@@ -4882,8 +4893,8 @@ innobase_kill_query(
48824893
wsrep_thd_is_BF(current_thd, FALSE),
48834894
lock_get_info(trx->lock.wait_lock).c_str());
48844895

4885-
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) &&
4886-
trx->abort_type == TRX_SERVER_ABORT) {
4896+
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)
4897+
&& trx->abort_type == TRX_SERVER_ABORT) {
48874898
ut_ad(!lock_mutex_own());
48884899
lock_mutex_enter();
48894900
}
@@ -19234,7 +19245,7 @@ static MYSQL_SYSVAR_ULONG(doublewrite_batch_size, srv_doublewrite_batch_size,
1923419245
#endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
1923519246

1923619247
static MYSQL_SYSVAR_ENUM(lock_schedule_algorithm, innodb_lock_schedule_algorithm,
19237-
PLUGIN_VAR_RQCMDARG,
19248+
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1923819249
"The algorithm Innodb uses for deciding which locks to grant next when"
1923919250
" a lock is released. Possible values are"
1924019251
" FCFS"

storage/innobase/lock/lock0lock.cc

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -925,15 +925,21 @@ lock_reset_lock_and_trx_wait(
925925

926926
ib_logf(IB_LOG_LEVEL_INFO,
927927
"Trx id " TRX_ID_FMT
928-
" is waiting a lock in statement %s"
928+
" is waiting a lock "
929929
" for this trx id " TRX_ID_FMT
930-
" and statement %s wait_lock %p",
930+
" wait_lock %p",
931931
lock->trx->id,
932-
stmt ? stmt : "NULL",
933932
trx_id,
934-
stmt2 ? stmt2 : "NULL",
935933
lock->trx->lock.wait_lock);
936934

935+
if (stmt) {
936+
ib_logf(IB_LOG_LEVEL_INFO, " SQL1: %s\n", stmt);
937+
}
938+
939+
if (stmt2) {
940+
ib_logf(IB_LOG_LEVEL_INFO, " SQL2: %s\n", stmt2);
941+
}
942+
937943
ut_ad(lock->trx->lock.wait_lock == lock);
938944
}
939945

@@ -1151,7 +1157,7 @@ lock_rec_has_to_wait(
11511157
type_mode, lock_is_on_supremum);
11521158
fprintf(stderr,
11531159
"conflicts states: my %d locked %d\n",
1154-
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
1160+
wsrep_thd_conflict_state(trx->mysql_thd, FALSE),
11551161
wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) );
11561162
lock_rec_print(stderr, lock2);
11571163
if (for_locking) return FALSE;
@@ -1687,7 +1693,7 @@ lock_rec_discard(lock_t* in_lock);
16871693
Checks if some other transaction has a lock request in the queue.
16881694
@return lock or NULL */
16891695
static
1690-
const lock_t*
1696+
lock_t*
16911697
lock_rec_other_has_expl_req(
16921698
/*========================*/
16931699
enum lock_mode mode,/*!< in: LOCK_S or LOCK_X */
@@ -1704,7 +1710,7 @@ lock_rec_other_has_expl_req(
17041710
requests by all transactions
17051711
are taken into account */
17061712
{
1707-
const lock_t* lock;
1713+
lock_t* lock;
17081714

17091715
ut_ad(lock_mutex_own());
17101716
ut_ad(mode == LOCK_X || mode == LOCK_S);
@@ -1713,7 +1719,7 @@ lock_rec_other_has_expl_req(
17131719

17141720
for (lock = lock_rec_get_first(block, heap_no);
17151721
lock != NULL;
1716-
lock = lock_rec_get_next_const(heap_no, lock)) {
1722+
lock = lock_rec_get_next(heap_no, lock)) {
17171723

17181724
if (lock->trx != trx
17191725
&& (gap
@@ -1800,7 +1806,7 @@ Checks if some other transaction has a conflicting explicit lock request
18001806
in the queue, so that we have to wait.
18011807
@return lock or NULL */
18021808
static
1803-
const lock_t*
1809+
lock_t*
18041810
lock_rec_other_has_conflicting(
18051811
/*===========================*/
18061812
enum lock_mode mode,/*!< in: LOCK_S or LOCK_X,
@@ -1812,7 +1818,7 @@ lock_rec_other_has_conflicting(
18121818
ulint heap_no,/*!< in: heap number of the record */
18131819
const trx_t* trx)/*!< in: our transaction */
18141820
{
1815-
const lock_t* lock;
1821+
lock_t* lock;
18161822
ibool is_supremum;
18171823

18181824
ut_ad(lock_mutex_own());
@@ -1821,13 +1827,16 @@ lock_rec_other_has_conflicting(
18211827

18221828
for (lock = lock_rec_get_first(block, heap_no);
18231829
lock != NULL;
1824-
lock = lock_rec_get_next_const(heap_no, lock)) {
1830+
lock = lock_rec_get_next(heap_no, lock)) {
18251831

18261832
#ifdef WITH_WSREP
18271833
if (lock_rec_has_to_wait(TRUE, trx, mode, lock, is_supremum)) {
18281834
if (wsrep_on_trx(trx)) {
18291835
trx_mutex_enter(lock->trx);
1830-
wsrep_kill_victim(trx, lock);
1836+
/* Below function will roll back either trx
1837+
or lock->trx depending on priority of the
1838+
transaction. */
1839+
wsrep_kill_victim(const_cast<trx_t*>(trx), lock);
18311840
trx_mutex_exit(lock->trx);
18321841
}
18331842
#else
@@ -2023,15 +2032,17 @@ wsrep_print_wait_locks(
20232032
{
20242033
if (wsrep_debug && c_lock->trx->lock.wait_lock != c_lock) {
20252034
fprintf(stderr, "WSREP: c_lock != wait lock\n");
2026-
if (lock_get_type_low(c_lock) & LOCK_TABLE)
2035+
if (lock_get_type_low(c_lock) & LOCK_TABLE) {
20272036
lock_table_print(stderr, c_lock);
2028-
else
2037+
} else {
20292038
lock_rec_print(stderr, c_lock);
2039+
}
20302040

2031-
if (lock_get_type_low(c_lock->trx->lock.wait_lock) & LOCK_TABLE)
2041+
if (lock_get_type_low(c_lock->trx->lock.wait_lock) & LOCK_TABLE) {
20322042
lock_table_print(stderr, c_lock->trx->lock.wait_lock);
2033-
else
2043+
} else {
20342044
lock_rec_print(stderr, c_lock->trx->lock.wait_lock);
2045+
}
20352046
}
20362047
}
20372048
#endif /* WITH_WSREP */
@@ -2217,8 +2228,8 @@ lock_rec_create(
22172228
if (wsrep_debug) {
22182229
fprintf(
22192230
stderr,
2220-
"WSREP: c_lock canceled %llu\n",
2221-
(ulonglong) c_lock->trx->id);
2231+
"WSREP: c_lock canceled " TRX_ID_FMT "\n",
2232+
c_lock->trx->id);
22222233
}
22232234

22242235
/* have to bail out here to avoid lock_set_lock... */
@@ -2519,6 +2530,16 @@ lock_rec_enqueue_waiting(
25192530
err = DB_LOCK_WAIT;
25202531
}
25212532

2533+
#ifdef WITH_WSREP
2534+
if (!lock_get_wait(lock) && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
2535+
if (wsrep_debug) {
2536+
fprintf(stderr, "WSREP: BF thread got lock granted early, ID " TRX_ID_FMT
2537+
"\n",
2538+
lock->trx->id);
2539+
}
2540+
return(DB_SUCCESS);
2541+
}
2542+
#endif /* WITH_WSREP */
25222543
// Move it only when it does not cause a deadlock.
25232544
if (err != DB_DEADLOCK
25242545
&& innodb_lock_schedule_algorithm
@@ -2814,7 +2835,7 @@ lock_rec_lock_slow(
28142835
/* The trx already has a strong enough lock on rec: do
28152836
nothing */
28162837
#ifdef WITH_WSREP
2817-
} else if ((c_lock = (ib_lock_t*)lock_rec_other_has_conflicting(
2838+
} else if ((c_lock = lock_rec_other_has_conflicting(
28182839
static_cast<enum lock_mode>(mode),
28192840
block, heap_no, trx))) {
28202841
#else
@@ -2946,6 +2967,15 @@ lock_rec_has_to_wait_in_queue(
29462967
#ifdef WITH_WSREP
29472968
if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) &&
29482969
wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) {
2970+
if (wsrep_debug) {
2971+
fprintf(stderr,
2972+
"BF-BF lock conflict " TRX_ID_FMT
2973+
" : " TRX_ID_FMT "\n",
2974+
wait_lock->trx->id,
2975+
lock->trx->id);
2976+
lock_rec_print(stderr, wait_lock);
2977+
lock_rec_print(stderr, lock);
2978+
}
29492979
/* don't wait for another BF lock */
29502980
continue;
29512981
}
@@ -3104,7 +3134,7 @@ lock_grant_and_move_on_page(
31043134
&& !lock_rec_has_to_wait_in_queue(lock)) {
31053135

31063136
lock_grant(lock, false);
3107-
3137+
31083138
if (previous != NULL) {
31093139
/* Move the lock to the head of the list. */
31103140
HASH_GET_NEXT(hash, previous) = HASH_GET_NEXT(hash, lock);
@@ -4978,8 +5008,8 @@ lock_table_create(
49785008
}
49795009

49805010
if (wsrep_debug) {
4981-
fprintf(stderr, "WSREP: c_lock canceled %llu\n",
4982-
(ulonglong) c_lock->trx->id);
5011+
fprintf(stderr, "WSREP: c_lock canceled " TRX_ID_FMT "\n",
5012+
c_lock->trx->id);
49835013
}
49845014
}
49855015
if (c_lock) {
@@ -5251,7 +5281,7 @@ Checks if other transactions have an incompatible mode lock request in
52515281
the lock queue.
52525282
@return lock or NULL */
52535283
UNIV_INLINE
5254-
const lock_t*
5284+
lock_t*
52555285
lock_table_other_has_incompatible(
52565286
/*==============================*/
52575287
const trx_t* trx,/*!< in: transaction, or NULL if all
@@ -5262,7 +5292,7 @@ lock_table_other_has_incompatible(
52625292
const dict_table_t* table,/*!< in: table */
52635293
enum lock_mode mode)/*!< in: lock mode */
52645294
{
5265-
const lock_t* lock;
5295+
lock_t* lock;
52665296

52675297
ut_ad(lock_mutex_own());
52685298

@@ -5315,7 +5345,7 @@ lock_table(
53155345
#endif
53165346
trx_t* trx;
53175347
dberr_terr;
5318-
const lock_t* wait_for;
5348+
lock_t*wait_for;
53195349

53205350
ut_ad(table != NULL);
53215351
ut_ad(thr != NULL);
@@ -5362,13 +5392,13 @@ lock_table(
53625392

53635393
if (wait_for != NULL) {
53645394
#ifdef WITH_WSREP
5365-
err = lock_table_enqueue_waiting((ib_lock_t*)wait_for, mode | flags, table, thr);
5395+
err = lock_table_enqueue_waiting(wait_for, mode | flags, table, thr);
53665396
#else
53675397
err = lock_table_enqueue_waiting(mode | flags, table, thr);
53685398
#endif
53695399
} else {
53705400
#ifdef WITH_WSREP
5371-
lock_table_create(c_lock, table, mode | flags, trx);
5401+
lock_table_create(c_lock, table, mode | flags, trx);
53725402
#else
53735403
lock_table_create(table, mode | flags, trx);
53745404
#endif
@@ -7036,10 +7066,10 @@ lock_rec_insert_check_and_lock(
70367066
on the successor, which produced an unnecessary deadlock. */
70377067

70387068
#ifdef WITH_WSREP
7039-
if ((c_lock = (ib_lock_t*)lock_rec_other_has_conflicting(
7040-
static_cast<enum lock_mode>(
7041-
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
7042-
block, next_rec_heap_no, trx))) {
7069+
if ((c_lock = lock_rec_other_has_conflicting(
7070+
static_cast<enum lock_mode>(
7071+
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
7072+
block, next_rec_heap_no, trx))) {
70437073
#else
70447074
if (lock_rec_other_has_conflicting(
70457075
static_cast<enum lock_mode>(
@@ -7052,7 +7082,7 @@ lock_rec_insert_check_and_lock(
70527082

70537083
#ifdef WITH_WSREP
70547084
err = lock_rec_enqueue_waiting(c_lock,
7055-
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
7085+
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
70567086
block, next_rec_heap_no, index, thr);
70577087
#else
70587088
err = lock_rec_enqueue_waiting(

0 commit comments

Comments
 (0)