Commit da3a3a68 authored by Jan Lindström's avatar Jan Lindström

MDEV-12837: WSREP: BF lock wait long

Problem was a merge error from MySQL wsrep i.e. Galera.

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 fall back to First-Come-First-Served (FCFS)
	with notice to user.

Changed innodb-lock-schedule-algorithm as read-only parameter
as it was designed to be.

lock_reset_lock_and_trx_wait
	Use ib::hex() to print out transaction ID.

lock_rec_other_has_expl_req,
lock_rec_other_has_conflicting,
RecLock::add_to_waitq
lock_rec_lock_slow
lock_table_other_has_incompatible
lock_rec_insert_check_and_lock
lock_prdt_other_has_conflicting

	Change pointer to conflicting lock to normal pointer as this
	pointer contents could be changed later.

RecLock::create
	Conclicting lock pointer is moved to last parameter with
	default value NULL. This conflicting transaction could
	be selected as victim in Galera if requesting transaction
	is BF (brute force) transaction. In this case contents
	of conflicting lock pointer will be changed. Use ib::hex() to print
	transaction ids.
parent 3eaca005
......@@ -5005,7 +5005,8 @@ static Sys_var_mybool Sys_wsrep_on (
"wsrep_on", "To enable wsrep replication ",
SESSION_VAR(wsrep_on),
CMD_LINE(OPT_ARG), DEFAULT(FALSE),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(wsrep_on_check),
ON_UPDATE(wsrep_on_update));
static Sys_var_charptr Sys_wsrep_start_position (
......
......@@ -42,12 +42,28 @@ int wsrep_init_vars()
return 0;
}
extern ulong innodb_lock_schedule_algorithm;
bool wsrep_on_update (sys_var *self, THD* thd, enum_var_type var_type)
{
if (var_type == OPT_GLOBAL) {
// FIXME: this variable probably should be changed only per session
thd->variables.wsrep_on = global_system_variables.wsrep_on;
}
return false;
}
bool wsrep_on_check(sys_var *self, THD* thd, set_var* var)
{
bool new_wsrep_on= (bool)var->save_result.ulonglong_value;
if (new_wsrep_on && innodb_lock_schedule_algorithm != 0) {
my_message(ER_WRONG_ARGUMENTS, " WSREP (galera) can't be enabled "
"if innodb_lock_schedule_algorithm=VATS. Please configure"
" innodb_lock_schedule_algorithm=FCFS and restart.", MYF(0));
return true;
}
return false;
}
......
......@@ -41,7 +41,8 @@ int wsrep_init_vars();
#define DEFAULT_ARGS (THD* thd, enum_var_type var_type)
#define INIT_ARGS (const char* opt)
extern bool wsrep_causal_reads_update UPDATE_ARGS;
extern bool wsrep_causal_reads_update UPDATE_ARGS;
extern bool wsrep_on_check CHECK_ARGS;
extern bool wsrep_on_update UPDATE_ARGS;
extern bool wsrep_sync_wait_update UPDATE_ARGS;
extern bool wsrep_start_position_check CHECK_ARGS;
......
......@@ -3862,6 +3862,16 @@ innobase_init(
goto error;
}
#ifdef WITH_WSREP
/* Currently, Galera does not support VATS lock schedule algorithm. */
if (innodb_lock_schedule_algorithm == INNODB_LOCK_SCHEDULE_ALGORITHM_VATS
&& global_system_variables.wsrep_on) {
ib::info() << "In Galera environment Variance-Aware-Transaction-Sheduling Algorithm"
" is not supported. Falling back to First-Come-First-Served order. ";
innodb_lock_schedule_algorithm = INNODB_LOCK_SCHEDULE_ALGORITHM_FCFS;
}
#endif /* WITH_WSREP */
#ifndef HAVE_LZ4
if (innodb_compression_algorithm == PAGE_LZ4_ALGORITHM) {
sql_print_error("InnoDB: innodb_compression_algorithm = %lu unsupported.\n"
......@@ -5351,7 +5361,7 @@ innobase_kill_query(
wsrep_thd_is_BF(current_thd, FALSE));
}
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
if (!wsrep_thd_is_BF(trx->mysql_thd, FALSE) && trx->abort_type != TRX_WSREP_ABORT) {
lock_mutex_enter();
lock_mutex_taken = true;
}
......@@ -20863,7 +20873,7 @@ static MYSQL_SYSVAR_ULONG(doublewrite_batch_size, srv_doublewrite_batch_size,
#endif /* defined UNIV_DEBUG || defined UNIV_PERF_DEBUG */
static MYSQL_SYSVAR_ENUM(lock_schedule_algorithm, innodb_lock_schedule_algorithm,
PLUGIN_VAR_RQCMDARG,
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
"The algorithm Innodb uses for deciding which locks to grant next when"
" a lock is released. Possible values are"
" FCFS"
......
......@@ -721,7 +721,7 @@ class RecLock {
as a victim, and we got the lock immediately: no need to
wait then */
dberr_t add_to_waitq(
const lock_t* wait_for,
lock_t* wait_for,
const lock_prdt_t*
prdt = NULL);
......@@ -731,21 +731,22 @@ class RecLock {
@param[in] owns_trx_mutex true if caller owns the trx_t::mutex
@param[in] add_to_hash add the lock to hash table
@param[in] prdt Predicate lock (optional)
@param[in,out] c_lock Conflicting lock request or NULL
in Galera conflicting lock is selected
as deadlock victim if requester
is BF transaction.
@return new lock instance */
lock_t* create(
trx_t* trx,
bool owns_trx_mutex,
bool add_to_hash,
const lock_prdt_t*
prdt = NULL);
prdt = NULL
#ifdef WITH_WSREP
,lock_t* c_lock = NULL
#endif /* WITH_WSREP */
);
lock_t* create(
lock_t* const c_lock,
trx_t* trx,
bool owns_trx_mutex,
bool add_to_hash,
const lock_prdt_t*
prdt = NULL);
/**
Check of the lock is on m_rec_id.
@param[in] lock Lock to compare with
......
This diff is collapsed.
......@@ -290,7 +290,7 @@ Checks if some other transaction has a conflicting predicate
lock request in the queue, so that we have to wait.
@return lock or NULL */
static
const lock_t*
lock_t*
lock_prdt_other_has_conflicting(
/*============================*/
ulint mode, /*!< in: LOCK_S or LOCK_X,
......@@ -305,10 +305,10 @@ lock_prdt_other_has_conflicting(
{
ut_ad(lock_mutex_own());
for (const lock_t* lock = lock_rec_get_first(
for (lock_t* lock = lock_rec_get_first(
lock_hash_get(mode), block, PRDT_HEAPNO);
lock != NULL;
lock = lock_rec_get_next_const(PRDT_HEAPNO, lock)) {
lock = lock_rec_get_next(PRDT_HEAPNO, lock)) {
if (lock->trx == trx) {
continue;
......@@ -565,7 +565,7 @@ lock_prdt_insert_check_and_lock(
const ulint mode = LOCK_X | LOCK_PREDICATE | LOCK_INSERT_INTENTION;
const lock_t* wait_for = lock_prdt_other_has_conflicting(
lock_t* wait_for = lock_prdt_other_has_conflicting(
mode, block, prdt, trx);
if (wait_for != NULL) {
......@@ -854,7 +854,7 @@ lock_prdt_lock(
if (lock == NULL) {
const lock_t* wait_for;
lock_t* wait_for;
wait_for = lock_prdt_other_has_conflicting(
prdt_mode, block, prdt, trx);
......
......@@ -183,20 +183,38 @@ lock_wait_table_reserve_slot(
/*********************************************************************//**
check if lock timeout was for priority thread,
as a side effect trigger lock monitor
@param[in] trx transaction owning the lock
@param[in] locked true if trx and lock_sys_mutex is ownd
@return false for regular lock timeout */
static ibool
static
bool
wsrep_is_BF_lock_timeout(
/*====================*/
trx_t* trx) /* in: trx to check for lock priority */
const trx_t* trx,
bool locked = true)
{
if (wsrep_on_trx(trx) && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) {
fprintf(stderr, "WSREP: BF lock wait long\n");
if (wsrep_on_trx(trx)
&& wsrep_thd_is_BF(trx->mysql_thd, FALSE)
&& trx->error_state != DB_DEADLOCK) {
ib::info() << "WSREP: BF lock wait long for trx:" << ib::hex(trx->id)
<< " query: " << wsrep_thd_query(trx->mysql_thd);
if (!locked) {
lock_mutex_enter();
}
ut_ad(lock_mutex_own());
wsrep_trx_print_locking(stderr, trx, 3000);
if (!locked) {
lock_mutex_exit();
}
srv_print_innodb_monitor = TRUE;
srv_print_innodb_lock_monitor = TRUE;
os_event_set(srv_monitor_event);
return TRUE;
return true;
}
return FALSE;
return false;
}
#endif /* WITH_WSREP */
......@@ -399,7 +417,7 @@ lock_wait_suspend_thread(
&& wait_time > (double) lock_wait_timeout
#ifdef WITH_WSREP
&& (!wsrep_on_trx(trx) ||
(!wsrep_is_BF_lock_timeout(trx) && trx->error_state != DB_DEADLOCK))
(!wsrep_is_BF_lock_timeout(trx, false) && trx->error_state != DB_DEADLOCK))
#endif /* WITH_WSREP */
&& !trx_is_high_priority(trx)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment