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

2.11.3 MySQL 5.7 的变化

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

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

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

配置更改

系统表更改

服务器变更

  • 不兼容的更改:从 MySQL 5.7.5 开始,删除了对使用较旧的 4.1 之前的密码哈希格式的密码的支持,这涉及以下更改。必须修改使用不再受支持的任何功能的应用程序。

    • 使用 pre-4.1 密码哈希值的mysql_old_password身份验证插件已被删除。使用此插件的帐户在启动时被禁用,服务器会在错误日志中写入一条未知插件”消息。有关升级使用此插件的帐户的说明,请参阅第 6.4.1.3 节,“从 4.1 版之前的密码哈希和 mysql_old_password 插件迁移”

    • 对于old_passwords 系统变量,不再允许值为 1(生成 4.1 之前的哈希值)。

    • 服务器和客户端程序的--secure-auth选项是默认选项,但现在是空操作。它已被弃用;预计在未来的 MySQL 版本中将其删除。

    • --skip-secure-auth不再支持服务器和客户端程序 的选项,使用它会产生错误。

    • 系统secure_auth变量只允许值为 1;不再允许值为 0。

    • OLD_PASSWORD()功能已删除。

  • 不兼容的更改:在 MySQL 5.6.6 中,不推荐使用 2 位 YEAR(2)数据类型。在 MySQL 5.7.5 中, YEAR(2)删除了对的支持。升级到 MySQL 5.7.5 或更高版本后,任何剩余的 2 位列 YEAR(2)必须转换为 4 位列YEAR 才能再次使用。有关转换策略,请参阅第 11.2.5 节,“2 位 YEAR(2) 限制和迁移到 4 位 YEAR”。升级后运行 mysql_upgrade是一种可能的转换策略。

  • 从 MySQL 5.7.7 开始, 如果表包含 5.6.4 之前格式的旧时间列( 、 和 不支持小数秒精度的列)并且 系统变量被禁用,CHECK TABLE ... FOR UPGRADE则将表报告为需要重建。这有助于 mysql_upgrade检测和升级包含旧时间列的表。如果 启用,则忽略表中存在的旧时间列;因此, mysql_upgrade不会升级它们。 TIMEDATETIMETIMESTAMPavoid_temporal_upgradeavoid_temporal_upgradeFOR UPGRADE

    从 MySQL 5.7.7 开始,REPAIR TABLE如果表包含 5.6.4 之前格式的旧时间列并且 avoid_temporal_upgrade 系统变量被禁用,则升级表。如果 avoid_temporal_upgrade启用,则REPAIR TABLE忽略表中存在的旧时间列并且不升级它们。

    要检查包含此类临时列并需要重建的表,请 avoid_temporal_upgrade 在执行前 禁用CHECK TABLE ... FOR UPGRADE

    要升级包含此类临时列的表, 请avoid_temporal_upgrade 在执行前禁用REPAIR TABLEmysql_upgrade

  • 不兼容的更改:从 MySQL 5.7.2 开始,服务器要求系统表中的帐户行 mysql.user具有非空plugin列值并禁用具有空值的帐户。这需要您升级mysql.user表格以填写所有 plugin值。从 MySQL 5.7.6 开始,使用以下过程:

    如果您计划使用现有 MySQL 安装中的数据目录进行升级:

    1. 停止旧的 (MySQL 5.6) 服务器

    2. 通过用新二进制文件替换旧二进制文件来就地升级 MySQL 二进制文件

    3. 正常启动MySQL 5.7服务器(无特殊选项)

    4. 运行mysql_upgrade升级系统表

    5. 重启 MySQL 5.7 服务器

    如果您计划通过重新加载从现有 MySQL 安装生成的转储文件来升级:

    1. 要生成转储文件,请运行 带 选项和不带 选项 的mysqldump--add-drop-table--flush-privileges

    2. 停止旧的 (MySQL 5.6) 服务器

    3. 就地升级 MySQL 二进制文件(用新二进制文件替换旧二进制文件)

    4. 正常启动MySQL 5.7服务器(无特殊选项)

    5. 重新加载转储文件 ( mysql < dump_file )

    6. 运行mysql_upgrade升级系统表

    7. 重启 MySQL 5.7 服务器

    MySQL 5.7.6之前,流程比较复杂:

    如果您计划使用现有 MySQL 安装中的数据目录进行升级:

    1. 停止旧的 (MySQL 5.6) 服务器

    2. 就地升级 MySQL 二进制文件(用新二进制文件替换旧二进制文件)

    3. --skip-grant-tables 使用禁用权限检查 的选项重新启动服务器

    4. 运行mysql_upgrade升级系统表

    5. 正常重启服务器(没有 --skip-grant-tables

    如果您计划通过重新加载从现有 MySQL 安装生成的转储文件来升级:

    1. 要生成转储文件,请运行 不带 选项 的mysqldump--flush-privileges

    2. 停止旧的 (MySQL 5.6) 服务器

    3. 就地升级 MySQL 二进制文件(用新二进制文件替换旧二进制文件)

    4. --skip-grant-tables 使用禁用权限检查 的选项重新启动服务器

    5. 重新加载转储文件 ( mysql < dump_file )

    6. 运行mysql_upgrade升级系统表

    7. 正常重启服务器(没有 --skip-grant-tables

    mysql_upgrade默认以 MySQLroot用户身份运行。对于上述过程,如果root运行mysql_upgrade时密码已过期,则会显示一条消息,通知您密码已过期,因此mysql_upgrade失败。要更正此问题,请重置root 密码并再次运行mysql_upgrade

    $> mysql -u root -p
    Enter password: ****  <- enter root password here
    mysql> ALTER USER USER() IDENTIFIED BY 'root-password'; # MySQL 5.7.6 and up
    mysql> SET PASSWORD = PASSWORD('root-password');        # Before MySQL 5.7.6
    mysql> quit
    
    $> mysql_upgrade -p
    Enter password: ****  <- enter root password here

    如果服务器以 启动,密码重置语句通常不起作用 --skip-grant-tables,但mysql_upgrade的第一次调用刷新权限,因此当您运行mysql时,该语句被接受。

    如果mysql_upgrade本身使 root密码过期,您必须以同样的方式重新设置密码。

    在按照前面的说明进行操作后,建议 DBA 也将使用 mysql_old_password身份验证插件的帐户转换为使用mysql_native_password,因为对的支持mysql_old_password 已被删除。有关帐户升级说明,请参阅 第 6.4.1.3 节,“从 4.1 版之前的密码哈希和 mysql_old_password 插件迁移”

  • 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.7.2 开始,服务器应用适当的 sql_mode检查以在插入或更新时生成警告或错误。

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

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

  • 不兼容的更改:为了更好地与 Oracle Audit Vault 兼容,对审计日志插件进行了多项更改。出于升级目的,主要问题是审核日志文件的默认格式已更改: <AUDIT_RECORD>以前使用属性编写的元素中的信息现在使用子元素编写。

    <AUDIT_RECORD> 旧格式 示例:

    <AUDIT_RECORD
     TIMESTAMP="2013-04-15T15:27:27"
     NAME="Query"
     CONNECTION_ID="3"
     STATUS="0"
     SQLTEXT="SELECT 1"
    />

    新格式示例:

    <AUDIT_RECORD>
     <TIMESTAMP>2013-04-15T15:27:27 UTC</TIMESTAMP>
     <RECORD_ID>3998_2013-04-15T15:27:27</RECORD_ID>
     <NAME>Query</NAME>
     <CONNECTION_ID>3</CONNECTION_ID>
     <STATUS>0</STATUS>
     <STATUS_CODE>0</STATUS_CODE>
     <USER>root[root] @ localhost [127.0.0.1]</USER>
     <OS_LOGIN></OS_LOGIN>
     <HOST>localhost</HOST>
     <IP>127.0.0.1</IP>
     <COMMAND_CLASS>select</COMMAND_CLASS>
     <SQLTEXT>SELECT 1</SQLTEXT>
    </AUDIT_RECORD>

    如果您以前使用过旧版本的审计日志插件,请使用此过程来避免将新格式的日志条目写入包含旧格式条目的现有日志文件:

    1. 停止服务器。

    2. 手动重命名当前审计日志文件。此文件包含仅使用旧格式的日志条目。

    3. 更新服务器并重新启动它。审计日志插件创建一个新的日志文件,其中包含仅使用新格式的日志条目。

    有关审计日志插件的信息,请参阅 第 6.4.5 节,“MySQL 企业审计”

  • 从 MySQL 5.7.7 开始,副本的默认连接超时从 3600 秒(一小时)更改为 60 秒(一分钟)。slave_net_timeout当没有系统变量设置的副本升级到 MySQL 5.7 时,将应用新的默认值 。心跳间隔的默认设置,它调节心跳信号以在连接仍然良好的情况下停止在没有数据的情况下发生的连接超时,计算为值的一半 slave_net_timeout。心跳间隔记录在副本的源信息日志中(mysql.slave_master_info表或 master.info文件),并且当 的值或默认设置更改时,它不会自动 slave_net_timeout更改。使用默认连接超时和心跳间隔的 MySQL 5.6 副本,然后升级到 MySQL 5.7,因此心跳间隔比连接超时长得多。

    如果源上的活动级别使得对二进制日志的更新至少每 60 秒发送一次到副本,则这种情况不是问题。但是,如果没有从源接收到数据,因为没有发送心跳,连接超时到期。副本因此认为与源的连接已丢失并进行多次重新连接尝试(由MASTER_CONNECT_RETRYMASTER_RETRY_COUNT设置控制,也可以在源信息日志中看到)。重新连接尝试产生大量僵尸转储线程,源必须杀死这些线程,导致源上的错误日志包含多个形式的错误在使用 UUID 为从属初始化转储线程时 uuid,发现了一个具有相同 UUID 的僵尸转储线程。Master 正在杀死僵尸转储线程 threadid。为避免此问题,在将副本升级到 MySQL 5.7 之前,立即检查 slave_net_timeout系统变量是否使用默认设置。如果是这样,请发出 CHANGE MASTER TOMASTER_HEARTBEAT_PERIOD选项,并将心跳间隔设置为 30 秒,以便它适用于升级后适用的新连接超时 60 秒。

  • 不兼容的更改:MySQL 5.6.22 及更高版本承认该 REFERENCES特权但并未完全强制执行;SELECT具有、 INSERTUPDATEDELETE或 中至少一项的用户 REFERENCES可以在表上创建外键约束。MySQL 5.7(及更高版本)要求用户拥有REFERENCES这样做的特权。这意味着如果您将用户从 MySQL 5.6 服务器(任何版本)迁移到运行 MySQL 5.7 的服务器,您必须确保将此权限明确授予任何需要能够创建外键的用户。这包括用于导入包含带有外键的表的转储的用户帐户。

InnoDB 的变化

  • 从 MySQL 5.7.24 开始,与 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.7 测试实例上测试压缩表语句。

  • 不兼容的更改:为了简化InnoDB崩溃恢复期间的表空间发现,MySQL 5.7.5 中引入了新的重做日志记录类型。此增强功能更改了重做日志格式。在执行就地升级之前,使用 或innodb_fast_shutdown 设置。In-Place Upgrade中的推荐步骤是 使用缓慢关闭 。 01innodb_fast_shutdown=0

  • 不兼容的更改:MySQL 5.7.8 和 5.7.9 撤消日志可能包含有关空间列的信息不足,这可能导致升级失败(错误 #21508582)。在执行从 MySQL 5.7.8 或 5.7.9 到 5.7.10 或更高版本的就地升级之前,执行缓慢关闭 innodb_fast_shutdown=0以清除撤消日志。In-Place Upgradeinnodb_fast_shutdown=0中的推荐步骤是 使用缓慢关闭 。

  • 不兼容的更改:MySQL 5.7.8 撤消日志可能包含有关虚拟列和虚拟列索引的信息不足,这可能导致升级失败(错误 #21869656)。在执行从 MySQL 5.7.8 到 MySQL 5.7.9 或更高版本的就地升级之前,执行缓慢关闭 innodb_fast_shutdown=0以清除撤消日志。In-Place Upgradeinnodb_fast_shutdown=0中的推荐步骤是 使用缓慢关闭 。

  • 不兼容的更改:从 MySQL 5.7.9 开始,第一个重做日志文件 (ib_logfile0) 的重做日志标头包括一个格式版本标识符和一个文本字符串,用于标识创建重做日志文件的 MySQL 版本。此增强功能更改了重做日志格式,要求使用 或 在执行就地升级到 MySQL 5.7.9 或更高版本之前innodb_fast_shutdown 设置In-Place Upgrade中的推荐步骤是 使用缓慢关闭 。 01innodb_fast_shutdown=0

  • 在 MySQL 5.7.9 中,DYNAMIC替换 COMPACTInnoDB表的隐式默认行格式。一个新的配置选项, innodb_default_row_format指定默认的InnoDB行格式。允许DYNAMIC的值包括(默认值)COMPACT、 和 REDUNDANT

    升级到 5.7.9 后,您创建的任何新表都使用定义的行格式, innodb_default_row_format 除非您显式定义行格式 ( ROW_FORMAT)。

    对于未显式定义 ROW_FORMAT选项或使用 的现有表ROW_FORMAT=DEFAULT,任何重建表的操作也会默默地将表的行格式更改为由定义的格式 innodb_default_row_format。否则,现有表会保留其当前的行格式设置。有关详细信息,请参阅 定义表的行格式

  • 从 MySQL 5.7.6 开始存储引擎InnoDB 对使用. InnoDB在以前版本的 MySQL 中创建的分区 InnoDB表不会自动升级。您可以使用以下任一方法轻松升级此类表以InnoDB 在 MySQL 5.7.9 或更高版本中使用本机分区:

SQL 更改

  • 不兼容的更改:该 GET_LOCK()功能在 MySQL 5.7.5 中使用元数据锁定 (MDL) 子系统重新实现,并且其功能已得到扩展:

    • 以前,GET_LOCK() 一次只允许获取一个命名锁,第二次GET_LOCK() 调用会释放任何现有锁。现在 GET_LOCK()允许同时获取多个命名锁并且不释放现有锁。

      依赖 GET_LOCK()释放任何先前锁定行为的应用程序必须针对新行为进行修改。

    • 获取多个锁的能力引入了客户端之间死锁的可能性。MDL 子系统检测死锁并 ER_USER_LOCK_DEADLOCK 在发生这种情况时返回错误。

    • MDL 子系统对锁名称施加了 64 个字符的限制,因此此限制现在也适用于命名锁。以前,没有强制执行长度限制。

    • 获得的锁 GET_LOCK()现在出现在 Performance Schema metadata_locks表中。列 OBJECT_TYPE表示USER LEVEL LOCKOBJECT_NAME列表示锁名称。

    • 一个新功能, RELEASE_ALL_LOCKS() 允许一次释放所有获得的命名锁。

    有关详细信息,请参阅 第 12.15 节,“锁定功能”

  • 优化器现在以一致的方式处理子句中的派生表和视图, FROM以更好地避免不必要的具体化,并支持使用下推条件来生成更高效的执行计划。

    但是在 MySQL 5.7.11 之前的 MySQL 5.7 中,对于诸如DELETEor 之类UPDATE的修改表的语句,对先前物化的派生表使用合并策略会导致 ER_UPDATE_TABLE_USED错误:

    mysql> DELETE FROM t1
        -> WHERE id IN (SELECT id
        ->              FROM (SELECT t1.id
        ->                    FROM t1 INNER JOIN t2 USING (id)
        ->                    WHERE t2.status = 0) AS t);
    ERROR 1093 (HY000): You can't specify target table 't1'
    for update in FROM clause

    将派生表合并到外部查询块时会发生错误,导致语句同时从表中进行选择和修改。(具体化不会导致问题,因为实际上它将派生表转换为单独的表。)避免此错误的解决方法是在执行语句之前禁用系统变量 的derived_merge 标志 :optimizer_switch

    SET optimizer_switch = 'derived_merge=off';

    derived_merge标志控制优化器是否尝试将FROM子句中的子查询和视图合并到外部查询块中,假设没有其他规则阻止合并。默认情况下,该标志是on启用合并。将标志设置为off 防止合并并避免刚才描述的错误。有关详细信息,请参阅 第 8.2.2.4 节,“使用合并或实现优化派生表和视图引用”

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

  • 升级后,建议您测试应用程序代码中指定的优化器提示,以确保仍然需要这些提示来实现所需的优化策略。优化器增强功能有时会使某些优化器提示变得不必要。在某些情况下,不必要的优化器提示甚至可能适得其反。

  • UNION语句中,要将 ORDER BYorLIMIT应用于个人SELECT,请将子句放在括号内 SELECT

    (SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
    UNION
    (SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);

    以前版本的 MySQL 可能允许这样的语句不带括号。在 MySQL 5.7 中,强制要求使用括号。