/****************************************************************//** Starts a new transaction. @return TRUE */ UNIV_INTERN ibool trx_start( /*======*/ trx_t* trx, /*!< in: transaction */ ulint rseg_id)/*!< in: rollback segment id; if ULINT_UNDEFINED is passed, the system chooses the rollback segment automatically in a round-robin fashion */ { ibool ret; /* Update the info whether we should skip XA steps that eat CPU time For the duration of the transaction trx->support_xa is not reread from thd so any changes in the value take effect in the next transaction. This is to avoid a scenario where some undo generated by a transaction, has XA stuff, and other undo, generated by the same transaction, doesn't. */ trx->support_xa = thd_supports_xa(trx->mysql_thd); mutex_enter(&kernel_mutex); ret = trx_start_low(trx, rseg_id); mutex_exit(&kernel_mutex); return(ret); }
/********************************************************************//** Creates the global purge system control structure and inits the history mutex. */ UNIV_INTERN void trx_purge_sys_create( /*=================*/ ib_bh_t* ib_bh) /*!< in, own: UNDO log min binary heap */ { ut_ad(mutex_own(&kernel_mutex)); purge_sys = mem_zalloc(sizeof(trx_purge_t)); /* Take ownership of ib_bh, we are responsible for freeing it. */ purge_sys->ib_bh = ib_bh; purge_sys->state = TRX_STOP_PURGE; purge_sys->n_pages_handled = 0; purge_sys->purge_trx_no = 0; purge_sys->purge_undo_no = 0; purge_sys->next_stored = FALSE; ut_d(purge_sys->done_trx_no = 0); rw_lock_create(trx_purge_latch_key, &purge_sys->latch, SYNC_PURGE_LATCH); mutex_create( purge_sys_bh_mutex_key, &purge_sys->bh_mutex, SYNC_PURGE_QUEUE); purge_sys->heap = mem_heap_create(256); purge_sys->arr = trx_undo_arr_create(); purge_sys->sess = sess_open(); purge_sys->trx = purge_sys->sess->trx; purge_sys->trx->is_purge = 1; ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED)); purge_sys->query = trx_purge_graph_build(); purge_sys->prebuilt_view = read_view_oldest_copy_or_open_new(0, NULL); purge_sys->view = purge_sys->prebuilt_view; }
ibool trx_start( /*======*/ /* out: TRUE */ trx_t* trx, /* in: transaction */ ulint rseg_id)/* in: rollback segment id; if ULINT_UNDEFINED is passed, the system chooses the rollback segment automatically in a round-robin fashion */ { ibool ret; mutex_enter(&kernel_mutex); ret = trx_start_low(trx, rseg_id); mutex_exit(&kernel_mutex); return(ret); }
/********************************************************************//** Creates the global purge system control structure and inits the history mutex. */ UNIV_INTERN void trx_purge_sys_create(void) /*======================*/ { ut_ad(mutex_own(&kernel_mutex)); purge_sys = mem_alloc(sizeof(trx_purge_t)); purge_sys->state = TRX_STOP_PURGE; purge_sys->n_pages_handled = 0; purge_sys->purge_trx_no = ut_dulint_zero; purge_sys->purge_undo_no = ut_dulint_zero; purge_sys->next_stored = FALSE; ut_d(purge_sys->done_trx_no = ut_dulint_zero); rw_lock_create(&purge_sys->latch, SYNC_PURGE_LATCH); mutex_create(&purge_sys->mutex, SYNC_PURGE_SYS); purge_sys->heap = mem_heap_create(256); purge_sys->arr = trx_undo_arr_create(); purge_sys->sess = sess_open(); purge_sys->trx = purge_sys->sess->trx; purge_sys->trx->is_purge = 1; ut_a(trx_start_low(purge_sys->trx, ULINT_UNDEFINED)); purge_sys->query = trx_purge_graph_build(); purge_sys->view = read_view_oldest_copy_or_open_new(ut_dulint_zero, purge_sys->heap); }
/****************************************************************//** Starts handling of a trx signal. */ UNIV_INTERN void trx_sig_start_handle( /*=================*/ trx_t* trx, /*!< in: trx handle */ que_thr_t** next_thr) /*!< in/out: next query thread to run; if the value which is passed in is a pointer to a NULL pointer, then the calling function can start running a new query thread; if the parameter is NULL, it is ignored */ { trx_sig_t* sig; ulint type; loop: /* We loop in this function body as long as there are queued signals we can process immediately */ ut_ad(trx); ut_ad(mutex_own(&kernel_mutex)); if (trx->handling_signals && (UT_LIST_GET_LEN(trx->signals) == 0)) { trx_end_signal_handling(trx); return; } if (trx->conc_state == TRX_NOT_STARTED) { trx_start_low(trx, ULINT_UNDEFINED); } /* If the trx is in a lock wait state, moves the waiting query threads to the suspended state */ if (trx->que_state == TRX_QUE_LOCK_WAIT) { trx_lock_wait_to_suspended(trx); } /* If the session is in the error state and this trx has threads waiting for reply from signals, moves these threads to the suspended state, canceling wait reservations; note that if the transaction has sent a commit or rollback signal to itself, and its session is not in the error state, then nothing is done here. */ if (trx->sess->state == SESS_ERROR) { trx_sig_reply_wait_to_suspended(trx); } /* If there are no running query threads, we can start processing of a signal, otherwise we have to wait until all query threads of this transaction are aware of the arrival of the signal. */ if (trx->n_active_thrs > 0) { return; } if (trx->handling_signals == FALSE) { trx->graph_before_signal_handling = trx->graph; trx->handling_signals = TRUE; } sig = UT_LIST_GET_FIRST(trx->signals); type = sig->type; if (type == TRX_SIG_COMMIT) { trx_handle_commit_sig_off_kernel(trx, next_thr); } else if ((type == TRX_SIG_TOTAL_ROLLBACK) || (type == TRX_SIG_ROLLBACK_TO_SAVEPT)) { trx_rollback(trx, sig, next_thr); /* No further signals can be handled until the rollback completes, therefore we return */ return; } else if (type == TRX_SIG_ERROR_OCCURRED) { trx_rollback(trx, sig, next_thr); /* No further signals can be handled until the rollback completes, therefore we return */ return; } else if (type == TRX_SIG_BREAK_EXECUTION) { trx_sig_reply(sig, next_thr); trx_sig_remove(trx, sig); } else { ut_error; } goto loop; }