Skip to content

Commit b762541

Browse files
janlindstromsysprg
authored andcommitted
MDEV-33278 : Assertion failure in thd_get_thread_id at lock_wait_wsrep
Problem is that not all conflicting transactions have THD object. Therefore, it must be checked that victim has THD before it's identification is added to victim list as victim's thread identification is later requested using thd_get_thread_id function that requires that we have valid pointer to THD object in trx->mysql_thd. Victim might not have trx->mysql_thd in two cases: (1) An incomplete transaction that was recovered from undo logs on server startup (and not yet rolled back). (2) Transaction that is in XA PREPARE state and whose client connection was disconnected. Neither of these can complete before lock_wait_wsrep() releases lock_sys.latch. (1) trx_t::commit_in_memory() is clearing both trx_t::state and trx_t::is_recovered before it invokes lock_release(trx_t*) (which would be blocked by the exclusive lock_sys.latch that we are holding here). Hence, it is not possible to write a debug assertion to document this scenario. (2) If is in XA PREPARE state, it would eventually be rolled back and the lock conflict would be resolved when an XA COMMIT or XA ROLLBACK statement is executed in some other connection. Signed-off-by: Julius Goryavsky <julius.goryavsky@mariadb.com>
1 parent c1da568 commit b762541

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

storage/innobase/lock/lock0lock.cc

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -970,8 +970,31 @@ static void lock_wait_wsrep(trx_t *trx)
970970
for (lock_t *lock= UT_LIST_GET_FIRST(table->locks); lock;
971971
lock= UT_LIST_GET_NEXT(un_member.tab_lock.locks, lock))
972972
{
973-
/* if victim has also BF status, but has earlier seqno, we have to wait */
974-
if (lock->trx != trx &&
973+
/* Victim trx needs to be different from BF trx and it has to have a
974+
THD so that we can kill it. Victim might not have THD in two cases:
975+
976+
(1) An incomplete transaction that was recovered from undo logs
977+
on server startup (and not yet rolled back).
978+
979+
(2) Transaction that is in XA PREPARE state and whose client
980+
connection was disconnected.
981+
982+
Neither of these can complete before lock_wait_wsrep() releases
983+
lock_sys.latch.
984+
985+
(1) trx_t::commit_in_memory() is clearing both
986+
trx_t::state and trx_t::is_recovered before it invokes
987+
lock_release(trx_t*) (which would be blocked by the exclusive
988+
lock_sys.latch that we are holding here). Hence, it is not
989+
possible to write a debug assertion to document this scenario.
990+
991+
(2) If is in XA PREPARE state, it would eventually be rolled
992+
back and the lock conflict would be resolved when an XA COMMIT
993+
or XA ROLLBACK statement is executed in some other connection.
994+
995+
If victim has also BF status, but has earlier seqno, we have to wait.
996+
*/
997+
if (lock->trx != trx && lock->trx->mysql_thd &&
975998
!(wsrep_thd_is_BF(lock->trx->mysql_thd, false) &&
976999
wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd)))
9771000
{
@@ -1003,8 +1026,11 @@ static void lock_wait_wsrep(trx_t *trx)
10031026
lock= lock_rec_get_next(heap_no, lock);
10041027
do
10051028
{
1006-
/* if victim has also BF status, but has earlier seqno, we have to wait */
1007-
if (lock->trx != trx &&
1029+
/* This is similar case as above except here we have
1030+
record-locks instead of table locks. See details
1031+
from comment above.
1032+
*/
1033+
if (lock->trx != trx && lock->trx->mysql_thd &&
10081034
!(wsrep_thd_is_BF(lock->trx->mysql_thd, false) &&
10091035
wsrep_thd_order_before(lock->trx->mysql_thd, trx->mysql_thd)))
10101036
{
@@ -1030,8 +1056,12 @@ static void lock_wait_wsrep(trx_t *trx)
10301056

10311057
std::vector<std::pair<ulong,trx_id_t>> victim_id;
10321058
for (trx_t *v : victims)
1059+
{
1060+
/* Victim must have THD */
1061+
ut_ad(v->mysql_thd);
10331062
victim_id.emplace_back(std::pair<ulong,trx_id_t>
10341063
{thd_get_thread_id(v->mysql_thd), v->id});
1064+
}
10351065

10361066
DBUG_EXECUTE_IF("sync.before_wsrep_thd_abort",
10371067
{

0 commit comments

Comments
 (0)