| Bug #75697 | Add a consistency check against DB_TRX_ID being in the future | ||
|---|---|---|---|
| Submitted: | 30 Jan 2015 12:28 | Modified: | 11 May 2015 13:25 |
| Reporter: | Marko Mäkelä | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: InnoDB storage engine | Severity: | S3 (Non-critical) |
| Version: | 3.23.53 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[30 Jan 2015 12:28]
Marko Mäkelä
[23 Feb 2015 12:27]
Marko Mäkelä
Posted by developer:
I reproduced this in MySQL 5.5.43. I am convinced that every InnoDB version is affected.
I created the following test as innodb.foo:
CREATE TABLE foo(a INT PRIMARY KEY)engine=innoDB;
INSERT INTO foo VALUES(1),(2),(3),(4),(5);
let MYSQLD_DATADIR=`select @@datadir`;
-- exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-- shutdown_server
-- source include/wait_until_disconnected.inc
perl;
my $file = "$ENV{MYSQLD_DATADIR}/ibdata1";
open(FILE, "+<", $file) || die "Unable to open $file";
seek(FILE, 5*16384+38+4, 0) || die "Unable to seek $file";
die unless read(FILE, $_, 4) == 4;
print "trx_id=", unpack("H*", $_), "\n";
seek(FILE, 5*16384+38, 0) || die "Unable to seek $file";
syswrite(FILE, pack("N*", 0, 0)) || die "Unable to write $file";
close(FILE)
EOF
-- exec echo "restart" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
-- enable_reconnect
-- source include/wait_until_connected_again.inc
-- disable_reconnect
SELECT * FROM foo;
DROP TABLE foo;
Then, run it as
./mtr --mysqld=--skip-innodb-checksums innodb.foo
The DROP TABLE will crash, because the transaction system is corrupted:
Version: '5.5.43-debug-log' socket: '/dev/shm/u/mysql-test/var/tmp/mysqld.1.sock' port: 13000 Source distribution
150223 15:21:10 InnoDB: Error: transaction id associated with record
PHYSICAL RECORD: n_fields 5; 1-byte offsets; info bits 32
0: len 8; hex 000000000000000f; asc ;;
1: len 4; hex 00000000; asc ;;
2: len 6; hex 000000000500; asc ;;
3: len 7; hex 810000012d014e; asc - N;;
4: len 1; hex 61; asc a;;
InnoDB: in index "CLUST_IND" of table "SYS_FIELDS"
InnoDB: is 500 which is higher than the global trx id counter 202!
InnoDB: The table is corrupt. You have to do dump + drop + reimport.
150223 15:21:10 InnoDB: Assertion failure in thread 140031783208704 in file row0upd.ic line 176
InnoDB: Failing assertion: lock_check_trx_id_sanity(trx_read_trx_id(rec + offset), rec, index, offsets, (0))
But, the SELECT returned wrong (empty) result without flagging any problems to the error log or the client.
The result to the mtr client was as follows:
CREATE TABLE foo(a INT PRIMARY KEY)engine=innoDB;
INSERT INTO foo VALUES(1),(2),(3),(4),(5);
trx_id=00000500
SELECT * FROM foo;
a
innodb.foo [ fail ]
Note that this test is only a proof-of-concept. For a proper mtr test, some special measures would be needed in order to bump the trx_id back to the correct value and to continue running other tests. Also, without disabling checksums, the server restart would fail:
CREATE TABLE foo(a INT PRIMARY KEY)engine=innoDB;
INSERT INTO foo VALUES(1),(2),(3),(4),(5);
trx_id=00000500
innodb.foo [ fail ]
Test ended at 2015-02-23 14:25:22
CURRENT_TEST: innodb.foo
Server [mysqld.1 - pid: 11503, winpid: 11503, exit: 256] failed during test run
Server log from this test:
----------SERVER LOG START-----------
[snip]
InnoDB: Database page corruption on disk or a failed
InnoDB: file read of page 5.
InnoDB: You may have to recover from a backup.
[11 May 2015 13:25]
Daniel Price
Posted by developer: Fixed as of the upcoming 5.7.8, 5.8.0 releases, and here's the changelog entry: A warning message is now printed if "DB_TRX_ID" stored in a record is found to be greater than "max_trx_id". In debug builds, an assertion is raised.
