Skip to content
  • Annamalai Gurusami's avatar
    f452bbd8
    Bug #20005279 ASSERT !OTHER_LOCK, LOCK_MOVE_REORGANIZE_PAGE() · f452bbd8
    Annamalai Gurusami authored
    Problem:
    
    Consider a clustered index page P1 holding a record r1.  Let two
    sessions S1 and S2 operate on the page P1.  Let S1 hold an exclusive
    lock on r1.  Let S2 attempt to take an exclusive lock on r1.  Now
    there will be two locks L1 and L2 on the record r1.  Let L1 be the
    granted lock and L2 be the waiting lock.  Let S1 initiate a page
    reorganize of P1.  The locks will also be reorganized.  During this
    reorganize if the lock is reorganized in the order L2, L1 then the
    assert in function lock_rec_add_to_queue() fails.
    
    	if (!(type_mode & (LOCK_WAIT | LOCK_GAP))) {
    		lock_mode	mode = (type_mode & LOCK_MODE_MASK) == LOCK_S
    			? LOCK_X
    			: LOCK_S;
    		const lock_t*	other_lock
    			= lock_rec_other_has_expl_req(
    				mode, block, false, heap_no, trx);
    		ut_a(!other_lock);
    	}
    
    Notice the 3rd argument to lock_rec_other_has_expl_req().  We have
    requested that wait locks are not to be considered.  Even then the
    assert has failed.
    
    Solution:
    
    There seems to be problem in the if condition in function
    lock_rec_other_has_expl_req().
    
    		if (lock->trx != trx
    		    && !lock_rec_get_gap(lock)
    		    && (!wait || !lock_get_wait(lock))
    		    && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
    
    			return(lock);
    		}
    
    The truth table of the relevant expression is given below:
    
    lock_get_wait    wait    (!wait || !lock_get_wait)
    1                1                0
    1                0                1 =====>> CHECK?
    0                0                1
    0                1                1
    
    The correct one is as follows:
    
    lock_get_wait    wait    (wait || !lock_get_wait)
    1                1                1
    1                0                0
    0                0                1
    0                1                1
    
    The solution is to use the expression "(wait || !lock_get_wait)".
    
    Additional Change:
    
    While reorganizing the page, we can process the granted locks before
    processing the waiting locks.
    
    rb#9289 approved by Marko.
    f452bbd8
    Bug #20005279 ASSERT !OTHER_LOCK, LOCK_MOVE_REORGANIZE_PAGE()
    Annamalai Gurusami authored
    Problem:
    
    Consider a clustered index page P1 holding a record r1.  Let two
    sessions S1 and S2 operate on the page P1.  Let S1 hold an exclusive
    lock on r1.  Let S2 attempt to take an exclusive lock on r1.  Now
    there will be two locks L1 and L2 on the record r1.  Let L1 be the
    granted lock and L2 be the waiting lock.  Let S1 initiate a page
    reorganize of P1.  The locks will also be reorganized.  During this
    reorganize if the lock is reorganized in the order L2, L1 then the
    assert in function lock_rec_add_to_queue() fails.
    
    	if (!(type_mode & (LOCK_WAIT | LOCK_GAP))) {
    		lock_mode	mode = (type_mode & LOCK_MODE_MASK) == LOCK_S
    			? LOCK_X
    			: LOCK_S;
    		const lock_t*	other_lock
    			= lock_rec_other_has_expl_req(
    				mode, block, false, heap_no, trx);
    		ut_a(!other_lock);
    	}
    
    Notice the 3rd argument to lock_rec_other_has_expl_req().  We have
    requested that wait locks are not to be considered.  Even then the
    assert has failed.
    
    Solution:
    
    There seems to be problem in the if condition in function
    lock_rec_other_has_expl_req().
    
    		if (lock->trx != trx
    		    && !lock_rec_get_gap(lock)
    		    && (!wait || !lock_get_wait(lock))
    		    && lock_mode_stronger_or_eq(lock_get_mode(lock), mode)) {
    
    			return(lock);
    		}
    
    The truth table of the relevant expression is given below:
    
    lock_get_wait    wait    (!wait || !lock_get_wait)
    1                1                0
    1                0                1 =====>> CHECK?
    0                0                1
    0                1                1
    
    The correct one is as follows:
    
    lock_get_wait    wait    (wait || !lock_get_wait)
    1                1                1
    1                0                0
    0                0                1
    0                1                1
    
    The solution is to use the expression "(wait || !lock_get_wait)".
    
    Additional Change:
    
    While reorganizing the page, we can process the granted locks before
    processing the waiting locks.
    
    rb#9289 approved by Marko.
Loading