Bug #95478 CREATE TABLE LIKE does not honour ROW_FORMAT.
Submitted: 22 May 2019 15:31 Modified: 23 May 2019 13:15
Reporter: Jean-François Gagné Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S4 (Feature request)
Version:5.7.26 OS:Any
Assigned to: CPU Architecture:Any

[22 May 2019 15:31] Jean-François Gagné
Description:
Hi,

I have a table that has ROW_FORMAT=Compact, but it is not reported in the SHOW CREATE TABLE.  When I CREATE TABLE LIKE this "Compact" table, it is created as ROW_FORMAT=Dynamic (maybe because different values of innodb_default_row_format, I cannot tell what this was when the original table was created).  I would expect CREATE TABLE LIKE to honour the ROW_FORMAT of the original table, not use the default.

Also, this is problematic when I follow the steps in [1] for working with EXCHANGE PARTITION (see how to reproduce).

Many thanks for looking into that,

JFG

How to repeat:
# Using dbdeployer, create a test instance:

dbdeployer deploy single mysql_5.7.26

-- Create a database and a table in row format compact.
-- (I do not know if this is the way my production table was created in ROW_FORMAT=Compact,
--    but what I can see in production is that ROW_FORMAT=Compact does not show in SHOW CREATE TABLE.)

mysql [localhost:5726] {msandbox} ((none)) > CREATE DATABASE test_jfg;
Query OK, 1 row affected (0.00 sec)

mysql [localhost:5726] {msandbox} ((none)) > SET GLOBAL innodb_default_row_format=compact;
Query OK, 0 rows affected (0.00 sec)

mysql [localhost:5726] {msandbox} ((none)) > CREATE TABLE test_jfg.t1 (
    ->   id bigint unsigned NOT NULL AUTO_INCREMENT,
    ->   created_at datetime NOT NULL,
    ->   str1 varchar(50) DEFAULT NULL,
    ->   PRIMARY KEY (id,created_at)
    -> ) PARTITION BY RANGE ( MONTH(`created_at`))
    -> (PARTITION p1 VALUES LESS THAN (2),
    ->  PARTITION p2 VALUES LESS THAN (3));
Query OK, 0 rows affected (0.03 sec)

mysql [localhost:5726] {msandbox} ((none)) > SHOW CREATE TABLE test_jfg.t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `created_at` datetime NOT NULL,
  `str1` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE ( MONTH(`created_at`))
(PARTITION p1 VALUES LESS THAN (2) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (3) ENGINE = InnoDB) */
1 row in set (0.00 sec)

-- Now use CREATE TABLE LIKE with a different value for innodb_default_row_format.
-- (I cannot tell for sure that the reason for different ROW_FORMAT in production is because
--   of using different values for innodb_default_row_format at the time of creation of the table,
--   but the outcome is the same as below.)

mysql [localhost:5726] {msandbox} ((none)) > SET GLOBAL innodb_default_row_format=dynamic;
Query OK, 0 rows affected (0.01 sec)

mysql [localhost:5726] {msandbox} ((none)) > CREATE TABLE test_jfg.t2 LIKE test_jfg.t1;
Query OK, 0 rows affected (0.02 sec)

mysql [localhost:5726] {msandbox} ((none)) > SHOW CREATE TABLE test_jfg.t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `created_at` datetime NOT NULL,
  `str1` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`,`created_at`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE ( MONTH(`created_at`))
(PARTITION p1 VALUES LESS THAN (2) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (3) ENGINE = InnoDB) */
1 row in set (0.00 sec)

-- Let's look in I_S, I would expect the ROW_FORMAT of both tables to be the same
--   (after all, I ran CREATE TABLE LIKE), but it is not the case.

mysql [localhost:5726] {msandbox} ((none)) > SELECT TABLE_SCHEMA, TABLE_NAME, ROW_FORMAT FROM information_schema.TABLES WHERE TABLE_SCHEMA = "test_jfg";
+--------------+------------+------------+
| TABLE_SCHEMA | TABLE_NAME | ROW_FORMAT |
+--------------+------------+------------+
| test_jfg     | t1         | Compact    |
| test_jfg     | t2         | Dynamic    |
+--------------+------------+------------+
2 rows in set (0.00 sec)

-- And this causes EXCHANGE PARTITION to fail.

mysql [localhost:5726] {msandbox} ((none)) > ALTER TABLE test_jfg.t2 REMOVE PARTITIONING;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql [localhost:5726] {msandbox} ((none)) > ALTER TABLE test_jfg.t1 EXCHANGE PARTITION p2 WITH TABLE test_jfg.t2;
ERROR 1731 (HY000): Non matching attribute 'ROW_FORMAT' between partition and table

-- Obviously, an easy work-around is to ALTER the table to ROW_FORMAT=Compact, but this should not be needed.

mysql [localhost:5726] {msandbox} ((none)) > ALTER TABLE test_jfg.t2 ROW_FORMAT=Compact;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql [localhost:5726] {msandbox} ((none)) > ALTER TABLE test_jfg.t1 EXCHANGE PARTITION p2 WITH TABLE test_jfg.t2;
Query OK, 0 rows affected (0.02 sec)

Suggested fix:
CREATE TABLE LIKE should honour the original ROW_FORMAT of the table, not use the default specified by innodb_default_row_format.
[22 May 2019 15:34] Jean-François Gagné
Adding [1] mentioned in bug description...

[1]: https://dev.mysql.com/doc/refman/5.7/en/partitioning-management-exchange.html
[22 May 2019 16:46] MySQL Verification Team
Hi Jean-Francois,

Thank you for your bug report.

I think that your bug is for the documentation and I will write down exactly why.  If you read chapter 15.10 from 8.0 Reference Manual and especially, the paragraph related to table rebuilding, you will understand why I think it is a documentation bug.

Simply, that part on the table rebuilding should be appended to include the case that you have described. Even if this get verified as a code bug, it will finish only as the addition to that chapter. 

Let me know if you agree with me.
[23 May 2019 5:29] Giuseppe Maxia
I don't think it's a bug.

If you create the table with explicit ROW_FORMAT, it shows up in the "SHOW CREATE TABLE" statement. If you don't specify it, it doesn't show up.

In the first case, CREATE TABLE ... LIKE does what you expect, i.e. copies the WOR_FORMAT. In the case where you rely on the default row format, it is not stored in the table definition.

Depending on how you look at it, it's a feature, meaning that the ROW_FORMAT is preserved only when it's part of the create table statement.
[23 May 2019 9:37] Jean-François Gagné
Related Bug#95484.
[23 May 2019 13:15] MySQL Verification Team
Hi,

I agree with Giuseppe ........

Feature request it is ......