Bug #10767 Killing OPTIMIZE TABLE process corrupts MyISAM table
Submitted: 20 May 2005 15:00 Modified: 20 May 2005 15:36
Reporter: Geert Vanderkelen Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: MyISAM storage engine Severity:S2 (Serious)
Version:4.1.12 OS:Linux (Linux)
Assigned to: CPU Architecture:Any

[20 May 2005 15:00] Geert Vanderkelen
Description:
Hi,

Killing a mysql process doing OPTIMIZE TABLE on a MyISAM table will leave it corrupted.
Test table, attached to this report, has only one field:  c char(0), no indexes.

Tested with 4.1.12 and 5.0.6-beta.

Regards,

Geert

How to repeat:

-- Attached is a small table
SHOW TABLE STATUS LIKE 'small'\G
/*
CREATE TABLE `small` (
  `c` char(0) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
*************************** 1. row ***************************
           Name: small
         Engine: MyISAM
        Version: 9
     Row_format: Fixed
           Rows: 6619136
 Avg_row_length: 5
    Data_length: 33095680
[..]
*/

-- delete a row so it gets changed:
DELETE FROM small LIMIT 1;

-- Have an extra terminal ready to kill the process using the 
-- connection id running OPTIMIZE TABLE.
-- Or make the table bigger if you want more time :)
-- shell> mysqladmin -uroot kill <connid>
OPTIMIZE TABLE small;

-- when killed 'succesfully', it reports following:
/*
+---------------+----------+----------+-------------------------------+
| Table         | Op       | Msg_type | Msg_text                      |
+---------------+----------+----------+-------------------------------+
| bigdata.small | optimize | error    | 22 for record at pos 15699435 |
| bigdata.small | optimize | status   | Operation failed              |
+---------------+----------+----------+-------------------------------+
*/

CHECK TABLE small;
/*
+---------------+-------+----------+-------------------------------------------------------------+
| Table         | Op    | Msg_type | Msg_text                                                    |
+---------------+-------+----------+-------------------------------------------------------------+
| bigdata.small | check | warning  | Table is marked as crashed and last repair failed           |
| bigdata.small | check | error    | Record-count is not ok; is 6619131   Should be: 3139887     |
| bigdata.small | check | warning  | Found 5 deleted space.   Should be 0                        |
| bigdata.small | check | warning  | Found 1 deleted blocks       Should be: 0                   |
| bigdata.small | check | warning  | Found 6619132 parts                Should be: 3139887 parts |
| bigdata.small | check | error    | Corrupt                                                     |
+---------------+-------+----------+-------------------------------------------------------------+

From 5.0:
   Table: bigdata.small
      Op: check
Msg_type: error
Msg_text: Table './bigdata/small' is marked as crashed and last (automatic?) repair failed
*/

REPAIR TABLE small;
/*
+---------------+--------+----------+------------------------------------------------+
| Table         | Op     | Msg_type | Msg_text                                       |
+---------------+--------+----------+------------------------------------------------+
| bigdata.small | repair | warning  | Number of rows changed from 3139887 to 6619131 |
| bigdata.small | repair | status   | OK                                             |
+---------------+--------+----------+------------------------------------------------+
*/
[20 May 2005 15:02] Geert Vanderkelen
Small silly table with char(0) field.

Attachment: small.table.tar.gz (application/x-gzip, text), 47.48 KiB.

[20 May 2005 15:36] Guilhem Bichot
Hi,
This is documented:
"Some threads might refuse to be killed. For example, REPAIR TABLE, CHECK TABLE, and OPTIMIZE TABLE cannot be killed before MySQL 4.1 and run to completion. This is changed: REPAIR TABLE and OPTIMIZE TABLE can be killed as of MySQL 4.1.0, as can CHECK TABLE as of MySQL 4.1.3. However, killing a REPAIR TABLE or OPTIMIZE TABLE operation on a MyISAM table results in a table that is corrupted and is unusable (reads and writes to it fail) until you optimize or repair it again."
("KILL syntax" section).
It can't be fixed easily because OPTIMIZE TABLE does not save a copy of the MYI: it overwrites it as it optimizes.