diff options
Diffstat (limited to 'innobase/trx/trx0undo.c')
-rw-r--r-- | innobase/trx/trx0undo.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c index 7441dd3f152..251cd355897 100644 --- a/innobase/trx/trx0undo.c +++ b/innobase/trx/trx0undo.c @@ -1724,6 +1724,7 @@ trx_undo_set_state_at_finish( /*=========================*/ /* out: undo log segment header page, x-latched */ + trx_rseg_t* rseg, /* in: rollback segment memory object */ trx_t* trx __attribute__((unused)), /* in: transaction */ trx_undo_t* undo, /* in: undo log memory copy */ mtr_t* mtr) /* in: mtr */ @@ -1732,8 +1733,10 @@ trx_undo_set_state_at_finish( trx_upagef_t* page_hdr; page_t* undo_page; ulint state; - - ut_ad(trx && undo && mtr); + + ut_ad(trx); + ut_ad(undo); + ut_ad(mtr); if (undo->id >= TRX_RSEG_N_SLOTS) { fprintf(stderr, "InnoDB: Error: undo->id is %lu\n", @@ -1747,9 +1750,23 @@ trx_undo_set_state_at_finish( seg_hdr = undo_page + TRX_UNDO_SEG_HDR; page_hdr = undo_page + TRX_UNDO_PAGE_HDR; - if (undo->size == 1 && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) - < TRX_UNDO_PAGE_REUSE_LIMIT) { - state = TRX_UNDO_CACHED; + if (undo->size == 1 + && mach_read_from_2(page_hdr + TRX_UNDO_PAGE_FREE) + < TRX_UNDO_PAGE_REUSE_LIMIT) { + + /* This is a heuristic to avoid the problem of all UNDO + slots ending up in one of the UNDO lists. Previously if + the server crashed with all the slots in one of the lists, + transactions that required the slots of a different type + would fail for lack of slots. */ + + if (UT_LIST_GET_LEN(rseg->update_undo_list) < 500 + && UT_LIST_GET_LEN(rseg->insert_undo_list) < 500) { + + state = TRX_UNDO_CACHED; + } else { + state = TRX_UNDO_TO_FREE; + } } else if (undo->type == TRX_UNDO_INSERT) { @@ -1759,7 +1776,7 @@ trx_undo_set_state_at_finish( } undo->state = state; - + mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, state, MLOG_2BYTES, mtr); return(undo_page); |