trx0roll.c

来自「这是linux下运行的mysql软件包,可用于linux 下安装 php + m」· C语言 代码 · 共 1,347 行 · 第 1/3 页

C
1,347
字号
		mutex_exit(&kernel_mutex);	if (trx == NULL) {		ut_print_timestamp(stderr);		fprintf(stderr,		"  InnoDB: Rollback of non-prepared transactions completed\n"); 		mem_heap_free(heap);		goto leave_function;	}	trx->sess = trx_dummy_sess;	if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {			fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",					(ulong) ut_dulint_get_high(trx->id),					(ulong) ut_dulint_get_low(trx->id));		trx_cleanup_at_db_startup(trx);							mem_heap_free(heap);		goto loop;	}	fork = que_fork_create(NULL, NULL, QUE_FORK_RECOVERY, heap);	fork->trx = trx;	thr = que_thr_create(fork, heap);	roll_node = roll_node_create(heap);	thr->child = roll_node;	roll_node->common.parent = thr;	mutex_enter(&kernel_mutex);		trx->graph = fork;	ut_a(thr == que_fork_start_command(fork));		trx_roll_crash_recv_trx	= trx;	trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no);	trx_roll_progress_printed_pct = 0;	rows_to_undo = trx_roll_max_undo_no;	if (rows_to_undo > 1000000000) {		rows_to_undo = rows_to_undo / 1000000;		unit = "M";	}	ut_print_timestamp(stderr);	fprintf(stderr,"  InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo\n",					(ulong) ut_dulint_get_high(trx->id),					(ulong) ut_dulint_get_low(trx->id),					(ulong) rows_to_undo, unit);	mutex_exit(&kernel_mutex);	trx->mysql_thread_id = os_thread_get_curr_id();	trx->mysql_process_no = os_proc_get_number();	if (trx->dict_operation) {		row_mysql_lock_data_dictionary(trx);	}	que_run_threads(thr);	mutex_enter(&kernel_mutex);	while (trx->que_state != TRX_QUE_RUNNING) {		mutex_exit(&kernel_mutex);		fprintf(stderr,		"InnoDB: Waiting for rollback of trx id %lu to end\n",					(ulong) ut_dulint_get_low(trx->id));		os_thread_sleep(100000);		mutex_enter(&kernel_mutex);	}	mutex_exit(&kernel_mutex);	if (trx->dict_operation) {		/* If the transaction was for a dictionary operation, we		drop the relevant table, if it still exists */		fprintf(stderr,"InnoDB: Dropping table with id %lu %lu in recovery if it exists\n",			(ulong) ut_dulint_get_high(trx->table_id),			(ulong) ut_dulint_get_low(trx->table_id));		table = dict_table_get_on_id_low(trx->table_id, trx);		if (table) {					fputs("InnoDB: Table found: dropping table ", stderr);			ut_print_name(stderr, trx, table->name);			fputs(" in recovery\n", stderr);			err = row_drop_table_for_mysql(table->name, trx, TRUE);			ut_a(err == (int) DB_SUCCESS);		}	}	if (trx->dict_operation) {		row_mysql_unlock_data_dictionary(trx);	}	fprintf(stderr, "\nInnoDB: Rolling back of trx id %lu %lu completed\n",					(ulong) ut_dulint_get_high(trx->id),					(ulong) ut_dulint_get_low(trx->id));	mem_heap_free(heap);	trx_roll_crash_recv_trx	= NULL;	goto loop;leave_function:	/* We count the number of threads in os_thread_exit(). A created	thread should always use that to exit and not use return() to exit. */	os_thread_exit(NULL);	/* The following is dummy code to keep the compiler happy: */#ifndef __WIN__        return(NULL);#else        return(0);#endif}	/***********************************************************************Creates an undo number array. */trx_undo_arr_t*trx_undo_arr_create(void)/*=====================*/{	trx_undo_arr_t*	arr;	mem_heap_t*	heap;	ulint		i;		heap = mem_heap_create(1024);	arr = mem_heap_alloc(heap, sizeof(trx_undo_arr_t));	arr->infos = mem_heap_alloc(heap, sizeof(trx_undo_inf_t)						* UNIV_MAX_PARALLELISM);	arr->n_cells = UNIV_MAX_PARALLELISM;	arr->n_used = 0;	arr->heap = heap;	for (i = 0; i < UNIV_MAX_PARALLELISM; i++) {		(trx_undo_arr_get_nth_info(arr, i))->in_use = FALSE;	}	return(arr);}/***********************************************************************Frees an undo number array. */voidtrx_undo_arr_free(/*==============*/	trx_undo_arr_t*	arr)	/* in: undo number array */{	ut_ad(arr->n_used == 0);	mem_heap_free(arr->heap);}/***********************************************************************Stores info of an undo log record to the array if it is not stored yet. */staticibooltrx_undo_arr_store_info(/*====================*/			/* out: FALSE if the record already existed in the			array */	trx_t*	trx,	/* in: transaction */	dulint	undo_no)/* in: undo number */{	trx_undo_inf_t*	cell;	trx_undo_inf_t*	stored_here;	trx_undo_arr_t*	arr;	ulint		n_used;	ulint		n;	ulint		i;	n = 0;	arr = trx->undo_no_arr;	n_used = arr->n_used;	stored_here = NULL;		for (i = 0;; i++) {		cell = trx_undo_arr_get_nth_info(arr, i);		if (!cell->in_use) {			if (!stored_here) {				/* Not in use, we may store here */				cell->undo_no = undo_no;				cell->in_use = TRUE;				arr->n_used++;				stored_here = cell;			}		} else {			n++;			if (0 == ut_dulint_cmp(cell->undo_no, undo_no)) {				if (stored_here) {					stored_here->in_use = FALSE;					ut_ad(arr->n_used > 0);					arr->n_used--;				}				ut_ad(arr->n_used == n_used);				return(FALSE);			}		}				if (n == n_used && stored_here) {			ut_ad(arr->n_used == 1 + n_used);			return(TRUE);		}	}}/***********************************************************************Removes an undo number from the array. */staticvoidtrx_undo_arr_remove_info(/*=====================*/	trx_undo_arr_t*	arr,	/* in: undo number array */	dulint		undo_no)/* in: undo number */{	trx_undo_inf_t*	cell;	ulint		n_used;	ulint		n;	ulint		i;	n_used = arr->n_used;	n = 0;	for (i = 0;; i++) {		cell = trx_undo_arr_get_nth_info(arr, i);		if (cell->in_use			     && 0 == ut_dulint_cmp(cell->undo_no, undo_no)) {			cell->in_use = FALSE;							ut_ad(arr->n_used > 0);			arr->n_used--;			return;		}	}}/***********************************************************************Gets the biggest undo number in an array. */staticdulinttrx_undo_arr_get_biggest(/*=====================*/				/* out: biggest value, ut_dulint_zero if				the array is empty */	trx_undo_arr_t*	arr)	/* in: undo number array */{	trx_undo_inf_t*	cell;	ulint		n_used;	dulint		biggest;	ulint		n;	ulint		i;		n = 0;	n_used = arr->n_used;	biggest = ut_dulint_zero;		for (i = 0;; i++) {		cell = trx_undo_arr_get_nth_info(arr, i);		if (cell->in_use) {			n++;			if (ut_dulint_cmp(cell->undo_no, biggest) > 0) {				biggest = cell->undo_no;			}		}				if (n == n_used) {			return(biggest);		}	}}/***************************************************************************Tries truncate the undo logs. */voidtrx_roll_try_truncate(/*==================*/	trx_t*	trx)	/* in: transaction */{	trx_undo_arr_t*	arr;	dulint		limit;	dulint		biggest;	#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&(trx->undo_mutex)));	ut_ad(mutex_own(&((trx->rseg)->mutex)));#endif /* UNIV_SYNC_DEBUG */	trx->pages_undone = 0;		arr = trx->undo_no_arr;	limit = trx->undo_no;	if (arr->n_used > 0) {		biggest = trx_undo_arr_get_biggest(arr);	    	if (ut_dulint_cmp(biggest, limit) >= 0) {	    		limit = ut_dulint_add(biggest, 1);	    	}	}	if (trx->insert_undo) {		trx_undo_truncate_end(trx, trx->insert_undo, limit);	}	if (trx->update_undo) {		trx_undo_truncate_end(trx, trx->update_undo, limit);	}}/***************************************************************************Pops the topmost undo log record in a single undo log and updates the infoabout the topmost record in the undo log memory struct. */statictrx_undo_rec_t*trx_roll_pop_top_rec(/*=================*/				/* out: undo log record, the page s-latched */	trx_t*		trx,	/* in: transaction */	trx_undo_t*	undo,	/* in: undo log */	mtr_t*		mtr)	/* in: mtr */{	page_t* 	undo_page;	ulint		offset;	trx_undo_rec_t*	prev_rec;	page_t*		prev_rec_page;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&(trx->undo_mutex)));#endif /* UNIV_SYNC_DEBUG */	undo_page = trx_undo_page_get_s_latched(undo->space,						undo->top_page_no, mtr);	offset = undo->top_offset;/*	fprintf(stderr, "Thread %lu undoing trx %lu undo record %lu\n",		os_thread_get_curr_id(), ut_dulint_get_low(trx->id),		ut_dulint_get_low(undo->top_undo_no)); */	prev_rec = trx_undo_get_prev_rec(undo_page + offset,					undo->hdr_page_no, undo->hdr_offset,									mtr);	if (prev_rec == NULL) {		undo->empty = TRUE;	} else {		prev_rec_page = buf_frame_align(prev_rec);			if (prev_rec_page != undo_page) {			trx->pages_undone++;		}			undo->top_page_no = buf_frame_get_page_no(prev_rec_page);		undo->top_offset  = prev_rec - prev_rec_page;		undo->top_undo_no = trx_undo_rec_get_undo_no(prev_rec);	}	return(undo_page + offset);}/************************************************************************Pops the topmost record when the two undo logs of a transaction are seenas a single stack of records ordered by their undo numbers. Inserts theundo number of the popped undo record to the array of currently processedundo numbers in the transaction. When the query thread finishes processingof this undo record, it must be released with trx_undo_rec_release. */trx_undo_rec_t*trx_roll_pop_top_rec_of_trx(/*========================*/				/* out: undo log record copied to heap, NULL				if none left, or if the undo number of the				top record would be less than the limit */	trx_t*		trx,	/* in: transaction */	dulint		limit,	/* in: least undo number we need */	dulint*		roll_ptr,/* out: roll pointer to undo record */	mem_heap_t*	heap)	/* in: memory heap where copied */{	trx_undo_t*	undo;	trx_undo_t*	ins_undo;	trx_undo_t*	upd_undo;	trx_undo_rec_t*	undo_rec;	trx_undo_rec_t*	undo_rec_copy;	dulint		undo_no;	ibool		is_insert;	trx_rseg_t*	rseg;	ulint		progress_pct;	mtr_t		mtr;		rseg = trx->rseg;try_again:	mutex_enter(&(trx->undo_mutex));	if (trx->pages_undone >= TRX_ROLL_TRUNC_THRESHOLD) {		mutex_enter(&(rseg->mutex));		trx_roll_try_truncate(trx);		mutex_exit(&(rseg->mutex));	}	ins_undo = trx->insert_undo;	upd_undo = trx->update_undo;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?