13.1.20.10 Invisible Columns不可见列

MySQL supports invisible columns as of MySQL 8.0.23. 从MySQL 8.0.23开始,MySQL支持不可见列。An invisible column is normally hidden to queries, but can be accessed if explicitly referenced. 不可见列通常对查询隐藏,但如果显式引用,则可以访问该列。Prior to MySQL 8.0.23, all columns are visible.在MySQL 8.0.23之前,所有列都是可见的。

As an illustration of when invisible columns may be useful, suppose that an application uses SELECT * queries to access a table, and must continue to work without modification even if the table is altered to add a new column that the application does not expect to be there. 作为不可见列何时有用的说明,假设应用程序使用SELECT *查询访问表,并且必须在不进行修改的情况下继续工作,即使该表被更改为添加应用程序不希望出现的新列。In a SELECT * query, the * evaluates to all table columns, except those that are invisible, so the solution is to add the new column as an invisible column. SELECT *查询中,*将计算所有表列(不可见列除外),因此解决方案是将新列添加为不可见列。The column remains hidden from SELECT * queries, and the application continues to work as previously. 该列在SELECT *查询中保持“隐藏”,并且应用程序继续像以前一样工作。A newer version of the application can refer to the invisible column if necessary by explicitly referencing it.如果需要,应用程序的较新版本可以通过显式引用不可见列来引用该列。

The following sections detail how MySQL treats invisible columns.以下各节详细介绍了MySQL如何处理不可见列。

DDL Statements and Invisible ColumnsDDL语句和不可见列

Columns are visible by default. 默认情况下,列是可见的。To explicitly specify visibility for a new column, use a VISIBLE or INVISIBLE keyword as part of the column definition for CREATE TABLE or ALTER TABLE:要显式指定新列的可见性,请在CREATE TABLEALTER TABLE的列定义中使用VISIBLEINVISIBLE关键字:

CREATE TABLE t1 (
  i INT,
  j DATE INVISIBLE
) ENGINE = InnoDB;
ALTER TABLE t1 ADD COLUMN k INT INVISIBLE;

To alter the visibility of an existing column, use a VISIBLE or INVISIBLE keyword with one of the ALTER TABLE column-modification clauses:要更改现有列的可见性,请在ALTER TABLE列修饰子句中使用VISIBLEINVISIBLE关键字:

ALTER TABLE t1 CHANGE COLUMN j j DATE VISIBLE;
ALTER TABLE t1 MODIFY COLUMN j DATE INVISIBLE;
ALTER TABLE t1 ALTER COLUMN j SET VISIBLE;

A table must have at least one visible column. Attempting to make all columns invisible produces an error.表必须至少有一个可见列。试图使所有列不可见会产生错误。

Invisible columns support the usual column attributes: NULL, NOT NULL, AUTO_INCREMENT, and so forth.不可见列支持常用的列属性:NULLNOT NULLAUTO_INCREMENT等等。

Generated columns can be invisible.生成的列可以不可见。

Index definitions can name invisible columns, including definitions for PRIMARY KEY and UNIQUE indexes. 索引定义可以命名不可见列,包括PRIMARY KEYUNIQUE索引的定义。Although a table must have at least one visible column, an index definition need not have any visible columns.尽管表必须至少有一个可见列,但索引定义不需要有任何可见列。

An invisible column dropped from a table is dropped in the usual way from any index definition that names the column.从表中删除的不可见列以通常的方式从命名该列的任何索引定义中删除。

Foreign key constraints can be defined on invisible columns, and foreign key constraints can reference invisible columns.可以在不可见列上定义外键约束,并且外键约束可以引用不可见列。

CHECK constraints can be defined on invisible columns. 可以在不可见列上定义CHECK约束。For new or modified rows, violation of a CHECK constraint on an invisible column produces an error.对于新行或修改行,违反不可见列上的CHECK约束会产生错误。

CREATE TABLE ... LIKE includes invisible columns, and they are invisible in the new table.CREATE TABLE ... LIKE包含不可见列,它们在新表中不可见。

CREATE TABLE ... SELECT does not include invisible columns, unless they are explicitly referenced in the SELECT part. CREATE TABLE ... SELECT不包括不可见列,除非它们在SELECT部分中被明确引用。However, even if explicitly referenced, a column that is invisible in the existing table is visible in the new table:但是,即使显式引用,在现有表中不可见的列在新表中也是可见的:

mysql> CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
mysql> CREATE TABLE t2 AS SELECT col1, col2 FROM t1;
mysql> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `col1` int DEFAULT NULL,
  `col2` int DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

If invisibility should be preserved, provide a definition for the invisible column in the CREATE TABLE part of the CREATE TABLE ... SELECT statement:如果应保留不可见性,请在CREATE TABLE ... SELECT语句的CREATE TABLE部分中为不可见列提供定义:

mysql> CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
mysql> CREATE TABLE t2 (col2 INT INVISIBLE) AS SELECT col1, col2 FROM t1;
mysql> SHOW CREATE TABLE t2\G
*************************** 1. row ***************************
       Table: t2
Create Table: CREATE TABLE `t2` (
  `col1` int DEFAULT NULL,
  `col2` int DEFAULT NULL /*!80023 INVISIBLE */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

Views can refer to invisible columns by explicitly referencing them in the SELECT statement that defines the view. 视图可以通过在定义视图的SELECT语句中显式引用不可见列来引用这些列。Changing a column's visibility subsequent to defining a view that references the column does not change view behavior.在定义引用列的视图之后更改列的可见性不会更改视图行为。

DML Statements and Invisible ColumnsDML语句和不可见列

For SELECT statements, an invisible column is not part of the result set unless explicitly referenced in the select list. 对于SELECT语句,不可见列不是结果集的一部分,除非在选择列表中显式引用。In a select list, the * and tbl_name.* shorthands do not include invisible columns. 在选择列表中,*tbl_name.*缩写不包括不可见列。Natural joins do not include invisible columns.自然连接不包括不可见的列。

Consider the following statement sequence:考虑下面的语句序列:

mysql> CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
mysql> INSERT INTO t1 (col1, col2) VALUES(1, 2), (3, 4);

mysql> SELECT * FROM t1;
+------+
| col1 |
+------+
|    1 |
|    3 |
+------+

mysql> SELECT col1, col2 FROM t1;
+------+------+
| col1 | col2 |
+------+------+
|    1 |    2 |
|    3 |    4 |
+------+------+

The first SELECT does not reference the invisible column col2 in the select list (because * does not include invisible columns), so col2 does not appear in the statement result. 第一个SELECT不引用选择列表中的不可见列col2(因为*不包括不可见列),因此col2不会出现在语句结果中。The second SELECT does reference col2, so it does appear in the result.第二个SELECT引用col2,因此它确实出现在结果中。

For statements that create new rows, an invisible column is assigned its implicit default value unless explicitly referenced and assigned a value. 对于创建新行的语句,除非显式引用并指定值,否则将为不可见列指定其隐式默认值。For information about implicit defaults, see Implicit Default Handling.有关隐式默认值的信息,请参阅隐式默认值处理。

For INSERT (and REPLACE, for non-replaced rows), implicit default assignment occurs with a missing column list, an empty column list, or a nonempty column list that does not include the invisible column:对于INSERT(和REPLACE,对于未替换的行),隐式默认赋值发生在缺少列列表、空列列表或不包含不可见列的非空列列表中:

CREATE TABLE t1 (col1 INT, col2 INT INVISIBLE);
INSERT INTO t1 VALUES(...);
INSERT INTO t1 () VALUES(...);
INSERT INTO t1 (col1) VALUES(...);

For the first two INSERT statements, the VALUES() list must provide a value for each visible column and no invisible column. 对于前两个INSERT语句,VALUES()列表必须为每个可见列和不可见列提供一个值。For the third INSERT statement, the VALUES() list must provide the same number of values as the number of named columns.对于第三条INSERT语句,VALUES()列表必须提供与命名列数相同的值数。

For LOAD DATA and LOAD XML, implicit default assignment occurs with a missing column list or a nonempty column list that does not include the invisible column. 对于LOAD DATALOAD XML,隐式默认赋值会在缺少列列表或不包含不可见列的非空列列表中发生。Input rows should not include a value for the invisible column.输入行不应包含不可见列的值。

To assign a value other than the implicit default for the preceding statements, explicitly name the invisible column in the column list and provide a value for it.要为前面的语句指定非隐式默认值的值,请在列列表中显式命名不可见列并为其提供值。

INSERT INTO ... SELECT * and REPLACE INTO ... SELECT * do not include invisible columns because * does not include invisible columns. INSERT INTO ... SELECT *REPLACE INTO ... SELECT *不包括不可见列,因为*不包括不可见列。Implicit default assignment occurs as described previously.隐式默认赋值如前所述发生。

For statements that insert or ignore new rows, or that replace or modify existing rows, based on values in a PRIMARY KEY or UNIQUE index, MySQL treats invisible columns the same as visible columns: Invisible columns participate in key value comparisons. 对于基于PRIMARY KEYUNIQUE索引中的值插入或忽略新行,或替换或修改现有行的语句,MySQL将不可见列视为与可见列相同:不可见列参与键值比较。Specifically, if a new row has the same value as an existing row for a unique key value, these behaviors occur whether the index columns are visible or invisible:具体地说,如果新行具有与唯一键值的现有行相同的值,则无论索引列是可见的还是不可见的,都会发生以下行为:

  • With the IGNORE modifier, INSERT, LOAD DATA, and LOAD XML ignore the new row.使用IGNORE修饰符,INSERTLOAD DATALOAD XML忽略新行。

  • REPLACE replaces the existing row with the new row. REPLACE将现有行替换为新行。With the REPLACE modifier, LOAD DATA and LOAD XML do the same.使用REPLACE修饰符,LOAD DATALOAD XML的操作相同。

  • INSERT ... ON DUPLICATE KEY UPDATE updates the existing row.INSERT ... ON DUPLICATE KEY UPDATE更新现有行。

To update invisible columns for UPDATE statements, name them and assign a value, just as for visible columns.要更新UPDATE语句的不可见列,请将它们命名并赋值,就像对可见列一样。

Invisible Column Metadata不可见列元数据

Information about whether a column is visible or invisible is available from the EXTRA column of the INFORMATION_SCHEMA.COLUMNS table or SHOW COLUMNS output. 有关列是可见还是不可见的信息可从INFORMATION_SCHEMA.COLUMNS表的EXTRA列或SHOW COLUMNS输出中获得。For example:例如:

mysql> SELECT TABLE_NAME, COLUMN_NAME, EXTRA
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 't1';
+------------+-------------+-----------+
| TABLE_NAME | COLUMN_NAME | EXTRA     |
+------------+-------------+-----------+
| t1         | i           |           |
| t1         | j           |           |
| t1         | k           | INVISIBLE |
+------------+-------------+-----------+

Columns are visible by default, so in that case, EXTRA displays no visibility information. 默认情况下,列是可见的,因此在这种情况下,EXTRA不显示可见性信息。For invisible columns, EXTRA displays INVISIBLE.对于不可见列,EXTRA显示不可见。

SHOW CREATE TABLE displays invisible columns in the table definition, with the INVISIBLE keyword in a version-specific comment:SHOW CREATE TABLE在表定义中显示不可见列,在特定于版本的注释中使用INVISIBLE关键字:

mysql> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
       Table: t1
Create Table: CREATE TABLE `t1` (
  `i` int DEFAULT NULL,
  `j` int DEFAULT NULL,
  `k` int DEFAULT NULL /*!80023 INVISIBLE */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci

mysqldump and mysqlpump use SHOW CREATE TABLE, so they include invisible columns in dumped table definitions. mysqldumpmysqlpump使用SHOW CREATE TABLE表,因此它们在转储表定义中包含不可见列。They also include invisible column values in dumped data.它们还包括转储数据中不可见的列值。

Reloading a dump file into an older version of MySQL that does not support invisible columns causes the version-specific comment to be ignored, which creates any invisible columns as visible.将转储文件重新加载到不支持不可见列的旧版本MySQL中会导致忽略特定于版本的注释,从而将任何不可见列创建为可见。

The Binary Log and Invisible Columns二进制日志和不可见列

MySQL treats invisible columns as follows with respect to events in the binary log:MySQL对二进制日志中的事件处理不可见列如下:

  • Table-creation events include the INVISIBLE attribute for invisible columns.表创建事件包括不可见列的INVISIBLE属性。

  • Invisible columns are treated like visible columns in row events. 不可见列被视为行事件中的可见列。They are included if needed according to the binlog_row_image system variable setting.根据系统变量binlog_row_image设置,如果需要,可将其包括在内。

  • When row events are applied, invisible columns are treated like visible columns in row events. 应用行事件时,不可见列将被视为行事件中的可见列。In particular, the algorithm and index to use are chosen according to the slave_rows_search_algorithms system variable setting.特别是,要使用的算法和索引是根据系统变量slave_rows_search_algorithms设置来选择的。

  • Invisible columns are treated like visible columns when computing writesets. 在计算写集时,不可见列被视为可见列。In particular, writesets include indexes defined on invisible columns.特别是,WriteSet包括在不可见列上定义的索引。

  • The mysqlbinlog command includes visibility in column metadata.mysqlbinlog命令包含列元数据中的可见性。