Commit 4150dfda authored by Michael Widenius's avatar Michael Widenius

Fix for bug: Bug #40391 Maria deadlock in trnman_get_min_trid , trnman_end_trn

storage/maria/trnman.c:
  Store min used trid in a global variable and change trnman_get_min_trid() to return this variable without using a mutex.
  This is safe as trnman_get_min_trid() is used for trid optimization and all algoritms will work even if it returns a slightly older trid.
  
  Also ensure that LOCK_trn_list is unlocked in trnman_new_trn() in the very unlikely case that lf_hash_get_pins() fails
parent e4febda8
......@@ -37,6 +37,13 @@ static TRN committed_list_min, committed_list_max;
/* a counter, used to generate transaction ids */
static TrID global_trid_generator;
/*
The minimum existing transaction id for trnman_get_min_trid()
The default value is used when transaction manager not initialize;
Probably called from maria_chk
*/
static TrID trid_min_read_from= ~(TrID) 0;
/* the mutex for everything above */
static pthread_mutex_t LOCK_trn_list;
......@@ -158,6 +165,7 @@ int trnman_init(TrID initial_trid)
pool= 0;
global_trid_generator= initial_trid;
trid_min_read_from= initial_trid;
lf_hash_init(&trid_to_trn, sizeof(TRN*), LF_HASH_UNIQUE,
0, 0, trn_get_hash_key, 0);
DBUG_PRINT("info", ("pthread_mutex_init LOCK_trn_list"));
......@@ -303,6 +311,7 @@ TRN *trnman_new_trn(WT_THD *wt)
if (!trn->pins)
{
trnman_free_trn(trn);
pthread_mutex_unlock(&LOCK_trn_list);
return 0;
}
......@@ -315,6 +324,7 @@ TRN *trnman_new_trn(WT_THD *wt)
trn->next= &active_list_max;
trn->prev= active_list_max.prev;
active_list_max.prev= trn->prev->next= trn;
trid_min_read_from= active_list_min.next->min_read_from;
DBUG_PRINT("info", ("pthread_mutex_unlock LOCK_trn_list"));
pthread_mutex_unlock(&LOCK_trn_list);
......@@ -437,6 +447,8 @@ my_bool trnman_end_trn(TRN *trn, my_bool commit)
trn->next= free_me;
free_me= trn;
}
trid_min_read_from= active_list_min.next->min_read_from;
if ((*trnman_end_trans_hook)(trn, commit,
active_list_min.next != &active_list_max))
res= -1;
......@@ -787,25 +799,14 @@ TRN *trnman_get_any_trn()
/**
Returns the minimum existing transaction id
@notes
This can only be called when we have at least one running transaction.
Returns the minimum existing transaction id. May return a too small
number in race conditions, but this is ok as the value is used to
remove not visible transid from index/rows.
*/
TrID trnman_get_min_trid()
{
TrID min_read_from;
if (short_trid_to_active_trn == NULL)
{
/* Transaction manager not initialize; Probably called from maria_chk */
return ~(TrID) 0;
}
pthread_mutex_lock(&LOCK_trn_list);
min_read_from= active_list_min.next->min_read_from;
pthread_mutex_unlock(&LOCK_trn_list);
return min_read_from;
return trid_min_read_from;
}
......
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