diff options
author | Michael Widenius <monty@mysql.com> | 2008-11-05 23:17:09 +0200 |
---|---|---|
committer | Michael Widenius <monty@mysql.com> | 2008-11-05 23:17:09 +0200 |
commit | 4150dfda93d870e7b567ac4184c59bb6f342a58a (patch) | |
tree | d7cce88b719658bd8e40e7ff5d0f0f5cd364e8d0 /storage/maria/trnman.c | |
parent | e4febda89ed483e36656862682dfa16e6de05185 (diff) | |
download | mariadb-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.c | 31 |
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; } |