@ -1733,11 +1733,11 @@ lock_rec_create(
Enqueues a waiting request for a lock which cannot be granted immediately .
Checks for deadlocks .
@ return 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 */
DB_SUCCESS_LOCKED_REC ; DB_SUCCESS_LOCKED_REC 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 */
static
ulint
enum db_err
lock_rec_enqueue_waiting (
/*=====================*/
ulint type_mode , /*!< in: lock mode this
@ -1809,7 +1809,7 @@ lock_rec_enqueue_waiting(
if ( trx - > wait_lock = = NULL ) {
return ( DB_SUCCESS ) ;
return ( DB_SUCCESS_LOCKED_REC ) ;
}
trx - > que_state = TRX_QUE_LOCK_WAIT ;
@ -1925,6 +1925,16 @@ somebody_waits:
return ( lock_rec_create ( type_mode , block , heap_no , index , trx ) ) ;
}
/** Record locking request status */
enum lock_rec_req_status {
/** Failed to acquire a lock */
LOCK_REC_FAIL ,
/** Succeeded in acquiring a lock (implicit or already acquired) */
LOCK_REC_SUCCESS ,
/** Explicitly created a new lock */
LOCK_REC_SUCCESS_CREATED
} ;
/*********************************************************************/ /**
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 , owned
@ -1932,9 +1942,9 @@ by this transaction, and of the right type_mode. This is a low-level function
which does NOT look at implicit locks ! Checks lock compatibility within
explicit locks . This function sets a normal next - key lock , or in the case of
a page supremum record , a gap type lock .
@ return TRUE if locking succeeded */
@ return whether the locking succeeded */
UNIV_INLINE
ibool
enum lock_rec_req_status
lock_rec_lock_fast (
/*===============*/
ibool impl , /*!< in: if TRUE, no lock is set
@ -1973,19 +1983,19 @@ lock_rec_lock_fast(
lock_rec_create ( mode , block , heap_no , index , trx ) ;
}
return ( TRUE ) ;
return ( LOCK_REC_SUCCESS_CREATED ) ;
}
if ( lock_rec_get_next_on_page ( lock ) ) {
return ( FALSE ) ;
return ( LOCK_REC_ FAI L) ;
}
if ( lock - > trx ! = trx
| | lock - > type_mode ! = ( mode | LOCK_REC )
| | lock_rec_get_n_bits ( lock ) < = heap_no ) {
return ( FALSE ) ;
return ( LOCK_REC_ FAI L) ;
}
if ( ! impl ) {
@ -1994,10 +2004,11 @@ lock_rec_lock_fast(
if ( ! lock_rec_get_nth_bit ( lock , heap_no ) ) {
lock_rec_set_nth_bit ( lock , heap_no ) ;
return ( LOCK_REC_SUCCESS_CREATED ) ;
}
}
return ( TRUE ) ;
return ( LOCK_REC_SUCCESS ) ;
}
/*********************************************************************/ /**
@ -2005,9 +2016,10 @@ This is the general, and slower, routine for locking a record. This is a
low - level function which does NOT look at implicit locks ! Checks lock
compatibility within explicit locks . This function sets a normal next - key
lock , or in the case of a page supremum record , a gap type lock .
@ return DB_SUCCESS , DB_LOCK_WAIT , or error code */
@ return DB_SUCCESS , DB_SUCCESS_LOCKED_REC , DB_LOCK_WAIT , DB_DEADLOCK ,
or DB_QUE_THR_SUSPENDED */
static
ulint
enum db_err
lock_rec_lock_slow (
/*===============*/
ibool impl , /*!< in: if TRUE, no lock is set
@ -2024,7 +2036,6 @@ lock_rec_lock_slow(
que_thr_t * thr ) /*!< in: query thread */
{
trx_t * trx ;
ulint err ;
ut_ad ( mutex_own ( & kernel_mutex ) ) ;
ut_ad ( ( LOCK_MODE_MASK & mode ) ! = LOCK_S
@ -2043,27 +2054,23 @@ lock_rec_lock_slow(
/* The trx already has a strong enough lock on rec: do
nothing */
err = DB_SUCCESS ;
} else if ( lock_rec_other_has_conflicting ( mode , block , heap_no , 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 , block , heap_no ,
index , thr ) ;
} else {
if ( ! impl ) {
/* Set the requested lock on the record */
return ( lock_rec_enqueue_waiting ( mode , block , heap_no ,
index , thr ) ) ;
} else if ( ! impl ) {
/* Set the requested lock on the record */
lock_rec_add_to_queue ( LOCK_REC | mode , block ,
heap_no , index , trx ) ;
}
err = DB_SUCCESS ;
lock_rec_add_to_queue ( LOCK_REC | mode , block ,
heap_no , index , trx ) ;
return ( DB_SUCCESS_LOCKED_REC ) ;
}
return ( err ) ;
return ( DB_SUCCESS ) ;
}
/*********************************************************************/ /**
@ -2072,9 +2079,10 @@ possible, enqueues a waiting lock request. This is a low-level function
which does NOT look at implicit locks ! Checks lock compatibility within
explicit locks . This function sets a normal next - key lock , or in the case
of a page supremum record , a gap type lock .
@ return DB_SUCCESS , DB_LOCK_WAIT , or error code */
@ return DB_SUCCESS , DB_SUCCESS_LOCKED_REC , DB_LOCK_WAIT , DB_DEADLOCK ,
or DB_QUE_THR_SUSPENDED */
static
ulint
enum db_err
lock_rec_lock (
/*==========*/
ibool impl , /*!< in: if TRUE, no lock is set
@ -2090,8 +2098,6 @@ lock_rec_lock(
dict_index_t * index , /*!< in: index of record */
que_thr_t * thr ) /*!< in: query thread */
{
ulint err ;
ut_ad ( mutex_own ( & kernel_mutex ) ) ;
ut_ad ( ( LOCK_MODE_MASK & mode ) ! = LOCK_S
| | lock_table_has ( thr_get_trx ( thr ) , index - > table , LOCK_IS ) ) ;
@ -2103,18 +2109,20 @@ lock_rec_lock(
| | mode - ( LOCK_MODE_MASK & mode ) = = LOCK_REC_NOT_GAP
| | mode - ( LOCK_MODE_MASK & mode ) = = 0 ) ;
if ( lock_rec_lock_fast ( impl , mode , block , heap_no , 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 , block ,
heap_no , index , thr ) ;
/* We try a simplified and faster subroutine for the most
common cases */
switch ( lock_rec_lock_fast ( impl , mode , block , heap_no , index , thr ) ) {
case LOCK_REC_SUCCESS :
return ( DB_SUCCESS ) ;
case LOCK_REC_SUCCESS_CREATED :
return ( DB_SUCCESS_LOCKED_REC ) ;
case LOCK_REC_FAIL :
return ( lock_rec_lock_slow ( impl , mode , block ,
heap_no , index , thr ) ) ;
}
return ( err ) ;
ut_error ;
return ( DB_ERROR ) ;
}
/*********************************************************************/ /**
@ -5072,7 +5080,14 @@ lock_rec_insert_check_and_lock(
lock_mutex_exit_kernel ( ) ;
if ( ( err = = DB_SUCCESS ) & & ! dict_index_is_clust ( index ) ) {
switch ( err ) {
case DB_SUCCESS_LOCKED_REC :
err = DB_SUCCESS ;
/* fall through */
case DB_SUCCESS :
if ( dict_index_is_clust ( index ) ) {
break ;
}
/* Update the page max trx id field */
page_update_max_trx_id ( block ,
buf_block_get_page_zip ( block ) ,
@ -5195,6 +5210,10 @@ lock_clust_rec_modify_check_and_lock(
ut_ad ( lock_rec_queue_validate ( block , rec , index , offsets ) ) ;
if ( UNIV_UNLIKELY ( err = = DB_SUCCESS_LOCKED_REC ) ) {
err = DB_SUCCESS ;
}
return ( err ) ;
}
@ -5261,22 +5280,27 @@ lock_sec_rec_modify_check_and_lock(
}
# endif /* UNIV_DEBUG */
if ( err = = DB_SUCCESS ) {
if ( err = = DB_SUCCESS | | err = = DB_SUCCESS_LOCKED_REC ) {
/* Update the page max trx id field */
/* It might not be necessary to do this if
err = = DB_SUCCESS ( no new lock created ) ,
but it should not cost too much performance . */
page_update_max_trx_id ( block ,
buf_block_get_page_zip ( block ) ,
thr_get_trx ( thr ) - > id , mtr ) ;
err = DB_SUCCESS ;
}
return ( err ) ;
}
/*********************************************************************/ /**
Like the counterpart for a clustered index below , but now we read a
Like lock_clust_rec_read_check_and_lock ( ) , but reads a
secondary index record .
@ return DB_SUCCESS , DB_LOCK_WAIT , DB_DEADLOCK , or DB_QUE_THR_SUSPENDED */
@ return DB_SUCCESS , DB_SUCCESS_LOCKED_REC , DB_LOCK_WAIT , DB_DEADLOCK ,
or DB_QUE_THR_SUSPENDED */
UNIV_INTERN
ulint
enum db_err
lock_sec_rec_read_check_and_lock (
/*=============================*/
ulint flags , /*!< in: if BTR_NO_LOCKING_FLAG
@ -5297,8 +5321,8 @@ lock_sec_rec_read_check_and_lock(
LOCK_REC_NOT_GAP */
que_thr_t * thr ) /*!< in: query thread */
{
ulint err ;
ulint heap_no ;
enum db_err err ;
ulint heap_no ;
ut_ad ( ! dict_index_is_clust ( index ) ) ;
ut_ad ( block - > frame = = page_align ( rec ) ) ;
@ -5349,9 +5373,10 @@ if the query thread should anyway be suspended for some reason; if not, then
puts the transaction and the query thread to the lock wait state and inserts a
waiting request for a record lock to the lock queue . Sets the requested mode
lock on the record .
@ return DB_SUCCESS , DB_LOCK_WAIT , DB_DEADLOCK , or DB_QUE_THR_SUSPENDED */
@ return DB_SUCCESS , DB_SUCCESS_LOCKED_REC , DB_LOCK_WAIT , DB_DEADLOCK ,
or DB_QUE_THR_SUSPENDED */
UNIV_INTERN
ulint
enum db_err
lock_clust_rec_read_check_and_lock (
/*===============================*/
ulint flags , /*!< in: if BTR_NO_LOCKING_FLAG
@ -5372,8 +5397,8 @@ lock_clust_rec_read_check_and_lock(
LOCK_REC_NOT_GAP */
que_thr_t * thr ) /*!< in: query thread */
{
ulint err ;
ulint heap_no ;
enum db_err err ;
ulint heap_no ;
ut_ad ( dict_index_is_clust ( index ) ) ;
ut_ad ( block - > frame = = page_align ( rec ) ) ;
@ -5444,17 +5469,22 @@ lock_clust_rec_read_check_and_lock_alt(
mem_heap_t * tmp_heap = NULL ;
ulint offsets_ [ REC_OFFS_NORMAL_SIZE ] ;
ulint * offsets = offsets_ ;
ulint ret ;
ulint err ;
rec_offs_init ( offsets_ ) ;
offsets = rec_get_offsets ( rec , index , offsets ,
ULINT_UNDEFINED , & tmp_heap ) ;
ret = lock_clust_rec_read_check_and_lock ( flags , block , rec , index ,
err = lock_clust_rec_read_check_and_lock ( flags , block , rec , index ,
offsets , mode , gap_mode , thr ) ;
if ( tmp_heap ) {
mem_heap_free ( tmp_heap ) ;
}
return ( ret ) ;
if ( UNIV_UNLIKELY ( err = = DB_SUCCESS_LOCKED_REC ) ) {
err = DB_SUCCESS ;
}
return ( err ) ;
}
/*******************************************************************/ /**