Documentation Home
MySQL 8.0 参考手册  / 第 2 章安装和升级 MySQL  / 2.11 升级MySQL  /  2.11.3 MySQL 5.6 的变化

2.11.3 MySQL 5.6 的变化

在升级到 MySQL 5.6 之前,请查看本节中描述的更改以确定适用于您当前的 MySQL 安装和应用程序的更改。执行任何建议的操作。

标记为不兼容更改的更改与早期版本的 MySQL 不兼容,可能需要您在升级前注意。我们的目标是避免这些更改,但有时它们是纠正比版本之间不兼容更糟糕的问题所必需的。如果适用于您的安装的升级问题涉及不兼容性,请按照说明中给出的说明进行操作。有时这涉及转储和重新加载表,或使用诸如CHECK TABLEor 之类的语句REPAIR TABLE

有关转储和重新加载的说明,请参阅 第 2.11.10 节,“重建或修复表或索引”。任何涉及 REPAIR TABLEUSE_FRM选项的过程都必须在升级前完成。将此语句用于与用于创建表的版本不同的 MySQL 版本(即,在升级后使用它)可能会损坏表。请参阅 第 13.7.2.5 节,“REPAIR TABLE 语句”

笔记

从 MySQL 5.6.6 开始,几个 MySQL 服务器参数的默认值与以前的版本不同。请参阅Configuration Changes下有关这些更改的说明 ,特别是关于覆盖它们以保持向后兼容性(如果有问题)。

配置更改

  • 从 MySQL 5.6.6 开始,几个 MySQL 服务器参数的默认值与以前的版本不同。这些更改的动机是提供更好的开箱即用性能并减少数据库管理员手动更改设置的需要。随着我们获得反馈,这些更改可能会在未来的版本中进行修订。

    在某些情况下,参数具有不同的静态默认值。在其他情况下,服务器会在启动时使用基于其他相关参数或服务器主机配置的公式自动调整参数大小,而不是使用静态值。例如, back_log现在的设置是其先前的默认值 50,按与 值成比例的量向上调整 max_connections。autosizing 背后的想法是,当服务器有可用信息来决定参数设置可能优于固定默认值时,它会这样做。

    下表总结了对默认值的更改。通过在服务器启动时指定一个显式值,可以覆盖其中任何一个。

    范围 旧默认 新默认
    back_log 50 自动调整使用max_connections
    binlog_checksum NONE CRC32
    --binlog-row-event-max-size 1024 8192
    flush_time 1800(在 Windows 上) 0
    innodb_autoextend_increment 8个 64
    innodb_buffer_pool_instances 1个 8(取决于平台)
    innodb_checksum_algorithm INNODB CRC32 (changed back to INNODB in MySQL 5.6.7)
    innodb_concurrency_tickets 500 5000
    innodb_file_per_table 0 1
    innodb_old_blocks_time 0 1000
    innodb_open_files 300 自动调整使用innodb_file_per_table, table_open_cache
    innodb_stats_on_metadata ON OFF
    join_buffer_size 128KB 256KB
    max_allowed_packet 1MB 4MB
    max_connect_errors 10 100
    sync_master_info 0 10000
    sync_relay_log 0 10000
    sync_relay_log_info 0 10000

    关于与以前版本的兼容性,最重要的变化是:

    因此,如果您正在升级现有的 MySQL 安装,尚未更改这些参数的先前默认值,并且考虑向后兼容性,您可能希望将这些参数显式设置为其先前的默认值。例如,将这些行放在服务器选项文件中:

    [mysqld]
    innodb_file_per_table=0
    innodb_checksum_algorithm=INNODB
    binlog_checksum=NONE

    这些设置保持兼容性如下:

  • 从 MySQL 5.6.5 开始,4.1 之前的密码和 mysql_old_password身份验证插件已弃用。以 MySQL 4.1 之前使用的旧哈希格式存储的密码不如使用本机密码哈希方法的密码安全,应避免使用。为防止使用具有 4.1 之前密码哈希的帐户进行连接, secure_auth现在默认启用系统变量。(要允许具有此类密码哈希的帐户连接,请使用 启动服务器--secure_auth=0。)

    建议 DBA 将使用 mysql_old_password身份验证插件的帐户转换为使用mysql_native_password。有关帐户升级说明,请参阅 第 6.4.1.3 节,“从 4.1 版之前的密码哈希和 mysql_old_password 插件迁移”

    在 MySQL 5.6(5.6.6 到 5.6.10)的一些早期开发版本中,服务器可以使用不匹配的密码哈希和身份验证插件创建帐户。例如,如果默认身份验证插件是 mysql_native_password,则此语句序列会生成一个带有插件 mysql_native_password但 pre-4.1 密码哈希(由 所使用的格式 mysql_old_password)的帐户:

    SET old_passwords = 1;
    CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';

    不匹配会产生无法连接MySQL服务器、无法使用 SET PASSWORDwith OLD_PASSWORD()或with 等症状old_passwords=1

    从 MySQL 5.6.11 开始,这种不匹配不再发生。相反,服务器会产生一个错误:

    mysql> SET old_passwords = 1;
    mysql> CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'password';
    ERROR 1827 (HY000): The password hash doesn't have the expected
    format. Check if the correct password algorithm is being used with
    the PASSWORD() function.

    要处理受不匹配影响的帐户,DBA 可以修改帐户系统表行中 的plugin或 列,使其与其他列保持一致: Passwordmysql.user

    • 设置为 0,然后使用和 old_passwords为帐户分配一个新密码 。这会将 列设置为具有 4.1 密码哈希,与 插件一致。这是修复帐户的首选方法。 SET PASSWORDPASSWORD()Passwordmysql_native_password

    • 或者,DBA 可以将插件更改 mysql_old_password为使插件匹配密码哈希格式,然后刷新权限。不推荐这样做,因为 mysql_old_password插件和 pre-4.1 密码散列已被弃用;期望在未来版本的 MySQL 中删除对它们的支持。

服务器变更

  • Incompatible change:列DEFAULT值可能对于创建表时的值有效,插入或更新行时sql_mode 的值无效 sql_mode例子:

    SET sql_mode = '';
    CREATE TABLE t (d DATE DEFAULT 0);
    SET sql_mode = 'NO_ZERO_DATE,STRICT_ALL_TABLES';
    INSERT INTO t (d) VALUES(DEFAULT);

    在这种情况下,应该接受 0 CREATE TABLE而拒绝0 INSERT。但是,服务器没有DEFAULT根据当前的 sql_mode. 在示例中, INSERT成功并插入 '0000-00-00'DATE列中。

    从 MySQL 5.6.13 开始,服务器应用适当的 sql_mode检查以在插入或更新时生成警告或错误。

    如果您使用基于语句的日志记录 ( binlog_format=STATEMENT),则复制的不兼容性是,如果升级了副本,则尚未升级的源会无错误地执行前面的示例,而INSERT副本上的失败和复制停止。

    为了解决这个问题,停止源上的所有新语句并等待副本赶上。然后升级副本,然后升级源。或者,如果您无法停止新语句,请暂时更改为源 ( binlog_format=ROW) 上的基于行的日志记录,并等待所有副本处理到此更改点为止生成的所有二进制日志。然后升级副本,然后升级源,并将源更改回基于语句的日志记录。

  • Incompatible change : MySQL 5.6.11 and later supports ,可用于创建 分区兼容MySQL 5.1服务器的表(=1)。(Bug #14521864,Bug #66462)尽管从 MySQL 5.5.31 开始的 MySQL 5.5 支持此语法,但 MySQL 5.6.10 及更早版本不接受此语法。MySQL 5.5.31 和更高版本的 MySQL 5.5 中的 mysqldump包括使用此选项转储表时的选项,但用条件注释包围它,如下所示: CREATE TABLE ... [SUB]PARTITION BY ALGORITHM=n [LINEAR] KEY (...)KEYnALGORITHM

    CREATE TABLE t1 (a INT)
    /*!50100 PARTITION BY KEY */ /*!50531 ALGORITHM = 1 */ /*!50100 ()
          PARTITIONS 3 */

    将包含此类CREATE TABLE语句的转储导入 MySQL 5.6.10 或更早的 MySQL 5.6 服务器时,不会忽略版本注释,这会导致语法错误。因此,在导入这样的转储文件之前,您必须更改注释以便 MySQL 5.6 服务器忽略它们(通过删除字符串!50531或将其替换为 !50611,无论它出现在哪里),或者删除它们。

    这不是使用 MySQL 5.6.11 或更高版本生成的转储文件的问题,其中ALGORITHM选项使用/*!50611 ... */.

  • Incompatible change:对于 TIMEDATETIMETIMESTAMPcolumns,MySQL 5.6.4 之前创建的表所需的存储与 5.6.4 及更高版本中创建的表所需的存储不同。这是由于 5.6.4 中的更改允许这些时间类型具有小数部分。此更改会影响依赖于行格式的语句的输出,例如CHECKSUM TABLE. 从 MySQL 5.5 升级到 MySQL 5.6.4 或更高版本后,建议您也从 MySQL 5.5 升级到 MySQL 5.6TIMEDATETIMETIMESTAMPtypes。 ALTER TABLE目前允许创建包含 MySQL 5.5 和 MySQL 5.6.4(或更高版本)二进制格式的临时列的表,但这使得在 .frm文件不可用的情况下重新创建表变得更加困难。此外,从 MySQL 5.6.4 开始,上述时间类型的空间效率更高。有关 MySQL 5.6.4 中时间类型更改的更多信息,请参阅 日期和时间类型存储要求

    从 MySQL 5.6.16 开始,ALTER TABLE将旧的临时列升级到 5.6 格式,用于ADD COLUMNCHANGE COLUMNMODIFY COLUMNADD INDEXFORCE 操作。因此,以下语句升级包含旧格式列的表:

    ALTER TABLE tbl_name FORCE;

    INPLACE由于必须重建表,因此 无法使用该算法完成此转换 ,因此ALGORITHM=INPLACE在这些情况下指定会导致错误。ALGORITHM=COPY必要时 指定。

    ALTER TABLE确实产生时间格式转换时,它会生成一条消息,该消息可以用SHOW WARNINGS:显示TIME/TIMESTAMP/DATETIME columns of old format have been upgraded to the new format

    升级到 MySQL 5.6.4 或更高版本时,请注意 CHECK TABLE ... FOR UPGRADE不会报告使用 MySQL 5.6.4 之前的格式的临时列(Bug #73008,Bug #18985579)。在 MySQL 5.6.24 中,添加了两个新的系统变量 avoid_temporal_upgradeshow_old_temporals,以提供对时间列升级的控制(Bug #72997,Bug #18985760)。

  • 由于上面先前不兼容的更改项中描述的临时类型更改,将 ALTER TABLE ... IMPORT TABLESPACE包含 DATETIMETIMESTAMP类型的 MySQL 5.6.4 之前的表(使用)导入 MySQL 5.6.4(或更高版本)失败。将具有这些临时类型的 MySQL 5.5 表导入 MySQL 5.6.4(或更高版本)是最有可能发生此问题的情况。

    以下过程描述了使用原始 MySQL 5.6.4 之前的.frm文件重新创建具有与 5.6.4(或更高版本)兼容的行结构的表的变通方法。这些过程涉及将原始 MySQL 5.6.4 之前的.frm文件更改为使用Memory存储引擎而不是InnoDB,将文件复制 .frm到目标实例的数据目录,并使用ALTER TABLE将表的存储引擎类型更改回InnoDB。如果您的表没有外键,请使用第一个过程。如果您的表包含外键,请使用第二个过程,它有额外的步骤。

    如果表没有外键:

    1. 将表的原始.frm文件复制到要导入表空间的服务器上的数据目录。

    2. 修改表的.frm文件以使用Memory存储引擎而不是InnoDB存储引擎。此修改需要更改 .frm文件中定义表的存储引擎类型的 7 个字节。使用十六进制编辑工具:

      • 将偏移位置0003处的字节,即legacy_db_type,由 0c(for InnoDB)改为06 (for Memory),如下图:

        00000000  fe 01 09 06 03 00 00 10  01 00 00 30 00 00 10 00
      • 剩下的 6 个字节没有固定的偏移量。在.frm文件中 搜索InnoDB以找到包含其他 6 个字节的行。该行如下所示:

        00001010  ff 00 00 00 00 00 00 06  00 49 6e 6e 6f 44 42 00  |.........InnoDB.|
      • 修改字节,使该行显示如下:

        00001010  ff 00 00 00 00 00 00 06 00 4d 45 4d 4f 52 59 00
    3. 运行ALTER TABLE ... ENGINE=INNODB以将表定义添加到InnoDB数据字典。这将创建InnoDB 具有新格式的时态数据类型的表。要ALTER TABLE 成功完成操作, .frm文件必须对应于表空间。

    4. 使用导入表 ALTER TABLE ... IMPORT TABLESPACE

    如果表有外键:

    1. 使用输出中的表定义重新创建具有外键的表SHOW CREATE TABLE。此时不正确的时间列格式无关紧要。

    2. INFORMATION_SCHEMA.TABLE_CONSTRAINTS 通过从和 中 选择外键信息,将所有外键定义转储到文本文件中 INFORMATION_SCHEMA.KEY_COLUMN_USAGE

    3. 删除所有表并完成上述过程中针对没有外键的表的步骤 1 至 4 中描述的表导入过程。

    4. 导入操作完成后,将您保存的外键定义中的外键添加到文本文件中。

  • 不兼容的更改latin1:从 MySQL 5.6 开始,使用if character_set_serveris ucs2utf16utf16le或加载和搜索全文停用词文件utf32FULLTEXT 如果在服务器字符集为 ucs2utf16utf16le或使用索引创建了任何表utf32使用以下语句修复它:

    REPAIR TABLE tbl_name QUICK;
  • 不兼容的更改:在 MySQL 5.6.20 中,Bug #69477 的补丁将重做日志BLOB写入的大小限制为重做日志文件大小的 10%。由于此新限制, innodb_log_file_size应设置为大于 BLOB表行中最大数据大小的 10 倍的值。如果您的 innodb_log_file_size 设置已经是最大 BLOB数据大小的 10 倍或您的表不包含任何BLOB数据,则无需执行任何操作。

    在 MySQL 5.6.22 中,重做日志 BLOB写入限制放宽到重做日志总大小 ( innodb_log_file_size* innodb_log_files_in_group) 的 10%。(漏洞#19498877)

InnoDB 的变化

从 MySQL 5.6.42 开始,与 MySQL 捆绑的zlib 库版本从 1.2.3 版本提升到 1.2.11 版本。

zlib 1.2.11 中的 zlibcompressBound()函数返回比 zlib 版本 1.2.3 中压缩给定字节长度所需的缓冲区大小略高的估计值。该compressBound()函数由确定创建压缩表或将行插入压缩表InnoDB时允许的最大行大小 的函数调用。因此, 在早期版本中成功的行大小非常​​接近最大行大小的操作现在可能会失败 。 InnoDBInnoDBCREATE TABLE ... ROW_FORMAT=COMPRESSEDINSERT

如果您有大行压缩InnoDB表,建议您 CREATE TABLE在升级前在 MySQL 5.6 测试实例上测试压缩表语句。

SQL 更改

  • 一些关键字可能在 MySQL 5.6 中保留,但在 MySQL 5.5 中没有保留。请参阅 第 9.3 节,“关键字和保留字”。这可能会导致以前用作标识符的词变得非法。要修复受影响的语句,请使用标识符引用。请参阅 第 9.2 节,“模式对象名称”

  • 在选择使用该YEAR(2)数据类型之前,您应该考虑某些问题。从 MySQL 5.6.6 开始,YEAR(2)已弃用: YEAR(2)现有表中的列与以前一样处理,但YEAR(2)在新表或更改的表中将转换为YEAR(4). 有关详细信息,请参阅 第 11.2.5 节,“2 位 YEAR(2) 限制和迁移到 4 位 YEAR”

  • 从 MySQL 5.6.6 开始,明确不允许将值分配DEFAULT给存储过程或函数参数或存储程序局部变量(例如使用 语句)。这以前不受支持,也未按允许记录,但被标记为不兼容的更改,以防现有代码无意中使用此构造。仍然允许像以前一样分配给系统变量,但 现在分配给参数或局部变量会导致语法错误。 SET var_name = DEFAULTDEFAULTDEFAULT

    升级到 MySQL 5.6.6 或更高版本后,使用此构造的现有存储程序在调用时会产生语法错误。如果将 5.6.5 或更早版本的mysqldump文件加载到 5.6.6 或更高版本,加载操作将失败,并且必须更改受影响的存储程序定义。

  • 在 MySQL 中,TIMESTAMP数据类型与其他数据类型的非标准方式不同:

    • TIMESTAMP未明确声明该NULL 属性的列将分配该NOT NULL 属性。(其他数据类型的列,如果未明确声明为NOT NULL,则允许NULL值。)设置此类列以NULL将其设置为当前时间戳。

    • 表中的第一TIMESTAMP 列,如果未使用 NULL属性或显式 DEFAULTorON UPDATE子句声明,则自动分配 DEFAULT CURRENT_TIMESTAMPand ON UPDATE CURRENT_TIMESTAMP 属性。

    • TIMESTAMP第一列之后的列,如果未使用 NULL属性或显式 DEFAULT子句声明,将自动分配DEFAULT '0000-00-00 00:00:00'时间戳)。对于没有为此类列指定显式值的插入行,将分配该列 '0000-00-00 00:00:00'并且不会出现警告。

    这些非标准行为仍然是默认行为, TIMESTAMP但从 MySQL 5.6.6 开始已弃用,并且此警告出现在启动时:

    [Warning] TIMESTAMP with implicit DEFAULT value is deprecated.
    Please use --explicit_defaults_for_timestamp server option (see
    documentation for more details).

    如警告所示,要关闭非标准行为,请 explicit_defaults_for_timestamp 在服务器启动时启用新的系统变量。启用此变量后,服务器 TIMESTAMP将按如下方式处理:

    • TIMESTAMP未明确声明为NOT NULL 允许NULL值的列。设置此类列以NULL将其设置为 NULL,而不是当前时间戳。

    • 不会自动为任何TIMESTAMP列分配DEFAULT CURRENT_TIMESTAMPON UPDATE CURRENT_TIMESTAMP属性。必须明确指定这些属性。

    • TIMESTAMP声明为NOT NULL和没有显式DEFAULT子句的列被视为没有默认值。对于没有为此类列指定显式值的插入行,结果取决于 SQL 模式。如果启用严格 SQL 模式,则会发生错误。如果未启用严格 SQL 模式,则会为该列分配隐式默认值 '0000-00-00 00:00:00'并出现警告。这类似于 MySQL 处理其他时间类型的方式,例如 DATETIME.

    要升级用于复制的服务器,请先升级副本,然后再升级源。源及其副本之间的复制应该可以工作,前提是它们都使用相同的值 explicit_defaults_for_timestamp

    1. 关闭副本,升级它们,使用所需的值配置它们 explicit_defaults_for_timestamp,然后将它们重新启动。

      副本从源接收到的二进制日志的格式中识别出源较旧(早于引入 explicit_defaults_for_timestamp)并且对 TIMESTAMP来自源的列的操作使用旧 TIMESTAMP行为。

    2. 关闭源,对其进行升级, explicit_defaults_for_timestamp 使用在副本上使用的相同值对其进行配置,然后将其重新启动。