## 14.7 数据字典使用差异

[](<>)

与没有数据字典的服务器相比，使用启用数据字典的 MySQL 服务器需要一些操作差异：

-   以前，启用[`innodb_read_only`](innodb-parameters.html#sysvar_innodb_read_only)系统变量仅阻止创建和删除表`InnoDB`存储引擎。从 MySQL 8.0 开始，启用[`innodb_read_only`](innodb-parameters.html#sysvar_innodb_read_only)阻止所有存储引擎的这些操作。任何存储引擎的表创建和删除操作都会修改数据字典中的表`mysql`系统数据库，但这些表使用`InnoDB`存储引擎，不能修改时[`innodb_read_only`](innodb-parameters.html#sysvar_innodb_read_only)已启用。同样的原则也适用于其他需要修改数据字典表的表操作。例子：

    -   [`分析表`](analyze-table.html)失败，因为它更新了存储在数据字典中的表统计信息。

    -   [`更改表 *`tbl_name`*引擎=*`引擎名称`*`](alter-table.html)失败，因为它更新了存储在数据字典中的存储引擎名称。

    笔记

    启用[`innodb_read_only`](innodb-parameters.html#sysvar_innodb_read_only)对非数据字典表也有重要影响`mysql`系统数据库。有关详细信息，请参阅说明[`innodb_read_only`](innodb-parameters.html#sysvar_innodb_read_only)在[第 15.14 节，“InnoDB 启动选项和系统变量”](innodb-parameters.html)

-   以前，表中的`mysql`系统数据库对 DML 和 DDL 语句可见。从 MySQL 8.0 开始，数据字典表是不可见的，不能直接修改或查询。但是，在大多数情况下，有相应的`INFORMATION_SCHEMA`可以查询的表。这使得底层数据字典表可以随着服务器开发的进行而改变，同时保持稳定`INFORMATION_SCHEMA`应用程序使用的接口。

-   `INFORMATION_SCHEMA`MySQL 8.0 中的表与数据字典密切相关，导致使用上的一些差异：

    -   之前，`INFORMATION_SCHEMA`查询表中的统计信息[`统计数据`](information-schema-statistics-table.html)和[`表格`](information-schema-tables-table.html)表直接从存储引擎检索统计信息。从 MySQL 8.0 开始，默认使用缓存表统计信息。这[`information_schema_stats_expiry`](server-system-variables.html#sysvar_information_schema_stats_expiry)系统变量定义缓存表统计信息过期之前的时间段。默认值为 86400 秒（24 小时）。（要随时更新给定表的缓存值，请使用[`分析表`](analyze-table.html).) 如果没有缓存统计信息或统计信息已过期，则在查询表统计信息列时从存储引擎中检索统计信息。要始终直接从存储引擎中检索最新的统计信息，请设置[`information_schema_stats_expiry`](server-system-variables.html#sysvar_information_schema_stats_expiry)到`0`.有关详细信息，请参阅[第 8.2.3 节，“优化信息\_SCHEMA 查询”](information-schema-optimization.html).

    -   一些`INFORMATION_SCHEMA`表是数据字典表的视图，它使优化器能够在这些基础表上使用索引。因此，根据优化器的选择，结果的行顺序为`INFORMATION_SCHEMA`查询可能与以前的结果不同。如果查询结果必须具有特定的行排序特征，请包括`订购方式`条款。

    -   查询`INFORMATION_SCHEMA`表可能以不同于早期 MySQL 系列的字母大小写返回列名。应用程序应该以不区分大小写的方式测试结果集列名。如果这不可行，一种解决方法是在选择列表中使用列别名，以所需的字母大小写返回列名。例如：

        ```
        SELECT TABLE_SCHEMA AS table_schema, TABLE_NAME AS table_name
        FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'users';
        ```

    -   [**mysql转储**](mysqldump.html)和[**mysql泵**](mysqlpump.html)不再倾倒`INFORMATION_SCHEMA`数据库，即使在命令行上显式命名。

    -   [`创建表 *`dst_tbl`* 喜欢 *`src_tbl`*`](create-table-like.html)要求*`src_tbl`*是一个基表，如果它是一个则失败`INFORMATION_SCHEMA`表，它是数据字典表的视图。

    -   以前，从选择的列的结果集标题`INFORMATION_SCHEMA`表使用了查询中指定的大小写。此查询生成一个带有标题的结果集`表名`：

        ```
        SELECT table_name FROM INFORMATION_SCHEMA.TABLES;
        ```

        从 MySQL 8.0 开始，这些标头都是大写的；前面的查询产生一个带有标题的结果集`TABLE_NAME`.如有必要，可以使用列别名来实现不同的字母大小写。例如：

        ```
        SELECT table_name AS 'table_name' FROM INFORMATION_SCHEMA.TABLES;
        ```

-   数据目录影响如何[**mysql转储**](mysqldump.html)和[**mysql泵**](mysqlpump.html)转储信息`mysql`系统数据库：

    -   以前，可以将所有表转储到`mysql`系统数据库。从 MySQL 8.0 开始，[**mysql转储**](mysqldump.html)和[**mysql泵**](mysqlpump.html)仅转储该数据库中的非数据字典表。

    -   此前，该[`--例程`](mysqldump.html#option_mysqldump_routines)和[`--事件`](mysqldump.html#option_mysqldump_events)选项不需要包括存储的例程和事件时使用[`--所有数据库`](mysqldump.html#option_mysqldump_all-databases)选项：转储包括`mysql`系统数据库，因此也`过程`和`事件`包含存储的例程和事件定义的表。从 MySQL 8.0 开始，`事件`和`过程`不使用表。相应对象的定义存储在数据字典表中，但不会转储这些表。在转储中包含存储的例程和事件，使用[`--所有数据库`](mysqldump.html#option_mysqldump_all-databases)， 使用[`--例程`](mysqldump.html#option_mysqldump_routines)和[`--事件`](mysqldump.html#option_mysqldump_events)明确的选项。

    -   此前，该[`--例程`](mysqldump.html#option_mysqldump_routines)选项需要[`选择`](privileges-provided.html#priv_select)的特权`过程`桌子。从 MySQL 8.0 开始，不使用该表；[`--例程`](mysqldump.html#option_mysqldump_routines)需要全局[`选择`](privileges-provided.html#priv_select)取而代之的是特权。

    -   以前，可以将存储的例程和事件定义连同它们的创建和修改时间戳一起转储，通过转储`过程`和`事件`表。从 MySQL 8.0 开始，这些表未使用，因此无法转储时间戳。

-   以前，创建包含非法字符的存储例程会产生警告。从 MySQL 8.0 开始，这是一个错误。
