diff options
author | Guilhem Bichot <guilhem@mysql.com> | 2009-03-05 14:46:45 +0100 |
---|---|---|
committer | Guilhem Bichot <guilhem@mysql.com> | 2009-03-05 14:46:45 +0100 |
commit | 8a715a599077b7546af558aa47e37423dc322f7e (patch) | |
tree | aa8f7d6fda3fb4480d819043de8d56fb19dd78a2 /storage/maria/trnman.c | |
parent | 6a1bc662d67cdb7716480654ddd63d504508b4fa (diff) | |
download | mariadb-git-8a715a599077b7546af558aa47e37423dc322f7e.tar.gz |
Fix for BUG#42180 "Maria: maria-recovery-bitmap.test fails repeatedly"
storage/maria/ma_loghandler.c:
Normally, when we log LOGREC_LONG_TRANSACTION_ID, undo_lsn should be 0: assert this.
storage/maria/ma_test_force_start.pl:
this script does not work with mtr2, make it use mtr1
storage/maria/trnman.c:
The bug's cause was that: transaction would log LOGREC_LONG_TRANSACTION_ID, then Checkpoint would run
and skip it (because its undo_lsn is still 0), then transaction would log REDO+UNDO, then crash. At Recovery,
REDO phase would start from Checkpoint's record LSN, so wouldn't see LOGREC_LONG_TRANSACTION_ID, and
as Checkpoint record does not mention transaction, transaction would be unknown, so its REDO+UNDO would
be thrown away (assumed to belong to a transaction committed long ago as unknown), so transaction
would not be rolled back, which is wrong. Fix is: it was wrong to skip a transaction if undo_lsn is 0;
as soon as LOGREC_LONG_TRANSACTION_ID has been logged, it becomes potentially invisible to the REDO
phase, and so we must include this transaction in the checkpoint record.
Diffstat (limited to 'storage/maria/trnman.c')
-rw-r--r-- | storage/maria/trnman.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c index 06b3b828d50..43fac68806f 100644 --- a/storage/maria/trnman.c +++ b/storage/maria/trnman.c @@ -712,11 +712,6 @@ my_bool trnman_collect_transactions(LEX_STRING *str_act, LEX_STRING *str_com, ptr+= TRANSID_SIZE; for (trn= active_list_min.next; trn != &active_list_max; trn= trn->next) { - /* - trns with a short trid of 0 are not even initialized, we can ignore - them. trns with undo_lsn==0 have done no writes, we can ignore them - too. XID not needed now. - */ uint sid; LSN rec_lsn, undo_lsn, first_undo_lsn; pthread_mutex_lock(&trn->state_lock); @@ -732,16 +727,24 @@ my_bool trnman_collect_transactions(LEX_STRING *str_act, LEX_STRING *str_com, */ continue; } - /* needed for low-water mark calculation */ + /* needed for low-water mark calculation */ if (((rec_lsn= lsn_read_non_atomic(trn->rec_lsn)) > 0) && (cmp_translog_addr(rec_lsn, minimum_rec_lsn) < 0)) minimum_rec_lsn= rec_lsn; /* - trn may have logged REDOs but not yet UNDO, that's why we read rec_lsn - before deciding to ignore if undo_lsn==0. + If trn has not logged LOGREC_LONG_TRANSACTION_ID, this trn will be + discovered when seeing that log record which is for sure located after + checkpoint_start_log_horizon. */ - if ((undo_lsn= trn->undo_lsn) == 0) /* trn can be forgotten */ + if ((LSN_WITH_FLAGS_TO_FLAGS(trn->first_undo_lsn) & + TRANSACTION_LOGGED_LONG_ID) == 0) continue; + /* + On the other hand, if undo_lsn is LSN_IMPOSSIBLE, trn may later log + records; so we must include trn in the checkpoint now, because we cannot + count on LOGREC_LONG_TRANSACTION_ID (as we are already past it). + */ + undo_lsn= trn->undo_lsn; stored_transactions++; int2store(ptr, sid); ptr+= 2; |