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

📄 lock0lock.c

📁 这是linux下运行的mysql软件包,可用于linux 下安装 php + mysql + apach 的网络配置
💻 C
📖 第 1 页 / 共 5 页
字号:
	lock->trx = trx;	lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC;	lock->index = index;		lock->un_member.rec_lock.space = space;	lock->un_member.rec_lock.page_no = page_no;	lock->un_member.rec_lock.n_bits = n_bytes * 8;	/* Reset to zero the bitmap which resides immediately after the	lock struct */	lock_rec_bitmap_reset(lock);	/* Set the bit corresponding to rec */	lock_rec_set_nth_bit(lock, heap_no);	HASH_INSERT(lock_t, hash, lock_sys->rec_hash,					lock_rec_fold(space, page_no), lock);	if (type_mode & LOCK_WAIT) {		lock_set_lock_and_trx_wait(lock, trx);	}		return(lock);}/*************************************************************************Enqueues a waiting request for a lock which cannot be granted immediately.Checks for deadlocks. */staticulintlock_rec_enqueue_waiting(/*=====================*/				/* out: DB_LOCK_WAIT, DB_DEADLOCK, or				DB_QUE_THR_SUSPENDED, or DB_SUCCESS;				DB_SUCCESS means that there was a deadlock,				but another transaction was chosen as a				victim, and we got the lock immediately:				no need to wait then */	ulint		type_mode,/* in: lock mode this transaction is				requesting: LOCK_S or LOCK_X, possibly ORed				with LOCK_GAP or LOCK_REC_NOT_GAP, ORed				with LOCK_INSERT_INTENTION if this waiting				lock request is set when performing an				insert of an index record */	rec_t*		rec,	/* in: record */	dict_index_t*	index,	/* in: index of record */	que_thr_t*	thr)	/* in: query thread */{	lock_t*	lock;	trx_t*	trx;	#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	/* Test if there already is some other reason to suspend thread:	we do not enqueue a lock request if the query thread should be	stopped anyway */	if (que_thr_stop(thr)) {		ut_error;		return(DB_QUE_THR_SUSPENDED);	}			trx = thr_get_trx(thr);	if (trx->dict_operation) {		ut_print_timestamp(stderr);		fputs("  InnoDB: Error: a record lock wait happens in a dictionary operation!\n""InnoDB: Table name ", stderr);		ut_print_name(stderr, trx, index->table_name);		fputs(".\n""InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n",			stderr);	}		/* Enqueue the lock request that will wait to be granted */	lock = lock_rec_create(type_mode | LOCK_WAIT, rec, index, trx);	/* Check if a deadlock occurs: if yes, remove the lock request and	return an error code */		if (lock_deadlock_occurs(lock, trx)) {		lock_reset_lock_and_trx_wait(lock);		lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec,					page_rec_is_comp(rec)));		return(DB_DEADLOCK);	}	/* If there was a deadlock but we chose another transaction as a	victim, it is possible that we already have the lock now granted! */	if (trx->wait_lock == NULL) {		return(DB_SUCCESS);	}	trx->que_state = TRX_QUE_LOCK_WAIT;	trx->was_chosen_as_deadlock_victim = FALSE;	trx->wait_started = time(NULL);	ut_a(que_thr_stop(thr));#ifdef UNIV_DEBUG	if (lock_print_waits) {		fprintf(stderr, "Lock wait for trx %lu in index ",			(ulong) ut_dulint_get_low(trx->id));		ut_print_name(stderr, trx, index->name);	}#endif /* UNIV_DEBUG */		return(DB_LOCK_WAIT);	}/*************************************************************************Adds a record lock request in the record queue. The request is normallyadded as the last in the queue, but if there are no waiting lock requestson the record, and the request to be added is not a waiting request, wecan reuse a suitable record lock object already existing on the same page,just setting the appropriate bit in its bitmap. This is a low-level functionwhich does NOT check for deadlocks or lock compatibility! */staticlock_t*lock_rec_add_to_queue(/*==================*/				/* out: lock where the bit was set, NULL if out				of memory */	ulint		type_mode,/* in: lock mode, wait, gap etc. flags;				type is ignored and replaced by LOCK_REC */	rec_t*		rec,	/* in: record on page */	dict_index_t*	index,	/* in: index of record */	trx_t*		trx)	/* in: transaction */{	lock_t*	lock;	lock_t*	similar_lock	= NULL;	ulint	heap_no;	ibool	somebody_waits	= FALSE;	#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))	      || ((type_mode & LOCK_MODE_MASK) != LOCK_S)	      || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,					rec, trx));	ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))	      || ((type_mode & LOCK_MODE_MASK) != LOCK_X)	      || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,					rec, trx));	type_mode = type_mode | LOCK_REC;	/* If rec is the supremum record, then we can reset the gap bit, as	all locks on the supremum are automatically of the gap type, and we	try to avoid unnecessary memory consumption of a new record lock	struct for a gap type lock */	if (page_rec_is_supremum(rec)) {		ut_ad(!(type_mode & LOCK_REC_NOT_GAP));		/* There should never be LOCK_REC_NOT_GAP on a supremum		record, but let us play safe */				type_mode = type_mode & ~(LOCK_GAP | LOCK_REC_NOT_GAP);	}	/* Look for a waiting lock request on the same record or on a gap */	heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));	lock = lock_rec_get_first_on_page(rec);	while (lock != NULL) {		if (lock_get_wait(lock)				&& (lock_rec_get_nth_bit(lock, heap_no))) {			somebody_waits = TRUE;		}		lock = lock_rec_get_next_on_page(lock);	}	/* Look for a similar record lock on the same page: if one is found	and there are no waiting lock requests, we can just set the bit */	similar_lock = lock_rec_find_similar_on_page(type_mode, rec, trx);	if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {		lock_rec_set_nth_bit(similar_lock, heap_no);		return(similar_lock);	}	return(lock_rec_create(type_mode, rec, index, trx));}/*************************************************************************This is a fast routine for locking a record in the most common cases:there are no explicit locks on the page, or there is just one lock, ownedby this transaction, and of the right type_mode. This is a low-level functionwhich does NOT look at implicit locks! Checks lock compatibility withinexplicit locks. This function sets a normal next-key lock, or in the case ofa page supremum record, a gap type lock. */UNIV_INLINEiboollock_rec_lock_fast(/*===============*/				/* out: TRUE if locking succeeded */	ibool		impl,	/* in: if TRUE, no lock is set if no wait				is necessary: we assume that the caller will				set an implicit lock */	ulint		mode,	/* in: lock mode: LOCK_X or LOCK_S possibly				ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */	rec_t*		rec,	/* in: record */	dict_index_t*	index,	/* in: index of record */	que_thr_t* 	thr)	/* in: query thread */{	lock_t*	lock;	ulint	heap_no;	trx_t*  trx;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	ut_ad((LOCK_MODE_MASK & mode) != LOCK_S		|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));	ut_ad((LOCK_MODE_MASK & mode) != LOCK_X		|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));	ut_ad((LOCK_MODE_MASK & mode) == LOCK_S		|| (LOCK_MODE_MASK & mode) == LOCK_X);	ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP			|| mode - (LOCK_MODE_MASK & mode) == 0			|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);				heap_no = rec_get_heap_no(rec, page_rec_is_comp(rec));		lock = lock_rec_get_first_on_page(rec);	trx = thr_get_trx(thr);	if (lock == NULL) {		if (!impl) {			lock_rec_create(mode, rec, index, trx);						if (srv_locks_unsafe_for_binlog) {				trx_register_new_rec_lock(trx, index);			}		}				return(TRUE);	}		if (lock_rec_get_next_on_page(lock)) {		return(FALSE);	}	if (lock->trx != trx	    || lock->type_mode != (mode | LOCK_REC)	    || lock_rec_get_n_bits(lock) <= heap_no) {	    	return(FALSE);	}	if (!impl) {		/* If the nth bit of the record lock is already set then we		do not set a new lock bit, otherwise we do set */		if (!lock_rec_get_nth_bit(lock, heap_no)) {			lock_rec_set_nth_bit(lock, heap_no);			if (srv_locks_unsafe_for_binlog) {				trx_register_new_rec_lock(trx, index);			}		}	}	return(TRUE);}/*************************************************************************This is the general, and slower, routine for locking a record. This is alow-level function which does NOT look at implicit locks! Checks lockcompatibility within explicit locks. This function sets a normal next-keylock, or in the case of a page supremum record, a gap type lock. */staticulintlock_rec_lock_slow(/*===============*/				/* out: DB_SUCCESS, DB_LOCK_WAIT, or error				code */	ibool		impl,	/* in: if TRUE, no lock is set if no wait is				necessary: we assume that the caller will set				an implicit lock */	ulint		mode,	/* in: lock mode: LOCK_X or LOCK_S possibly				ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */	rec_t*		rec,	/* in: record */	dict_index_t*	index,	/* in: index of record */	que_thr_t* 	thr)	/* in: query thread */{	trx_t*	trx;	ulint	err;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	ut_ad((LOCK_MODE_MASK & mode) != LOCK_S		|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));	ut_ad((LOCK_MODE_MASK & mode) != LOCK_X		|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));	ut_ad((LOCK_MODE_MASK & mode) == LOCK_S		|| (LOCK_MODE_MASK & mode) == LOCK_X);	ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP			|| mode - (LOCK_MODE_MASK & mode) == 0			|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);				trx = thr_get_trx(thr);			if (lock_rec_has_expl(mode, rec, trx)) {		/* The trx already has a strong enough lock on rec: do		nothing */		err = DB_SUCCESS;	} else if (lock_rec_other_has_conflicting(mode, rec, trx)) {		/* If another transaction has a non-gap conflicting request in		the queue, as this transaction does not have a lock strong		enough already granted on the record, we have to wait. */    						err = lock_rec_enqueue_waiting(mode, rec, index, thr);		if (srv_locks_unsafe_for_binlog) {			trx_register_new_rec_lock(trx, index);		}	} else {		if (!impl) {			/* Set the requested lock on the record */			lock_rec_add_to_queue(LOCK_REC | mode, rec, index,									trx);			if (srv_locks_unsafe_for_binlog) {				trx_register_new_rec_lock(trx, index);			}		}		err = DB_SUCCESS;	}	return(err);}/*************************************************************************Tries to lock the specified record in the mode requested. If not immediatelypossible, enqueues a waiting lock request. This is a low-level functionwhich does NOT look at implicit locks! Checks lock compatibility withinexplicit locks. This function sets a normal next-key lock, or in the caseof a page supremum record, a gap type lock. */staticulintlock_rec_lock(/*==========*/				/* out: DB_SUCCESS, DB_LOCK_WAIT, or error				code */	ibool		impl,	/* in: if TRUE, no lock is set if no wait is				necessary: we assume that the caller will set				an implicit lock */	ulint		mode,	/* in: lock mode: LOCK_X or LOCK_S possibly				ORed to either LOCK_GAP or LOCK_REC_NOT_GAP */	rec_t*		rec,	/* in: record */	dict_index_t*	index,	/* in: index of record */	que_thr_t* 	thr)	/* in: query thread */{	ulint	err;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */	ut_ad((LOCK_MODE_MASK & mode) != LOCK_S		|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));	ut_ad((LOCK_MODE_MASK & mode) != LOCK_X		|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));	ut_ad((LOCK_MODE_MASK & mode) == LOCK_S		|| (LOCK_MODE_MASK & mode) == LOCK_X);	ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP			|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP			|| mode - (LOCK_MODE_MASK & mode) == 0);				if (lock_rec_lock_fast(impl, mode, rec, index, thr)) {		/* We try a simplified and faster subroutine for the most		common cases */		err = DB_SUCCESS;	} else {		err = lock_rec_lock_slow(impl, mode, rec, index, thr);	}	return(err);}/*************************************************************************Checks if a waiting record lock request still has to wait in a queue. */staticiboollock_rec_has_to_wait_in_queue(/*==========================*/				/* out: TRUE if still has to wait */	lock_t*	wait_lock)	/* in: waiting record lock */{	lock_t*	lock;	ulint	space;	ulint	page_no;	ulint	heap_no;#ifdef UNIV_SYNC_DEBUG	ut_ad(mutex_own(&kernel_mutex));#endif /* UNIV_SYNC_DEBUG */ 	ut_ad(lock_get_wait(wait_lock));	ut_ad(lock_get_type(wait_lock) == LOCK_REC); 		space = wait_lock->un_member.rec_lock.space;	page_no = wait_lock->un_member.rec_lock.page_no;	heap_no = lock_rec_find_set_bit(wait_lock);	lock = lock_rec_get_first_on_page_addr(space, page_no);	while (lock != wait_lock) {		if (lock_rec_get_nth_bit(lock, heap_no)		    && lock_has_to_wait(wait_lock, lock)) 

⌨️ 快捷键说明

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