summaryrefslogtreecommitdiff
path: root/storage/maria/trnman.c
diff options
context:
space:
mode:
authorGuilhem Bichot <guilhem@mysql.com>2009-03-05 14:46:45 +0100
committerGuilhem Bichot <guilhem@mysql.com>2009-03-05 14:46:45 +0100
commit8a715a599077b7546af558aa47e37423dc322f7e (patch)
treeaa8f7d6fda3fb4480d819043de8d56fb19dd78a2 /storage/maria/trnman.c
parent6a1bc662d67cdb7716480654ddd63d504508b4fa (diff)
downloadmariadb-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.c21
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;