• Marko Mäkelä's avatar
    MDEV-14906 Assertion index->is_instant() failed on DELETE · cb16bc95
    Marko Mäkelä authored
    The assertion would fail with the following trace:
    
    rec_init_offsets_comp_ordinary(..., format=REC_LEAF_COLUMNS_ADDED)
    rec_init_offsets()
    rec_get_offsets_func()
    rec_copy_prefix_to_dtuple()
    dict_index_build_data_tuple()
    btr_pcur_restore_position_func()
    
    When btr_cur_store_position() had stored pcur->old_rec, the table
    contained instantly added columns. The table was emptied
    (dict_index_t::remove_instant() invoked) between the 'store' and 'restore'
    operations, causing the assertion to fail. Here is a non-deterministic
    test case to repeat the scenario:
    
    	--source include/have_innodb.inc
    	--connect (con1,localhost,root,,test)
    	CREATE TABLE t1 (pk INT PRIMARY KEY) ENGINE = InnoDB;
    	INSERT INTO t1 VALUES (0);
    	ALTER TABLE t1 ADD COLUMN a INT;
    	ALTER TABLE t1 ADD UNIQUE KEY (a);
    	DELETE FROM t1;
    	send INSERT INTO t1 VALUES (1,0),(2,0);
    	--connection default
    	DELETE FROM t1; # the assertion could fail here
    	DROP TABLE t1;
    	--disconnect con1
    
    The fix is to normalize the pcur->old_rec so that when the
    record prefix is stored, it will always be in the plain format.
    This can be done, because the record prefix never includes any
    instantly added columns. (It can only include key columns, which
    can never be instantly added.)
    
    rec_copy_prefix_to_buf(): Convert REC_STATUS_COLUMNS_ADDED to
    REC_STATUS_ORDINARY format.
    cb16bc95
rem0rec.cc 71.5 KB