[MDEV-5248] Serious incompatibility and data corruption of DATETIME and DATE types due to get_innobase_type_from_mysql_type refactor combined with InnoDB Online DDL Created: 2013-11-06 Updated: 2014-01-06 Resolved: 2013-11-14 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | None |
| Affects Version/s: | 10.0.4, 10.0.5 |
| Fix Version/s: | 10.0.6 |
| Type: | Bug | Priority: | Blocker |
| Reporter: | Jeremy Cole | Assignee: | Sergei Golubchik |
| Resolution: | Fixed | Votes: | 2 |
| Labels: | date, datetime, innodb, online-ddl | ||
| Environment: |
All |
||
| Issue Links: |
|
||||||||
| Description |
|
Note that this issue has been discussed somewhat in Per the discussion in
In addition to the incompatibilities in TINYINT UNSIGNED, ENUM, SET, and YEAR described in Using DATETIME as an example (and the MySQL 5.5 code, but it doesn't actually matter), Field_datetime returns HA_KEYTYPE_ULONGLONG as its key_type: And inside InnoDB in MySQL 5.5, it is mapped to DATA_INT in get_innobase_type_from_mysql_type: However, in MySQL 5.5, it is NOT marked as DATA_UNSIGNED despite it being treated by the handler as HA_KEYTYPE_ULONGLONG. This should perhaps be considered a bug in MySQL/InnoDB, but it is ancient history at this point, and cannot be changed without extensive consideration. In MariaDB since the refactor of get_innobase_type_from_mysql_type which occurred in the 5.3 series (and is now included in 5.5 and 10.0), DATETIME is now handled by the generic case for HA_KEYTYPE_ULONGLONG, which does set DATA_UNSIGNED (because this code is shared with BIGINT UNSIGNED, of course): InnoDB's on-disk integer format for all sizes reverse the meaning of the sign bit and flips it with XOR on write and read (to allow the big endian byte representation of integers to sort correctly as binary data): Nothing breaks immediately because of this, due to the fact that get_innobase_type_from_mysql_type is largely used only for table creation. Where this breaks badly, is if InnoDB Online DDL is ever exercised on such a table. In that case the new table will be created using MariaDB's definition of these columns rather than MySQL's. When the values are copied from one table to another, it will be done using buffers inside InnoDB without reinterpreting the values, which will cause them to become corrupted in the destination table. Additionally, the same problem exists in reverse with tables created on MariaDB during cross-grade to MySQL 5.6 – the exact same misinterpretation will occur. Unfortunately there is not a very good way to determine whether any given table or column may be corrupted or how to properly interpret its values. Furthermore once corruption has occurred, single tables may contain a mix of corrupted-sign-bit and uncorrupted records, making either upgrade or downgrade impossible to resolve the situation. How to repeat
|
| Comments |
| Comment by Jeremy Cole [ 2013-11-06 ] |
|
Apologies for the terrible formatting. I didn't realize wiki markup was allowed/used. Should look better now. |
| Comment by VAROQUI Stephane [ 2013-11-08 ] |
|
For my personal knowledge why not reimplementing online alter table the way it is done by the toolkits: full table copy. assync binlog catchup and rename table. Independent storage engine DDL change It seams that the time spend on fixing would be better use for a more generic solution. Covering non transactional engines as well. I'm using the toolkits and so far scary to use something else provide by any storage engine . May be the lack internal knowledge of every storage design push me to trust a solution that recreate a table from scratch. And may be the need of analyze and optimize table push me more in that feeling . |
| Comment by Jorge Manuel Silva [ 2013-11-08 ] |
|
I am also able to reproduce this issue: I started with MariaDB 5.3.12 I then retried all the process from scratch but after upgrading to MariaDB 10.0.5 added to my.ini: And with that switch I am unable to reproduce this bug. |
| Comment by Sergei Golubchik [ 2013-11-11 ] |
|
This seems to the the full list of types where mtype/unsigned_flag change between InnoDB in MariDB-10.0.5 and MySQL-5.6: BIT |
| Comment by Sergei Golubchik [ 2013-11-11 ] |
|
jeremycole — here's the proposed fix: http://bazaar.launchpad.net/~maria-captains/maria/10.0-serg/revision/3899 |
| Comment by Jeremy Cole [ 2013-11-12 ] |
|
I've sent a review by email cc the developer list. |
| Comment by Elena Stepanova [ 2013-11-13 ] |
|
I've run some basic tests on the revision above. The general test scenario:
CREATE TABLE t1
The complete list of checked upgrade paths is below, if you see any gaps, please let me know. Summary:
Upgrade paths Upgrade to 10.0-before-fix: 5.5 => 10.0 corrupt Upgrade to 10.0-with-fix: 5.5 => 10.0-serg ok Upgrade from 10.0 to 5.6: 10.0 => mysql-5.6 - |