mariadb/mysql-test/suite/innodb/t/innodb-blob.test
Marko Mäkelä e8889c8002 MDEV-12745 InnoDB Assertion `0' failed at row0umod.cc:1181
row_undo_mod_parse_undo_rec(): Relax the too strict assertion and
correct the comment.

innodb.innodb-blob: Force a flush of the redo log right before
killing the server, to ensure that the code path gets exercised.
(The bogus debug assertion failed on the rollback of the statement
UPDATE t3 SET c=REPEAT('j',3000) WHERE a=2 which did not modify
any indexes before the server was killed.)
2017-05-09 10:00:49 +03:00

208 lines
5.6 KiB
Text

# 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
# DEBUG_SYNC must be compiled in.
--source include/have_debug_sync.inc
# Embedded server does not support restarting
--source include/not_embedded.inc
call mtr.add_suppression("InnoDB: The log sequence numbers [0-9]+ and [0-9]+ in ibdata files do not match the log sequence number [0-9]+ in the ib_logfiles!");
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;