Commit 399ec848 authored by Eugene Kosov's avatar Eugene Kosov

prettify lock_rec_has_to_wait()

parent e4fa5492
...@@ -738,7 +738,7 @@ lock_rec_get_insert_intention( ...@@ -738,7 +738,7 @@ lock_rec_get_insert_intention(
Checks if a lock request for a new lock has to wait for request lock2. Checks if a lock request for a new lock has to wait for request lock2.
@return TRUE if new lock has to wait for lock2 to be removed */ @return TRUE if new lock has to wait for lock2 to be removed */
UNIV_INLINE UNIV_INLINE
ibool bool
lock_rec_has_to_wait( lock_rec_has_to_wait(
/*=================*/ /*=================*/
bool for_locking, bool for_locking,
...@@ -761,154 +761,156 @@ lock_rec_has_to_wait( ...@@ -761,154 +761,156 @@ lock_rec_has_to_wait(
ut_ad(trx && lock2); ut_ad(trx && lock2);
ut_ad(lock_get_type_low(lock2) == LOCK_REC); ut_ad(lock_get_type_low(lock2) == LOCK_REC);
if (trx != lock2->trx if (trx == lock2->trx
&& !lock_mode_compatible(static_cast<lock_mode>( || lock_mode_compatible(
LOCK_MODE_MASK & type_mode), static_cast<lock_mode>(LOCK_MODE_MASK & type_mode),
lock_get_mode(lock2))) { lock_get_mode(lock2))) {
return(false);
}
/* We have somewhat complex rules when gap type record locks /* We have somewhat complex rules when gap type record locks
cause waits */ cause waits */
if ((lock_is_on_supremum || (type_mode & LOCK_GAP)) if ((lock_is_on_supremum || (type_mode & LOCK_GAP))
&& !(type_mode & LOCK_INSERT_INTENTION)) { && !(type_mode & LOCK_INSERT_INTENTION)) {
/* Gap type locks without LOCK_INSERT_INTENTION flag /* Gap type locks without LOCK_INSERT_INTENTION flag
do not need to wait for anything. This is because do not need to wait for anything. This is because
different users can have conflicting lock types different users can have conflicting lock types
on gaps. */ on gaps. */
return(FALSE); return(false);
} }
if (!(type_mode & LOCK_INSERT_INTENTION) if (!(type_mode & LOCK_INSERT_INTENTION) && lock_rec_get_gap(lock2)) {
&& lock_rec_get_gap(lock2)) {
/* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP /* Record lock (LOCK_ORDINARY or LOCK_REC_NOT_GAP
does not need to wait for a gap type lock */ does not need to wait for a gap type lock */
return(FALSE); return(false);
} }
if ((type_mode & LOCK_GAP) if ((type_mode & LOCK_GAP) && lock_rec_get_rec_not_gap(lock2)) {
&& lock_rec_get_rec_not_gap(lock2)) {
/* Lock on gap does not need to wait for /* Lock on gap does not need to wait for
a LOCK_REC_NOT_GAP type lock */ a LOCK_REC_NOT_GAP type lock */
return(FALSE); return(false);
} }
if (lock_rec_get_insert_intention(lock2)) { if (lock_rec_get_insert_intention(lock2)) {
/* No lock request needs to wait for an insert /* No lock request needs to wait for an insert
intention lock to be removed. This is ok since our intention lock to be removed. This is ok since our
rules allow conflicting locks on gaps. This eliminates rules allow conflicting locks on gaps. This eliminates
a spurious deadlock caused by a next-key lock waiting a spurious deadlock caused by a next-key lock waiting
for an insert intention lock; when the insert for an insert intention lock; when the insert
intention lock was granted, the insert deadlocked on intention lock was granted, the insert deadlocked on
the waiting next-key lock. the waiting next-key lock.
Also, insert intention locks do not disturb each Also, insert intention locks do not disturb each
other. */ other. */
return(FALSE); return(false);
} }
if ((type_mode & LOCK_GAP || lock_rec_get_gap(lock2)) && if ((type_mode & LOCK_GAP || lock_rec_get_gap(lock2))
!thd_need_ordering_with(trx->mysql_thd, && !thd_need_ordering_with(trx->mysql_thd, lock2->trx->mysql_thd)) {
lock2->trx->mysql_thd)) { /* If the upper server layer has already decided on the
/* If the upper server layer has already decided on the commit order between the transaction requesting the
commit order between the transaction requesting the lock and the transaction owning the lock, we do not
lock and the transaction owning the lock, we do not need to wait for gap locks. Such ordeering by the upper
need to wait for gap locks. Such ordeering by the upper server layer happens in parallel replication, where the
server layer happens in parallel replication, where the commit order is fixed to match the original order on the
commit order is fixed to match the original order on the master.
master.
Such gap locks are mainly needed to get serialisability
Such gap locks are mainly needed to get serialisability between transactions so that they will be binlogged in
between transactions so that they will be binlogged in the correct order so that statement-based replication
the correct order so that statement-based replication will give the correct results. Since the right order
will give the correct results. Since the right order was already determined on the master, we do not need
was already determined on the master, we do not need to enforce it again here.
to enforce it again here.
Skipping the locks is not essential for correctness,
Skipping the locks is not essential for correctness, since in case of deadlock we will just kill the later
since in case of deadlock we will just kill the later transaction and retry it. But it can save some
transaction and retry it. But it can save some unnecessary rollbacks and retries. */
unnecessary rollbacks and retries. */
return(false);
return (FALSE); }
}
#ifdef WITH_WSREP #ifdef WITH_WSREP
/* if BF thread is locking and has conflict with another BF /* if BF thread is locking and has conflict with another BF
thread, we need to look at trx ordering and lock types */ thread, we need to look at trx ordering and lock types */
if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) && if (wsrep_thd_is_BF(trx->mysql_thd, FALSE)
wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { && wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) {
if (wsrep_debug) { if (wsrep_debug) {
ib::info() << ib::info() << "BF-BF lock conflict, locking: "
"BF-BF lock conflict, locking: " << for_locking; << for_locking;
lock_rec_print(stderr, lock2);
ib::info()
<< " SQL1: " << wsrep_thd_query(trx->mysql_thd)
<< " SQL2: "
<< wsrep_thd_query(lock2->trx->mysql_thd);
}
if (wsrep_trx_order_before(trx->mysql_thd,
lock2->trx->mysql_thd)
&& (type_mode & LOCK_MODE_MASK) == LOCK_X
&& (lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) {
if (for_locking || wsrep_debug) {
/* exclusive lock conflicts are not
accepted */
ib::info()
<< "BF-BF X lock conflict,mode: "
<< type_mode
<< " supremum: " << lock_is_on_supremum
<< "conflicts states: my "
<< wsrep_thd_conflict_state(
trx->mysql_thd, FALSE)
<< " locked "
<< wsrep_thd_conflict_state(
lock2->trx->mysql_thd,
FALSE);
lock_rec_print(stderr, lock2); lock_rec_print(stderr, lock2);
ib::info() << " SQL1: " ib::info() << " SQL1: "
<< wsrep_thd_query(trx->mysql_thd); << wsrep_thd_query(trx->mysql_thd)
ib::info() << " SQL2: " << " SQL2: "
<< wsrep_thd_query(lock2->trx->mysql_thd); << wsrep_thd_query(
} lock2->trx->mysql_thd);
if (wsrep_trx_order_before(trx->mysql_thd, if (for_locking) {
lock2->trx->mysql_thd) && return FALSE;
(type_mode & LOCK_MODE_MASK) == LOCK_X &&
(lock2->type_mode & LOCK_MODE_MASK) == LOCK_X) {
if (for_locking || wsrep_debug) {
/* exclusive lock conflicts are not
accepted */
ib::info() <<
"BF-BF X lock conflict,"
"mode: " << type_mode <<
" supremum: " << lock_is_on_supremum;
ib::info() <<
"conflicts states: my "
<< wsrep_thd_conflict_state(trx->mysql_thd, FALSE)
<< " locked "
<< wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE);
lock_rec_print(stderr, lock2);
ib::info() << " SQL1: "
<< wsrep_thd_query(trx->mysql_thd);
ib::info() << " SQL2: "
<< wsrep_thd_query(lock2->trx->mysql_thd);
if (for_locking) {
return FALSE;
}
}
} else {
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
if (wsrep_debug) {
ib::info() <<
"BF conflict, modes: "
<< type_mode << ":" << lock2->type_mode
<< " idx: " << lock2->index->name()
<< " table: " << lock2->index->table->name.m_name
<< " n_uniq: " << lock2->index->n_uniq
<< " n_user: " << lock2->index->n_user_defined_cols;
ib::info() << " SQL1: "
<< wsrep_thd_query(trx->mysql_thd);
ib::info() << " SQL2: "
<< wsrep_thd_query(lock2->trx->mysql_thd);
} }
return FALSE;
} }
} else {
/* if lock2->index->n_uniq <=
lock2->index->n_user_defined_cols
operation is on uniq index
*/
if (wsrep_debug) {
ib::info()
<< "BF conflict, modes: " << type_mode
<< ":" << lock2->type_mode
<< " idx: " << lock2->index->name()
<< " table: "
<< lock2->index->table->name.m_name
<< " n_uniq: " << lock2->index->n_uniq
<< " n_user: "
<< lock2->index->n_user_defined_cols
<< " SQL1: "
<< wsrep_thd_query(trx->mysql_thd)
<< " SQL2: "
<< wsrep_thd_query(
lock2->trx->mysql_thd);
}
return FALSE;
} }
#endif /* WITH_WSREP */
return(TRUE);
} }
#endif /* WITH_WSREP */
return(FALSE); return(true);
} }
/*********************************************************************//** /*********************************************************************//**
......
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