Bug #33222 | myisam-table drops rows when column is added and a char-field > 128 exists | ||
---|---|---|---|
Submitted: | 13 Dec 2007 16:57 | Modified: | 15 Apr 2008 2:09 |
Reporter: | Lutz Maibach | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: MyISAM storage engine | Severity: | S2 (Serious) |
Version: | 5.1.22 and 6.0 | OS: | Linux (RedHat ES5) (FreeBSD 7.0 AMD64) |
Assigned to: | Ingo Strüwing | CPU Architecture: | Any |
Tags: | char, loss of data, myisam |
[13 Dec 2007 16:57]
Lutz Maibach
[14 Dec 2007 11:28]
Hartmut Holzgraefe
A quick question: In the last step you write that you get this back from the ALTER TABLE statement: Query OK, 100 rows affected, 2 warnings Could you do a SHOW WARNINGS right after that and post the two reported warnings to this bug report, too?
[14 Dec 2007 11:46]
Lutz Maibach
Hi Hartmut, here is the requested information: mysql> alter table foo add column trara varchar(10); Query OK, 100 rows affected, 3 warnings (0.02 sec) Records: 100 Duplicates: 0 Warnings: 0 mysql> show warnings; +-------+------+--------------------------------------+ | Level | Code | Message | +-------+------+--------------------------------------+ | Error | 1034 | Found wrong packed record at 2144 | | Error | 1034 | Found wrong packed record at 2144 | | Error | 1034 | Number of rows changed from 49 to 99 | +-------+------+--------------------------------------+ 3 rows in set (0.00 sec)
[14 Dec 2007 18:43]
Susanne Ebrecht
mysql> CREATE TABLE `foo` ( -> `field1` int(11) NOT NULL AUTO_INCREMENT, -> `field2` int(11) NOT NULL DEFAULT '0', -> `field3` int(11) NOT NULL DEFAULT '0', -> `field4` date DEFAULT NULL, -> `field5` varchar(60) DEFAULT NULL, -> `longchar` char(250) DEFAULT NULL, -> `shortvchar` varchar(10) DEFAULT NULL, -> PRIMARY KEY (`field1`), -> KEY `field2` (`field2`), -> KEY `field3` (`field3`), -> KEY `field4` (`field4`), -> KEY `field5` (`field5`) -> ) ENGINE=MyISAM AUTO_INCREMENT=79170 DEFAULT CHARSET=latin1 -> ; Query OK, 0 rows affected (0.00 sec) mysql> insert into foo (field2, field3, field4, field5, longchar,shortvchar) values(1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'), (1,1,current_date,'abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghijklmnopqrstuvwxyzZYXWVUTSRQPOMNLKJIHGFEDCBA','abcdefghij'); Query OK, 10 rows affected (0.00 sec) Records: 10 Duplicates: 0 Warnings: 0 I repeated this 11 time ... mysql> select count(*) from foo\G *************************** 1. row *************************** count(*): 110 $ ls -lh /home/myhome/mysql51/var/mydatabase/ ... 14K 14 Dez 19:32 foo.MYI mysql> update foo set longchar=repeat("X",128) where field2=1;Query OK, 110 rows affected (0.02 sec)Rows matched: 110 Changed: 110 Warnings: 0 mysql> alter table foo add column whatever varchar(10); 071214 19:35:06 [Warning] Warning: Enabling keys got errno 137 on mydatabase.#sql-9df3_3, retryingQuery OK, 110 rows affected, 111 warnings (0.02 sec)Records: 110 Duplicates: 0 Warnings: 0 mysql> show warnings; +-------+------+------------------------------------+ | Level | Code | Message |+-------+------+------------------------------------+ | Error | 1034 | Found wrong packed record at 0 | | Error | 1034 | Found wrong packed record at 0 | | Error | 1034 | Found wrong packed record at 216 | | Error | 1034 | Found wrong packed record at 432 | | Error | 1034 | Found wrong packed record at 648 | | Error | 1034 | Found wrong packed record at 864 | | Error | 1034 | Found wrong packed record at 1080 | | Error | 1034 | Found wrong packed record at 1296 | | Error | 1034 | Found wrong packed record at 1512 | ... | Error | 1034 | Found wrong packed record at 12960 | | Error | 1034 | Found wrong packed record at 13176 | | Error | 1034 | Found wrong packed record at 13392 | +-------+------+------------------------------------+ 64 rows in set (0.00 sec) mysql>select count(*) from foo\G *************************** 1. row *************************** count(*): 0 With only 100 rows, my foo.MYI just was 6K and all worked fine.
[17 Dec 2007 8:03]
Lutz Maibach
Hello Susanne, sorry for the "incomplete" example. I didn't want to post our table where it happened cause it has 35 fields so description would have been very long. Therefore I created the foo-table but used the wrong no. of inserted columns. 100 were enough using the original table, I inserted more in foo but only looked at the size of the MYI file and forgot to put the right no. of inserted col. into the description. If I get you right you're now able to reproduce the problem. Any other information neccesary from my side to fix it? Greetings from Germany Lutz Maibach
[17 Dec 2007 11:08]
Susanne Ebrecht
Hello Lutz, all is fine. I understood what you did and could reproduce it with MySQL 5.1.22 and 6.0. I couldn't reproduce it with 5.0.51. I don't have further questions. Greetings from Germany back to Germany. Susanne
[17 Dec 2007 21:46]
Calvin Sun
Investigation result from svoj: I was able to track down the problem and have a fix for it. As this is my last working day, I will not be able to handle review/push cycle quickly, so please unassign this bug from me. Below comes detailed description of the problem. For dynamic record format tables with CHAR field, that contain value longer than 127 bytes CHECK TABLE may report that table has wrongly packed record, whereas records are fine. REPAIR TABLE (and sibling operations like ADD/DROP COLUMN) may throw away such records. The problem is signed vs unsigned comparision. Appeared after big types removal patch by Monty. That is affects 5.1 and up. Following is much simplier test case for this bug: CREATE TABLE t1(a CHAR(130) NOT NULL, b VARCHAR(1) NOT NULL); INSERT INTO t1 VALUES(REPEAT("X",128),''); CHECK TABLE t1; DROP TABLE t1; A minimal patch should look like (the function name is _mi_rec_check()): +++ edited/../storage/myisam/mi_dynrec.c 2007-12-18 00:20:27 +04:00 @@ -1133,7 +1133,7 @@ goto err; to+=2; } - else if (*to++ != (char) new_length) + else if (*to++ != (uchar) new_length) goto err; to+=new_length; } It would be great to check similiar case a few lines above: if (to[0] != (char) ((new_length & 127)+128) || to[1] != (char) (new_length >> 7)) But as I do not remember how FIELD_SKIP_ENDSPACE/FIELD_SKIP_PRESPACE could be longer than 255 bytes, I cannot write a test case for it. Ingo: do you remember how could that happen or it is just a dead code?
[18 Dec 2007 14:20]
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/40138 ChangeSet@1.2641, 2007-12-18 15:19:04+01:00, istruewing@stella.local +3 -0 Bug#33222 - myisam-table drops rows when column is added and a char-field > 128 exists ALTERing a table with long char columns warned about corruptions and left the altered table empty. The problem was a signed/unsigned compare in MyISAM code. A char to uchar change became necessary after the big byte to uchar change.
[10 Jan 2008 13:55]
Sergey Vojtovich
Approved with wishlist.
[14 Jan 2008 16:59]
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/40990 ChangeSet@1.2641, 2008-01-14 17:59:45+01:00, istruewing@stella.local +3 -0 Bug#33222 - myisam-table drops rows when column is added and a char-field > 128 exists CHECK TABLE (non-QUICK) and any form of repair table did wrongly rate records as corrupted under the following conditions: 1. The table has dynamic row format and 2. it has a CHAR like column > 127 bytes (but not VARCHAR) (for multi-byte character sets this could be less than 127 characters) and 3. it has records with > 127 bytes significant length in that column (a byte beyond byte position 127 must be non-space). Affected were the statements CHECK TABLE, REPAIR TABLE, OPTIMIZE TABLE, ALTER TABLE. CHECK TABLE reported and marked the table as crashed if any record was present that fulfilled condition 3. The other statements deleted these records. The problem was a signed/unsigned compare in MyISAM code. A char to uchar change became necessary after the big byte to uchar change.
[17 Jan 2008 9:01]
Ingo Strüwing
Queued to 6.0-engines, 5.1-engines
[27 Mar 2008 11:17]
Bugs System
Pushed into 5.1.24-rc
[27 Mar 2008 17:49]
Bugs System
Pushed into 6.0.5-alpha
[31 Mar 2008 20:20]
Jon Stephens
Pushed into 5.1.23-ndb-6.3.11.
[15 Apr 2008 2:09]
Paul DuBois
Noted in 5.1.24, 6.0.5 changelogs.