MySQL8 中文参考(十九)(mysql8中文官方文档)

MySQL8 中文参考(十九) 原文:docs.oracle.com/javase/tutorial/reallybigindex.html 7.1.11 服务器 SQL 模式 原文:dev.mysql.com/

原文:docs.oracle.com/javase/tutorial/reallybigindex.html

7.1.11 服务器 SQL 模式

原文:dev.mysql.com/doc/refman/8.0/en/sql-mode.html

MySQL服务器可以运行在不同的SQL模式下,并且根据sql_mode系统变量的值,这些模式可以应用于不同的客户端。数据库管理员可以设置全局SQL 模式以满足站点服务器的操作需要,每个应用程序可以设置会话SQL 模式以满足自己的需要。

模式影响MySQL 支持的SQL 语法及其执行的数据验证检查。这使得在各种环境中以及与其他数据库服务器一起使用MySQL 变得很容易。

设置SQL模式

最重要的SQL 模式

SQL 模式的完整列表

组合SQL 模式

严格SQL模式

比较IGNORE 关键字和严格SQL 模式

有关MySQL 服务器SQL 模式的常见问题解答,请参阅第A.3 节“MySQL 8.0 FAQ: 服务器SQL 模式”。

使用InnoDB 表时,还要考虑innodb_strict_mode 系统变量。这可以对InnoDB 表进行额外的错误检查。

设置 SQL 模式

MySQL 8.0 中默认的SQL 模式包括以下模式:ONLY_FULL_GROUP_BY、STRICT_TRANS_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO 和NO_ENGINE_SUBSTITUTION。

要在启动服务器时设置SQL 模式,请在命令行中使用–sql-mode=\’*modes*\’ 选项,或者创建一个文件,例如my.cnf(Unix 操作系统)或my.ini(Windows 操作系统)系统)。 )使用sql-mode=\’*modes*\’。 *modes* 是不同模式的逗号分隔列表。要显式清除SQL 模式,请在命令行上使用–sql-mode=\’\’ 并使用空字符串,或在选项文件中使用sql-mode=\’\’ 。

消息

MySQL 安装程序可能会在安装过程中配置SQL 模式。

如果SQL 模式与默认或预期模式不同,请检查服务器在启动时读取的选项文件中的设置。

要在运行时更改SQL 模式,请使用SET 语句设置全局或会话sql_mode 系统变量。

设置全局sql_mode=\’*模式*\’;

设置会话sql_mode=\’*模式*\’;

设置GLOBAL 变量需要SYSTEM_VARIABLES_ADMIN 权限(或已弃用的SUPER 权限),并会影响从那时起所有连接的客户端的行为。设置SESSION 变量仅影响当前客户端。每个客户端都可以随时更改其会话的sql_mode 值。

要查看当前全局或会话sql_mode 设置,请选择其值。

选择@@GLOBAL.sql_mode;

选择@@SESSION.sql_mode;

重要的

SQL 模式和用户定义的分区。 创建数据并将其插入分区表后更改服务器SQL 架构可能会显着改变这些表的行为,并可能导致数据丢失或损坏。我们强烈建议您在创建具有用户定义分区的表后不要修改SQL 架构。

复制分区表时,源和副本上的不同SQL 模式也可能会导致问题。为了获得最佳结果,源和副本应始终使用相同的服务器SQL 模式。

有关详细信息,请参阅分区限制和限制。

最重要的 SQL 模式

最重要的sql_mode 值可能是:

美国国家标准协会

此模式更改语法和行为,使其与标准SQL 更加一致。这是本节末尾列出的特殊组合模式之一。

STRICT_TRANS_TABLES

如果指定的值无法插入到事务表中,则语句将中止。对于非事务表,如果该值出现在单行或多行语句的第一行中,则会中止该语句。本节稍后将提供更多详细信息。

传统的

使MySQL 表现得像“传统”SQL 数据库系统。此模式的一个简单解释是,当您将无效值插入到列中时,您会收到错误而不是警告。这是本节末尾列出的特殊组合模式之一。

消息

启用TRADITIONAL 模式后,一旦发生错误,INSERT 或UPDATE 就会中止。如果您使用的是非事务性存储引擎,这可能不是期望的结果,因为错误之前所做的数据更改不会回滚,并且更新可能是“部分完成”的。

当本手册提到“严格模式”时,意味着STRICT_TRANS_TABLES 和STRICT_ALL_TABLES 之一或两者均有效。

SQL 模式的完整列表

以下列表描述了所有支持的SQL 模式。

ALLOW_INVALID_DATES

不要彻底检查日期。确保月份在1-12 范围内,日期在1-31 范围内。这在Web 应用程序中可能很有用,其中年、月和日单独存储为用户插入的数据而无需进行日期验证。此模式适用于DATE 和DATETIME 列。它不适用于始终需要有效日期的TIMESTAMP 列。

当禁用ALLOW_INVALID_DATES 时,除了范围1-12 和1-31 之外,服务器还需要有效的月份和日期值。禁用严格模式时,无效日期(例如“2004-04-31”)将转换为“0000-00-00”并生成警告。如果启用严格模式,无效日期将生成错误。要允许此类日期,请启用ALLOW_INVALID_DATES。

ANSI_引号

将\’ 视为标识引号字符而不是字符串引号字符(类似于允许在此模式下使用SQL 引号字符)。仍然可以使用带引号的标识符。当启用ANSI_QUOTES 时,文本字符串不能使用双引号引起来,因为它们被解释为标识符。

ERROR_FOR_DIVISION_BY_ZERO

ERROR_FOR_DIVISION_BY_ZERO 模式影响除零运算的处理,包括MOD(*N*,0)。对于数据修改操作(INSERT、UPDATE),效果还取决于是否启用严格SQL模式。

如果未启用此模式,除零运算将插入NULL 并且不会生成警告。

启用此模式时,除零运算会插入NULL 并生成警告。

当启用此模式和严格模式时,除以零会导致错误,除非还指定了IGNORE。对于INSERT IGNORE 和UPDATE IGNORE,除以零会插入NULL 并生成警告。

对于SELECT,除以零将返回NULL。无论是否启用严格模式,启用ERROR_FOR_DIVISION_BY_ZERO 都会生成警告。

ERROR_FOR_DIVISION_BY_ZERO 已被弃用。 ERROR_FOR_DIVISION_BY_ZERO 不是严格模式的一部分,但必须在严格模式下使用,并且默认启用。如果启用ERROR_FOR_DIVISION_BY_ZERO 而不启用严格模式,则会生成警告,反之亦然。

ERROR_FOR_DIVISION_BY_ZERO 已被弃用,因此您应该期望它在未来的MySQL 版本中作为单独的模式名称被删除,并且其效果并入严格的SQL 模式效果中。

HIGH_NOT_PRECEDENCE

由于NOT 运算符的优先级,诸如NOT a BETWEEN b AND c 之类的表达式将被解析为NOT (a BETWEEN b AND c)。在某些旧版本的MySQL 中,此表达式被解析为(NOT a) BETWEEN b AND c。您可以通过启用HIGH_NOT_PRECEDENCE SQL 模式来获得旧的高优先级行为。

mysql SET sql_mode=\’\’;

mysql -5 和5 之间不要选择1;

-0

mysql SET sql_mode=\’HIGH_NOT_PRECEDENCE\’;

mysql -5 和5 之间不要选择1;

– 1

忽略空间

函数名称和( 字符之间允许有空格,这会导致内置函数名称被视为保留字。因此,如架构对象名称中所述,与函数名称相同的标识符例如,使用count因为下面语句中的表名会导致错误,因为有一个COUNT() 函数。

mysql 创建表计数(i INT);

错误1064 (42000): SQL 语法错误

表名必须用引号引起来。

mysql 创建表`count` (i INT);

查询正常,0 行受影响(0.00 秒)

IGNORE_SPACE SQL 模式适用于内置函数,不适用于可加载或存储函数。可加载或存储的函数名称后面可以有空格,无论IGNORE_SPACE 是否有效。

有关IGNORE_SPACE 的更多信息,请参阅函数名称解析和解析。

NO_AUTO_VALUE_ON_ZERO

NO_AUTO_VALUE_ON_ZERO 影响AUTO_INCREMENT 列的处理。通常,列的下一个序列号是通过插入NULL 或0 生成的。 NO_AUTO_VALUE_ON_ZERO 将这种行为抑制为0,因此只有NULL 才会生成下一个序列号。

如果您想将0 存储在表的AUTO_INCRMENT 列中(顺便说一句,不建议这样做),则此模式非常有用。例如,如果使用mysqldump导出一个表,然后重新加载它,MySQL通常会在遇到0值时生成一个新的序列号,并且表的内容与导出时不同。您可以通过在重新加载导出文件之前启用NO_AUTO_VALUE_ON_ZERO 来解决此问题。因此,mysqldump 自动在其输出中包含启用NO_AUTO_VALUE_ON_ZERO 的语句。

NO_BACKSLASH_ESCAPES

启用此模式会禁用反斜杠字符(\\) 作为字符串和标识符中的转义字符。启用此模式会使反斜杠像任何其他字符一样成为普通字符,更改LIKE 表达式的默认转义序列,并且不再使用转义字符。

NO_DIR_IN_CREATE

创建表时,所有INDEX DIRECTORY 和DATA DIRECTORY 指令都会被忽略。此选项在复制服务器上很有用。

NO_ENGINE_SUBSTITUTION

当语句(例如CREATE TABLE 或ALTER TABLE)指定无效或未编译的存储引擎时,控制默认存储引擎的自动替换。

默认情况下,启用NO_ENGINE_SUBSTITUTION。

存储引擎可以在运行时附加和删除,因此不可用的引擎会以相同的方式处理。

如果禁用NO_ENGINE_SUBSTITUTION,CREATE TABLE 将使用默认引擎,并在所需引擎不可用时发出警告。对于ALTER TABLE,会发出警告并且不会更改表。

当NO_ENGINE_SUBSTITUTION 生效时,如果所需的引擎不可用,则会发生错误,并且不会创建或更改表。

NO_UNSIGNED_SUBTRACTION

默认情况下,整数值(其中一个是UNSIGNED 类型)之间的减法会产生无符号结果。如果预期结果为负,则会发生错误。

mysql SET sql_mode=\’\’;

查询正常,0 行受影响(0.00 秒)

mysql SELECT CAST(0 AS UNSIGNED) – 1;

错误1690 (22003): BIGINT UNSIGNED 值超出范围\'(cast(0 as unsigned) – 1)\’

如果NO_UNSIGNED_SUBTRACTION SQL 模式有效,则结果为负。

mysql SET sql_mode=\’NO_UNSIGNED_SUBTRACTION\’;

mysql SELECT CAST(0 AS UNSIGNED) – 1;

+————————————————+

| 强制转换(0 为无符号)- 1 |

+————————————————+

| -1 |

+————————————————+

当使用此类操作的结果更新UNSIGNED 整数列时,结果将被截断为该列类型的最大值,或者如果NO_UNSIGNED_SUBTRACTION 有效,则截断为0。如果启用严格SQL 模式,则会发生错误并且列保持不变。

当NO_UNSIGNED_SUBTRACTION 有效时,即使操作数无符号,减法结果也会有符号。例如,将表t1 中的列c2 的类型与表t2 中的列c2 的类型进行比较。

mysql SET sql_mode=\’\’;

mysql CREATE TABLE 测试(c1 BIGINT UNSIGNED NOT NULL);

mysql 创建表t1 从测试中选择c1 – 1 AS c2;

mysql 描述t1;

+——+———-+——+——+——+——+

| 字段类型| 默认|

+——+———-+——+——+——+——+

| c2 | 未签名|

+——+———-+——+——+——+——+

mysql SET sql_mode=\’NO_UNSIGNED_SUBTRACTION\’;

mysql 创建表t2 从测试中选择c1 – 1 AS c2;

mysql 描述t2;

+——+————+——+—–+———+—– — +

| 字段类型| 默认|

+——+————+——+—–+———+—– — +

| c2(21) |

+——+————+——+—–+———+—– — +

这意味着BIGINT UNSIGNED 不能在100% 的所有情况下使用。请参阅转换函数和运算符。

NO_ZERO_DATE

NO_ZERO_DATE 模式影响服务器是否允许“0000-00-00”作为有效日期。影响还取决于是否启用严格SQL 模式。

如果未启用此模式,则允许使用“0000-00-00”并且插入不会生成警告。

当启用此模式时,允许使用“0000-00-00”并且插入将生成警告。

当启用此模式和严格模式时,不允许使用“0000-00-00”,并且如果插入将生成错误,除非同时使用IGNORE。 INSERT IGNORE 和UPDATE IGNORE 允许“0000-00-00”并且插入将生成警告。

NO_ZERO_DATE 已被弃用。 NO_ZERO_DATE 不是严格模式的一部分,但必须在严格模式下使用,并且默认启用。如果在未启用严格模式的情况下启用NO_ZERO_DATE,则会发出警告。反之亦然。

由于NO_ZERO_DATE 已被弃用,因此您应该期望它在未来的MySQL 版本中作为单独的模式名称被删除,并且其效果并入严格SQL 模式的效果中。

NO_ZERO_IN_DATE

NO_ZERO_IN_DATE 模式影响服务器是否允许具有非零年份部分和零月份或日期部分的日期。 (此模式影响“2010-00-01”和“2010-01-00”等日期,但不影响“0000-00-00”。) NO_ZERO_IN_DATE 的效果还取决于是否启用严格SQL 模式。

如果未启用此模式,则允许包含零部分的日期,并且插入它们不会生成警告。

启用此模式后,组件为零的日期将插入为“0000-00-00”,并生成警告。

当启用此模式和严格模式时,不允许包含零部分的日期,并且在插入时将生成错误,除非同时使用IGNORE。 INSERT IGNORE 和UPDATE IGNORE 将零部分日期插入为“0000-00-00”并生成警告。

NO_ZERO_IN_DATE 已被弃用。 NO_ZERO_IN_DATE 不是严格模式的一部分,但必须在严格模式下使用,并且默认启用。如果在未启用严格模式的情况下启用NO_ZERO_IN_DATE,则会发出警告,反之亦然。

NO_ZERO_IN_DATE 已被弃用,因此您应该期望它在MySQL 的未来版本中作为单独的模式名称被删除,并且其效果并入严格SQL 模式的效果中。

ONLY_FULL_GROUP_BY

选择列表、HAVING 条件或ORDER BY 列表未在GROUP BY 子句中命名,并且在功能上不依赖于GROUP BY 列(由GROUP BY 唯一确定) 拒绝引用该列的查询。

MySQL 对标准SQL 的扩展允许在HAVING 子句中引用选择列表中的别名表达式。无论ONLY_FULL_GROUP_BY 是否有效,HAVING 子句都可以引用别名。

有关详细说明和示例,请参见第14.19.3 节“MySQL 如何处理GROUP BY”。

PAD_CHAR_TO_FULL_LENGTH

默认情况下,从CHAR 列值检索时会删除尾随空格。如果启用PAD_CHAR_TO_FULL_LENGTH,则不会发生修剪,并且检索到的CHAR 值将填充为其全长。此模式不适用于在检索期间保留尾随空格的VARCHAR 列。

消息

从MySQL 8.0.13 开始,PAD_CHAR_TO_FULL_LENGTH 已被弃用。它将在未来的MySQL 版本中删除。

mysql 创建表t1 (c1 CHAR(10));

查询正常,0 行受影响(0.37 秒)

mysql INSERT INTO t1 (c1) VALUES(\’xy\’);

查询正常,1 行受影响(0.01 秒)

mysql SET sql_mode=\’\’;

查询正常,0 行受影响(0.00 秒)

mysql 选择c1, CHAR_LENGTH(c1) FROM t1;

+——+—————–+

| c1 | 字符长度(c1) |

+——+—————–+

| XY |

+——+—————–+

一组1 行(0.00 秒)

mysql SET sql_mode=\’PAD_CHAR_TO_FULL_LENGTH\’;

查询正常,0 行受影响(0.00 秒)

mysql 选择c1, CHAR_LENGTH(c1) FROM t1;

+—————-+—————-+

| c1 | 字符长度(c1) |

+—————-+—————-+

| XY |

+—————-+—————-+

一组1 行(0.00 秒)

PIPES_AS_CONCAT

将|| 视为字符串连接运算符(与CONCAT() 相同),而不是OR 的同义词。

REAL_AS_FLOAT

将REAL 视为FLOAT 的同义词。默认情况下,MySQL 将REAL 视为DOUBLE 的同义词。

STRICT_ALL_TABLES

为所有存储引擎启用严格的SQL 模式。无效数据值将被拒绝。有关详细信息,请参阅严格SQL 模式。

STRICT_TRANS_TABLES

为事务性存储引擎和非事务性存储引擎(如果可能)启用严格的SQL 模式。有关详细信息,请参阅严格SQL 模式。

TIME_TRUNCATE_FRACTIONAL

控制将带有秒小数部分的TIME、DATE 或TIMESTAMP 值插入到小数位数较少的相同类型的列中时发生的舍入或截断。默认行为是使用舍入。启用此模式时会发生截断。下面的一组语句说明了其中的差异。

创建表t (id INT, tval TIME(1));

设置sql_mode=\’\’;

插入t (id, tval) VALUES(1, 1.55);

设置sql_mode=\’TIME_TRUNCATE_FRACTIONAL\’;

插入t (id, tval) VALUES(2, 1.55);

结果表的内容应如下所示:第一个值被四舍五入,第二个值被截断。

mysql SELECT id, tval FROM t ORDER BY id;

+——+————+

| 身份证|

+——+————+

| 00:00:01.6 |

| 2 | 00:00:01.5 |

+——+————+

另请参见第13.2.6 节“时间值中的小数秒”。

组合 SQL 模式

以下特殊模式提供了前面列表中的模式值组合的简写。

美国国家标准协会

相当于REAL_AS_FLOAT、PIPES_AS_CONCAT、ANSI_QUOTES、IGNORE_SPACE 和ONLY_FULL_GROUP_BY。

此外,在ANSI 模式下,如果具有外部引用*S* (*outer_ref*) 的聚合函数*S* 无法通过解析外部引用的外部查询进行聚合,则服务器会返回错误。下面是这样一个查询。

SELECT * FROM t1 WHERE t1.a IN (SELECT MAX(t1.b) FROM t2 WHERE .);

这里,MAX(t1.b)不能在外部查询中聚合。

为它出现在该查询的WHERE子句中。标准 SQL 要求在这种情况下出错。如果未启用ANSI模式,服务器将在这些查询中以与解释*S*(*const*)相同的方式解释*S*(*outer_ref*)。
参见第 1.6 节,“MySQL 标准兼容性”。
TRADITIONAL
TRADITIONAL等同于STRICT_TRANS_TABLES、STRICT_ALL_TABLES、NO_ZERO_IN_DATE、NO_ZERO_DATE、ERROR_FOR_DIVISION_BY_ZERO和NO_ENGINE_SUBSTITUTION。

严格 SQL 模式

严格模式控制 MySQL 如何处理数据更改语句中的无效或缺失值,例如INSERT或UPDATE。值可能无效的原因有多种。例如,它可能对于列的数据类型错误,或者超出范围。当要插入的新行不包含非NULL列的值且该列在定义中没有显式的DEFAULT子句时,值就会缺失。(对于NULL列,如果值缺失,则插入NULL。)严格模式还影响 DDL 语句,例如CREATE TABLE。

如果严格模式未生效,MySQL 会为无效或缺失的值插入调整后的值,并生成警告(参见第 15.7.7.42 节,“SHOW WARNINGS 语句”)。在严格模式下,您可以通过使用INSERT IGNORE或UPDATE IGNORE来产生这种行为。

对于诸如SELECT这样不改变数据的语句,在严格模式下,无效值会生成警告,而不是错误。

严格模式会在尝试创建超过最大键长度的键时产生错误。当未启用严格模式时,这会导致警告并将键截断为最大键长度。

严格模式不影响外键约束的检查。可以使用foreign_key_checks进行检查。(参见第 7.1.8 节,“服务器系统变量”。)

如果启用了STRICT_ALL_TABLES或STRICT_TRANS_TABLES,则严格 SQL 模式生效,尽管这些模式的影响略有不同:

对于事务表,在数据更改语句中出现无效或缺失值时,当STRICT_ALL_TABLES或STRICT_TRANS_TABLES启用时会发生错误。该语句将被中止并回滚。
对于非事务表,如果坏值出现在要插入或更新的第一行中,无论哪种模式,行为都是相同的:语句会被中止,表保持不变。如果语句插入或修改多行,且坏值出现在第二行或之后的行中,结果取决于启用了哪种严格模式:

对于STRICT_ALL_TABLES,MySQL 会返回错误并忽略其余行。然而,由于较早的行已被插入或更新,结果是部分更新。为避免这种情况,请使用单行语句,可以在不更改表的情况下中止。
对于STRICT_TRANS_TABLES,MySQL 会将无效值转换为列的最接近有效值并插入调整后的值。如果值缺失,MySQL 会插入列数据类型的隐式默认值。在任一情况下,MySQL 会生成警告而不是错误,并继续处理语句。隐式默认值在第 13.6 节,“数据类型默认值”中描述。

严格模式影响对零除法、零日期和日期中的零的处理如下:

严格模式影响对零除法的处理,包括MOD(*N*,0):
对于数据更改操作(INSERT,UPDATE):

如果未启用严格模式,零除法会插入NULL并不会产生警告。
如果启用了严格模式,零除法会产生错误,除非也给出了IGNORE。对于INSERT IGNORE和UPDATE IGNORE,零除法会插入NULL并生成警告。
对于SELECT,零除法返回NULL。启用严格模式会产生警告。
严格模式影响服务器是否允许\’0000-00-00\’作为有效日期:

如果未启用严格模式,允许\’0000-00-00\’并且插入不会产生警告。
如果启用了严格模式,不允许\’0000-00-00\’,并且插入会产生错误,除非也给出了IGNORE。对于INSERT IGNORE和UPDATE IGNORE,\’0000-00-00\’是允许的,并且插入会生成警告。
严格模式影响服务器是否允许年份部分为非零但月份或日期部分为 0 的日期(例如 \’2010-00-01\’ 或 \’2010-01-00\’):

如果未启用严格模式,允许具有零部分的日期,并且插入不会产生警告。
如果启用了严格模式,不允许具有零部分的日期,并且插入会产生错误,除非也给出了IGNORE。对于INSERT IGNORE和UPDATE IGNORE,具有零部分的日期会插入为\’0000-00-00\’(在IGNORE情况下被视为有效)并生成警告。

有关IGNORE与严格模式的更多信息,请参阅 IGNORE 关键字和严格 SQL 模式的比较。

严格模式影响对零除法、零日期和日期中的零的处理,与ERROR_FOR_DIVISION_BY_ZERO、NO_ZERO_DATE和NO_ZERO_IN_DATE模式一起。

IGNORE关键字和严格 SQL 模式的比较

本节比较了IGNORE关键字(将错误降级为警告)和严格 SQL 模式(将警告升级为错误)对语句执行的影响。它描述了它们影响的语句以及它们适用的错误。

以下表格总结了当默认为产生错误与警告时语句行为的比较。当默认为产生错误时的示例是将NULL插入NOT NULL列。当默认为产生警告时的示例是将错误数据类型的值插入列(例如将字符串\’abc\’插入整数列)。

操作模式当语句默认为错误时当语句默认为警告时没有IGNORE或严格 SQL 模式错误警告使用IGNORE警告警告(与没有IGNORE或严格 SQL 模式相同)使用严格的 SQL 模式错误(与没有IGNORE或严格的 SQL 模式相同)错误使用IGNORE和严格 SQL 模式警告警告
从表中可以得出一个结论,即当IGNORE关键字和严格的 SQL 模式同时生效时,IGNORE优先。这意味着,尽管IGNORE和严格的 SQL 模式在错误处理方面可以被认为具有相反的效果,但在一起使用时并不会被取消。

IGNORE 对语句执行的影响
严格 SQL 模式对语句执行的影响

IGNORE 对语句执行的影响

MySQL 中的几个语句支持可选的IGNORE关键字。此关键字导致服务器将某些类型的错误降级并生成警告。对于多行语句,将错误降级为警告可能会使一行得以处理。否则,IGNORE会导致语句跳到下一行而不是中止。(对于不可忽略的错误,无论有无IGNORE关键字,都会发生错误。)

例如:如果表t具有包含唯一值的主键列i,尝试将相同值的i插入多行通常会产生重复键错误:

mysql> CREATE TABLE t (i INT NOT NULL PRIMARY KEY);
mysql> INSERT INTO t (i) VALUES(1),(1);
ERROR 1062 (23000): Duplicate entry \’1\’ for key \’t.PRIMARY\’

使用IGNORE,包含重复键的行仍然不会被插入,但会产生警告而不是错误:

mysql> INSERT IGNORE INTO t (i) VALUES(1),(1);
Query OK, 1 row affected, 1 warning (0.01 sec)
Records: 2 Duplicates: 1 Warnings: 1
mysql> SHOW WARNINGS;
+———+——+—————————————–+
| Level | Code | Message |
+———+——+—————————————–+
| Warning | 1062 | Duplicate entry \’1\’ for key \’t.PRIMARY\’ |
+———+——+—————————————–+
1 row in set (0.00 sec)

示例:如果表t2有一个NOT NULL列id,尝试插入NULL在严格 SQL 模式下会产生错误:

mysql> CREATE TABLE t2 (id INT NOT NULL);
mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
ERROR 1048 (23000): Column \’id\’ cannot be null
mysql> SELECT * FROM t2;
Empty set (0.00 sec)

如果 SQL 模式不是严格的,IGNORE会将NULL插入为列的隐式默认值(在本例中为 0),从而使行能够在不跳过的情况下处理:

mysql> INSERT INTO t2 (id) VALUES(1),(NULL),(3);
mysql> SELECT * FROM t2;
+—-+
| id |
+—-+
| 1 |
| 0 |
| 3 |
+—-+

这些语句支持IGNORE关键字:

CREATE TABLE … SELECT: IGNORE不适用于语句的CREATE TABLE或SELECT部分,而适用于由SELECT生成的行插入到表中。重复现有唯一键值的行将被丢弃。
DELETE: IGNORE使 MySQL 在删除行的过程中忽略错误。
INSERT: 使用IGNORE,重复现有唯一键值的行将被丢弃。将导致数据转换错误的行设置为最接近的有效值。
对于分区表中找不到与给定值匹配的分区的情况,IGNORE会导致包含不匹配值的行的插入操作静默失败。
LOAD DATA, LOAD XML: 使用IGNORE,重复现有唯一键值的行将被丢弃。
UPDATE: 使用IGNORE时,对于唯一键值发生重复键冲突的行不会被更新。将导致数据转换错误的行更新为最接近的有效值。

IGNORE关键字适用于以下可忽略的错误:

ER_BAD_NULL_ERROR
ER_DUP_ENTRY
ER_DUP_ENTRY_WITH_KEY_NAME
ER_DUP_KEY
ER_NO_PARTITION_FOR_GIVEN_VALUE
ER_NO_PARTITION_FOR_GIVEN_VALUE_SILENT
ER_NO_REFERENCED_ROW_2
ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET
ER_ROW_IS_REFERENCED_2
ER_SUBQUERY_NO_1_ROW
ER_VIEW_CHECK_FAILED

严格 SQL 模式对语句执行的影响

MySQL 服务器可以在不同的 SQL 模式下运行,并且可以根据sql_mode系统变量的值为不同的客户端应用这些模式。在“严格”SQL 模式下,服务器将某些警告升级为错误。

例如,在非严格 SQL 模式下,将字符串\’abc\’插入整数列会将该值转换为 0 并产生警告:

mysql> SET sql_mode = \’\’;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t (i) VALUES(\’abc\’);
Query OK, 1 row affected, 1 warning (0.01 sec)
mysql> SHOW WARNINGS;
+———+——+——————————————————–+
| Level | Code | Message |
+———+——+——————————————————–+
| Warning | 1366 | Incorrect integer value: \’abc\’ for column \’i\’ at row 1 |
+———+——+——————————————————–+
1 row in set (0.00 sec)

在严格 SQL 模式下,无效值将被拒绝并产生错误:

mysql> SET sql_mode = \’STRICT_ALL_TABLES\’;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t (i) VALUES(\’abc\’);
ERROR 1366 (HY000): Incorrect integer value: \’abc\’ for column \’i\’ at row 1

有关sql_mode系统变量可能设置的更多信息,请参见第 7.1.11 节,“服务器 SQL 模式”。

严格的 SQL 模式适用于以下语句,在某些值可能超出范围或将无效行插入或删除表时:

ALTER TABLE
CREATE TABLE
CREATE TABLE … SELECT
DELETE(单表和多表)
INSERT
LOAD DATA
LOAD XML
SELECT SLEEP()
UPDATE(单表和多表)

在存储程序中,如果在严格模式下定义程序,则刚才列出的类型的单个语句将以严格的 SQL 模式执行。

严格的 SQL 模式适用于以下错误,这些错误代表一类错误,其中输入值无效或缺失。 如果值的数据类型对于列来说是错误的或可能超出范围,则该值无效。 如果要插入的新行不包含在其定义中没有显式DEFAULT子句的NOT NULL列的值,则该值缺失。

ER_BAD_NULL_ERROR
ER_CUT_VALUE_GROUP_CONCAT
ER_DATA_TOO_LONG
ER_DATETIME_FUNCTION_OVERFLOW
ER_DIVISION_BY_ZERO
ER_INVALID_ARGUMENT_FOR_LOGARITHM
ER_NO_DEFAULT_FOR_FIELD
ER_NO_DEFAULT_FOR_VIEW_FIELD
ER_TOO_LONG_KEY
ER_TRUNCATED_WRONG_VALUE
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD
ER_WARN_DATA_OUT_OF_RANGE
ER_WARN_NULL_TO_NOTNULL
ER_WARN_TOO_FEW_RECORDS
ER_WRONG_ARGUMENTS
ER_WRONG_VALUE_FOR_TYPE
WARN_DATA_TRUNCATED

注意

由于持续的 MySQL 开发定义了新的错误,可能存在不在前述列表中的错误,严格的 SQL 模式适用于这些错误。

7.1.12 连接管理

原文:dev.mysql.com/doc/refman/8.0/en/connection-management.html

7.1.12.1 连接接口

7.1.12.2 管理连接管理

7.1.12.3 DNS 查找和主机缓存

这一部分描述了 MySQL 服务器如何管理连接。这包括可用连接接口的描述,服务器如何使用连接处理程序线程,关于管理连接接口的详细信息,以及 DNS 查找的管理。

原文:dev.mysql.com/doc/refman/8.0/en/connection-interfaces.html

7.1.12.1 连接接口

本节描述了 MySQL 服务器管理客户端连接的方面。

网络接口和连接管理器线程
客户端连接线程管理
连接量管理

网络接口和连接管理器线程

服务器能够在多个网络接口上监听客户端连接。连接管理器线程处理服务器监听的网络接口上的客户端连接请求:

在所有平台上,一个管理器线程处理 TCP/IP 连接请求。
在 Unix 上,同一个管理器线程还处理 Unix 套接字文件连接请求。
在 Windows 上,一个管理器线程处理共享内存连接请求,另一个处理命名管道连接请求。
在所有平台上,可以启用额外的网络接口以接受管理 TCP/IP 连接请求。此接口可以使用处理“普通”TCP/IP 请求的管理器线程,或者使用单独的线程。

服务器不会创建用于处理其未监听的接口的线程。例如,未启用对命名管道连接的支持的 Windows 服务器不会创建用于处理它们的线程。

单独的服务器插件或组件可能会实现自己的连接接口:

X 插件使 MySQL 服务器能够使用 X 协议与客户端通信。请参阅第 22.5 节,“X 插件”。

客户端连接线程管理

连接管理器线程将每个客户端连接与专用于处理该连接的线程关联起来,负责认证和请求处理。管理器线程在必要时创建新线程,但会首先查看线程缓存,以查看是否有可用于连接的线程,以避免创建新线程。当连接结束时,如果缓存未满,则将其线程返回到线程缓存中。

在这种连接线程模型中,当前连接的客户端数量与线程数量相同,当服务器工作负载必须扩展以处理大量连接时,会出现一些缺点。例如,线程的创建和销毁变得昂贵。此外,每个线程都需要服务器和内核资源,如堆栈空间。为了容纳大量同时连接,必须保持每个线程的堆栈大小较小,导致堆栈大小要么太小,要么服务器消耗大量内存。其他资源的耗尽也可能发生,并且调度开销可能变得显著。

MySQL 企业版包括一个线程池插件,提供了一种旨在减少开销并提高性能的替代线程处理模型。它实现了一个线程池,通过有效管理大量客户端连接的语句执行线程来提高服务器性能。请参阅第 7.6.3 节,“MySQL 企业线程池”。

要控制和监视服务器如何管理处理客户端连接的线程,有几个相关的系统和状态变量。(请参阅第 7.1.8 节,“服务器系统变量”和第 7.1.10 节,“服务器状态变量”。)

thread_cache_size系统变量确定线程缓存大小。默认情况下,服务器在启动时自动调整该值,但可以显式设置以覆盖此默认值。值为 0 会禁用缓存,这会导致每个新连接都设置一个线程,并在连接终止时将其销毁。要启用*N个非活动连接线程缓存,请在服务器启动时或运行时将thread_cache_size设置为N*。当与其关联的客户端连接终止时,连接线程变为非活动状态。
要监视缓存中的线程数以及由于无法从缓存中获取线程而创建的线程数,请检查Threads_cached和Threads_created状态变量。
当线程堆栈太小时,这限制了服务器可以处理的 SQL 语句的复杂性,存储过程的递归深度以及其他消耗内存的操作。要为每个线程设置*N字节的堆栈大小,请使用thread_stack设置为N*来启动服务器。

连接数量管理

要控制服务器允许同时连接的最大客户端数,请在服务器启动或运行时设置 max_connections 系统变量。如果更多客户端尝试同时连接,而服务器配置为处理的数量不够,则可能需要增加 max_connections(请参阅 Section B.3.2.5, “Too many connections”)。如果服务器因达到 max_connections 限制而拒绝连接,则会增加 Connection_errors_max_connections 状态变量。

mysqld 实际上允许 max_connections + 1 个客户端连接。额外的连接保留供具有 CONNECTION_ADMIN 权限(或已弃用的 SUPER 权限)的帐户使用。通过将权限授予管理员而不授予普通用户(不应该需要该权限),管理员可以连接到服务器并使用 SHOW PROCESSLIST 来诊断问题,即使已连接了最大数量的非特权客户端。参见 Section 15.7.7.29, “SHOW PROCESSLIST Statement”。

从 MySQL 8.0.14 开始,服务器还允许在管理网络接口上进行管理连接,您可以使用专用 IP 地址和端口进行设置。参见 Section 7.1.12.2, “Administrative Connection Management”。

Group Replication 插件通过内部会话与 MySQL Server 进行交互,执行 SQL API 操作。在 MySQL 8.0.18 版本中,这些会话计入由 max_connections 服务器系统变量指定的客户端连接限制。在这些版本中,如果服务器在启动 Group Replication 或尝试执行操作时已达到 max_connections 限制,则操作将失败,Group Replication 或服务器本身可能会停止。从 MySQL 8.0.19 开始,Group Replication 的内部会话与客户端连接分开处理,因此它们不计入 max_connections 限制,并且如果服务器达到此限制,则不会被拒绝。

MySQL 支持的客户端连接的最大数量(即可以设置为的max_connections的最大值)取决于几个因素:

给定平台上线程库的质量。
可用的 RAM 量。
每个连接使用的 RAM 量。
每个连接的工作负载。
期望的响应时间。
可用的文件描述符数量。

Linux 或 Solaris 应该能够常规支持至少 500 到 1000 个同时连接,并且如果你有许多 GB 的可用 RAM 并且每个连接的工作负载较低或响应时间目标不苛刻,那么可以支持多达 10,000 个连接。

增加max_connections值会增加mysqld需要的文件描述符数量。如果所需的描述符数量不可用,服务器会降低max_connections的值。有关文件描述符限制的评论,请参见 Section 10.4.3.1, “How MySQL Opens and Closes Tables”。

可能需要增加open_files_limit系统变量,这可能还需要提高操作系统对 MySQL 可以使用多少文件描述符的限制。请参阅您的操作系统文档,以确定是否可以增加限制以及如何操作。另请参见 Section B.3.2.16, “File Not Found and Similar Errors”。

原文:dev.mysql.com/doc/refman/8.0/en/administrative-connection-interface.html

7.1.12.2 管理连接管理

如在连接量管理中提到的,即使在用于普通连接的接口上已经建立了max_connections连接,MySQL 服务器也允许具有CONNECTION_ADMIN权限(或已弃用的SUPER权限)的用户进行单个管理连接,以满足执行管理操作的需要。

此外,从 MySQL 8.0.14 开始,服务器允许为管理连接专用一个 TCP/IP 端口,如下节所述。

管理界面特性
管理界面支持加密连接

管理界面特性

管理连接界面具有以下特性:

服务器仅在启动时将admin_address系统变量设置为指示其 IP 地址时才启用接口。如果未设置admin_address,服务器将不维护任何管理界面。
admin_port系统变量指定接口 TCP/IP 端口号(默认为 33062)。
管理连接数量没有限制,但只允许具有SERVICE_CONNECTION_ADMIN权限的用户连接。
create_admin_listener_thread系统变量允许 DBA 在启动时选择管理界面是否有自己独立的线程。默认为OFF;即,用于主接口上普通连接的管理线程也处理管理界面的连接。

在服务器的my.cnf文件中,这些行启用了回环接口上的管理界面,并配置其使用端口号 33064(即与默认端口不同):

[mysqld]
admin_address=127.0.0.1
admin_port=33064

MySQL 客户端程序通过指定适当的连接参数连接到主界面或管理界面。如果运行在本地主机上的服务器使用默认的 TCP/IP 端口号 3306 和 33062 用于主界面和管理界面,这些命令将连接到这些界面:

mysql –protocol=TCP –port=3306
mysql –protocol=TCP –port=33062

管理界面支持加密连接

在 MySQL 8.0.21 之前,管理界面支持使用适用于主界面的连接加密配置进行加密连接。从 MySQL 8.0.21 开始,管理界面有自己的加密连接配置参数。这些参数对应于主界面参数,但允许独立配置管理界面的加密连接:

admin_tls_*xxx* 和 admin_ssl_*xxx* 系统变量类似于 tls_*xxx* 和 ssl_*xxx* 系统变量,但它们配置管理界面而不是主界面的 TLS 上下文。
–admin-ssl 选项类似于 –ssl 选项,但它启用或禁用管理界面而不是主界面上的加密连接支持。
因为默认情况下启用了对加密连接的支持,通常不需要指定 –admin-ssl。从 MySQL 8.0.26 开始,–admin-ssl 已被弃用,并可能在未来的 MySQL 版本中移除。

有关配置连接加密支持的一般信息,请参阅 第 8.3.1 节,“配置 MySQL 使用加密连接” 和 第 8.3.2 节,“加密连接 TLS 协议和密码”。该讨论是针对主连接界面编写的,但管理连接界面的参数名称类似。结合该讨论和以下提供的信息,这些信息提供了管理界面特定的信息。

管理界面的 TLS 配置遵循以下规则:

如果启用了 –admin-ssl(默认情况下),管理界面支持加密连接。对于界面上的连接,适用的 TLS 上下文取决于是否配置了任何非默认的管理 TLS 参数:

如果所有管理 TLS 参数都采用默认值,则管理界面将使用与主界面相同的 TLS 上下文。
如果任何管理 TLS 参数具有非默认值,则管理界面使用由其自身参数定义的 TLS 上下文。(如果任何admin_tls_*xxx*或admin_ssl_*xxx*系统变量设置为与其默认值不同的值,则是这种情况。)如果无法从这些参数创建有效的 TLS 上下文,则管理界面将退回到主界面 TLS 上下文。
如果–admin-ssl被禁用(例如,通过指定–admin-ssl=OFF,则对管理界面的加密连接被禁用。即使管理 TLS 参数具有非默认值,因为禁用–admin-ssl优先。
也可以在不指定–admin-ssl的否定形式的情况下禁用管理界面上的加密连接。将admin_tls_version系统变量设置为空值表示不支持任何 TLS 版本。例如,服务器my.cnf文件中的这些行禁用了管理界面上的加密连接:
[mysqld]
admin_tls_version=\’\’

例子:

这个在服务器my.cnf文件中的配置启用了管理界面,但没有设置任何特定于该界面的 TLS 参数:
[mysqld]
admin_address=127.0.0.1
结果,管理界面支持加密连接(因为当管理界面启用时,默认支持加密),并使用主界面 TLS 上下文。当客户端连接到管理界面时,他们应该使用与主界面上普通连接相同的证书和密钥文件。例如(在一行上输入命令):
mysql –protocol=TCP –port=33062
–ssl-ca=ca.pem
–ssl-cert=client-cert.pem
–ssl-key=client-key.pem
这个服务器配置启用了管理界面,并设置了特定于该界面的 TLS 证书和密钥文件参数:
[mysqld]
admin_address=127.0.0.1
admin_ssl_ca=admin-ca.pem
admin_ssl_cert=admin-server-cert.pem
admin_ssl_key=admin-server-key.pem
结果,管理界面支持使用其自己的 TLS 上下文进行加密连接。当客户端连接到管理界面时,他们应该使用特定于该界面的证书和密钥文件。例如(在一行上输入命令):
mysql –protocol=TCP –port=33062
–ssl-ca=admin-ca.pem
–ssl-cert=admin-client-cert.pem
–ssl-key=admin-client-key.pem

原文:dev.mysql.com/doc/refman/8.0/en/host-cache.html

7.1.12.3 DNS 查找和主机缓存

MySQL 服务器维护一个内存中的主机缓存,其中包含有关客户端的信息:IP 地址、主机名和错误信息。性能模式host_cache表公开主机缓存的内容,以便可以使用SELECT语句进行检查。这可能有助于诊断连接问题的原因。参见 Section 29.12.21.3,“主机缓存表”。

以下各节讨论了主机缓存的工作原理,以及如何配置和监视缓存等其他主题。

主机缓存操作
配置主机缓存
监视主机缓存
刷新主机缓存
处理被阻止的主机

主机缓存操作

服务器仅针对非本地主机的 TCP 连接使用主机缓存。它不会对使用回环接口地址(例如,127.0.0.1或::1)建立的 TCP 连接,或者使用 Unix 套接字文件、命名管道或共享内存建立的连接使用缓存。

服务器使用主机缓存有几个目的:

通过缓存 IP 到主机名查找的结果,服务器避免为每个客户端连接执行域名系统(DNS)查找。相反,对于给定的主机,它只需要在来自该主机的第一个连接时执行查找。
缓存包含在客户端连接过程中发生的错误信息。一些错误被视为“阻塞”。如果来自给定主机的这些错误过多连续发生而没有成功连接,服务器将阻止该主机的进一步连接。max_connect_errors系统变量确定在发生阻塞之前允许的连续错误数量。

对于每个适用的新客户端连接,服务器使用客户端 IP 地址来检查客户端主机名是否在主机缓存中。如果是,服务器会根据主机是否被阻止来拒绝或继续处理连接请求。如果主机不在缓存中,服务器会尝试解析主机名。首先,它将 IP 地址解析为主机名,然后将该主机名解析回 IP 地址。然后将结果与原始 IP 地址进行比较,以确保它们相同。服务器将此操作的结果信息存储在主机缓存中。如果缓存已满,最近最少使用的条目将被丢弃。

服务器使用getaddrinfo()系统调用执行主机名解析。

服务器处理主机缓存条目如下:

当来自特定 IP 地址的第一个 TCP 客户端连接到达服务器时,将创建一个新的缓存条目来记录客户端 IP、主机名和客户端查找验证标志。最初,主机名设置为NULL,标志为 false。此条目还用于来自相同原始 IP 的后续客户端 TCP 连接。
如果客户端 IP 条目的验证标志为 false,则服务器尝试进行 IP 到主机名到 IP 的 DNS 解析。如果成功,主机名将更新为解析后的主机名,并将验证标志设置为 true。如果解析失败,则采取的操作取决于错误是永久的还是暂时的。对于永久性失败,主机名保持为NULL,验证标志设置为 true。对于暂时性失败,主机名和验证标志保持不变。(在这种情况下,下次有客户端从此 IP 连接时将再次进行 DNS 解析尝试。)
如果在处理来自特定 IP 地址的传入客户端连接时发生错误,服务器会更新该 IP 对应条目中的错误计数器。有关记录的错误描述,请参见 Section 29.12.21.3,“主机缓存表”。

要解除被阻止的主机,清空主机缓存;参见处理被阻止的主机。

即使在不清空主机缓存的情况下,也有可能使一个被阻止的主机变为未阻止状态,只要来自其他主机的活动发生:

如果连接到服务器的客户端 IP 不在缓存中且缓存已满,服务器会丢弃最近最少使用的缓存条目,为新条目腾出空间。
如果被丢弃的条目是针对一个被阻止的主机,那么该主机将变为未阻止状态。

一些连接错误与 TCP 连接无关,出现在连接过程的非常早期(甚至在知道 IP 地址之前),或者不特定于任何特定的 IP 地址(例如内存不足条件)。有关这些错误的信息,请查看Connection_errors_*xxx*状态变量(请参阅第 7.1.10 节,“服务器状态变量”)。

配置主机缓存

主机缓存默认启用。host_cache_size系统变量控制其大小,以及暴露缓存内容的性能模式host_cache表的大小。缓存大小可以在服务器启动时设置并在运行时更改。例如,要在启动时将大小设置为 100,请将以下行放入服务器的my.cnf文件中:

[mysqld]
host_cache_size=200

在运行时将大小更改为 300,请执行以下操作:

SET GLOBAL host_cache_size=300;

将host_cache_size设置为 0,无论是在服务器启动时还是在运行时,都会禁用主机缓存。禁用缓存后,服务器在每次客户端连接时执行 DNS 查找。

在运行时更改缓存大小会导致隐式主机缓存刷新操作,清除主机缓存,截断host_cache表,并解除任何被阻止的主机;参见刷新主机缓存。

使用–skip-host-cache选项类似于将host_cache_size系统变量设置为 0,但host_cache_size更灵活,因为它还可以用于在运行时调整、启用和禁用主机缓存,而不仅仅是在服务器启动时。使用–skip-host-cache启动服务器不会阻止对host_cache_size值的运行时更改,但这些更改没有效果,即使将host_cache_size设置为大于 0,缓存也不会重新启用。

要禁用 DNS 主机名查找,请启用skip_name_resolve系统变量启动服务器。在这种情况下,服务器仅使用 IP 地址而不是主机名来将连接主机与 MySQL 授权表中的行匹配。只能使用在这些表中使用 IP 地址指定的帐户。 (如果没有指定客户端 IP 地址的帐户,则客户端可能无法连接。)

如果您的 DNS 非常慢且有许多主机,您可以通过启用skip_name_resolve来禁用 DNS 查找,或者通过增加host_cache_size的值来使主机缓存更大来提高性能。

要完全禁止 TCP/IP 连接,请启动时启用skip_networking系统变量。

要调整在主机阻止发生之前允许的连续连接错误数,请设置max_connect_errors系统变量。例如,要在启动时设置该值,请将以下行放入服务器的my.cnf文件中:

[mysqld]
max_connect_errors=10000

要在运行时更改该值,请执行以下操作:

SET GLOBAL max_connect_errors=10000;

监控主机缓存

Performance Schema host_cache 表公开了主机缓存的内容。可以使用SELECT语句检查此表,这可能有助于诊断连接问题的原因。有关此表的信息,请参阅 Section 29.12.21.3, “The host_cache Table”。

刷新主机缓存

在以下情况下刷新主机缓存可能是明智或可取的:

您的一些客户端主机更改了 IP 地址。
错误消息Host \’*host_name*\’ is blocked出现在来自合法主机的连接中。(参见处理被阻止的主机。)

刷新主机缓存会产生以下效果:

它清除内存中的主机缓存。
它会从 Performance Schema host_cache 表中删除所有行,该表公开了缓存内容。
它解除任何被阻止的主机。这使得这些主机可以进一步尝试连接。

要刷新主机缓存,请使用以下任一方法:

更改host_cache_size系统变量的值。这需要SYSTEM_VARIABLES_ADMIN权限(或已弃用的SUPER权限)。
执行一个截断 Performance Schema host_cache 表的TRUNCATE TABLE语句。这需要表的DROP权限。
执行一个FLUSH HOSTS语句。这需要RELOAD权限。
注意
FLUSH HOSTS在 MySQL 8.0.23 中已弃用,并计划在将来的版本中删除。
执行mysqladmin flush-hosts命令。这需要对性能模式host_cache表或RELOAD权限的DROP权限。

处理被阻止的主机

服务器使用主机缓存来跟踪客户端连接过程中发生的错误。如果出现以下错误,意味着mysqld从给定主机接收了许多连接请求,但在中途被中断:

Host \’*host_name*\’ is blocked because of many connection errors.
Unblock with \’mysqladmin flush-hosts\’

max_connect_errors系统变量的值确定服务器在阻止主机之前允许多少连续中断的连接请求。在连续max_connect_errors个失败请求而没有成功连接之后,服务器会认为出现了问题(例如,有人试图入侵),并阻止主机进一步的连接请求。

要解除被阻止的主机,刷新主机缓存;参见刷新主机缓存。

或者,为了避免出现错误消息,按照配置主机缓存中描述的方式设置max_connect_errors。max_connect_errors的默认值为 100。将max_connect_errors增加到一个较大的值可以减少主机达到阈值并被阻止的可能性。然而,如果出现主机\’*host_name*\’被阻止的错误消息,请首先验证被阻止主机的 TCP/IP 连接是否正常。如果存在网络问题,则增加max_connect_errors的值是没有好处的。

7.1.13 IPv6 Support

原文:dev.mysql.com/doc/refman/8.0/en/ipv6-support.html

7.1.13.1 Verifying System Support for IPv6

7.1.13.2 Configuring the MySQL Server to Permit IPv6 Connections

7.1.13.3 Connecting Using the IPv6 Local Host Address

7.1.13.4 Connecting Using IPv6 Nonlocal Host Addresses

7.1.13.5 Obtaining an IPv6 Address from a Broker

MySQL 中对 IPv6 的支持包括以下功能:

MySQL 服务器可以接受通过 IPv6 连接的客户端的 TCP/IP 连接。���如,此命令通过 IPv6 连接到本地主机上的 MySQL 服务器:
$> mysql -h ::1
要使用此功能,必须满足两个条件:

您的系统必须配置为支持 IPv6。参见 Section 7.1.13.1, “Verifying System Support for IPv6”。
默认的 MySQL 服务器配置允许 IPv4 连接以及 IPv6 连接。要更改默认配置,请使用bind_address系统变量设置适当的值启动服务器。参见 Section 7.1.8, “Server System Variables”。
MySQL 帐户名称允许 IPv6 地址,以便 DBA 可以为通过 IPv6 连接到服务器的客户端指定权限。参见 Section 8.2.4, “Specifying Account Names”。IPv6 地址可以在语句中指定帐户名称,例如CREATE USER、GRANT和REVOKE。例如:
mysql> CREATE USER \’bill\’@\’::1\’ IDENTIFIED BY \’secret\’;
mysql> GRANT SELECT ON mydb.* TO \’bill\’@\’::1\’;
IPv6 函数允许在字符串和内部格式 IPv6 地址格式之间进行转换,并检查值是否表示有效的 IPv6 地址。例如,INET6_ATON()和INET6_NTOA()类似于INET_ATON()和INET_NTOA(),但除了 IPv4 地址外,还处理 IPv6 地址。参见 Section 14.23, “Miscellaneous Functions”。
从 MySQL 8.0.14 开始,Group Replication 组成员可以在组内使用 IPv6 地址进行通信。一个组可以包含使用 IPv6 和使用 IPv4 的成员的混合。参见 Section 20.5.5, “Support For IPv6 And For Mixed IPv6 And IPv4 Groups”。

以下各节描述了如何设置 MySQL,以便客户端可以通过 IPv6 连接到服务器。

原文:dev.mysql.com/doc/refman/8.0/en/ipv6-system-support.html

7.1.13.1 验证系统对 IPv6 的支持

在 MySQL 服务器可以接受 IPv6 连接之前,您的服务器主机上的操作系统必须支持 IPv6。要确定这一点是否成立,可以尝试运行以下命令:

$> ping6 ::1
16 bytes from ::1, icmp_seq=0 hlim=64 time=0.171 ms
16 bytes from ::1, icmp_seq=1 hlim=64 time=0.077 ms

要生成系统网络接口的描述,请调用ifconfig -a并查看输出中的 IPv6 地址。

如果您的主机不支持 IPv6,请查阅系统文档以获取启用指南。也许您只需要重新配置现有网络接口以添加 IPv6 地址。或者可能需要进行更广泛的更改,比如使用启用 IPv6 选项重新构建内核。

这些链接可能有助于在各种平台上设置 IPv6:

Windows
Gentoo Linux
Ubuntu Linux
Linux(通用)
macOS

原文:dev.mysql.com/doc/refman/8.0/en/ipv6-server-config.html

7.1.13.2 配置 MySQL 服务器以允许 IPv6 连接

MySQL 服务器在一个或多个网络套接字上监听 TCP/IP 连接。每个套接字绑定到一个地址,但一个地址可能映射到多个网络接口。

在服务器启动时设置bind_address系统变量,以指定服务器实例接受的 TCP/IP 连接。从 MySQL 8.0.13 开始,您可以为此选项指定多个值,包括任何组合的 IPv6 地址、IPv4 地址和解析为 IPv6 或 IPv4 地址的主机名。或者,您可以指定允许监听多个网络接口的通配符地址格式之一。值为 *(默认值)或值为 :: 允许在所有服务器主机的 IPv4 和 IPv6 接口上进行 IPv4 和 IPv6 连接。有关更多信息,请参阅第 7.1.8 节,“服务器系统变量”中的bind_address描述。

原文:dev.mysql.com/doc/refman/8.0/en/ipv6-local-connections.html

7.1.13.3 使用 IPv6 本地主机地址连接

以下步骤显示了如何配置 MySQL 以允许通过::1本地主机地址连接到本地服务器的客户端的 IPv6 连接。这里给出的说明假定您的系统支持 IPv6。

使用适当的bind_address设置启动 MySQL 服务器,以允许其接受 IPv6 连接。例如,将以下行放入服务器选项文件并重新启动服务器:
[mysqld]
bind_address = *
将*(或::)指定为bind_address的值允许在所有服务器主机 IPv4 和 IPv6 接口上进行 IPv4 和 IPv6 连接。如果您想将服务器绑定到特定地址列表,您可以在 MySQL 8.0.13 中通过为bind_address指定逗号分隔的值来实现。此示例指定了 IPv4 和 IPv6 的本地主机地址:
[mysqld]
bind_address = 127.0.0.1,::1
有关更多信息,请参见第 7.1.8 节“服务器系统变量”中的bind_address描述。
作为管理员,连接到服务器并为可以从::1本地 IPv6 主机地址连接的本地用户创建一个帐户:
mysql> CREATE USER \’ipv6user\’@\’::1\’ IDENTIFIED BY \’ipv6pass\’;
有关帐户名称中 IPv6 地址的允许语法,请参见第 8.2.4 节“指定帐户名称”。除了CREATE USER语句外,您还可以发出GRANT语句,为帐户授予特定权限,尽管这对本过程中的其余步骤并不是必需的。
调用mysql客户端,使用新帐户连接到服务器:
$> mysql -h ::1 -u ipv6user -pipv6pass
尝试一些显示连接信息的简单语句:
mysql> STATUS

Connection: ::1 via TCP/IP

mysql> SELECT CURRENT_USER(), @@bind_address;
+—————-+—————-+
| CURRENT_USER() | @@bind_address |
+—————-+—————-+
| ipv6user@::1 | :: |
+—————-+—————-+

原文:dev.mysql.com/doc/refman/8.0/en/ipv6-remote-connections.html

7.1.13.4 使用 IPv6 非本地主机地址进行连接

以下过程展示了如何配置 MySQL 以允许远程客户端进行 IPv6 连接。与本地客户端的前面过程类似,但服务器和客户端主机是不同的,并且每个主机都有自己的非本地 IPv6 地址。示例使用以下地址:

Server host: 2001:db8:0:f101::1
Client host: 2001:db8:0:f101::2

这些地址是从IANA推荐的非路由地址范围中选择的,用于文档目的并足以在本地网络上进行测试。要接受来自本地网络之外客户端的 IPv6 连接,服务器主机必须具有公共地址。如果您的网络提供商分配给您一个 IPv6 地址,您可以使用该地址。否则,获取地址的另一种方法是使用 IPv6 代理;请参阅 Section 7.1.13.5, “Obtaining an IPv6 Address from a Broker”。

使用适当的bind_address设置启动 MySQL 服务器,以允许其接受 IPv6 连接。例如,在服务器选项文件中放入以下行并重新启动服务器:
[mysqld]
bind_address = *
将 *(或 ::)指定为bind_address的值,允许所有服务器主机 IPv4 和 IPv6 接口上的 IPv4 和 IPv6 连接。如果要将服务器绑定到特定地址列表,您可以在 MySQL 8.0.13 中通过为bind_address指定逗号分隔的值来实现。此示例指定了一个 IPv4 地址以及所需的服务器主机 IPv6 地址:
[mysqld]
bind_address = 198.51.100.20,2001:db8:0:f101::1
欲了解更多信息,请参阅 Section 7.1.8, “Server System Variables”中的bind_address描述。
在服务器主机(2001:db8:0:f101::1)上,为可以从客户端主机(2001:db8:0:f101::2)连接的用户创建一个帐户:
mysql> CREATE USER \’remoteipv6user\’@\’2001:db8:0:f101::2\’ IDENTIFIED BY \’remoteipv6pass\’;
在客户端主机(2001:db8:0:f101::2)上,调用mysql客户端以使用新帐户连接到服务器:
$> mysql -h 2001:db8:0:f101::1 -u remoteipv6user -premoteipv6pass
尝试一些简单的语句,显示连接信息:
mysql> STATUS

Connection: 2001:db8:0:f101::1 via TCP/IP

mysql> SELECT CURRENT_USER(), @@bind_address;
+———————————–+—————-+
| CURRENT_USER() | @@bind_address |
+———————————–+—————-+
| remoteipv6user@2001:db8:0:f101::2 | :: |
+———————————–+—————-+

原文:dev.mysql.com/doc/refman/8.0/en/ipv6-brokers.html

7.1.13.5 从代理获取 IPv6 地址

如果您没有一个能够使您的系统在本地网络之外通过 IPv6 进行通信的公共 IPv6 地址,您可以从 IPv6 代理处获取一个。Wikipedia IPv6 隧道代理页面列出了几个代理及其功能,例如它们是否提供静态地址和支持的路由协议。

在配置服务器主机使用代理提供的 IPv6 地址后,使用适当的bind_address设置启动 MySQL 服务器,以允许服务器接受 IPv6 连接。您可以将*(或::)指定为bind_address值,或将服务器绑定到代理提供的特定 IPv6 地址。有关更多信息,请参见第 7.1.8 节,“服务器系统变量”中的bind_address描述。

请注意,如果代理分配动态地址,则为您的系统提供的地址可能会在下次连接到代理时更改。如果是这样,任何使用原始地址命名的帐户都将变为无效。为了绑定到特定地址但避免这种地址更改问题,您可以尝试与代理安排获得静态 IPv6 地址。

以下示例展示了如何在 Gentoo Linux 上将 Freenet6 用作代理和gogoc IPv6 客户端包的使用方法。

在 Freenet6 创建一个帐户,访问此 URL 并注册:
http://gogonet.gogo6.com
创建帐户后,转到此 URL,登录并为 IPv6 代理创建用户 ID 和密码:
http://gogonet.gogo6.com/page/freenet6-registration
作为root,安装gogoc:
$> emerge gogoc
编辑/etc/gogoc/gogoc.conf以设置userid和password的值。例如:
userid=gogouser
passwd=gogopass
启动gogoc:
$> /etc/init.d/gogoc start
每次系统启动时启动gogoc,执行此命令:
$> rc-update add gogoc default
使用ping6尝试 ping 主机:
$> ping6 ipv6.google.com
查看你的 IPv6 地址:
$> ifconfig tun

7.1.14 网络命名空间支持

原文:dev.mysql.com/doc/refman/8.0/en/network-namespace-support.html

网络命名空间是主机系统网络堆栈的逻辑副本。网络命名空间适用于设置容器或虚拟环境。每个命名空间都有自己的 IP 地址、网络接口、路由表等。默认或全局命名空间是主机系统物理接口存在的命名空间。

命名空间特定的地址空间可能会导致 MySQL 连接跨越命名空间时出现问题。例如,在容器或虚拟网络中运行的 MySQL 实例的网络地址空间可能与主机机器的地址空间不同。这可能会导致诸如来自一个命名空间中的地址的客户端连接似乎来自不同地址的 MySQL 服务器,即使客户端和服务器在同一台机器上运行。假设两个进程都在具有 IP 地址203.0.113.10的主机上运行,但使用不同的命名空间。连接可能产生如下结果:

$> mysql –user=admin –host=203.0.113.10 –protocol=tcp
mysql> SELECT USER();
+——————–+
| USER() |
+——————–+
| admin@198.51.100.2 |
+——————–+

在这种情况下,预期的USER()值为admin@203.0.113.10。如果连接发起的地址与其表面不符,这种行为可能会使正确分配帐户权限变得困难。

为解决此问题,MySQL 允许指定用于 TCP/IP 连接的网络命名空间,以便连接的两端使用约定的共同地址空间。

MySQL 8.0.22 及更高版本支持实现网络命名空间的平台上的网络命名空间。MySQL 内的支持适用于:

MySQL 服务器,mysqld。
X 插件。
mysql客户端和mysqlxtest测试套件客户端。(不支持其他客户端。它们必须从要连接的服务器的网络命名空间内调用。)
常规复制。
组复制,仅在使用 MySQL 通信堆栈建立组通信连接时(从 MySQL 8.0.27 开始)。

以下部分描述了如何在 MySQL 中使用网络命名空间:

主机系统先决条件
MySQL 配置
网络命名空间监控

主机系统先决条件

在 MySQL 中使用网络命名空间支持之前,必须满足这些主机系统先决条件:

主机操作系统必须支持网络命名空间。(例如,Linux。)
MySQL 要使用的任何网络命名空间必须首先在主机系统上创建。
主机名解析必须由系统管理员配置以支持网络命名空间。
注意
已知的限制是,在 MySQL 中,主机名解析对于在特定网络命名空间主机文件中指定的名称不起作用。例如,如果在red命名空间中的主机名的地址在/etc/netns/red/hosts文件中指定,那么在服务器和客户端端都无法绑定到该名称。解决方法是使用 IP 地址而不是主机名。
系统管理员必须为支持网络命名空间的 MySQL 二进制文件启用CAP_SYS_ADMIN操作系统特权(mysqld,mysql,mysqlxtest)。
重要提示
启用CAP_SYS_ADMIN是一个安全敏感的操作,因为它使进程能够执行其他特权操作,除了设置命名空间。有关其影响的描述,请参见man7.org/linux/man-pages/man7/capabilities.7.html。
因为CAP_SYS_ADMIN必须由系统管理员显式启用,所以默认情况下 MySQL 二进制文件不具有启用网络命���空间支持。在启用之前,系统管理员应评估使用CAP_SYS_ADMIN运行 MySQL 进程的安全性影响。

以下示例中的说明设置了名为red和blue的网络命名空间。您选择的名称可能不同,主机系统上的网络地址和接口也可能不同。

在此处显示的命令要么作为root操作系统用户调用,要么在每个命令前加上sudo前缀。例如,如果你不是root用户,要调用ip或setcap命令,使用sudo ip或sudo setcap。

要配置网络命名空间,请使用ip命令。对于某些操作,ip命令必须在特定的命名空间内执行(该命名空间必须已经存在)。在这种情况下,命令应该这样开始:

ip netns exec *namespace_name*

例如,此命令在red命名空间内执行以启动环回接口:

ip netns exec red ip link set lo up

要添加名为red和blue的命名空间,每个命名空间都有自己的虚拟以太网设备用作命名空间之间的链接以及自己的环回接口:

ip netns add red
ip link add veth-red type veth peer name vpeer-red
ip link set vpeer-red netns red
ip addr add 192.0.2.1/24 dev veth-red
ip link set veth-red up
ip netns exec red ip addr add 192.0.2.2/24 dev vpeer-red
ip netns exec red ip link set vpeer-red up
ip netns exec red ip link set lo up
ip netns add blue
ip link add veth-blue type veth peer name vpeer-blue
ip link set vpeer-blue netns blue
ip addr add 198.51.100.1/24 dev veth-blue
ip link set veth-blue up
ip netns exec blue ip addr add 198.51.100.2/24 dev vpeer-blue
ip netns exec blue ip link set vpeer-blue up
ip netns exec blue ip link set lo up
# if you want to enable inter-subnet routing…
sysctl net.ipv4.ip_forward=1
ip netns exec red ip route add default via 192.0.2.1
ip netns exec blue ip route add default via 198.51.100.1

命名空间之间链接的图示如下:

red global blue
192.0.2.2 <=> 192.0.2.1
(vpeer-red) (veth-red)
198.51.100.1 <=> 198.51.100.2
(veth-blue) (vpeer-blue)

要检查存在哪些命名空间和链接:

ip netns list
ip link list

要查看全局和命名空间的路由表:

ip route show
ip netns exec red ip route show
ip netns exec blue ip route show

要删除red和blue的链接和命名空间:

ip link del veth-red
ip link del veth-blue
ip netns del red
ip netns del blue
sysctl net.ipv4.ip_forward=0

为了使包含网络命名空间支持的 MySQL 二进制文件实际上可以使用命名空间,您必须授予它们CAP_SYS_ADMIN权限。以下setcap命令假定您已更改位置到包含 MySQL 二进制文件的目录(根据需要调整系统的路径名):

cd /usr/local/mysql/bin

要将CAP_SYS_ADMIN权限授予适当的二进制文件:

setcap cap_sys_admin+ep ./mysqld
setcap cap_sys_admin+ep ./mysql
setcap cap_sys_admin+ep ./mysqlxtest

要检查CAP_SYS_ADMIN权限:

$> getcap ./mysqld ./mysql ./mysqlxtest
./mysqld = cap_sys_admin+ep
./mysql = cap_sys_admin+ep
./mysqlxtest = cap_sys_admin+ep

要删除CAP_SYS_ADMIN权限:

setcap -r ./mysqld
setcap -r ./mysql
setcap -r ./mysqlxtest

重要提示

如果重新安装之前已应用setcap的二进制文件,则必须再次使用setcap。例如,如果执行原地 MySQL 升级,未再次授予CAP_SYS_ADMIN权限将导致与命名空间相关的失败。服务器在尝试绑定到具有命名空间的地址���将失败,并显示此错误:

[ERROR] [MY-013408] [Server] setns() failed with error \’Operation not permitted\’

使用–network-namespace选项调用的客户端会失败,如下所示:

ERROR: Network namespace error: Operation not permitted

MySQL 配置

假设前述主机系统先决条件已满足,MySQL 可以配置服务器端命名空间以监听(入站)连接的一侧,以及客户端端命名空间以进行出站连接。

在服务器端,bind_address、admin_address和mysqlx_bind_address系统变量具有扩展语法,用于指定用于给定 IP 地址或主机名监听传入连接的网络命名空间。要为地址指定命名空间,请添加斜杠和命名空间名称。例如,服务器的my.cnf文件可能包含以下行:

[mysqld]
bind_address = 127.0.1.1,192.0.2.2/red,198.51.100.2/blue
admin_address = 102.0.2.2/red
mysqlx_bind_address = 102.0.2.2/red

这些规则适用:

可以为 IP 地址或主机名指定网络命名空间。
无法为通配符 IP 地址指定网络命名空间。
对于给定的地址,网络命名空间是可选的。如果指定了,必须在地址后面立即添加/*ns*后缀。
没有/*ns*后缀的地址使用主机系统的全局命名空间。因此,全局命名空间是默认值。
带有/*ns*后缀的地址使用名为*ns*的命名空间。
主机系统必须支持网络命名空间,并且每个命名命名空间必须事先设置好。命名不存在的命名空间会产生错误。
bind_address和(自 MySQL 8.0.21 起)mysqlx_bind_address接受多个逗号分隔地址的列表,变量值可以指定全局命名空间中的地址、命名命名空间中的地址或混合地址。

如果在服务器启动过程中发生错误,尝试使用命名空间,则服务器将无法启动。如果在插件初始化过程中发生 X 插件的错误,导致无法绑定到任何地址,插件将在初始化序列中失败,服务器将无法加载它。

在客户端端,可以在以下情境中指定网络命名空间:

对于mysql客户端和mysqlxtest测试套件客户端,使用–network-namespace选项。例如:
mysql –host=192.0.2.2 –network-namespace=red
如果省略了–network-namespace选项,连接将使用默认(全局)命名空间。
对于从副本服务器到源服务器的复制连接,请使用CHANGE REPLICATION SOURCE TO语句(从 MySQL 8.0.23 开始)或CHANGE MASTER TO语句(MySQL 8.0.23 之前),并指定NETWORK_NAMESPACE选项。例如:
CHANGE REPLICATION SOURCE TO
SOURCE_HOST = \’192.0.2.2\’,
NETWORK_NAMESPACE = \’red\’;
如果省略了NETWORK_NAMESPACE选项,复制连接将使用默认(全局)命名空间。

以下示例设置了一个 MySQL 服务器,监听全局、red 和 blue 命名空间中的连接,并展示了如何配置从red 和 blue 命名空间连接的帐户。假设red 和 blue 命名空间已经像主机系统先决条件中所示创建。

配置服务器以在多个命名空间中监听地址。将这些行放入服务器的my.cnf文件中并启动服务器:
[mysqld]
bind_address = 127.0.1.1,192.0.2.2/red,198.51.100.2/blue
该值告诉服务器在全局命名空间中监听回环地址127.0.0.1,在red命名空间中监听地址192.0.2.2,在blue命名空间中监听地址198.51.100.2。
连接到全局命名空间中的服务器,并创建具有连接权限的帐户,这些帐户可以从每个命名空间的地址空间连接:
$> mysql -u root -h 127.0.0.1 -p
Enter password: *root_password*
mysql> CREATE USER \’red_user\’@\’192.0.2.2\’
IDENTIFIED BY \’*red_user_password*\’;
mysql> CREATE USER \’blue_user\’@\’198.51.100.2\’
IDENTIFIED BY \’*blue_user_password*\’;
验证您是否可以连接到每个命名空间中的服务器:
$> mysql -u red_user -h 192.0.2.2 –network-namespace=red -p
Enter password: *red_user_password*
mysql> SELECT USER();
+——————–+
| USER() |
+——————–+
| red_user@192.0.2.2 |
+——————–+
$> mysql -u blue_user -h 198.51.100.2 –network-namespace=blue -p
Enter password: *blue_user_password*
mysql> SELECT USER();
+————————+
| USER() |
+————————+
| blue_user@198.51.100.2 |
+————————+
注意
USER()可能返回不同的结果,如果您的 DNS 配置能够将地址解析为相应的主机名,而服务器未启用skip_name_resolve系统变量,则可能返回包含主机名而不是 IP 地址的值。
您也可以尝试在不使用–network-namespace选项的情况下调用mysql,以查看连接尝试是否成功,以及USER()值如何受到影响。

网络命名空间监控

为了复制监控目的,这些信息源具有显示连接适用的网络命名空间的列:

Performance Schema replication_connection_configuration 表。参见 Section 29.12.11.1, “The replication_connection_configuration Table”。
复制服务器连接元数据存储库。参见第 19.2.4.2 节,“复制元数据存储库”。
SHOW REPLICA STATUS(或在 MySQL 8.0.22 之前,SHOW SLAVE STATUS)语句。参见第 15.7.7.35 节,“SHOW REPLICA STATUS 语句”。

7.1.15 MySQL 服务器时区支持

原文:dev.mysql.com/doc/refman/8.0/en/time-zone-support.html

本节描述了 MySQL 维护的时区设置,如何加载命名时间支持所需的系统表,如何跟进时区变更以及如何启用闰秒支持。

从 MySQL 8.0.19 开始,插入的日期时间值也支持时区偏移;请参见第 13.2.2 节,“DATE、DATETIME 和 TIMESTAMP 类型”,以获取更多信息。

有关复制设置中的时区设置信息,请参见第 19.5.1.14 节,“复制和系统函数”和第 19.5.1.33 节,“复制和时区”。

时区变量
填充时区表
时区变更跟进
时区闰秒支持

时区变量

MySQL 服务器维护了几个时区设置:

服务器系统时区。服务器启动时,会尝试确定主机机器的时区并将其用于设置system_time_zone系统变量。
要在 MySQL 服务器启动时明确指定系统时区,请在启动mysqld之前设置TZ环境变量。如果使用mysqld_safe启动服务器,则其–timezone选项提供了另一种设置系统时区的方式。TZ和–timezone的可接受值取决于系统。请查阅您的操作系统文档以查看哪些值是可接受的。
服务器当前时区。全局time_zone系统变量指示服务器当前操作的时区。初始time_zone值为\’SYSTEM\’,表示服务器时区与系统时区相同。
注意
如果设置为SYSTEM,则每个需要时区计算的 MySQL 函数调用都会进行系统库调用以确定当前系统时区。这个调用可能受到全局互斥锁的保护,导致争用。
初始全局服务器时区值可以在启动时通过命令行上的–default-time-zone选项明确指定,或者可以在选项文件中使用以下行:
default-time-zone=\’*timezone*\’
如果您拥有SYSTEM_VARIABLES_ADMIN权限(或已弃用的SUPER权限),您可以使用以下语句在运行时设置全局服务器时区值:
SET GLOBAL time_zone = *timezone*;
每个连接的客户端都有自己的会话时区设置,由会话time_zone变量给出。最初,会话变量从全局time_zone变量中获取其值,但客户端可以使用以下语句更改自己的时区:
SET time_zone = *timezone*;

会话时区设置会影响对时区敏感的时间值的显示和存储。这包括由NOW()或CURTIME()等函数显示的值,以及存储在和从TIMESTAMP列中检索的值。TIMESTAMP列的值会在存储时从会话时区转换为 UTC,并在检索时从 UTC 转换为会话时区。

会话时区设置不会影响诸如UTC_TIMESTAMP()等函数显示的值,也不会影响DATE、TIME或DATETIME列中的值。这些数据类型中的值也不会以 UTC 存储;时区仅在从TIMESTAMP值转换时应用。如果您想要对DATE、TIME或DATETIME值进行区域特定的算术运算,将它们转换为 UTC,执行算术运算,然后再转换回来。

当前的全局和会话时区值可以这样检索:

SELECT @@GLOBAL.time_zone, @@SESSION.time_zone;

timezone 值可以以几种格式给出,大小写不敏感:

作为值\’SYSTEM\’,表示服务器时区与系统时区相同。
作为一个表示与 UTC 偏移的字符串,格式为[*H*]*H*:*MM*,前缀带有+或-,例如\’+10:00\’,\’-6:00\’或\’+05:30\’。对于小时值小于 10 的情况,可以选择性地使用前导零;在这种情况下,MySQL 在存储和检索值时会添加前导零。MySQL 将\’-00:00\’或\’-0:00\’转换为\’+00:00\’。
在 MySQL 8.0.19 之前,此值必须在\’-12:59\’到\’+13:00\’的范围内;从 MySQL 8.0.19 开始,允许的范围是\’-13:59\’到\’+14:00\’,包括在内。
作为一个命名的时区,例如\’Europe/Helsinki\’,\’US/Eastern\’,\’MET\’或\’UTC\’。
注意
只有在mysql数据库中的时区信息表已创建并填充的情况下才能使用命名时区。否则,使用命名时区会导致错误:
mysql> SET time_zone = \’UTC\’;
ERROR 1298 (HY000): Unknown or incorrect time zone: \’UTC\’

填充时区表

mysql系统模式中存在几个表用于存储时区信息(参见第 7.3 节,“mysql 系统模式”)。MySQL 安装过程会创建时区表,但不会加载它们。要手动加载,请使用以下说明。

注意

加载时区信息不一定是一次性操作,因为信息偶尔会发生变化。当发生这种变化时,使用旧规则的应用程序会变得过时,您可能需要重新加载时区表以保持 MySQL 服务器使用的信息最新。请参阅保持时区更改最新。

如果您的系统有自己的 zoneinfo 数据库(描述时区的文件集),请使用mysql_tzinfo_to_sql程序加载时区表。这些系统的示例包括 Linux、macOS、FreeBSD 和 Solaris。这些文件的一个可能位置是/usr/share/zoneinfo目录。如果您的系统没有 zoneinfo 数据库,可以使用后面本节中描述的可下载包。

要从命令行加载时区表,请将 zoneinfo 目录路径名称传递给mysql_tzinfo_to_sql并将输出发送到mysql程序。例如:

mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql

这里显示的mysql命令假定您使用具有修改mysql系统模式中表权限的帐户(如root)连接到服务器。根据需要调整连接参数。

mysql_tzinfo_to_sql读取系统的时区文件,并从中生成 SQL 语句。mysql处理这些语句以加载时区表。

mysql_tzinfo_to_sql也可用于加载单个时区文件或生成闰秒信息:

要加载与时区名称*tz_name对应的单个时区文件tz_file*,请像这样调用mysql_tzinfo_to_sql:
mysql_tzinfo_to_sql *tz_file* *tz_name* | mysql -u root -p mysql
使用这种方法,您必须为服务器需要了解的每个命名区域执行一个单独的命令来加载时区文件。
如果您的时区必须考虑闰秒,像这样初始化闰秒信息,其中*tz_file*是您的时区文件的名称:
mysql_tzinfo_to_sql –leap *tz_file* | mysql -u root -p mysql

运行完mysql_tzinfo_to_sql后,重新启动服务器,以确保它不会继续使用任何先前缓存的时区数据。

如果您的系统没有 zoneinfo 数据库(例如 Windows),您可以使用一个包含 SQL 语句的软件包,可在 MySQL 开发者区下载:

https://dev.mysql.com/downloads/timezones.html

警告

如果您的系统有一个 zoneinfo 数据库,请不要使用可下载的时区包。而是使用mysql_tzinfo_to_sql实用程序。否则,可能会导致 MySQL 和系统上其他应用程序在处理日期时间时出现差异。

要使用已下载的 SQL 语句时区包,请解压缩它,然后将解压后的文件内容加载到时区表中:

mysql -u root -p mysql < *file_name*

然后重新启动服务器。

警告

不要使用包含MyISAM表的可下载时区包。这是为较旧的 MySQL 版本设计的。MySQL 现在使用InnoDB来存储时区表。尝试用MyISAM表替换它们会导致问题。

保持与时区变更同步

当时区规则发生变化时,使用旧规则的应用程序会变得过时。为了保持最新,必须确保您的系统使用当前的时区信息。对于 MySQL,有多个因素需要考虑以保持最新:

操作系统时间会影响 MySQL 服务器用于时间的值,如果其时区设置为SYSTEM。确保您的操作系统使用最新的时区信息。对于大多数操作系统,最新的更新或服务包会为时间更改做准备。查看您操作系统供应商的网站,了解解决时间更改的更新。
如果您用一个使用与mysqld启动时不同的规则的版本替换系统的 /etc/localtime 时区文件,请重新启动mysqld以使用更新的规则。否则,mysqld可能不会注意到系统更改时间。
如果您在 MySQL 中使用命名时区,请确保 mysql 数据库中的时区表是最新的:

如果您的系统有自己的 zoneinfo 数据库,请在 zoneinfo 数据库更新时重新加载 MySQL 时区表。
对于没有自己的 zoneinfo 数据库的系统,请查看 MySQL 开发者区域以获取更新。当有新的更新可用时,下载并使用它来替换当前时区表的内容。
有关两种方法的说明,请参见填充时区表。mysqld 缓存它查找的时区信息,因此在更新时区表后,重新启动mysqld以确保它不会继续提供过时的时区数据。

如果您不确定命名时区是否可用,无论是作为服务器的时区设置还是由设置自己时区的客户端使用,请检查您的时区表是否为空。以下查询确定包含时区名称的表是否有任何行:

mysql> SELECT COUNT(*) FROM mysql.time_zone_name;
+———-+
| COUNT(*) |
+———-+
| 0 |
+———-+

0 的计数表示表为空。在这种情况下,当前没有应用程序使用命名时区,您不需要更新表(除非您想启用命名时区支持)。大于零的计数表示表不为空,其内容可用于命名时区支持。在这种情况下,请确保重新加载您的时区表,以便使用命名时区的应用程序可以获得正确的查询结果。

要检查您的 MySQL 安装是否正确更新以适应夏令时规则的更改,请使用以下示例测试。该示例使用适用于 2007 年美国于 3 月 11 日凌晨 2 点发生的 DST 1 小时更改的值。

测试使用此查询:

SELECT
CONVERT_TZ(\’2007-03-11 2:00:00\’,\’US/Eastern\’,\’US/Central\’) AS time1,
CONVERT_TZ(\’2007-03-11 3:00:00\’,\’US/Eastern\’,\’US/Central\’) AS time2;

两个时间值表示 DST 更改发生的时间,使用命名时区需要使用时区表。期望的结果是两个查询返回相同的结果(输入时间转换为 ‘US/Central’ 时区中的等效值)。

在更新时区表之前,您会看到类似于这样的错误结果:

+———————+———————+
| time1 | time2 |
+———————+———————+
| 2007-03-11 01:00:00 | 2007-03-11 02:00:00 |
+———————+———————+

更新表后,您应该看到正确的结果:

+———————+———————+
| time1 | time2 |
+———————+———————+
| 2007-03-11 01:00:00 | 2007-03-11 01:00:00 |
+———————+———————+

时区闰秒支持

跳秒值返回的时间部分以:59:59结尾。这意味着在跳秒期间,诸如NOW()之类的函数可能在跳秒期间的两三秒内返回相同的值。仍然正确的是,时间部分以:59:60或:59:61结尾的文字时间值被视为无效。

如果需要搜索跳秒前一秒的TIMESTAMP值,如果使用与\’*YYYY-MM-DD hh:mm:ss*\’值进行比较,可能会得到异常结果。以下示例演示了这一点。它将会话时区更改为 UTC,因此内部TIMESTAMP值(在 UTC 中)和显示值(应用了时区校正的值)之间没有区别。

mysql> CREATE TABLE t1 (
a INT,
ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (ts)
);
Query OK, 0 rows affected (0.01 sec)
mysql> — change to UTC
mysql> SET time_zone = \’+00:00\’;
Query OK, 0 rows affected (0.00 sec)
mysql> — Simulate NOW() = \’2008-12-31 23:59:59\’
mysql> SET timestamp = 1230767999;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 (a) VALUES (1);
Query OK, 1 row affected (0.00 sec)
mysql> — Simulate NOW() = \’2008-12-31 23:59:60\’
mysql> SET timestamp = 1230768000;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO t1 (a) VALUES (2);
Query OK, 1 row affected (0.00 sec)
mysql> — values differ internally but display the same
mysql> SELECT a, ts, UNIX_TIMESTAMP(ts) FROM t1;
+——+———————+——————–+
| a | ts | UNIX_TIMESTAMP(ts) |
+——+———————+——————–+
| 1 | 2008-12-31 23:59:59 | 1230767999 |
| 2 | 2008-12-31 23:59:59 | 1230768000 |
+——+———————+——————–+
2 rows in set (0.00 sec)
mysql> — only the non-leap value matches
mysql> SELECT * FROM t1 WHERE ts = \’2008-12-31 23:59:59\’;
+——+———————+
| a | ts |
+——+———————+
| 1 | 2008-12-31 23:59:59 |
+——+———————+
1 row in set (0.00 sec)
mysql> — the leap value with seconds=60 is invalid
mysql> SELECT * FROM t1 WHERE ts = \’2008-12-31 23:59:60\’;
Empty set, 2 warnings (0.00 sec)

为了解决这个问题,您可以使用基于实际存储在列中的 UTC 值的比较,其中应用了跳秒校正:

mysql> — selecting using UNIX_TIMESTAMP value return leap value
mysql> SELECT * FROM t1 WHERE UNIX_TIMESTAMP(ts) = 1230768000;
+——+———————+
| a | ts |
+——+———————+
| 2 | 2008-12-31 23:59:59 |
+——+———————+
1 row in set (0.00 sec)

7.1.16 资源组

原文:dev.mysql.com/doc/refman/8.0/en/resource-groups.html

MySQL 支持创建和管理资源组,并允许将在服务器内运行的线程分配给特定组,以便线程根据组可用的资源执行。组属性使其资源可控,以启用或限制组中线程的资源消耗。DBA 可以根据不同的工作负载适当修改这些属性。

目前,CPU 时间是一种可管理的资源,由“虚拟 CPU”概念表示,该术语包括 CPU 核心、超线程、硬件线程等。服务器在启动时确定有多少虚拟 CPU 可用,并且具有适当权限的数据库管理员可以将这些 CPU 与资源组关联,并将线程分配给组。

例如,为了管理不需要以高优先级执行的批处理作业的执行,DBA 可以创建一个Batch资源组,并根据服务器的繁忙程度调整其优先级。 (也许应该在白天以较低优先级运行分配给该组的批处理作业,在晚上以较高优先级运行。)DBA 还可以调整组可用的 CPU 集。可以启用或禁用组以控制是否可以将线程分配给它们。

以下部分描述了 MySQL 中资源组使用的方面:

资源组元素
资源组属性
资源组管理
资源组复制
资源组限制

重要

在某些平台或 MySQL 服务器配置中,资源组可能不可用或存在限制。特别是,Linux 系统可能需要一些安装方法的手动步骤。详情请参阅资源组限制。

资源组元素

这些功能为 MySQL 中资源组管理提供了 SQL 接口:

SQL 语句使得可以创建、更改和删除资源组,并允许将线程分配给资源组。优化器提示使得可以将单个语句分配给资源组。
资源组权限提供对哪些用户可以执行资源组操作的控制。
信息模式RESOURCE_GROUPS表公开了有关资源组定义的信息,性能模式threads表显示了每个线程的资源组分配。
状态变量为每个管理 SQL 语句提供执行计数。

资源组属性

资源组具有定义组的属性。所有属性都可以在组创建时设置。一些属性在创建时是固定的,其他属性可以在之后的任何时候修改。

这些属性在资源组创建时被定义,不能被修改:

每个组都有一个名称。资源组名称是像表和列名称一样的标识符,在 SQL 语句中不需要用引号括起,除非它们包含特殊字符或是保留字。组名称不区分大小写,最长可达 64 个字符。
每个组都有一个类型,可以是SYSTEM或USER。资源组类型影响可分配给组的优先级值范围,如后文所述。这个属性与允许的优先级差异一起,使系统线程能够被识别,以免与用户线程争夺 CPU 资源。
系统和用户线程对应于性能模式threads表中列出的后台和前台线程。

这些属性在资源组创建时被定义,之后可以随时修改:

CPU 亲和性是资源组可以使用的虚拟 CPU 集合。亲和性可以是可用 CPU 的任何非空子集。如果一个组没有亲和性,它可以使用所有可用的 CPU。
线程优先级是分配给资源组的线程的执行优先级。优先级值范围从-20(最高优先级)到 19(最低优先级)。默认优先级为 0,对于系统组和用户组都是如此。
系统组允许比用户组更高的优先级,确保用户线程永远不会比系统线程具有更高的优先级:

对于系统资源组,允许的优先级范围是-20 到 0。
对于用户资源组,允许的优先级范围是 0 到 19。
每个组可以启用或禁用,管理员可以控制线程分配。只有启用的组才能分配线程。

资源组管理

默认情况下,有一个系统组和一个用户组,分别命名为SYS_default和USR_default。这些默认组不能被删除,它们的属性也不能被修改。每个默认组没有 CPU 亲和性和优先级 0。

新创建的系统和用户线程分别分配给SYS_default和USR_default组。

对于用户定义的资源组,所有属性在组创建时被分配。创建组后,除了名称和类型属性外,其属性可以被修改。

要创建和管理用户定义的资源组,请使用以下 SQL 语句:

CREATE RESOURCE GROUP 创建一个新的组。参见 第 15.7.2.2 节,“创建资源组语句”。
ALTER RESOURCE GROUP 修改现有组。参见 第 15.7.2.1 节,“修改资源组语句”。
DROP RESOURCE GROUP 删除现有组。参见 第 15.7.2.3 节,“删除资源组语句”。

这些语句需要 RESOURCE_GROUP_ADMIN 权限。

要管理资源组分配,请使用以下功能:

SET RESOURCE GROUP 将线程分配给一个组。参见 第 15.7.2.4 节,“设置资源组语句”。
RESOURCE_GROUP 优化器提示将单个语句分配给一个组。参见 第 10.9.3 节,“优化器提示”。

这些操作需要 RESOURCE_GROUP_ADMIN 或 RESOURCE_GROUP_USER 权限。

资源组定义存储在 resource_groups 数据字典表中,以便在服务器重新启动时保持组的持久性。由于 resource_groups 是数据字典的一部分,用户无法直接访问它。资源组信息可通过信息模式 RESOURCE_GROUPS 表获取,该表实际上是数据字典表上的视图。参见 第 28.3.26 节,“INFORMATION_SCHEMA RESOURCE_GROUPS 表”。

最初,RESOURCE_GROUPS 表中有这些行描述默认组:

mysql> SELECT * FROM INFORMATION_SCHEMA.RESOURCE_GROUPS\\G
*************************** 1\\. row ***************************
RESOURCE_GROUP_NAME: USR_default
RESOURCE_GROUP_TYPE: USER
RESOURCE_GROUP_ENABLED: 1
VCPU_IDS: 0-3
THREAD_PRIORITY: 0
*************************** 2\\. row ***************************
RESOURCE_GROUP_NAME: SYS_default
RESOURCE_GROUP_TYPE: SYSTEM
RESOURCE_GROUP_ENABLED: 1
VCPU_IDS: 0-3
THREAD_PRIORITY: 0

THREAD_PRIORITY 值为 0,表示默认优先级。VCPU_IDS 值显示一个包含所有可用 CPU 的范围。对于默认组,显示的值取决于 MySQL 服务器运行的系统。

早些讨论提到了一个名为Batch的资源组来管理不需要以高优先级执行的批处理作业的情景。要创建这样一个组,使用类似于以下语句:

CREATE RESOURCE GROUP Batch
TYPE = USER
VCPU = 2-3 — assumes a system with at least 4 CPUs
THREAD_PRIORITY = 10;

要验证资源组是否按预期创建,请检查RESOURCE_GROUPS表:

mysql> SELECT * FROM INFORMATION_SCHEMA.RESOURCE_GROUPS
WHERE RESOURCE_GROUP_NAME = \’Batch\’\\G
*************************** 1\\. row ***************************
RESOURCE_GROUP_NAME: Batch
RESOURCE_GROUP_TYPE: USER
RESOURCE_GROUP_ENABLED: 1
VCPU_IDS: 2-3
THREAD_PRIORITY: 10

如果THREAD_PRIORITY值为 0 而不是 10,请检查您的平台或系统配置是否限制了资源组功能;请参阅资源组限制。

要将线程分配给Batch组,请执行以下操作:

SET RESOURCE GROUP Batch FOR *thread_id*;

之后,命名线程中的语句将使用Batch组资源执行。

如果会话的当前线程应该在Batch组中,那么在会话中执行此语句:

SET RESOURCE GROUP Batch;

之后,会话中的语句将使用Batch组资源执行。

要使用Batch组执行单个语句,请使用RESOURCE_GROUP优化器提示:

INSERT /*+ RESOURCE_GROUP(Batch) */ INTO t2 VALUES(2);

分配给Batch组的线程将使用其资源执行,可以根据需要进行修改:

在系统负载高的时候,减少分配给组的 CPU 数量,降低其优先级,或者(如所示)两者都做:
ALTER RESOURCE GROUP Batch
VCPU = 3
THREAD_PRIORITY = 19;
在系统负载轻的时候,增加分配给组的 CPU 数量,提高其优先级,或者(如所示)两者都做:
ALTER RESOURCE GROUP Batch
VCPU = 0-3
THREAD_PRIORITY = 0;

资源组复制

资源组管理是在发生的服务器上本地的。资源组 SQL 语句和对resource_groups数据字典表的修改不会被写入二进制日志,也不会被复制。

资源组限制

在某些平台或 MySQL 服务器配置中,资源组不可用或存在限制:

如果安装了线程池插件,则资源组不可用。
在 macOS 上,资源组不可用,因为它没有提供将 CPU 绑定到线程的 API。
在 FreeBSD 和 Solaris 上,资源组线程优先级会被忽略。(实际上,所有线程都以优先级 0 运行。)尝试更改优先级会导致警告:
mysql> ALTER RESOURCE GROUP abc THREAD_PRIORITY = 10;
Query OK, 0 rows affected, 1 warning (0.18 sec)
mysql> SHOW WARNINGS;
+———+——+————————————————————-+
| Level | Code | Message |
+———+——+————————————————————-+
| Warning | 4560 | Attribute thread_priority is ignored (using default value). |
+———+——+————————————————————-+
在 Linux 上,除非设置了CAP_SYS_NICE能力,否则将忽略资源组线程优先级。授予进程CAP_SYS_NICE能力将启用一系列特权;请参考man7.org/linux/man-pages/man7/capabilities.7.html获取完整列表。在启用此能力时请小心。
在使用 systemd 和内核支持环境能力(Linux 4.3 或更新版本)的 Linux 平台上,启用CAP_SYS_NICE能力的推荐方法是修改 MySQL 服务文件,保持mysqld二进制文件不变。要调整 MySQL 的服务文件,请使用以下步骤:

根据您的平台运行适当的命令:

Oracle Linux、Red Hat 和 Fedora 系统:
$> sudo systemctl edit mysqld
SUSE、Ubuntu 和 Debian 系统:
$> sudo systemctl edit mysql
使用编辑器,将以下文本添加到服务文件中:
[Service]
AmbientCapabilities=CAP_SYS_NICE
重新启动 MySQL 服务。
如果无法像刚才描述的那样启用CAP_SYS_NICE功能,则可以使用setcap命令手动设置,指定路径名到mysqld可执行文件(这需要sudo访问权限)。您可以使用getcap检查权限。例如:
$> sudo setcap cap_sys_nice+ep */path/to/mysqld*
$> getcap */path/to/mysqld*
*/path/to/mysqld* = cap_sys_nice+ep
作为安全措施,将mysqld二进制文件的执行权限限制为root用户和具有mysql组成员资格的用户:
$> sudo chown root:mysql */path/to/mysqld*
$> sudo chmod 0750 */path/to/mysqld*
重要提示
如果需要手动使用setcap,则必须在每次重新安装后执行。
在 Windows 上,线程以五个线程优先级级别之一运行。资源组线程优先级范围从-20 到 19 映射到以下表中指示的级别。
表 7.6 Windows 上的资源组线程优先级

优先级范围Windows 优先级级别-20 到 -10THREAD_PRIORITY_HIGHEST-9 到 -1THREAD_PRIORITY_ABOVE_NORMAL0THREAD_PRIORITY_NORMAL1 到 10THREAD_PRIORITY_BELOW_NORMAL11 到 19THREAD_PRIORITY_LOWEST

#以上关于MySQL8 中文参考(十九)的相关内容来源网络仅供参考,相关信息请以官方公告为准!

原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/92362.html

Like (0)
CSDN的头像CSDN
Previous 2024年6月26日
Next 2024年6月26日

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注