mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 15:50:51 +03:00 
			
		
		
		
	- n_ext value may be less than dtuple_get_n_ext(dtuple) when PK is being updated and new record inherits the externally stored fields from delete mark old record.
		
			
				
	
	
		
			216 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| # Bug#13721257 RACE CONDITION IN UPDATES OR INSERTS OF WIDE RECORDS
 | |
| # Test what happens when a record is inserted or updated so that some
 | |
| # columns are stored off-page.
 | |
| 
 | |
| --source include/have_innodb.inc
 | |
| # The 7000 in this test is a bit less than half the innodb_page_size.
 | |
| --source include/have_innodb_16k.inc
 | |
| 
 | |
| --source include/have_debug.inc
 | |
| --source include/have_debug_sync.inc
 | |
| 
 | |
| # Embedded server does not support restarting
 | |
| --source include/not_embedded.inc
 | |
| 
 | |
| FLUSH TABLES;
 | |
| 
 | |
| CREATE TABLE t1 (a INT PRIMARY KEY, b TEXT) ENGINE=InnoDB;
 | |
| CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=InnoDB;
 | |
| CREATE TABLE t3 (a INT PRIMARY KEY, b TEXT, c TEXT) ENGINE=InnoDB;
 | |
| 
 | |
| INSERT INTO t1 VALUES (1,REPEAT('a',30000)),(2,REPEAT('b',40000));
 | |
| SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR go1';
 | |
| BEGIN;
 | |
| # This will not block, because it will not store new BLOBs.
 | |
| UPDATE t1 SET a=a+2;
 | |
| ROLLBACK;
 | |
| BEGIN;
 | |
| --send
 | |
| UPDATE t1 SET b=CONCAT(b,'foo');
 | |
| 
 | |
| connect (con1,localhost,root,,);
 | |
| SET DEBUG_SYNC='now WAIT_FOR have_latch';
 | |
| 
 | |
| # this one should block due to the clustered index tree and leaf page latches
 | |
| --send
 | |
| SELECT a, RIGHT(b,20) FROM t1;
 | |
| 
 | |
| connect (con2,localhost,root,,);
 | |
| 
 | |
| # Check that the above SELECT is blocked
 | |
| let $wait_condition=
 | |
|   select count(*) = 1 from information_schema.processlist
 | |
|   where state in ('Sending data', 'Opening tables') and
 | |
|         info = 'SELECT a, RIGHT(b,20) FROM t1';
 | |
| --source include/wait_condition.inc
 | |
| 
 | |
| SET DEBUG_SYNC='now SIGNAL go1';
 | |
| 
 | |
| connection con1;
 | |
| reap;
 | |
| connection default;
 | |
| reap;
 | |
| SET DEBUG='+d,row_ins_extern_checkpoint';
 | |
| SET DEBUG_SYNC='before_row_ins_extern_latch SIGNAL rec_not_blob WAIT_FOR crash';
 | |
| ROLLBACK;
 | |
| BEGIN;
 | |
| --send
 | |
| INSERT INTO t1 VALUES (3,REPEAT('c',50000));
 | |
| 
 | |
| connection con1;
 | |
| SET DEBUG_SYNC='now WAIT_FOR rec_not_blob';
 | |
| SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
 | |
| SELECT @@tx_isolation;
 | |
| 
 | |
| # this one should see (3,NULL_BLOB)
 | |
| SELECT a, RIGHT(b,20) FROM t1;
 | |
| SELECT a FROM t1;
 | |
| 
 | |
| # Request a crash, and restart the server.
 | |
| BEGIN;
 | |
| INSERT INTO t2 VALUES (42);
 | |
| 
 | |
| --let $shutdown_timeout=0
 | |
| --source include/restart_mysqld.inc
 | |
| 
 | |
| disconnect con1;
 | |
| disconnect con2;
 | |
| connection default;
 | |
| # This connection should notice the crash as well.
 | |
| --error 2013
 | |
| reap;
 | |
| 
 | |
| --enable_reconnect
 | |
| --source include/wait_until_connected_again.inc
 | |
| --disable_reconnect
 | |
| 
 | |
| CHECK TABLE t1;
 | |
| 
 | |
| INSERT INTO t3 VALUES
 | |
|        (1,REPEAT('d',7000),REPEAT('e',100)),
 | |
|        (2,REPEAT('g',7000),REPEAT('h',100));
 | |
| SET DEBUG_SYNC='blob_write_middle SIGNAL go_sel WAIT_FOR go_upd';
 | |
| # This should move column b off-page.
 | |
| --send
 | |
| UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1;
 | |
| 
 | |
| --echo # Connection con1:
 | |
| connect (con1,localhost,root,,);
 | |
| SET DEBUG_SYNC='now WAIT_FOR go_sel';
 | |
| SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
 | |
| SELECT @@tx_isolation;
 | |
| SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
 | |
| set debug_sync='now SIGNAL go_upd';
 | |
| 
 | |
| --echo # Connection default:
 | |
| connection default;
 | |
| --echo # reap UPDATE t3 SET c=REPEAT('f',3000) WHERE a=1;
 | |
| reap;
 | |
| 
 | |
| --echo # Connection con1:
 | |
| connection con1;
 | |
| SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
 | |
| 
 | |
| disconnect con1;
 | |
| 
 | |
| connection default;
 | |
| CHECK TABLE t1,t2,t3;
 | |
| 
 | |
| connect (con2,localhost,root,,);
 | |
| BEGIN;
 | |
| INSERT INTO t2 VALUES (347);
 | |
| connection default;
 | |
| 
 | |
| # The row_upd_extern_checkpoint was removed in Bug#13721257,
 | |
| # because the mini-transaction of the B-tree modification would
 | |
| # remain open while we are writing the off-page columns and are
 | |
| # stuck in the DEBUG_SYNC. A checkpoint involves a flush, which
 | |
| # would wait for the buffer-fix to cease.
 | |
| SET DEBUG='+d,row_upd_extern_checkpoint';
 | |
| SET DEBUG_SYNC='before_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
 | |
| # This should move column b off-page.
 | |
| --send
 | |
| UPDATE t3 SET c=REPEAT('i',3000) WHERE a=2;
 | |
| 
 | |
| connection con2;
 | |
| SET DEBUG_SYNC='now WAIT_FOR have_latch';
 | |
| 
 | |
| # Check that the above UPDATE is blocked
 | |
| SELECT info FROM information_schema.processlist
 | |
| WHERE state = 'debug sync point: before_row_upd_extern';
 | |
| 
 | |
| connect (con3,localhost,root,,);
 | |
| SET GLOBAL innodb_flush_log_at_trx_commit=1;
 | |
| DELETE FROM t1;
 | |
| ROLLBACK;
 | |
| disconnect con3;
 | |
| 
 | |
| connection con2;
 | |
| 
 | |
| --let $shutdown_timeout=0
 | |
| --source include/restart_mysqld.inc
 | |
| 
 | |
| disconnect con2;
 | |
| connection default;
 | |
| # This connection should notice the crash as well.
 | |
| --error 2013
 | |
| reap;
 | |
| 
 | |
| --enable_reconnect
 | |
| --source include/wait_until_connected_again.inc
 | |
| --disable_reconnect
 | |
| 
 | |
| CHECK TABLE t1,t2,t3;
 | |
| SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
 | |
| SELECT a FROM t3;
 | |
| 
 | |
| connect (con2,localhost,root,,);
 | |
| BEGIN;
 | |
| INSERT INTO t2 VALUES (33101);
 | |
| connection default;
 | |
| 
 | |
| # The row_upd_extern_checkpoint was removed in Bug#13721257,
 | |
| # because the mini-transaction of the B-tree modification would
 | |
| # remain open while we are writing the off-page columns and are
 | |
| # stuck in the DEBUG_SYNC. A checkpoint involves a flush, which
 | |
| # would wait for the buffer-fix to cease.
 | |
| SET DEBUG='+d,row_upd_extern_checkpoint';
 | |
| SET DEBUG_SYNC='after_row_upd_extern SIGNAL have_latch WAIT_FOR crash';
 | |
| # This should move column b off-page.
 | |
| --send
 | |
| UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2;
 | |
| 
 | |
| connection con2;
 | |
| SET DEBUG_SYNC='now WAIT_FOR have_latch';
 | |
| 
 | |
| # Check that the above UPDATE is blocked
 | |
| SELECT info FROM information_schema.processlist
 | |
| WHERE state = 'debug sync point: after_row_upd_extern';
 | |
| 
 | |
| --let $shutdown_timeout=0
 | |
| --source include/restart_mysqld.inc
 | |
| 
 | |
| disconnect con2;
 | |
| connection default;
 | |
| # This connection should notice the crash as well.
 | |
| --error 2013
 | |
| reap;
 | |
| 
 | |
| --enable_reconnect
 | |
| --source include/wait_until_connected_again.inc
 | |
| --disable_reconnect
 | |
| CHECK TABLE t1,t2,t3;
 | |
| SELECT a, RIGHT(b,20), RIGHT(c,20) FROM t3;
 | |
| SELECT a FROM t3;
 | |
| 
 | |
| SELECT * FROM t2;
 | |
| 
 | |
| DROP TABLE t1,t2,t3;
 | |
| 
 | |
| CREATE TABLE t1(f1 INT PRIMARY KEY, f2 TEXT)ENGINE=InnoDB
 | |
| 		ROW_FORMAT=REDUNDANT;
 | |
| SET @fill_amount = (@@innodb_page_size / 2 ) + 1 ;
 | |
| INSERT INTO t1 VALUES(1, REPEAT(2, @fill_amount));
 | |
| UPDATE t1 SET f1 = 2;
 | |
| DROP TABLE t1;
 |