8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 100%

17.10 InnoDB 行格式17.10 InnoDB Row Formats

表的行格式决定了其行数据的物理存储方式,这反过来会影响查询和 DML 操作的性能。当更多的行可以存放在一个磁盘页中时,查询和索引查找可以更快完成,缓冲池中所需的缓存内存更少,写出更新值所需的 I/O 也更少。The row format of a table determines how its rows are physically stored, which in turn can affect the performance of queries and DML operations. As more rows fit into a single disk page, queries and index lookups can work faster, less cache memory is required in the buffer pool, and less I/O is required to write out updated values.

每个表中的数据被划分为页。组成每个表的页排列成一种称为 B 树索引的树状数据结构。表数据和二级索引都使用这种结构。代表整个表的 B 树索引被称为聚簇索引,它是根据主键列组织的。聚簇索引数据结构的节点包含行中所有列的值。二级索引结构的节点包含索引列和主键列的值。The data in each table is divided into pages. The pages that make up each table are arranged in a tree data structure called a B-tree index. Table data and secondary indexes both use this type of structure. The B-tree index that represents an entire table is known as the clustered index, which is organized according to the primary key columns. The nodes of a clustered index data structure contain the values of all columns in the row. The nodes of a secondary index structure contain the values of index columns and primary key columns.

可变长度列是列值存储在 B 树索引节点中的规则的一个例外。过长而无法放入 B 树页的可变长度列存储在单独分配的磁盘页上,称为溢出页。这样的列被称为页外列。页外列的值存储在溢出页的单向链表中,每个此类列都有自己的一条或多条溢出页链表。根据列的长度,可变长度列的全部或部分前缀值存储在 B 树中,以避免浪费存储空间并且避免读取单独的页面。Variable-length columns are an exception to the rule that column values are stored in B-tree index nodes. Variable-length columns that are too long to fit on a B-tree page are stored on separately allocated disk pages called overflow pages. Such columns are referred to as off-page columns. The values of off-page columns are stored in singly-linked lists of overflow pages, with each such column having its own list of one or more overflow pages. Depending on column length, all or a prefix of variable-length column values are stored in the B-tree to avoid wasting storage and having to read a separate page.

InnoDB 存储引擎支持四种行格式:REDUNDANT、COMPACT、DYNAMIC 和 COMPRESSED。The InnoDB storage engine supports four row formats: REDUNDANT, COMPACT, DYNAMIC, and COMPRESSED.

表 17.14 InnoDB 行格式概述Table 17.14 InnoDB Row Format Overview

行格式Row Format 紧凑存储特性Compact Storage Characteristics 增强的可变长度列存储Enhanced Variable-Length Column Storage 大索引键前缀支持Large Index Key Prefix Support 压缩支持Compression Support 支持的表空间类型Supported Tablespace Types
REDUNDANTREDUNDANT 否No 否No 否No 否No system, 每表文件, generalsystem, file-per-table, general
COMPACTCOMPACT 是Yes 否No 否No 否No system, 每表文件, generalsystem, file-per-table, general
DYNAMICDYNAMIC 是Yes 是Yes 是Yes 否No system, 每表文件, generalsystem, file-per-table, general
COMPRESSEDCOMPRESSED 是Yes 是Yes 是Yes 是Yes 每表文件, generalfile-per-table, general

以下主题描述了行格式存储特性以及如何定义和确定表的行格式。The topics that follow describe row format storage characteristics and how to define and determine the row format of a table.

冗余行格式REDUNDANT Row Format

REDUNDANT 格式提供与旧版本 MySQL 的兼容性。The REDUNDANT format provides compatibility with older versions of MySQL.

使用 REDUNDANT 行格式的表在 B 树节点的索引记录中存储可变长度列值的前 768 个字节(VARCHAR、VARBINARY 和 BLOB 以及 TEXT 类型),其余部分存储在溢出页上。大于或等于 768 字节的固定长度列会被编码为可变长度列,可以存储在页外。例如,如果字符集的最大字节长度大于 3(如 utf8mb4),则 CHAR(255) 列的大小可以超过 768 字节。Tables that use the REDUNDANT row format store the first 768 bytes of variable-length column values (VARCHAR, VARBINARY, and BLOB and TEXT types) in the index record within the B-tree node, with the remainder stored on overflow pages. Fixed-length columns greater than or equal to 768 bytes are encoded as variable-length columns, which can be stored off-page. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.

如果列的值为 768 字节或更少,则不会使用溢出页,这可能会节省一些 I/O 操作,因为值完全存储在 B 树节点中。这对于比较短的BLOB列值效果很好,但可能导致 B 树节点被数据而非键值填满,从而降低其效率。拥有许多BLOB列的表可能会导致 B 树节点过于饱满,包含的行数过少,使整个索引的效率比行更短或列值存储在页外时更低。If the value of a column is 768 bytes or less, an overflow page is not used, and some savings in I/O may result, since the value is stored entirely in the B-tree node. This works well for relatively short BLOB column values, but may cause B-tree nodes to fill with data rather than key values, reducing their efficiency. Tables with many BLOB columns could cause B-tree nodes to become too full, and contain too few rows, making the entire index less efficient than if rows were shorter or column values were stored off-page.

REDUNDANT 行格式存储特性REDUNDANT Row Format Storage Characteristics

REDUNDANT行格式具有以下存储特性:The REDUNDANT row format has the following storage characteristics:

  • 每个索引记录包含一个 6 字节的头部。该头部用于连接连续的记录,并用于行级锁定。Each index record contains a 6-byte header. The header is used to link together consecutive records, and for row-level locking.

  • 聚集索引中的记录包含所有用户定义列的字段。此外,还有一个 6 字节的事务 ID 字段和一个 7 字节的回滚指针字段。Records in the clustered index contain fields for all user-defined columns. In addition, there is a 6-byte transaction ID field and a 7-byte roll pointer field.

  • 如果表没有定义主键,每个聚集索引记录还包含一个 6 字节的行 ID 字段。If no primary key is defined for a table, each clustered index record also contains a 6-byte row ID field.

  • 每个二级索引记录包含为聚集索引键定义的所有主键列,这些列不在二级索引中。Each secondary index record contains all the primary key columns defined for the clustered index key that are not in the secondary index.

  • 一条记录包含指向记录中每个字段的指针。如果记录中字段的总长度小于 128 字节,则指针为 1 字节;否则为 2 字节。指针数组称为记录目录。指针指向的区域是记录的数据部分。A record contains a pointer to each field of the record. If the total length of the fields in a record is less than 128 bytes, the pointer is one byte; otherwise, two bytes. The array of pointers is called the record directory. The area where the pointers point is the data part of the record.

  • 在内部,固定长度字符列,如 CHAR(10) 以固定长度格式存储。VARCHAR 列的尾随空格不会被截断。Internally, fixed-length character columns such as CHAR(10) in stored in fixed-length format. Trailing spaces are not truncated from VARCHAR columns.

  • 大于或等于 768 字节的固定长度列会被编码为可变长度列,可以存储在页外。例如,如果字符集的最大字节长度大于 3(如 utf8mb4),则 CHAR(255) 列可以超过 768 字节。Fixed-length columns greater than or equal to 768 bytes are encoded as variable-length columns, which can be stored off-page. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.

  • 一个 SQL NULL 值在记录目录中保留一或两个字节。如果存储在可变长度列中,SQL NULL 值在记录的数据部分中不占用任何字节。对于固定长度列,记录的数据部分会保留列的固定长度。为 NULL 值保留固定空间允许列在原地从 NULL 更新为非 NULL 值,而不会导致索引页碎片化。An SQL NULL value reserves one or two bytes in the record directory. An SQL NULL value reserves zero bytes in the data part of the record if stored in a variable-length column. For a fixed-length column, the fixed length of the column is reserved in the data part of the record. Reserving fixed space for NULL values permits columns to be updated in place from NULL to non-NULL values without causing index page fragmentation.

COMPACT 行格式COMPACT Row Format

COMPACT 行格式相比 REDUNDANT 行格式能减少大约 20% 的行存储空间,但代价是某些操作的 CPU 使用增加。如果您的工作负载是典型的、受缓存命中率和磁盘速度限制的,COMPACT 格式可能会更快。如果工作负载受 CPU 速度限制,紧凑格式可能会更慢。The COMPACT row format reduces row storage space by about 20% compared to the REDUNDANT row format, at the cost of increasing CPU use for some operations. If your workload is a typical one that is limited by cache hit rates and disk speed, COMPACT format is likely to be faster. If the workload is limited by CPU speed, compact format might be slower.

使用 COMPACT 行格式的表在 VARCHAR、VARBINARY 和 BLOB 以及 TEXT 类型的可变长度列值的前 768 字节存储在 B 树 节点的索引记录中,其余部分存储在溢出页上。固定长度列大于或等于 768 字节时将被编码为可变长度列,可以存储在页外。例如,如果字符集的最大字节长度大于 3(如 utf8mb4),则 CHAR(255) 列可能会超过 768 字节。Tables that use the COMPACT row format store the first 768 bytes of variable-length column values (VARCHAR, VARBINARY, and BLOB and TEXT types) in the index record within the B-tree node, with the remainder stored on overflow pages. Fixed-length columns greater than or equal to 768 bytes are encoded as variable-length columns, which can be stored off-page. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.

如果列的值为 768 字节或更少,则不会使用溢出页,这可能会节省一些 I/O 操作,因为值完全存储在 B 树节点中。这对于比较短的BLOB列值效果很好,但可能导致 B 树节点被数据而非键值填满,从而降低其效率。拥有许多BLOB列的表可能会导致 B 树节点过于饱满,包含的行数过少,使整个索引的效率比行更短或列值存储在页外时更低。If the value of a column is 768 bytes or less, an overflow page is not used, and some savings in I/O may result, since the value is stored entirely in the B-tree node. This works well for relatively short BLOB column values, but may cause B-tree nodes to fill with data rather than key values, reducing their efficiency. Tables with many BLOB columns could cause B-tree nodes to become too full, and contain too few rows, making the entire index less efficient than if rows were shorter or column values were stored off-page.

COMPACT 行格式存储特性COMPACT Row Format Storage Characteristics

COMPACT 行格式具有以下存储特性:The COMPACT row format has the following storage characteristics:

  • 每个索引记录包含一个 5 字节的头部,该头部可能前面还有一个可变长度的头部。头部用于将连续记录链接在一起,以及用于行级锁定。Each index record contains a 5-byte header that may be preceded by a variable-length header. The header is used to link together consecutive records, and for row-level locking.

  • 记录头的可变长度部分包含一个位向量,用于指示NULL列。如果索引中可以为NULL的列数为N,则该位向量占用CEILING(N/8)字节。(例如,如果有 9 到 16 列可以为NULL,则位向量使用两个字节。)为NULL的列除了该位向量中的位之外,不占用其他空间。记录头的可变长度部分还包含可变长度列的长度。每个长度占用一到两个字节,取决于该列的最大长度。如果索引中的所有列都是NOT NULL并且长度固定,则记录头没有可变长度部分。The variable-length part of the record header contains a bit vector for indicating NULL columns. If the number of columns in the index that can be NULL is N, the bit vector occupies CEILING(N/8) bytes. (For example, if there are anywhere from 9 to 16 columns that can be NULL, the bit vector uses two bytes.) Columns that are NULL do not occupy space other than the bit in this vector. The variable-length part of the header also contains the lengths of variable-length columns. Each length takes one or two bytes, depending on the maximum length of the column. If all columns in the index are NOT NULL and have a fixed length, the record header has no variable-length part.

  • 对于每个非NULL的可变长度字段,记录头包含列长度信息,使用一到两个字节。只有当列的部分内容存储在外部溢出页中,或者最大长度超过 255 字节且实际长度超过 127 字节时,才需要两个字节。对于外部存储的列,2 字节长度表示内部存储部分的长度加上指向外部存储部分的 20 字节指针。内部部分为 768 字节,因此长度为 768+20。20 字节指针存储列的实际长度。For each non-NULL variable-length field, the record header contains the length of the column in one or two bytes. Two bytes are only needed if part of the column is stored externally in overflow pages or the maximum length exceeds 255 bytes and the actual length exceeds 127 bytes. For an externally stored column, the 2-byte length indicates the length of the internally stored part plus the 20-byte pointer to the externally stored part. The internal part is 768 bytes, so the length is 768+20. The 20-byte pointer stores the true length of the column.

  • 记录头之后是非NULL列的数据内容。The record header is followed by the data contents of non-NULL columns.

  • 聚集索引中的记录包含所有用户定义列的字段。此外,还有一个 6 字节的事务 ID 字段和一个 7 字节的回滚指针字段。Records in the clustered index contain fields for all user-defined columns. In addition, there is a 6-byte transaction ID field and a 7-byte roll pointer field.

  • 如果表没有定义主键,每个聚集索引记录还包含一个 6 字节的行 ID 字段。If no primary key is defined for a table, each clustered index record also contains a 6-byte row ID field.

  • 每个二级索引记录包含为聚集索引键定义的所有主键列,这些列不包含在二级索引中。如果任何主键列是可变长度的,则每个二级索引的记录头都有一个可变长度部分来记录它们的长度,即使二级索引是在固定长度列上定义的。Each secondary index record contains all the primary key columns defined for the clustered index key that are not in the secondary index. If any of the primary key columns are variable length, the record header for each secondary index has a variable-length part to record their lengths, even if the secondary index is defined on fixed-length columns.

  • 在内部,对于非可变长度字符集,固定长度字符列如 CHAR(10) 是以固定长度格式存储的。Internally, for nonvariable-length character sets, fixed-length character columns such as CHAR(10) are stored in a fixed-length format.

    尾随空格不会从 VARCHAR 列中截掉。Trailing spaces are not truncated from VARCHAR columns.

  • 在内部,对于可变长度字符集,例如 utf8mb3 和 utf8mb4,InnoDB 尝试通过修剪尾随空格来以 N 字节存储 CHAR(N)。如果 CHAR(N) 列值的字节长度超过 N 字节,则尾随空格会被修剪到列值字节长度的最大值。CHAR(N) 列的最大长度为最大字符字节长度 × N。Internally, for variable-length character sets such as utf8mb3 and utf8mb4, InnoDB attempts to store CHAR(N) in N bytes by trimming trailing spaces. If the byte length of a CHAR(N) column value exceeds N bytes, trailing spaces are trimmed to a maximum of the column value byte length. The maximum length of a CHAR(N) column is the maximum character byte length × N.

    对于 CHAR(N),至少保留 N 字节。在许多情况下,保留最小空间 N 可以使列更新就地进行,而不会导致索引页碎片。相比之下,使用 REDUNDANT 行格式时,CHAR(N) 列占用的字节数是最大字符字节长度 × N。A minimum of N bytes is reserved for CHAR(N). Reserving the minimum space N in many cases enables column updates to be done in place without causing index page fragmentation. By comparison, CHAR(N) columns occupy the maximum character byte length × N when using the REDUNDANT row format.

    固定长度列大于或等于 768 字节时,会被编码为可变长度字段,可以存储在页外。例如,如果字符集的最大字节长度大于 3(如utf8mb4),则CHAR(255)列可能超过 768 字节。Fixed-length columns greater than or equal to 768 bytes are encoded as variable-length fields, which can be stored off-page. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.

DYNAMIC 行格式DYNAMIC Row Format

DYNAMIC行格式提供与COMPACT行格式相同的存储特性,但增加了对长可变长度列的增强存储能力,并支持大索引键前缀。The DYNAMIC row format offers the same storage characteristics as the COMPACT row format but adds enhanced storage capabilities for long variable-length columns and supports large index key prefixes.

当使用 ROW_FORMAT=DYNAMIC 创建表时,InnoDB 可以将长可变长度列的值(对于 VARCHAR、VARBINARY 和 BLOB 以及 TEXT 类型)完全存储在页外,聚簇索引记录只包含一个指向溢出页的 20 字节指针。大于或等于 768 字节的固定长度字段会被编码为可变长度字段。例如,如果字符集的最大字节长度大于 3(如 utf8mb4),CHAR(255) 列的大小可能超过 768 字节。When a table is created with ROW_FORMAT=DYNAMIC, InnoDB can store long variable-length column values (for VARCHAR, VARBINARY, and BLOB and TEXT types) fully off-page, with the clustered index record containing only a 20-byte pointer to the overflow page. Fixed-length fields greater than or equal to 768 bytes are encoded as variable-length fields. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.

列是否存储在页外取决于页大小和行的总大小。当行过长时,最长的列会被选择存储在页外,直到聚集索引记录适合在B 树页面上。小于或等于 40 字节的TEXT和BLOB列是存储在行内的。Whether columns are stored off-page depends on the page size and the total size of the row. When a row is too long, the longest columns are chosen for off-page storage until the clustered index record fits on the B-tree page. TEXT and BLOB columns that are less than or equal to 40 bytes are stored in line.

DYNAMIC 行格式保持了在索引节点中存储整个行的效率(就像 COMPACT 和 REDUNDANT 格式一样),但 DYNAMIC 行格式避免了用长列的大量数据字节填充 B 树节点的问题。DYNAMIC 行格式的理念是,如果长数据值的一部分存储在页外,通常将整个值存储在页外是最有效的。使用 DYNAMIC 格式时,较短的列可能会保留在 B 树节点中,从而最小化给定行所需的溢出页数。The DYNAMIC row format maintains the efficiency of storing the entire row in the index node if it fits (as do the COMPACT and REDUNDANT formats), but the DYNAMIC row format avoids the problem of filling B-tree nodes with a large number of data bytes of long columns. The DYNAMIC row format is based on the idea that if a portion of a long data value is stored off-page, it is usually most efficient to store the entire value off-page. With DYNAMIC format, shorter columns are likely to remain in the B-tree node, minimizing the number of overflow pages required for a given row.

DYNAMIC 行格式支持最多 3072 字节的索引键前缀。The DYNAMIC row format supports index key prefixes up to 3072 bytes.

使用DYNAMIC行格式的表可以存储在系统表空间、每表文件表空间和通用表空间中。要将DYNAMIC表存储在系统表空间中,可以禁用innodb_file_per_table并使用常规的CREATE TABLE或ALTER TABLE语句,或者在ALTER TABLE或TABLESPACE [=] innodb_system中使用TABLESPACE [=] innodb_system表选项。innodb_file_per_table变量不适用于通用表空间,也不适用于使用CREATE TABLE表选项将DYNAMIC表存储在系统表空间时。Tables that use the DYNAMIC row format can be stored in the system tablespace, file-per-table tablespaces, and general tablespaces. To store DYNAMIC tables in the system tablespace, either disable innodb_file_per_table and use a regular CREATE TABLE or ALTER TABLE statement, or use the TABLESPACE [=] innodb_system table option with CREATE TABLE or ALTER TABLE. The innodb_file_per_table variable is not applicable to general tablespaces, nor is it applicable when using the TABLESPACE [=] innodb_system table option to store DYNAMIC tables in the system tablespace.

DYNAMIC 行格式存储特性DYNAMIC Row Format Storage Characteristics

DYNAMIC 行格式是 COMPACT 行格式的一种变体。关于存储特性,请参见 COMPACT 行格式存储特性。The DYNAMIC row format is a variation of the COMPACT row format. For storage characteristics, see COMPACT Row Format Storage Characteristics.

COMPRESSED 行格式COMPRESSED Row Format

COMPRESSED 行格式提供与 DYNAMIC 行格式相同的存储特性和能力,但增加了对表和索引数据压缩的支持。The COMPRESSED row format offers the same storage characteristics and capabilities as the DYNAMIC row format but adds support for table and index data compression.

COMPRESSED 行格式在页外存储的内部细节上与 DYNAMIC 行格式类似,但由于表和索引数据被压缩并使用更小的页尺寸,因此在存储和性能上有额外的考虑。使用 COMPRESSED 行格式时,KEY_BLOCK_SIZE 选项控制多少列数据存储在聚簇索引中,以及多少数据存放在溢出页上。有关 COMPRESSED 行格式的更多信息,请参见 第 17.9 节,“InnoDB 表和页压缩”。The COMPRESSED row format uses similar internal details for off-page storage as the DYNAMIC row format, with additional storage and performance considerations from the table and index data being compressed and using smaller page sizes. With the COMPRESSED row format, the KEY_BLOCK_SIZE option controls how much column data is stored in the clustered index, and how much is placed on overflow pages. For more information about the COMPRESSED row format, see Section 17.9, “InnoDB Table and Page Compression”.

COMPRESSED 行格式支持最大 3072 字节的索引键前缀。The COMPRESSED row format supports index key prefixes up to 3072 bytes.

使用 COMPRESSED 行格式的表可以在每表文件表空间或通用表空间中创建。系统表空间不支持 COMPRESSED 行格式。要在每表文件表空间中存储 COMPRESSED 表,必须启用 innodb_file_per_table 变量。innodb_file_per_table 变量不适用于通用表空间。通用表空间支持所有行格式,但需要注意,由于物理页大小不同,压缩表和非压缩表不能共存于同一通用表空间。更多信息,请参见 第 17.6.3.3 节,“通用表空间”。Tables that use the COMPRESSED row format can be created in file-per-table tablespaces or general tablespaces. The system tablespace does not support the COMPRESSED row format. To store a COMPRESSED table in a file-per-table tablespace, the innodb_file_per_table variable must be enabled. The innodb_file_per_table variable is not applicable to general tablespaces. General tablespaces support all row formats with the caveat that compressed and uncompressed tables cannot coexist in the same general tablespace due to different physical page sizes. For more information, see Section 17.6.3.3, “General Tablespaces”.

压缩行格式存储特性Compressed Row Format Storage Characteristics

COMPRESSED 行格式是 COMPACT 行格式的一种变体。有关存储特性,请参见 COMPACT 行格式存储特性。The COMPRESSED row format is a variation of the COMPACT row format. For storage characteristics, see COMPACT Row Format Storage Characteristics.

定义表的行格式Defining the Row Format of a Table

InnoDB 表的默认行格式由 innodb_default_row_format 变量定义,默认值为 DYNAMIC。当未显式定义 ROW_FORMAT 表选项或指定 ROW_FORMAT=DEFAULT 时,会使用默认行格式。The default row format for InnoDB tables is defined by innodb_default_row_format variable, which has a default value of DYNAMIC. The default row format is used when the ROW_FORMAT table option is not defined explicitly or when ROW_FORMAT=DEFAULT is specified.

可以在 CREATE TABLE 或 ALTER TABLE 语句中使用 ROW_FORMAT 表选项显式定义表的行格式。例如:The row format of a table can be defined explicitly using the ROW_FORMAT table option in a CREATE TABLE or ALTER TABLE statement. For example:

CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;

显式定义的 ROW_FORMAT 设置会覆盖默认的行格式。指定 ROW_FORMAT=DEFAULT 相当于使用隐式默认值。An explicitly defined ROW_FORMAT setting overrides the default row format. Specifying ROW_FORMAT=DEFAULT is equivalent to using the implicit default.

innodb_default_row_format 变量可以动态设置:The innodb_default_row_format variable can be set dynamically:

mysql> SET GLOBAL innodb_default_row_format=DYNAMIC;

有效的 innodb_default_row_format 选项包括 DYNAMIC、COMPACT 和 REDUNDANT。COMPRESSED 行格式不支持在系统表空间中使用,因此不能被定义为默认格式。它只能在 CREATE TABLE 或 ALTER TABLE 语句中显式指定。尝试将 innodb_default_row_format 变量设置为 COMPRESSED 会返回错误:Valid innodb_default_row_format options include DYNAMIC, COMPACT, and REDUNDANT. The COMPRESSED row format, which is not supported for use in the system tablespace, cannot be defined as the default. It can only be specified explicitly in a CREATE TABLE or ALTER TABLE statement. Attempting to set the innodb_default_row_format variable to COMPRESSED returns an error:

mysql> SET GLOBAL innodb_default_row_format=COMPRESSED;
ERROR 1231 (42000): Variable 'innodb_default_row_format'
can't be set to the value of 'COMPRESSED'

当未明确指定 ROW_FORMAT 选项,或使用 ROW_FORMAT=DEFAULT 时,新创建的表将使用 innodb_default_row_format 变量定义的行格式。例如,以下 CREATE TABLE 语句使用由 innodb_default_row_format 变量定义的行格式。Newly created tables use the row format defined by the innodb_default_row_format variable when a ROW_FORMAT option is not specified explicitly, or when ROW_FORMAT=DEFAULT is used. For example, the following CREATE TABLE statements use the row format defined by the innodb_default_row_format variable.

CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c1 INT) ROW_FORMAT=DEFAULT;

当没有明确指定 ROW_FORMAT 选项,或者使用 ROW_FORMAT=DEFAULT 时,重建表的操作会悄悄地将表的行格式更改为由 innodb_default_row_format 变量定义的格式。When a ROW_FORMAT option is not specified explicitly, or when ROW_FORMAT=DEFAULT is used, an operation that rebuilds a table silently changes the row format of the table to the format defined by the innodb_default_row_format variable.

表重建操作包括使用 ALGORITHM=COPY 或 ALGORITHM=INPLACE 且需要重建表的 ALTER TABLE 操作。有关更多信息,请参见 第 17.12.1 节,“在线 DDL 操作”。OPTIMIZE TABLE 也是一种表重建操作。Table-rebuilding operations include ALTER TABLE operations that use ALGORITHM=COPY or ALGORITHM=INPLACE where table rebuilding is required. See Section 17.12.1, “Online DDL Operations” for more information. OPTIMIZE TABLE is also a table-rebuilding operation.

下面的示例演示了一个表重建操作,该操作悄无声息地更改了未明确定义行格式的表的行格式。The following example demonstrates a table-rebuilding operation that silently changes the row format of a table created without an explicitly defined row format.

mysql> SELECT @@innodb_default_row_format;
+-----------------------------+
| @@innodb_default_row_format |
+-----------------------------+
| dynamic                     |
+-----------------------------+

mysql> CREATE TABLE t1 (c1 INT);

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ***************************
     TABLE_ID: 54
         NAME: test/t1
         FLAG: 33
       N_COLS: 4
        SPACE: 35
   ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single

mysql> SET GLOBAL innodb_default_row_format=COMPACT;

mysql> ALTER TABLE t1 ADD COLUMN (c2 INT);

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ***************************
     TABLE_ID: 55
         NAME: test/t1
         FLAG: 1
       N_COLS: 5
        SPACE: 36
   ROW_FORMAT: Compact
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single

在将现有表的行格式从 REDUNDANT 或 COMPACT 更改为 DYNAMIC 之前,请考虑以下潜在问题。Consider the following potential issues before changing the row format of existing tables from REDUNDANT or COMPACT to DYNAMIC.

  • REDUNDANT 和 COMPACT 行格式支持的最大索引键前缀长度为 767 字节,而 DYNAMIC 和 COMPRESSED 行格式支持的索引键前缀长度为 3072 字节。在复制环境中,如果在源端将 innodb_default_row_format 变量设置为 DYNAMIC,而在副本端设置为 COMPACT,则以下未明确指定行格式的 DDL 语句在源端执行成功,但在副本端执行失败:The REDUNDANT and COMPACT row formats support a maximum index key prefix length of 767 bytes whereas DYNAMIC and COMPRESSED row formats support an index key prefix length of 3072 bytes. In a replication environment, if the innodb_default_row_format variable is set to DYNAMIC on the source, and set to COMPACT on the replica, the following DDL statement, which does not explicitly define a row format, succeeds on the source but fails on the replica:

    CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 VARCHAR(5000), KEY i1(c2(3070)));
    

    有关相关信息,请参见 第 17.21 节,“InnoDB 限制”。For related information, see Section 17.21, “InnoDB Limits”.

  • 如果源服务器上的 innodb_default_row_format 设置与目标服务器上的设置不同,则导入未显式定义行格式的表会导致模式不匹配错误。有关更多信息,请参见 第 17.6.1.3 节,“导入 InnoDB 表”。Importing a table that does not explicitly define a row format results in a schema mismatch error if the innodb_default_row_format setting on the source server differs from the setting on the destination server. For more information, see Section 17.6.1.3, “Importing InnoDB Tables”.

确定表的行格式Determining the Row Format of a Table

要确定表的行格式,请使用 SHOW TABLE STATUS:To determine the row format of a table, use SHOW TABLE STATUS:

mysql> SHOW TABLE STATUS IN test1\G
*************************** 1. row ***************************
           Name: t1
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 16384
      Data_free: 0
 Auto_increment: 1
    Create_time: 2016-09-14 16:29:38
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb4_0900_ai_ci
       Checksum: NULL
 Create_options:
        Comment:

或者,查询信息模式 INNODB_TABLES 表:Alternatively, query the Information Schema INNODB_TABLES table:

mysql> SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_TABLES WHERE NAME='test1/t1';
+----------+------------+
| NAME     | ROW_FORMAT |
+----------+------------+
| test1/t1 | Dynamic    |
+----------+------------+