【问题标题】:MySQL 8 ignoring integer lengthsMySQL 8 忽略整数长度
【发布时间】:2020-07-08 14:10:28
【问题描述】:

我有一个在 Docker 容器中运行并使用 InnoDB 引擎的 MySQL 8.0.19。我注意到表整数字段长度被忽略了。

无论是运行 CREATE 还是 ALTER 查询,整数数据类型都会出现问题

CREATE TABLE `test` (
  `id` int DEFAULT NULL,
  `text_field` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `decimal_field` decimal(6,2) DEFAULT NULL,
  `int_field` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

长度在我的 MySQL 客户端 (Navicat) 中显示为 0,但如果使用 SHOW FULL COLUMNS FROMtest; 在控制台中检查,也会出现同样的情况

mysql> SHOW FULL COLUMNS FROM `test`;
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field         | Type         | Collation          | Null | Key | Default | Extra | Privileges                      | Comment |
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| id            | int          | NULL               | YES  |     | NULL    |       | select,insert,update,references |         |
| text_field    | varchar(20)  | utf8mb4_unicode_ci | YES  |     | NULL    |       | select,insert,update,references |         |
| decimal_field | decimal(6,2) | NULL               | YES  |     | NULL    |       | select,insert,update,references |         |
| int_field     | int          | NULL               | YES  |     | NULL    |       | select,insert,update,references |         |
+---------------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+

对于两个整数字段,Type 列应该显示 int(11),但事实并非如此。

这是否与我的 MySQL 设置中的某些内容有关,如果是,则必须更改哪个变量?

【问题讨论】:

    标签: mysql sql innodb mysql-8.0


    【解决方案1】:

    这是MySQL 8.0.19 release notes 中记录的更改:

    整数数据类型的显示宽度规范在 MySQL 8.0.17 和现在包含数据类型定义的语句 他们的输出不再显示整数类型的显示宽度, 这些例外:

    • 类型为 TINYINT(1)。 MySQL 连接器假设 TINYINT(1) 列起源于 BOOLEAN 列;这个例外 使他们能够继续做出这种假设。

    • 类型包括 ZEROFILL 属性。

    此更改适用于表、视图和存储例程,并影响 SHOW CREATE 和 DESCRIBE 语句的输出,以及 INFORMATION_SCHEMA 表。

    对于 DESCRIBE 语句和 INFORMATION_SCHEMA 查询,输出为 对在以前的 MySQL 8.0 版本中创建的对象不受影响,因为 已存储在数据字典中的信息保持不变。 此例外不适用于从 MySQL 5.7 升级到 8.0,因为 重新创建所有数据字典信息,以便数据 类型定义不包括显示宽度。 (错误 #30556657、错误 #97680)

    整数列的“长度”没有任何意义。 int(11) 的列与int(2)int(40) 相同。它们都是固定大小的 32 位整数数据类型。它们支持相同的最小值和最大值。

    多年来,整数列的“长度”一直是 MySQL 的一个令人困惑的特性。这只是影响显示宽度的提示,而不是存储或值范围。实际上,仅当您使用 ZEROFILL 选项时才重要。

    mysql> create table t ( i1 int(6) zerofill, i2 int(12) zerofill );
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> insert into t set i1 = 123, i2 = 123;
    Query OK, 1 row affected (0.00 sec)
    
    mysql> select * from t;
    +--------+--------------+
    | i1     | i2           |
    +--------+--------------+
    | 000123 | 000000000123 |
    +--------+--------------+
    1 row in set (0.00 sec)
    

    因此,误导性整数“长度”现在已被弃用和删除,这是一件好事。多年来一直引起混乱。

    【讨论】:

    • 我正在使用 MySQL 客户端工具在两个数据库之间同步数据库架构和数据。一个 AWS RDS MySQL 数据库使用 8.0.17 和我的本地 DB MySQL 8.0.19。同步标记了架构差异,并且由于架构不同而无法进行数据同步。我现在已经强制将 Docker 中的本地数据库更改为使用 8.0.17——这也使得它在生产中使用相同的版本保持一致——并且一切运行良好。期待在 AWS 提供此功能后升级到 8.0.19 - 摆脱整数长度会很棒!
    • 是的,像这样的微小差异使得在开发中使用与在生产中使用的所有软件完全相同的版本非常重要。我已经多次看到这种咬人的开发人员,当他们在开发中使用较新的版本时,当它在生产中的工作方式不同时感到惊讶。
    • 听起来需要客户端工具的一个错误——bugs.mysql.com
    • 现在如何解决这个问题?我的意思是如何手动重新创建数据字典信息?
    • @Fakipo 您不应该注意到(11) 部分。除非您使用ZEROFILL,否则它没有任何意义。只是假装它不在那里。它对列的大小或其支持的值范围没有影响。
    【解决方案2】:

    我可以确认已将 AWS RDS 升级到 MySQL 8.0.19,您现在可以使用 Navicat 正确同步。

    但是,请注意!!

    更新 id 列时,如果设置了 auto_increment,Navicat 会移除 auto_increment 以更改长度,然后在最后重新应用它。这会导致 auto_increment 列重新分配 id 是按顺序排列的!

    ALTER TABLE `database`.`table` MODIFY COLUMN `id` mediumint(0) NOT NULL FIRST;
    ...
    ...
    ALTER TABLE `database`.`table` MODIFY COLUMN `id` mediumint(0) NOT NULL AUTO_INCREMENT;
    

    如果您使用表关系并且没有正确设置外键,这将破坏您的数据库!

    此外,如果您的 auto_increment 列中的 id 编号为 0 或以下,则会导致以下错误:

    结果:1​​062 - ALTER TABLE 导致 auto_increment 重新排序, 导致键“table.PRIMARY”的重复条目“1”

    为避免上述情况,您需要手动将每个表的 id 长度更改为 0,然后在尝试使用 Navicat 同步功能之前保存更改。当使用 Navicat 保存更改时,这将自动将任何其他 int 列长度更改为 0。

    在尝试应用到任何生产数据库之前,请确保您在数据库副本上彻底测试您的更改。

    【讨论】:

      猜你喜欢
      • 2021-07-16
      • 1970-01-01
      • 2013-06-16
      • 1970-01-01
      • 2011-01-01
      • 2022-10-20
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      相关资源
      最近更新 更多