summaryrefslogtreecommitdiff
path: root/storage/maria/trnman.c
diff options
context:
space:
mode:
authorMichael Widenius <monty@mysql.com>2008-11-05 23:17:09 +0200
committerMichael Widenius <monty@mysql.com>2008-11-05 23:17:09 +0200
commit4150dfda93d870e7b567ac4184c59bb6f342a58a (patch)
treed7cce88b719658bd8e40e7ff5d0f0f5cd364e8d0 /storage/maria/trnman.c
parente4febda89ed483e36656862682dfa16e6de05185 (diff)
downloadmariadb-git-4150dfda93d870e7b567ac4184c59bb6f342a58a.tar.gz
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
Diffstat (limited to 'storage/maria/trnman.c')
-rw-r--r--storage/maria/trnman.c31
1 files changed, 16 insertions, 15 deletions
diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c
index d3d4053b4c5..6367d3653b1 100644
--- a/storage/maria/trnman.c
+++ b/storage/maria/trnman.c
@@ -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;
}