| Bug #87229 | Inplace upgrade 5.5 -> 5.6 -> 5.7 -> 8.0.2 fails: Error in fixing SE data | ||
|---|---|---|---|
| Submitted: | 28 Jul 2017 3:20 | Modified: | 30 Aug 2017 14:54 |
| Reporter: | Jesper wisborg Krogh | Email Updates: | |
| Status: | Closed | Impact on me: | |
| Category: | MySQL Server: Data Dictionary | Severity: | S2 (Serious) |
| Version: | 8.0.2 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
[28 Jul 2017 3:20]
Jesper wisborg Krogh
[28 Jul 2017 3:25]
Jesper wisborg Krogh
Posted by developer: For the upgrade from 5.1 (same principle as before - starting with 5.1.73), I use the tables and data: CREATE SCHEMA db1; CREATE TABLE db1.t1 ( id int unsigned NOT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB; INSERT INTO db1.t1 VALUES (1); CREATE TABLE db1.t2 ( id int unsigned NOT NULL, val decimal(6,4) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB; INSERT INTO db1.t2 VALUES (1, 1.2345); With this the errors for the data dictionary upgrade are: 2017-07-28T03:23:36.355071Z 2 [ERROR] Error in fixing SE data for db1.t1 2017-07-28T03:23:36.357070Z 2 [ERROR] InnoDB: Column precision type mismatch(i.e NULLs, SIGNED/UNSIGNED etc) for col: val 2017-07-28T03:23:36.357106Z 2 [ERROR] InnoDB: Column val for table: `db1`.`t2` mismatches with InnoDB Dictionary 2017-07-28T03:23:36.357123Z 2 [ERROR] Error in fixing SE data for db1.t2 2017-07-28T03:23:37.128175Z 0 [ERROR] Failed to Populate DD tables. 2017-07-28T03:23:37.128200Z 0 [ERROR] Aborting Note the different error for the decimal column.
[28 Jul 2017 3:31]
Jesper wisborg Krogh
Posted by developer: The workaround is to execute OPTIMIZE TABLE (or other copying ALTER) - this can be done as late as just before the upgrade to 8.0.2.
[28 Jul 2017 3:52]
Jesper wisborg Krogh
Posted by developer: my.cnf: [mysqld] basedir = /upgrade/mysql datadir = /upgrade/data socket = /upgrade/run/mysql.sock pid_file = /upgrade/run/mysql.pid port = 3306 innodb_file_per_table = 1
[16 Aug 2017 12:00]
Daniël van Eeden
Is there any way to check which tables on a 5.7 instance need rebuilding?
[17 Aug 2017 3:23]
Jesper wisborg Krogh
Posted by developer:
There is unfortunately no straight forward way to check. The only way I know of is to use mysqlfrm and check field_type:
shell$ mysqlfrm --diagnostic -vv data/db1/t1.frm
...
[{'bytes_in_col': 8,
'charset': 8,
'charset_low': 0,
'comment': '',
'comment_length': 0,
'default': None,
'enums': [],
'field_length': 8,
'field_type': 246, <----- this one
'field_type_name': 'decimal',
'flags': 3,
'flags_extra': 67,
'interval_nr': 0,
'name': 'val',
'recpos': 6,
'unireg': 0,
'unireg_type': 0}]
...
If field_type = 0, you are using the old decimal type, if field_type = 246, you use the new.
The values of field_type comes from include/mysql.h.pp:
typedef enum enum_field_types {
MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_SHORT, MYSQL_TYPE_LONG,
MYSQL_TYPE_FLOAT, MYSQL_TYPE_DOUBLE,
MYSQL_TYPE_NULL, MYSQL_TYPE_TIMESTAMP,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_BIT,
MYSQL_TYPE_TIMESTAMP2,
MYSQL_TYPE_DATETIME2,
MYSQL_TYPE_TIME2,
MYSQL_TYPE_JSON=245,
MYSQL_TYPE_NEWDECIMAL=246,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
MYSQL_TYPE_MEDIUM_BLOB=250,
MYSQL_TYPE_LONG_BLOB=251,
MYSQL_TYPE_BLOB=252,
MYSQL_TYPE_VAR_STRING=253,
MYSQL_TYPE_STRING=254,
MYSQL_TYPE_GEOMETRY=255
} enum_field_types;
[17 Aug 2017 11:03]
Daniël van Eeden
From my query on I_S it looks like the column has MYSQL_TYPE_NEWDECIMAL in both the old and new case. However the high bits of prtype are different, but I don't know why.. prtype for old is: 4130038 ( 1111110000010011110110 ) prtype for new is 525558 ( 0010000000010011110110 ) xor 1101110000000000000000 old >> 16 111111 = 63 This query lists the columns in need of an upgrade because of decimal types in my case: SELECT t.NAME, c.* FROM information_schema.INNODB_SYS_COLUMNS c LEFT JOIN information_schema.INNODB_SYS_TABLES t USING (TABLE_ID) WHERE c.MTYPE=3 AND PRTYPE >> 16 = 63 AND PRTYPE & 255 /* DATA_MYSQL_TYPE_MASK */ = 246 /* MYSQL_TYPE_NEWDECIMAL */;
[17 Aug 2017 11:14]
Daniël van Eeden
Comparing mysqlfrm output on 5.7.18 on one decimal-upgrade affected table. The column is 100% identical. However the table a new MYSQL_VERSION_ID as expected: it changes from 50147 to 50718. But the prtype did change.
[17 Aug 2017 12:10]
Naga Satyanarayana Bodapati
the first two bytes are storing charset collation codes
[18 Aug 2017 7:29]
Daniël van Eeden
This is the SQL I now use to identify which tables need to be rebuild before upgrading to 8.0.2
-- Find tables which do not have their tablespace registered in INNODB_SYS_TABLESPACES
-- This happens for tables created on MySQL 5.1
--
-- This ignores partitioned tables as mysql_upgrade should have ran
-- ALTER TABLE … UPGRADE PARTITIONING on them during the 5.7 upgrade.
--
-- The join might not work for non-ascii table names.
--
-- FIX: Run OPTIMIZE TABLE on them.
SELECT
it.table_schema,
it.table_name
FROM
information_schema.TABLES it
LEFT JOIN information_schema.PARTITIONS ip
ON (it.TABLE_SCHEMA=ip.TABLE_SCHEMA AND it.TABLE_NAME=ip.TABLE_NAME
AND ip.PARTITION_NAME IS NOT NULL)
LEFT JOIN information_schema.INNODB_SYS_TABLESPACES ts
ON ts.NAME=CONCAT(it.table_schema, '/', it.table_name)
WHERE
it.ENGINE='InnoDB'
AND it.TABLE_TYPE='BASE TABLE'
AND it.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema')
AND ip.PARTITION_NAME IS NULL
AND ts.SPACE IS NULL;
-- Find tables with "new" decimal columns which have a binary (63) charset
-- instead of latin1 (8)
--
-- FIX: Run OPTIMIZE TABLE on them
SELECT
t.NAME AS table_name,
c.NAME AS column_name
FROM
information_schema.INNODB_SYS_COLUMNS c
LEFT JOIN information_schema.INNODB_SYS_TABLES t USING (TABLE_ID)
WHERE
c.MTYPE=3 /* 3 = DATA_FIXBINARY */
AND PRTYPE >> 16 = 63 /* 63 = DATA_MYSQL_BINARY_CHARSET_COLL */
AND PRTYPE & 255 /* 255 = DATA_MYSQL_TYPE_MASK */
= 246 /* 246 = MYSQL_TYPE_NEWDECIMAL */;
[18 Aug 2017 7:30]
Daniël van Eeden
The SQL file to check which tables need to be rebuild
Attachment: mysql80_upgrade_check.sql (application/sql, text), 1.50 KiB.
[30 Aug 2017 14:54]
Daniel Price
Posted by developer: Fixed as of the upcoming 8.0.3 release, and here's the changelog entry: File-per-table tablespaces created prior to MySQL 5.6 caused a failure during an in-place upgrade to MySQL 8.0.2. The tablespaces were not registered with the InnoDB SYS_TABLESPACES system table, as required. Tables with decimal columns created prior to MySQL 5.5 also caused a failure during an in-place upgrade to MySQL 8.0.2, due to a precision type mismatch.
