⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 trx0purge.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&(purge_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */	if (purge_sys->arr->n_used == 0) {		trx_purge_truncate_history();		return(TRUE);	}	return(FALSE);}/***************************************************************************Updates the last not yet purged history log info in rseg when we have purgeda whole undo log. Advances also purge_sys->purge_trx_no past the purged log. */static voidtrx_purge_rseg_get_next_history_log(/*================================*/	trx_rseg_t*	rseg)	/* in: rollback segment */{	page_t* 	undo_page;	trx_ulogf_t*	log_hdr;	trx_usegf_t*	seg_hdr;	fil_addr_t	prev_log_addr;	dulint		trx_no;	ibool		del_marks;	mtr_t		mtr;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&(purge_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */	mutex_enter(&(rseg->mutex));	ut_a(rseg->last_page_no != FIL_NULL);	purge_sys->purge_trx_no = ut_dulint_add(rseg->last_trx_no, 1);	purge_sys->purge_undo_no = ut_dulint_zero;	purge_sys->next_stored = FALSE;		mtr_start(&mtr);		undo_page = trx_undo_page_get_s_latched(rseg->space,						rseg->last_page_no, &mtr);	log_hdr = undo_page + rseg->last_offset;	seg_hdr = undo_page + TRX_UNDO_SEG_HDR;	/* Increase the purge page count by one for every handled log */	purge_sys->n_pages_handled++;	prev_log_addr = trx_purge_get_log_from_hist(			 flst_get_prev_addr(log_hdr + TRX_UNDO_HISTORY_NODE,									&mtr));	if (prev_log_addr.page == FIL_NULL) {		/* No logs left in the history list */		rseg->last_page_no = FIL_NULL;			mutex_exit(&(rseg->mutex));		mtr_commit(&mtr);		mutex_enter(&kernel_mutex);				/* Add debug code to track history list corruption reported		on the MySQL mailing list on Nov 9, 2004. The fut0lst.c		file-based list was corrupt. The prev node pointer was		FIL_NULL, even though the list length was over 8 million nodes!		We assume that purge truncates the history list in moderate		size pieces, and if we here reach the head of the list, the		list cannot be longer than 20 000 undo logs now. */			if (trx_sys->rseg_history_len > 20000) {			ut_print_timestamp(stderr);			fprintf(stderr,"  InnoDB: Warning: purge reached the head of the history list,\n""InnoDB: but its length is still reported as %lu! Make a detailed bug\n""InnoDB: report, and post it to bugs.mysql.com\n",					(ulong)trx_sys->rseg_history_len);		}		mutex_exit(&kernel_mutex);		return;	}	mutex_exit(&(rseg->mutex));	mtr_commit(&mtr);	/* Read the trx number and del marks from the previous log header */	mtr_start(&mtr);	log_hdr = trx_undo_page_get_s_latched(rseg->space,						prev_log_addr.page, &mtr)		  + prev_log_addr.boffset;	trx_no = mach_read_from_8(log_hdr + TRX_UNDO_TRX_NO);		del_marks = mach_read_from_2(log_hdr + TRX_UNDO_DEL_MARKS);	mtr_commit(&mtr);	mutex_enter(&(rseg->mutex));	rseg->last_page_no = prev_log_addr.page;	rseg->last_offset = prev_log_addr.boffset;	rseg->last_trx_no = trx_no;	rseg->last_del_marks = del_marks;	mutex_exit(&(rseg->mutex));}	/***************************************************************************Chooses the next undo log to purge and updates the info in purge_sys. Thisfunction is used to initialize purge_sys when the next record to purge isnot known, and also to update the purge system info on the next record whenpurge has handled the whole undo log for a transaction. */static voidtrx_purge_choose_next_log(void)/*===========================*/{	trx_undo_rec_t*	rec;	trx_rseg_t*	rseg;	trx_rseg_t*	min_rseg;	dulint		min_trx_no;	ulint		space = 0;   /* remove warning (??? bug ???) */	ulint		page_no = 0; /* remove warning (??? bug ???) */	ulint		offset = 0;  /* remove warning (??? bug ???) */	mtr_t		mtr;	#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&(purge_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */	ut_ad(purge_sys->next_stored == FALSE);	rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);	min_trx_no = ut_dulint_max;	min_rseg = NULL;		while (rseg) {		mutex_enter(&(rseg->mutex));				if (rseg->last_page_no != FIL_NULL) {			if ((min_rseg == NULL)			    || (ut_dulint_cmp(min_trx_no, rseg->last_trx_no)			    	> 0)) {				min_rseg = rseg;				min_trx_no = rseg->last_trx_no;				space = rseg->space;				ut_a(space == 0); /* We assume in purge of						externally stored fields						that space id == 0 */				page_no = rseg->last_page_no;				offset = rseg->last_offset;			}		}		mutex_exit(&(rseg->mutex));		rseg = UT_LIST_GET_NEXT(rseg_list, rseg);	}		if (min_rseg == NULL) {		return;	}	mtr_start(&mtr);	if (!min_rseg->last_del_marks) {		/* No need to purge this log */		rec = &trx_purge_dummy_rec;	} else {		rec = trx_undo_get_first_rec(space, page_no, offset,							RW_S_LATCH, &mtr);		if (rec == NULL) {			/* Undo log empty */			rec = &trx_purge_dummy_rec;		}	}		purge_sys->next_stored = TRUE;	purge_sys->rseg = min_rseg;	purge_sys->hdr_page_no = page_no;	purge_sys->hdr_offset = offset;	purge_sys->purge_trx_no = min_trx_no;	if (rec == &trx_purge_dummy_rec) {		purge_sys->purge_undo_no = ut_dulint_zero;		purge_sys->page_no = page_no;		purge_sys->offset = 0;	} else {		purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec);		purge_sys->page_no = buf_frame_get_page_no(rec);		purge_sys->offset = rec - buf_frame_align(rec);	}	mtr_commit(&mtr);}/***************************************************************************Gets the next record to purge and updates the info in the purge system. */statictrx_undo_rec_t*trx_purge_get_next_rec(/*===================*/				/* out: copy of an undo log record or				pointer to the dummy undo log record */	mem_heap_t*	heap)	/* in: memory heap where copied */{	trx_undo_rec_t*	rec;	trx_undo_rec_t*	rec_copy;	trx_undo_rec_t*	rec2;	trx_undo_rec_t*	next_rec;	page_t* 	undo_page;	page_t* 	page;	ulint		offset;	ulint		page_no;	ulint		space;	ulint		type;	ulint		cmpl_info;	mtr_t		mtr;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&(purge_sys->mutex)));#endif /* UNIV_SYNC_DEBUG */	ut_ad(purge_sys->next_stored);	space = purge_sys->rseg->space;	page_no = purge_sys->page_no;	offset = purge_sys->offset;	if (offset == 0) {		/* It is the dummy undo log record, which means that there is		no need to purge this undo log */		trx_purge_rseg_get_next_history_log(purge_sys->rseg);			/* Look for the next undo log and record to purge */		trx_purge_choose_next_log();		return(&trx_purge_dummy_rec);	}				mtr_start(&mtr);	undo_page = trx_undo_page_get_s_latched(space, page_no, &mtr);	rec = undo_page + offset;	rec2 = rec;	for (;;) {		/* Try first to find the next record which requires a purge		operation from the same page of the same undo log */			next_rec = trx_undo_page_get_next_rec(rec2,						purge_sys->hdr_page_no,						purge_sys->hdr_offset);		if (next_rec == NULL) {			rec2 = trx_undo_get_next_rec(rec2,						purge_sys->hdr_page_no,						purge_sys->hdr_offset, &mtr);			break;		}		rec2 = next_rec;				type = trx_undo_rec_get_type(rec2);		if (type == TRX_UNDO_DEL_MARK_REC) {			break;		}	    				cmpl_info = trx_undo_rec_get_cmpl_info(rec2);		if (trx_undo_rec_get_extern_storage(rec2)) {			break;		}				if ((type == TRX_UNDO_UPD_EXIST_REC)				&& !(cmpl_info & UPD_NODE_NO_ORD_CHANGE)) {	    	    	break;	   	}	}	if (rec2 == NULL) {		mtr_commit(&mtr);				trx_purge_rseg_get_next_history_log(purge_sys->rseg);			/* Look for the next undo log and record to purge */		trx_purge_choose_next_log();				mtr_start(&mtr);		undo_page = trx_undo_page_get_s_latched(space, page_no, &mtr);		rec = undo_page + offset;	} else {		page = buf_frame_align(rec2);				purge_sys->purge_undo_no = trx_undo_rec_get_undo_no(rec2);		purge_sys->page_no = buf_frame_get_page_no(page);		purge_sys->offset = rec2 - page;		if (undo_page != page) {			/* We advance to a new page of the undo log: */			purge_sys->n_pages_handled++;		}	}		rec_copy = trx_undo_rec_copy(rec, heap);	mtr_commit(&mtr);	return(rec_copy);}/************************************************************************Fetches the next undo log record from the history list to purge. It must bereleased with the corresponding release function. */trx_undo_rec_t*trx_purge_fetch_next_rec(/*=====================*/				/* out: copy of an undo log record or				pointer to the dummy undo log record				&trx_purge_dummy_rec, if the whole undo log				can skipped in purge; NULL if none left */	dulint*		roll_ptr,/* out: roll pointer to undo record */	trx_undo_inf_t** cell,	/* out: storage cell for the record in the				purge array */	mem_heap_t*	heap)	/* in: memory heap where copied */{	trx_undo_rec_t*	undo_rec;		mutex_enter(&(purge_sys->mutex));	if (purge_sys->state == TRX_STOP_PURGE) {		trx_purge_truncate_if_arr_empty();		mutex_exit(&(purge_sys->mutex));		return(NULL);	}	if (!purge_sys->next_stored) {		trx_purge_choose_next_log();		if (!purge_sys->next_stored) {			purge_sys->state = TRX_STOP_PURGE;				trx_purge_truncate_if_arr_empty();			if (srv_print_thread_releases) {				fprintf(stderr,	"Purge: No logs left in the history list; pages handled %lu\n",					(ulong) purge_sys->n_pages_handled);			}			mutex_exit(&(purge_sys->mutex));			return(NULL);		}				}		if (purge_sys->n_pages_handled >= purge_sys->handle_limit) {		purge_sys->state = TRX_STOP_PURGE;			trx_purge_truncate_if_arr_empty();		mutex_exit(&(purge_sys->mutex));		return(NULL);	}			if (ut_dulint_cmp(purge_sys->purge_trx_no,				purge_sys->view->low_limit_no) >= 0) {		purge_sys->state = TRX_STOP_PURGE;			trx_purge_truncate_if_arr_empty();		mutex_exit(&(purge_sys->mutex));		return(NULL);	}		/*	fprintf(stderr, "Thread %lu purging trx %lu undo record %lu\n",		os_thread_get_curr_id(),		ut_dulint_get_low(purge_sys->purge_trx_no),		ut_dulint_get_low(purge_sys->purge_undo_no)); */	*roll_ptr = trx_undo_build_roll_ptr(FALSE, (purge_sys->rseg)->id,							purge_sys->page_no,							purge_sys->offset);	*cell = trx_purge_arr_store_info(purge_sys->purge_trx_no,					 purge_sys->purge_undo_no);	ut_ad(ut_dulint_cmp(purge_sys->purge_trx_no,			    (purge_sys->view)->low_limit_no) < 0);		/* The following call will advance the stored values of purge_trx_no	and purge_undo_no, therefore we had to store them first */		undo_rec = trx_purge_get_next_rec(heap);	mutex_exit(&(purge_sys->mutex));	return(undo_rec);}/***********************************************************************Releases a reserved purge undo record. */voidtrx_purge_rec_release(/*==================*/	trx_undo_inf_t*	cell)	/* in: storage cell */{	trx_undo_arr_t*	arr;		mutex_enter(&(purge_sys->mutex));	arr = purge_sys->arr;	trx_purge_arr_remove_info(cell);	mutex_exit(&(purge_sys->mutex));}/***********************************************************************This function runs a purge batch. */ulinttrx_purge(void)/*===========*/				/* out: number of undo log pages handled in				the batch */{	que_thr_t*	thr;/*	que_thr_t*	thr2; */	ulint		old_pages_handled;	mutex_enter(&(purge_sys->mutex));	if (purge_sys->trx->n_active_thrs > 0) {			mutex_exit(&(purge_sys->mutex));		/* Should not happen */		ut_error;				return(0);	}			rw_lock_x_lock(&(purge_sys->latch));	mutex_enter(&kernel_mutex);	/* Close and free the old purge view */		read_view_close(purge_sys->view);	purge_sys->view = NULL;	mem_heap_empty(purge_sys->heap);	/* Determine how much data manipulation language (DML) statements	need to be delayed in order to reduce the lagging of the purge	thread. */	srv_dml_needed_delay = 0; /* in microseconds; default: no delay */	/* If we cannot advance the 'purge view' because of an old	'consistent read view', then the DML statements cannot be delayed.	Also, srv_max_purge_lag <= 0 means 'infinity'. */	if (srv_max_purge_lag > 0			&& !UT_LIST_GET_LAST(trx_sys->view_list)) {		float	ratio = (float) trx_sys->rseg_history_len				/ srv_max_purge_lag;		if (ratio > ULINT_MAX / 10000) {			/* Avoid overflow: maximum delay is 4295 seconds */			srv_dml_needed_delay = ULINT_MAX;		} else if (ratio > 1) {			/* If the history list length exceeds the			innodb_max_purge_lag, the			data manipulation statements are delayed			by at least 5000 microseconds. */			srv_dml_needed_delay = (ulint) ((ratio - .5) * 10000);		}	}	purge_sys->view = read_view_oldest_copy_or_open_new(NULL,							purge_sys->heap);	mutex_exit(&kernel_mutex);		rw_lock_x_unlock(&(purge_sys->latch));	purge_sys->state = TRX_PURGE_ON;			/* Handle at most 20 undo log pages in one purge batch */	purge_sys->handle_limit = purge_sys->n_pages_handled + 20;	old_pages_handled = purge_sys->n_pages_handled;	mutex_exit(&(purge_sys->mutex));	mutex_enter(&kernel_mutex);	thr = que_fork_start_command(purge_sys->query);	ut_ad(thr);	/*	thr2 = que_fork_start_command(purge_sys->query);		ut_ad(thr2); */		mutex_exit(&kernel_mutex);/*	srv_que_task_enqueue(thr2); */	if (srv_print_thread_releases) {			fputs("Starting purge\n", stderr);	}	que_run_threads(thr);	if (srv_print_thread_releases) {		fprintf(stderr,		"Purge ends; pages handled %lu\n",		(ulong) purge_sys->n_pages_handled);	}	return(purge_sys->n_pages_handled - old_pages_handled);}/**********************************************************************Prints information of the purge system to stderr. */voidtrx_purge_sys_print(void)/*=====================*/{	fprintf(stderr, "InnoDB: Purge system view:\n");	read_view_print(purge_sys->view);	fprintf(stderr, "InnoDB: Purge trx n:o %lu %lu, undo n_o %lu %lu\n",			(ulong) ut_dulint_get_high(purge_sys->purge_trx_no),			(ulong) ut_dulint_get_low(purge_sys->purge_trx_no),			(ulong) ut_dulint_get_high(purge_sys->purge_undo_no),			(ulong) ut_dulint_get_low(purge_sys->purge_undo_no));	fprintf(stderr,	"InnoDB: Purge next stored %lu, page_no %lu, offset %lu,\n"	"InnoDB: Purge hdr_page_no %lu, hdr_offset %lu\n",		(ulong) purge_sys->next_stored,		(ulong) purge_sys->page_no,		(ulong) purge_sys->offset,		(ulong) purge_sys->hdr_page_no,		(ulong) purge_sys->hdr_offset);}

⌨️ 快捷键说明

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