/********************************************************************//** Removes unnecessary history data from rollback segments. NOTE that when this function is called, the caller must not have any latches on undo log pages! */ static void trx_purge_truncate_history(void) /*============================*/ { trx_rseg_t* rseg; trx_id_t limit_trx_no; undo_no_t limit_undo_no; ut_ad(mutex_own(&(purge_sys->mutex))); trx_purge_arr_get_biggest(purge_sys->arr, &limit_trx_no, &limit_undo_no); if (ut_dulint_is_zero(limit_trx_no)) { limit_trx_no = purge_sys->purge_trx_no; limit_undo_no = purge_sys->purge_undo_no; } /* We play safe and set the truncate limit at most to the purge view low_limit number, though this is not necessary */ if (ut_dulint_cmp(limit_trx_no, purge_sys->view->low_limit_no) >= 0) { limit_trx_no = purge_sys->view->low_limit_no; limit_undo_no = ut_dulint_zero; } ut_ad((ut_dulint_cmp(limit_trx_no, purge_sys->view->low_limit_no) <= 0)); rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list); while (rseg) { trx_purge_truncate_rseg_history(rseg, limit_trx_no, limit_undo_no); rseg = UT_LIST_GET_NEXT(rseg_list, rseg); } }
/************************************************************************ Does an asynchronous write of a buffer page. NOTE: in simulated aio and also when the doublewrite buffer is used, we must call buf_flush_buffered_writes after we have posted a batch of writes! */ static void buf_flush_write_block_low( /*======================*/ buf_block_t* block) /* in: buffer block to write */ { #ifdef UNIV_LOG_DEBUG static ibool univ_log_debug_warned; #endif /* UNIV_LOG_DEBUG */ ut_a(block->state == BUF_BLOCK_FILE_PAGE); #ifdef UNIV_IBUF_DEBUG ut_a(ibuf_count_get(block->space, block->offset) == 0); #endif ut_ad(!ut_dulint_is_zero(block->newest_modification)); #ifdef UNIV_LOG_DEBUG if (!univ_log_debug_warned) { univ_log_debug_warned = TRUE; fputs("Warning: cannot force log to disk if" " UNIV_LOG_DEBUG is defined!\n" "Crash recovery will not work!\n", stderr); } #else /* Force the log to the disk before writing the modified block */ log_write_up_to(block->newest_modification, LOG_WAIT_ALL_GROUPS, TRUE); #endif buf_flush_init_for_writing(block->frame, block->newest_modification, block->space, block->offset); if (!srv_use_doublewrite_buf || !trx_doublewrite) { fil_io(OS_FILE_WRITE | OS_AIO_SIMULATED_WAKE_LATER, FALSE, block->space, block->offset, 0, UNIV_PAGE_SIZE, (void*)block->frame, (void*)block); } else { buf_flush_post_to_doublewrite_buf(block); } }
/**********************************************************************//** Prints info about a transaction to the given file. The caller must own the kernel mutex. */ UNIV_INTERN void trx_print( /*======*/ FILE* f, /*!< in: output stream */ trx_t* trx, /*!< in: transaction */ ulint max_query_len) /*!< in: max query length to print, or 0 to use the default max length */ { ibool newline; fprintf(f, "TRANSACTION " TRX_ID_FMT, TRX_ID_PREP_PRINTF(trx->id)); switch (trx->conc_state) { case TRX_NOT_STARTED: fputs(", not started", f); break; case TRX_ACTIVE: fprintf(f, ", ACTIVE %lu sec", (ulong)difftime(time(NULL), trx->start_time)); break; case TRX_PREPARED: fprintf(f, ", ACTIVE (PREPARED) %lu sec", (ulong)difftime(time(NULL), trx->start_time)); break; case TRX_COMMITTED_IN_MEMORY: fputs(", COMMITTED IN MEMORY", f); break; default: fprintf(f, " state %lu", (ulong) trx->conc_state); } #ifdef UNIV_LINUX fprintf(f, ", process no %lu", trx->mysql_process_no); #endif fprintf(f, ", OS thread id %lu", (ulong) os_thread_pf(trx->mysql_thread_id)); if (*trx->op_info) { putc(' ', f); fputs(trx->op_info, f); } if (trx->is_recovered) { fputs(" recovered trx", f); } if (trx->is_purge) { fputs(" purge trx", f); } if (trx->declared_to_be_inside_innodb) { fprintf(f, ", thread declared inside InnoDB %lu", (ulong) trx->n_tickets_to_enter_innodb); } putc('\n', f); if (trx->n_mysql_tables_in_use > 0 || trx->mysql_n_tables_locked > 0) { fprintf(f, "mysql tables in use %lu, locked %lu\n", (ulong) trx->n_mysql_tables_in_use, (ulong) trx->mysql_n_tables_locked); } newline = TRUE; switch (trx->que_state) { case TRX_QUE_RUNNING: newline = FALSE; break; case TRX_QUE_LOCK_WAIT: fputs("LOCK WAIT ", f); break; case TRX_QUE_ROLLING_BACK: fputs("ROLLING BACK ", f); break; case TRX_QUE_COMMITTING: fputs("COMMITTING ", f); break; default: fprintf(f, "que state %lu ", (ulong) trx->que_state); } if (0 < UT_LIST_GET_LEN(trx->trx_locks) || mem_heap_get_size(trx->lock_heap) > 400) { newline = TRUE; fprintf(f, "%lu lock struct(s), heap size %lu," " %lu row lock(s)", (ulong) UT_LIST_GET_LEN(trx->trx_locks), (ulong) mem_heap_get_size(trx->lock_heap), (ulong) lock_number_of_rows_locked(trx)); } if (trx->has_search_latch) { newline = TRUE; fputs(", holds adaptive hash latch", f); } if (!ut_dulint_is_zero(trx->undo_no)) { newline = TRUE; fprintf(f, ", undo log entries %lu", (ulong) ut_dulint_get_low(trx->undo_no)); } if (newline) { putc('\n', f); } if (trx->mysql_thd != NULL) { innobase_mysql_print_thd(f, trx->mysql_thd, max_query_len); } }