Bug #8283 | OPTIMIZE TABLE causes data loss | ||
---|---|---|---|
Submitted: | 3 Feb 2005 13:21 | Modified: | 20 Oct 2006 17:24 |
Reporter: | Torsten Kasch | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: MyISAM storage engine | Severity: | S2 (Serious) |
Version: | 4.1.9 | OS: | Solaris (Solaris 9 (sparc)) |
Assigned to: | Ingo Strüwing | CPU Architecture: | Any |
Tags: | corruption, myisam |
[3 Feb 2005 13:21]
Torsten Kasch
[5 Feb 2005 16:55]
Jorge del Conde
mysql> DELETE FROM Sequence WHERE _id < 8; Query OK, 7 rows affected (0.00 sec) mysql> OPTIMIZE TABLE Sequence; +---------------+----------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------------+----------+----------+----------+ | test.Sequence | optimize | status | OK | +---------------+----------+----------+----------+ 1 row in set (0.01 sec) mysql> CHECK TABLE Sequence EXTENDED; +---------------+-------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------------+-------+----------+----------+ | test.Sequence | check | status | OK | +---------------+-------+----------+----------+ 1 row in set (0.00 sec) mysql> SELECT _id FROM Sequence; +-----+ | _id | +-----+ | 8 | | 9 | +-----+ 2 rows in set (0.00 sec)
[7 Feb 2005 12:20]
Torsten Kasch
We've done some further testing here and currently it seems that the bug is only triggered, if "myisam_repair_threads" is configured > 2. I must've overlooked the statement in the docs that this feature is alpha-quality (otherwise I would not have switched it on... ;-) Anyway, setting the value to "1" makes the reported test case pass flawlessly. Can it be that there is some kind of problem in the "multithreaded repair code" or did I do something wrong?
[7 Feb 2005 12:21]
Torsten Kasch
Sorry, my previous comment should have read ... if "myisam_repair_threads" is configured >= 2 ...
[7 Feb 2005 21:26]
Jorge del Conde
Thanks for your bug report. I was able to verify this bug under Linux after I set myisam_repair_threads to 2. DROP TABLE IF EXISTS `Sequence`; CREATE TABLE `Sequence` ( `_id` int(11) NOT NULL default '0', `url` text, `email` text, `description` text, `loverlap` int(11) default NULL, `roverlap` int(11) default NULL, `lneighbor_id` int(11) default NULL, `rneighbor_id` int(11) default NULL, `length_` int(11) default NULL, `sequence` mediumtext, `name` text, `_obj_class` text NOT NULL, PRIMARY KEY (`_id`), UNIQUE KEY `sequence_name_index` (`name`(50)) ) ENGINE=MyISAM DEFAULT CHARSET=latin1; -- -- Dumping data for table `Sequence` -- /*!40000 ALTER TABLE `Sequence` DISABLE KEYS */; LOCK TABLES `Sequence` WRITE; INSERT INTO `Sequence` VALUES (1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''),(2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample2',''),(3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample3',''),(4,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample4',''),(5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample5',''),(6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample6',''),(7,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample7',''),(8,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample8',''),(9,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample9',''); UNLOCK TABLES; /*!40000 ALTER TABLE `Sequence` ENABLE KEYS */; /*!40101 SET SQL_MODE=@OLD_SQL_MODE */; /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; mysql> show variables like 'myisam_repair%'; +-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | myisam_repair_threads | 2 | +-----------------------+-------+ 1 row in set (0.00 sec) mysql> select _id FROM Sequence; +-----+ | _id | +-----+ | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | +-----+ 9 rows in set (0.00 sec) mysql> DELETE FROM Sequence WHERE _id < 8; Query OK, 7 rows affected (0.00 sec) mysql> OPTIMIZE TABLE Sequence; +---------------+----------+----------+----------+ | Table | Op | Msg_type | Msg_text | +---------------+----------+----------+----------+ | test.Sequence | optimize | status | OK | +---------------+----------+----------+----------+ 1 row in set (0.00 sec) mysql> CHECK TABLE Sequence EXTENDED; +---------------+-------+----------+---------------------------------------------------------------+ | Table | Op | Msg_type | Msg_text | +---------------+-------+----------+---------------------------------------------------------------+ | test.Sequence | check | error | Found key at page 2048 that points to record outside datafile | | test.Sequence | check | error | Corrupt | +---------------+-------+----------+---------------------------------------------------------------+ 2 rows in set (0.00 sec) mysql> SELECT _id FROM Sequence; ERROR 1016 (HY000): Can't open file: 'Sequence.MYI' (errno: 145)
[28 Jun 2006 15:59]
Calvin Sun
mark bug#20051 as dup of this one.
[5 Aug 2006 10:41]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/10067 ChangeSet@1.2521, 2006-08-05 12:41:11+02:00, istruewing@chilla.local +9 -0 Bug#8283 - OPTIMIZE TABLE causes data loss [Not to be pushed. There is an issue with myisamchk -p left. I will fix it later. But please review the new design.] OPTIMIZE TABLE with myisam_repair_threads > 1 performs a non-quick parallel repair. This means that it does not only rebuild all indexes, but also the data file. Non-quick parallel repair works so that there is one thread per index. The first of the threads rebuilds also the new data file. The problem was that all threads shared the read io cache on the old data file. If there were holes (deleted records) in the table, the first thread skipped them, writing only contiguous, non-deleted records to the new data file. Then it built the new index so that its entries pointed to the correct record positions. But the other threads didn't know the new record positions, but put the positions from the old data file into the index. The new design is so that there is a shared io cache which is filled by the first thread and read by the other threads. Now they know the new record positions.
[14 Sep 2006 16:12]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/11951 ChangeSet@1.2514, 2006-09-14 18:11:59+02:00, istruewing@chilla.local +10 -0 Bug#8283 - OPTIMIZE TABLE causes data loss OPTIMIZE TABLE with myisam_repair_threads > 1 performs a non-quick parallel repair. This means that it does not only rebuild all indexes, but also the data file. Non-quick parallel repair works so that there is one thread per index. The first of the threads rebuilds also the new data file. The problem was that all threads shared the read io cache on the old data file. If there were holes (deleted records) in the table, the first thread skipped them, writing only contiguous, non-deleted records to the new data file. Then it built the new index so that its entries pointed to the correct record positions. But the other threads didn't know the new record positions, but put the positions from the old data file into the index. The new design is so that there is a shared io cache which is filled by the first thread (the data file writer) with the new contiguous records and read by the other threads. Now they know the new record positions. Another problem was that for the parallel repair of compressed tables a common bit_buff and rec_buff was used. I changed it so that thread specific buffers are used for parallel repair. A similar problem existed for checksum calculation. I made this multi-thread safe too.
[9 Oct 2006 17:27]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/13346 ChangeSet@1.2514, 2006-10-09 19:26:55+02:00, istruewing@chilla.local +10 -0 Bug#8283 - OPTIMIZE TABLE causes data loss OPTIMIZE TABLE with myisam_repair_threads > 1 performs a non-quick parallel repair. This means that it does not only rebuild all indexes, but also the data file. Non-quick parallel repair works so that there is one thread per index. The first of the threads rebuilds also the new data file. The problem was that all threads shared the read io cache on the old data file. If there were holes (deleted records) in the table, the first thread skipped them, writing only contiguous, non-deleted records to the new data file. Then it built the new index so that its entries pointed to the correct record positions. But the other threads didn't know the new record positions, but put the positions from the old data file into the index. The new design is so that there is a shared io cache which is filled by the first thread (the data file writer) with the new contiguous records and read by the other threads. Now they know the new record positions. Another problem was that for the parallel repair of compressed tables a common bit_buff and rec_buff was used. I changed it so that thread specific buffers are used for parallel repair. A similar problem existed for checksum calculation. I made this multi-thread safe too.
[9 Oct 2006 20:16]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/13356 ChangeSet@1.2296, 2006-10-09 22:16:22+02:00, istruewing@chilla.local +1 -0 Bug#8283 - OPTIMIZE TABLE causes data loss After merge fix. MyISAM version 10.
[10 Oct 2006 18:01]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/13421 ChangeSet@1.2346, 2006-10-10 20:01:39+02:00, istruewing@chilla.local +1 -0 Bug#8283 - OPTIMIZE TABLE causes data loss After merge fix. Renamed 'info' -> 'sort_param'.
[12 Oct 2006 7:13]
Ingo Strüwing
Pushed to 5.1-engines, 5.0-engines, and 4.1-engines.
[20 Oct 2006 9:08]
Ingo Strüwing
Pushed to 5.1.13, 5.0.27, and 4.1.22.
[20 Oct 2006 17:24]
Paul DuBois
Noted in 4.1.22, 5.0.27, 5.1.13 changelogs. OPTIMIZE TABLE with myisam_repair_threads > 1 could result in table corruption.
[25 Oct 2006 16:40]
Paul DuBois
The 5.0.x fix is in 5.0.30.