附录C限制和限制

目录

C.1存储程序的限制
C.2条件处理的限制
C.3服务器端游标的限制
C.4子查询的限制
C.5对视图的限制
C.6 XA事务的限制
C.7字符集的限制
C.8性能模式的限制
C.9可插拔认证的限制
C.10 MySQL中的限制
C.10.1连接限制
C.10.2数据库和表的数量限制
C.10.3桌面尺寸限制
C.10.4表列数和行大小的限制
C.10.5 Windows平台限制

此处的讨论描述了适用于使用MySQL功能(如子查询或视图)的限制。

C.1存储程序的限制

这些限制适用于 第24章 存储对象中 描述的功能

这里提到的一些限制适用于所有存储的例程; 也就是说,存储过程和存储的函数。 还存在一些 特定于存储函数的限制, 但不存在对存储过程的限制。

存储函数的限制也适用于触发器。 还有一些 特定于触发器的限制

存储过程的限制也适用于 DO Event Scheduler事件定义 子句。 还有一些 特定于事件的限制

存储例程中不允许的SQL语句

存储的例程不能包含任意SQL语句。 不允许以下声明:

  • 锁定语句 LOCK TABLES UNLOCK TABLES

  • ALTER VIEW

  • LOAD DATA LOAD TABLE

  • SQL语句制备( PREPARE EXECUTE DEALLOCATE PREPARE )可以在存储过程中使用,但没有存储功能或触发器。 因此,存储的函数和触发器不能使用动态SQL(将语句构造为字符串然后执行它们)。

  • 通常,SQL预处理语句中不允许的语句也不允许存储在程序中。 有关作为预准备语句支持的语句列表,请参见 第13.5节“准备的SQL语句语法” 例外是 SIGNAL RESIGNAL GET DIAGNOSTICS ,作为准备好的陈述是不允许的,但在存储的程序中是允许的。

  • 由于局部变量仅在存储程序执行期间在范围内,因此在存储程序中创建的预准备语句中不允许引用它们。 准备好的语句范围是当前会话,而不是存储的程序,因此语句可以在程序结束后执行,此时变量将不再在范围内。 例如, 不能用作预备语句。 此限制也适用于存储过程和函数参数。 请参见 第13.5.1节“PREPARE语法” SELECT ... INTO local_var

  • 在所有存储的程序(存储过程和函数,触发器和事件)中,解析器将其 BEGIN [WORK] 视为 BEGIN ... END 的开头 要在此上下文中开始事务,请 START TRANSACTION 改用。

存储函数的限制

存储的函数中不允许使用以下附加语句或操作。 它们在存储过程中是允许的,除了从存储函数或触发器中调用的存储过程之外。 例如,如果 FLUSH 在存储过程中使用,则无法从存储的函数或触发器调用该存储过程。

  • 执行显式或隐式提交或回滚的语句。 SQL标准不要求支持这些语句,该标准规定每个DBMS供应商可以决定是否允许它们。

  • 返回结果集的语句。 这包括 SELECT 不具有的声明 条款等语句,如 函数可以 使用游标和 语句 来处理结果集 请参见 第13.2.10.1节“SELECT ... INTO语法” 第13.6.6节“游标” INTO var_list SHOW EXPLAIN CHECK TABLE SELECT ... INTO var_list FETCH

  • FLUSH 声明。

  • 存储的函数不能递归使用。

  • 存储的函数或触发器不能通过调用函数或触发器的语句修改已经使用(用于读取或写入)的表。

  • 如果在不同别名下的存储函数中多次引用临时表, 则会发生错误,即使引用出现在函数内的不同语句中也是如此。 Can't reopen table: 'tbl_name'

  • HANDLER ... READ 调用存储函数的语句可能导致复制错误,并且是不允许的。

触发器的限制

对于触发器,以下附加限制适用:

  • 外键操作不会激活触发器。

  • 使用基于行的复制时,从站上的触发器不会由源自主服务器的语句激活。 使用基于语句的复制时,将激活从站上的触发器。 有关更多信息,请参见 第17.4.1.35节“复制和触发器”

  • RETURN 触发器中不允许使用 语句, 语句不能返回值。 要立即退出触发器,请使用该 LEAVE 语句。

  • mysql 数据库中的 表不允许触发器 也不允许他们 INFORMATION_SCHEMA performance_schema 桌子。 这些表实际上是视图上不允许的视图和触发器。

  • 触发器高速缓存不会检测基础对象的元数据何时发生更改。 如果触发器使用表并且自从触发器加载到缓存后表已更改,则触发器将使用过时的元数据进行操作。

存储例程中的名称冲突

相同的标识符可用于例程参数,局部变量和表列。 此外,可以在嵌套块中使用相同的局部变量名称。 例如:

CREATE PROCEDURE p(i INT)
开始
  DECLARE i INT DEFAULT 0;
  SELECT i FROM t;
  开始
    DECLARE i INT DEFAULT 1;
    SELECT i FROM t;
  结束;
结束;

在这种情况下,标识符不明确,并且适​​用以下优先规则:

  • 局部变量优先于例程参数或表列。

  • 例程参数优先于表列。

  • 内部块中的局部变量优先于外部块中的局部变量。

变量优先于表列的行为是非标准的。

复制注意事项

使用存储的例程可能会导致复制问题。 第24.7节“存储程序二进制日志记录” 中将进一步讨论此问题

选项适用于表,视图和触发器。 它不适用于存储过程和函数或事件。 要过滤对后一个对象进行操作的语句,请使用一个或多个 选项。 --replicate-wild-do-table=db_name.tbl_name --replicate-*-db

调试注意事项

没有存储的例程调试工具。

SQL:2003标准中不支持的语法

MySQL存储的例程语法基于SQL:2003标准。 目前不支持该标准中的以下项目:

  • UNDO 处理器

  • FOR 循环

并发注意事项

为了防止会话之间的交互问题,当客户端发出语句时,服务器使用可用于执行语句的例程和触发器的快照。 也就是说,服务器计算可在语句执行期间使用的过程,函数和触发器的列表,加载它们,然后继续执行语句。 在执行语句时,它不会看到其他会话执行的例程的更改。

为了获得最大的并发性,存储的函数应该最小化它们的副作用; 特别是,更新存储函数中的表可以减少该表上的并发操作。 存储函数在执行之前获取表锁,以避免由于语句执行顺序与日志中出现的顺序不匹配而导致二进制日志不一致。 当使用基于语句的二进制日志记录时,将记录调用函数的语句,而不是在函数内执行的语句。 因此,更新相同基础表的存储函数不会并行执行。 相反,存储过程不会获取表级锁。 存储过程中执行的所有语句都写入二进制日志, 甚至是基于语句的二进制日志记录。 看到 第24.7节“存储程序二进制日志”

事件调度程序限制

以下限制特定于事件调度程序:

  • 事件名称以不区分大小写的方式处理。 例如,您不能在同一个数据库中使用名称 anEvent 两个事件 AnEvent

  • 如果通过变量指定事件名称,则可能无法在存储的程序中创建,更改或删除事件。 事件也可能无法创建,更改或删除存储的例程或触发器。

  • 声明 LOCK TABLES 生效时, 禁止对事件进行DDL声明

  • 使用间隔事件时序 YEAR QUARTER MONTH ,并 YEAR_MONTH 在几个月解决; 使用任何其他间隔的那些在几秒钟内解决。 没有办法使计划在同一秒发生的事件以给定顺序执行。 此外 - 由于舍入,线程应用程序的性质以及创建事件和发出执行事件所需的非零时间长度这一事实可能会延迟1或2秒。 但是, INFORMATION_SCHEMA.EVENTS 表格 LAST_EXECUTED 列或 mysql.event 表格中显示的时间 last_executed 列始终精确到实际事件执行时间的一秒之内。 (另见Bug#16522。)

  • 事件正文中包含的语句的每次执行都在新连接中进行; 因此,这些语句在给定的用户会话中对服务器的语句计数没有影响,例如 Com_select Com_insert 显示的 SHOW STATUS 然而,这样的罪名 在全球范围内更新。 (Bug#16422)

  • 事件不支持晚于Unix Epoch结束的时间; 这大约是2038年的开始。事件安排者特别不允许这样的日期。 (Bug#16396)

  • 不支持 ON SCHEDULE CREATE EVENT ALTER EVENT 语句 子句中的 存储函数,用户定义函数和表的引用 不允许使用这些类型的引用。 (有关更多信息,请参阅Bug#22830。)

NDB群集中存储的例程和触发器。  使用 NDB 存储引擎的 表都支持存储过程,存储函数和触发器 ; 但是,请务必记住,它们 不会 在充当群集SQL节点的MySQL服务器之间自动传播。 这是因为存储的例程和触发器定义 mysql 使用 InnoDB 存储在 系统数据库的 表中,而这些表不在Cluster节点之间复制。

与MySQL集群表交互的任何存储程序或触发器必须通过运行适当的重新创建 CREATE PROCEDURE CREATE FUNCTION 或者 CREATE TRIGGER 说,你希望使用存储程序或触发器集群中参与的每个MySQL服务器上的发言。 同样,必须在所有Cluster SQL节点上显式执行对现有存储例程或触发器的任何更改,并使用 访问集群的每个MySQL Server上 的相应 ALTER DROP 语句。

警告

难道 不是 试图解决只是通过转换所描述的任何问题, mysql 数据库表使用的 NDB 存储引擎。 不支持 更改 mysql 数据库中 的系统表, 并且很可能产生不良结果。

C.2条件处理的限制

SIGNAL RESIGNAL 并且 GET DIAGNOSTICS 不允许作为准备好的陈述。 例如,此语句无效:

准备stmt1 FROM'SIGNAL SQLSTATE“02000”';

SQLSTATE 课堂 '04' 上的 价值 不予特别处理。 它们的处理方式与其他例外相同。

在标准SQL中,第一个条件与 SQLSTATE 前一个SQL语句返回 值有关。 在MySQL中,这不能保证,所以要获得主要错误,你不能这样做:

获得诊断条件1 @errno = MYSQL_ERRNO;

相反,这样做:

获取诊断@cno = NUM​​BER;
获得诊断条件@cno @errno = MYSQL_ERRNO;

C.3服务器端游标的限制

服务器端游标使用该 mysql_stmt_attr_set() 函数 在C API中实现 存储例程中的游标使用相同的实现。 服务器端游标可以在服务器端生成结果集,但不会传输到客户端,除了客户端请求的那些行。 例如,如果客户端执行查询但仅对第一行感兴趣,则不传输剩余的行。

在MySQL中,服务器端游标具体化为内部临时表。 最初,这是一个 MEMORY 表,但被转换为 MyISAM 当其大小超过了的最小值表 max_heap_table_size tmp_table_size 系统变量。 同样的限制适用于为保存游标结果集而创建的内部临时表,以及内部临时表的其他用途。 请参见 第8.4.4节“MySQL中的内部临时表使用” 实现的一个限制是,对于大的结果集,通过游标检索其行可能很慢。

游标是只读的; 你不能使用游标来更新行。

UPDATE WHERE CURRENT OF 并且 DELETE WHERE CURRENT OF 未实现,因为不支持可更新游标。

游标是不可保留的(在提交后不保持打开状态)。

游标是敏感的。

游标是不可滚动的。

游标没有命名。 语句处理程序充当游标ID。

每个预准备语句只能打开一个游标。 如果需要多个游标,则必须准备多个语句。

如果在准备模式下不支持该语句,则不能将游标用于生成结果集的语句。 这包括语句,如 CHECK TABLE HANDLER READ SHOW BINLOG EVENTS

C.4子查询的限制

  • 通常,您无法修改表并从子查询中的同一表中进行选择。 例如,此限制适用于以下形式的陈述:

    DELETE FROM t WHERE ...(SELECT ... FROM t ...);
    UPDATE t ... WHERE col =(SELECT ... FROM t ...);
    {INSERT | REPLACE} INTO t(SELECT ... FROM t ...);
    

    例外:如果对于修改后的表使用派生表并且派生表已实现而不是合并到外部查询中,则前面的禁止不适用。 (请参见 第8.2.2.4节“使用合并或实现优化派生表,视图引用和公用表表达式” 。)示例:

    UPDATE t ... WHERE col =(SELECT * FROM(SELECT ... FROM t ...)AS dt ...);
    

    这里派生表的结果被实现为临时表,因此 t 在更新 t 发生 时已经选择 了相关的行

    通常,您可以通过添加 NO_MERGE 优化程序提示 来影响优化程序以实现派生表 请参见 第8.9.3节“优化程序提示”

  • 仅部分支持行比较操作:

    • 对于 可以是 -tuple(使用行构造函数语法指定),子查询可以返回 -tuples的 因此,允许的语法更具体地表示为 expr [NOT] IN subquery expr n n row_constructor [NOT] IN table_subquery

    • 对于 必须是标量值,子查询必须是列子查询; 它不能返回多列行。 expr op {ALL|ANY|SOME} subquery expr

    换句话说,对于返回 n -tuples 行的子查询 ,这是受支持的:

    expr_1,...,expr_n)[NOT] INtable_subquery
    

    但是这不受支持:

    expr_1,...,expr_nop{ALL | ANY | SOME}subquery
    

    支持行比较 IN 但不支持其他 比较的原因 IN 是通过将其重写为一系列 = 比较和 AND 操作来实现。 这种方法不能用于 ALL ANY SOME

  • 中子查询 FROM 子句不能是相关子查询。 它们在查询执行期间实现了整体(计算生成结果集),因此无法对外部查询的每一行进行求值。 优化器延迟实现直到需要结果,这可以允许实现物化。 请参见 第8.2.2.4节“使用合并或实现优化派生表,视图引用和公用表表达式”

  • MySQL不支持 LIMIT 某些子查询运算符的子查询:

    MySQL的> SELECT * FROM t1
           WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1);
    ERROR 1235(42000):此版本的MySQL尚不支持
     'LIMIT&IN / ALL / ANY / SOME子查询'
    
  • MySQL允许子查询引用存储的函数,该函数具有数据修改副作用,例如将行插入表中。 例如,如果 f() 插入行,则以下查询可以修改数据:

    SELECT ... WHERE x IN(SELECT f()...);
    

    此行为是SQL标准的扩展。 在MySQL中,它可以产生不确定的结果,因为 f() 对于给定查询的不同执行,可能会执行不同的次数,具体取决于优化程序选择如何处理它。

    对于基于语句或混合格式的复制,这种不确定性的一个含义是这样的查询可以在主服务器及其从服务器上产生不同的结果。

C.5对视图的限制

视图处理未优化:

  • 无法在视图上创建索引。

  • 索引可用于使用合并算法处理的视图。 但是,使用temptable算法处理的视图无法利用其基础表上的索引(尽管可以在生成临时表期间使用索引)。

一般原则是您无法修改表并从子查询中的同一表中进行选择。 请参见 第C.4节“子查询的限制”

如果从从表中选择的视图中进行选择,如果视图从子查询中的表中进行选择并且使用合并算法评估视图,则同样的原则也适用。 例:

创建视图v1 AS
SELECT * FROM t2 WHERE EXISTS(SELECT 1 FROM t1 WHERE t1.a = t2.a);

UPDATE t1,v2 SET t1.a = 1 WHERE t1.b = v2.b;

如果使用临时表评估视图,则 可以 从视图子查询中的表中进行选择,并仍在外部查询中修改该表。 在这种情况下,视图将存储在临时表中,因此您实际上并不是从子查询中的表中进行选择并 同时修改它 (这是您可能希望通过 ALGORITHM = TEMPTABLE 在视图定义中 指定来强制MySQL使用temptable算法的另一个原因 。)

您可以使用 DROP TABLE ALTER TABLE 删除或更改视图定义中使用的表。 即使这会使视图无效,也 不会从 DROP ALTER 操作产生 警告 相反,使用视图时会发生错误。 CHECK TABLE 可用于检查已经失效的观点 DROP ALTER 操作。

关于视图可更新性,视图的总体目标是,如果任何视图在理论上是可更新的,那么它在实践中应该是可更新的。 MySQL尽可能快。 现在可以更新许多理论上可更新的视图,但仍然存在限制。 有关详细信息,请参见 第24.5.3节“可更新和可插入视图”

目前的意见实施存在缺陷。 如果为用户授予了创建视图所需的基本权限( CREATE VIEW SELECT 权限),则该用户将无法调用 SHOW CREATE VIEW 该对象,除非该用户也被授予该 SHOW VIEW 权限。

这个缺点可能会导致使用 mysqldump 备份数据库时出现问题 ,因为权限不足可能会失败。 Bug#22062中描述了此问题。

该问题的解决方法是管理员手动将 SHOW VIEW 权限 授予已授予的 用户 CREATE VIEW ,因为MySQL在创建视图时不会隐式授予它。

视图没有索引,因此索引提示不适用。 不允许在从视图中选择时使用索引提示。

SHOW CREATE VIEW 使用 每列 子句 显示视图定义 如果从表达式创建列,则默认别名是表达式文本,该文本可能很长。 将检查语句中 列名的别名, 最大列长度为64个字符(不是最大别名长度为256个字符)。 因此, 如果任何列别名超过64个字符 ,则从输出中创建的视图将 失败。 对于具有太长别名的视图,这可能会在以下情况下导致问题: AS alias_name CREATE VIEW SHOW CREATE VIEW

  • 视图定义无法复制到强制执行列长度限制的较新从属。

  • 使用 mysqldump 创建的转储文件 无法加载到强制执行列长度限制的服务器中。

任一问题的解决方法是修改每个有问题的视图定义以使用提供较短列名称的别名。 然后视图将正确复制,并且可以转储和重新加载而不会导致错误。 要修改定义,请使用 DROP VIEW 删除并再次创建视图 CREATE VIEW ,或者使用替换定义 CREATE OR REPLACE VIEW

对于在转储文件中重新加载视图定义时出现的问题,另一种解决方法是编辑转储文件以修改其 CREATE VIEW 语句。 但是,这不会更改原始视图定义,这可能会导致后续转储操作出现问题。

C.6 XA事务的限制

XA事务支持仅限于 InnoDB 存储引擎。

对于 外部XA ,MySQL服务器充当资源管理器,客户端程序充当事务管理器。 对于 内部XA ,MySQL服务器中的存储引擎充当RM,而服务器本身充当TM。 内部XA支持受到各个存储引擎功能的限制。 处理涉及多个存储引擎的XA事务需要内部XA。 内部XA的实现要求存储引擎支持表处理程序级别的两阶段提交,目前这仅适用于 InnoDB

因为 XA START 不支持 JOIN RESUME 子句。

因为 XA END SUSPEND [FOR MIGRATE] 不支持 条款。

全局事务中每个XA事务 bqual xid 部分 不同 的要求 是当前MySQL XA实现的限制。 它不是XA规范的一部分。

XA事务分两部分写入二进制日志。 XA PREPARE 发出后,交易起来的第一部分,以 XA PREPARE 使用初始GTID被写入。 A XA_prepare_log_event 用于在二进制日志中标识此类事务。 发布 XA COMMIT XA ROLLBACK 发布时,仅包含 XA COMMIT XA ROLLBACK 声明 的事务的第二部分 是使用第二个GTID编写的。 请注意,由其标识的事务的初始部分 XA_prepare_log_event 不一定是其 XA COMMIT XA ROLLBACK ,它可能导致任何两个XA事务的交叉二进制日志记录。 XA事务的两个部分甚至可以出现在不同的二进制日志文件中。 这意味着一个XA事务 PREPARED state现在是持久的,直到发出显式 XA COMMIT XA ROLLBACK 语句,确保XA事务与复制兼容。

在复制从属服务器上,在准备好XA事务之后,它立即与从属应用程序线程分离,并且可以由从属服务器上的任何线程提交或回滚。 这意味着相同的XA事务可以出现在 events_transactions_current 表中,在不同的线程上具有不同的状态。 events_transactions_current 表显示线程上最近监视的事务事件的当前状态,并且在线程空闲时不更新此状态。 因此 PREPARED ,在由另一个线程处理之后, XA事务仍然可以在 原始应用程序线程 状态 下显示 要正确识别仍处于 PREPARED 状态且需要恢复的 XA事务 ,请使用 XA RECOVER 语句而不是Performance Schema事务表。

使用XA事务存在以下限制:

  • XA事务对于二进制日志的意外停止不具有完全的弹性。 如果有意外的停顿,而服务器是在执行的中间 XA PREPARE XA COMMIT XA ROLLBACK ,或 XA COMMIT ... ONE PHASE 语句时,服务器可能无法恢复到正确的状态,使服务器和二进制日志中的不一致的状态。 在这种情况下,二进制日志可能包含未应用的额外XA事务,或者错过应用的XA事务。 此外,如果启用了GTID,则恢复后 @@GLOBAL.GTID_EXECUTED 可能无法正确描述已应用的事务。 请注意,如果在 XA PREPARE 之间,之间 发生意外停止 XA PREPARE XA COMMIT (或 XA ROLLBACK ),或 XA COMMIT (或 XA ROLLBACK )之后,服务器和二进制日志被正确恢复并进入一致状态。

  • 不支持将复制筛选器或二进制日志筛选器与XA事务结合使用。 过滤表可能导致复制从属设备上的XA事务为空,并且不支持空XA事务。 此外,通过设置 master_info_repository=TABLE relay_log_info_repository=TABLE 复制从属设备(它成为MySQL 8.0中的默认设置),数据引擎事务的内部状态在过滤的XA事务之后发生更改,并且可能与复制事务上下文状态不一致。

    ER_XA_REPLICATION_FILTERS 每当XA事务受复制过滤器影响时,都会记录 该错误 ,无论事务是否为空。 如果事务不为空,则复制从属设备可以继续运行,但您应该采取措施停止使用带有XA事务的复制过滤器以避免潜在问题。 如果事务为空,则复制从站停止。 在那种情况下,复制从站可能处于未确定状态,其中复制过程的一致性可能会受到影响。 特别是 gtid_executed 设置在从站的从站可能与主站上的设备不一致。 要解决此问题,请隔离主服务器并停止所有复制,然后检查复制拓扑中的GTID一致性。 撤消生成错误消息的XA事务,然后重新启动复制。

  • 对于基于语句的复制,XA事务被认为是不安全的。 如果正在主服务器上以并行顺序准备两个并行提交的XA事务,则可能会发生无法安全解析的锁定依赖关系,并且复制可能会因从服务器上的死锁而失败。 单线程或多线程复制从站可能会出现这种情况。 binlog_format=STATEMENT 设置,则会发出警告XA事务的内部DML语句。 binlog_format=MIXED binlog_format=ROW 设置,XA事务内的DML语句使用基于行的复制记录,以及潜在的问题是不存在的。

注意

在MySQL 5.7.7之前,XA事务根本不兼容复制。 这是因为处于 PREPARED 状态 的XA事务 将在干净的服务器关闭或客户端断开时回滚。 类似地,处于 PREPARED 状态 的XA事务 仍然存在 PREPARED 状态,以防服务器异常关闭然后再次启动,但事务的内容无法写入二进制日志。 在这两种情况下,都无法正确复制XA事务。

C.7字符集的限制

  • 标识符使用存储在 mysql 数据库表( user db 等)中 utf8 ,但标识符只能包含基本多语言平面(BMP)中的字符。 标识符中不允许使用补充字符。

  • ucs2 utf16 utf16le ,和 utf32 字符集有以下限制:

    • 它们都不能用作客户端字符集。 请参见 不允许的客户端字符集

    • 目前无法使用 LOAD DATA 加载使用这些字符集的数据文件。

    • FULLTEXT 无法在使用任何这些字符集的列上创建索引。 但是,您可以 IN BOOLEAN MODE 在没有索引的情况下对列 执行 搜索。

  • REGEXP RLIKE 在逐个字节的方式运营工作,所以他们没有多字节安全,可能产生与多字节字符集意想不到的效果。 此外,这些运算符通过字节值比较字符,并且即使给定的排序规则将重音字符视为相等,重音字符也可能无法比较。

C.8性能模式的限制

性能模式避免使用互斥锁来收集或生成数据,因此无法保证一致性,结果有时可能不正确。 performance_schema 表中的 事件值 是不确定的且不可重复的。

如果将事件信息保存在另一个表中,则不应假设原始事件以后仍可用。 例如,如果您从 performance_schema 表中 选择事件 到临时表,并打算稍后将该表与原始表连接,则可能没有匹配项。

mysqldump BACKUP DATABASE 忽略 performance_schema 数据库中的

在表 performance_schema 的数据库不能被锁定 LOCK TABLES ,除了 表。 setup_xxx

performance_schema 无法索引数据库中的

performance_schema 不复制数据库中的

计时器的类型可能因平台而异。 performance_timers 表显示了可用的事件计时器。 如果此表中给定计时器名称的值为, NULL 则您的平台不支持该计时器。

适用于存储引擎的仪器可能未针对所有存储引擎实施。 每个第三方引擎的仪表是引擎维护者的责任。

C.9可插拔认证的限制

本节的第一部分描述了 第6.2.17节“可插入身份验证”中 描述的可插入身份验证框架的适用性的一般限制 第二部分描述了第三方连接器开发人员如何确定连接器可以利用可插入身份验证功能的程度以及采取哪些步骤以使其更加合规。

这里使用 的术语 本机认证 是指对存储在 mysql.user 系统表 中的密码的认证 在实现可插入身份验证之前,这与旧MySQL服务器提供的身份验证方法相同。 Windows本机身份验证 是指使用已登录到Windows的用户的凭据进行身份验证,由Windows Native Authentication插件(简称 Windows插件 )实现。

一般可插入的身份验证限制

  • Connector / C,Connector / C ++: 使用这些连接器的客户端只能通过使用本机身份验证的帐户连接到服务器。

    例外:连接器支持可插入身份验证,如果它是为了 libmysqlclient 动态(而不是静态) 链接 构建的, 并且 libmysqlclient 如果安装了该版本 ,则加载当前版本 ,或者连接器是从源重新编译为链接当前版本 libmysqlclient

    有关编写连接器以从服务器处理有关默认服务器端身份验证插件的信息的信息,请参阅 身份验证插件连接器 - 编写注意事项

  • Connector / NET: 使用Connector / NET的客户端可以通过使用本机身份验证或Windows本机身份验证的帐户连接到服务器。

  • Connector / PHP: 使用此连接器的客户端只能通过使用本机身份验证的帐户连接到服务器,当使用PHP本机驱动程序进行编译时( mysqlnd )。

  • Windows本机身份验证: 通过使用Windows插件的帐户进行连接需要Windows域设置。 没有它,使用NTLM身份验证,然后只能进行本地连接; 也就是说,客户端和服务器必须在同一台计算机上运行。

  • 代理用户: 代理用户支持是可用的,客户端可以通过使用实现代理用户功能的插件进行身份验证的帐户进行连接(即,可以返回与连接用户的用户名不同的用户名的插件)。 例如,PAM和Windows插件支持代理用户。 mysql_native_password sha256_password 认证插件默认情况下不支持代理的用户,但可以被配置成这样; 请参阅 代理用户映射的服务器支持

  • 复制 :复制从属服务器不仅可以使用使用本机身份验证的主帐户,还可以通过使用非本地身份验证的主帐户进行连接(如果所需的客户端插件可用)。 如果插件是内置的 libmysqlclient ,则默认情况下可用。 否则,插件必须安装在从属 plugin_dir 系统变量 指定的目录中的从属端

  • FEDERATED 表: 一个 FEDERATED 表只能通过使用本地身份验证的远程服务器上的账户访问远程表。

可插拔身份验证和第三方连接器

第三方连接器开发人员可以使用以下准则来确定连接器是否已准备好利用可插入身份验证功能以及要采取哪些步骤以使其更加合规:

  • 未进行任何更改的现有连接器使用本机身份验证,使用连接器的客户端只能通过使用本机身份验证的帐户连接到服务器。 但是,您应该针对最新版本的服务器测试连接器,以验证此类连接是否仍然可以正常工作。

    例外:如果连接器可以 libmysqlclient 动态(而非静态) 链接, 并且加载当前版本( libmysqlclient 如果已安装该版本 ),则 连接器可以使用可插入身份验证而不进行任何更改

  • 要利用可插入的身份验证功能, libmysqlclient 应该根据当前版本重新链接基于 连接器的连接器 libmysqlclient 这使连接器能够通过现在需要内置客户端插件的帐​​户支持连接 libmysqlclient (例如PAM身份验证所需的明文插件和Windows本机身份验证所需的Windows插件)。 与当前链接 libmysqlclient 还使连接器能够访问安装在默认MySQL插件目录中的客户端插件(通常是由本地服务器的 plugin_dir 系统变量 的默认值命名的目录 )。

    如果连接器 libmysqlclient 动态 链接 ,则必须确保 libmysqlclient 在客户端主机上安装 较新版本, 并且连接器在运行时加载它。

  • 连接器支持给定身份验证方法的另一种方法是直接在客户端/服务器协议中实现它。 Connector / NET使用此方法为Windows本机身份验证提供支持。

  • 如果连接器应该能够从与默认插件目录不同的目录加载客户端插件,则必须为客户端用户实现一些指定目录的方法。 这种可能性包括命令行选项或环境变量,连接器可以从中获取目录名称。 标准MySQL客户端程序(如 mysql mysqladmin) 实现了一个 --plugin-dir 选项。 另请参见 第28.7.17节“C API客户端插件函数”

  • 如本节前面所述,连接器的代理用户支持取决于它支持的身份验证方法是否允许代理用户。

C.10 MySQL中的限制

本节列出了MySQL 8.0中的当前限制。

C.10.1连接限制

单个连接中可引用的最大表数为61.这包括通过将 FROM 子句 中的派生表和视图合并 到外部查询块中来处理的连接(请参见 第8.2.2.4节“优化派生表,视图引用,和合并或实现的公用表表达式“ )。 它还适用于可在视图定义中引用的表的数量。

C.10.2数据库和表的数量限制

MySQL对数据库的数量没有限制。 底层文件系统可能对目录数量有限制。

MySQL对表的数量没有限制。 底层文件系统可能对表示表的文件数量有限制。 单个存储引擎可能会施加特定于引擎的约束。 InnoDB 允许多达40亿张桌子。

C.10.3桌面尺寸限制

MySQL数据库的有效最大表大小通常由操作系统对文件大小的约束决定,而不是由MySQL内部限制决定。 有关操作系统文件大小限制的最新信息,请参阅特定于您的操作系统的文档。

Windows用户请注意,FAT和VFAT(FAT32) 适合与MySQL一起使用。 请改用NTFS。

如果遇到全表错误,可能会发生以下几种原因:

  • 磁盘可能已满。

  • 您正在使用 InnoDB 表并且在 InnoDB 表空间文件 中用 完了 空间。 最大表空间大小也是表的最大大小。 有关表空间大小限制,请参见 第15.6.1.6节“InnoDB表的限制”

    通常,对于大小超过1TB的表,建议将表分区为多个表空间文件。

  • 您已达到操作系统文件大小限制。 例如,您 MyISAM 在操作系统上 使用 表,该表支持最大2GB的文件,并且您已达到数据文件或索引文件的此限制。

  • 您正在使用 MyISAM 表,并且表所需的空间超出了内部指针大小所允许的范围。 MyISAM 允许数据和索引文件默认增长到256TB,但此限制可以更改为最大允许大小65,536TB(256 7 - 1字节)。

    如果您需要一个 MyISAM 大于默认限制 表,并且您的操作系统支持大文件,则该 CREATE TABLE 语句支持 AVG_ROW_LENGTH MAX_ROWS 选项。 请参见 第13.1.20节“CREATE TABLE语法” 服务器使用这些选项来确定允许的表的大小。

    如果指针大小对于现有表来说太小,则可以更改选项 ALTER TABLE 以增加表的最大允许大小。 请参见 第13.1.9节“ALTER TABLE语法”

    ALTER TABLE tbl_nameMAX_ROWS = 1000000000 AVG_ROW_LENGTH = nnn;
    

    AVG_ROW_LENGTH 只需为带有 BLOB TEXT 列的 指定 ; 在这种情况下,MySQL无法仅根据行数优化所需的空间。

    要更改 MyISAM 的默认大小限制 ,请设置 myisam_data_pointer_size ,设置用于内部行指针的字节数。 如果未指定 MAX_ROWS 选项, 则该值用于设置新表的指针大小 myisam_data_pointer_size 可以是2到7.值4允许表格高达4GB; 值为6允许表格高达256TB。

    您可以使用以下语句检查最大数据和索引大小:

    从表格中显示表状态db_name' tbl_name';
    

    您还可以使用 myisamchk -dv / path / to / table-index-file 请参见 第13.7.6节“显示语法” 第4.6.4节“ myisamchk - MyISAM表维护实用程序”

    解决 MyISAM 表的 文件大小限制的其他方法 如下:

  • 您正在使用 MEMORY HEAP )存储引擎; 在这种情况下,您需要增加 max_heap_table_size 系统变量 的值 请参见 第5.1.8节“服务器系统变量”

C.10.4表列数和行大小的限制

列数限制

MySQL每个表的硬限制为4096列,但对于给定的表,有效最大值可能更小。 确切的列限制取决于几个因素:

行大小限制

给定表的最大行大小由以下几个因素决定:

  • 即使存储引擎能够支持更大的行,MySQL表的内部表示的最大行大小限制为65,535字节。 BLOB TEXT 列只对行大小限制贡献9到12个字节,因为它们的内容与行的其余部分分开存储。

  • InnoDB 对于4KB,8KB,16KB和32KB innodb_page_size 设置 ,表 的最大行大小( 适用于本地存储在数据库页面中的数据)略小于半页 例如,对于默认的16KB InnoDB 页面大小 ,最大行大小略小于8KB 对于64KB页面,最大行大小略小于16KB。 请参见 第15.6.1.6节“InnoDB表的限制”

    如果包含 可变长度列 InnoDB 超过 最大行大小,请 InnoDB 选择可变长度列以进行外部页外存储,直到该行符合 InnoDB 行大小限制。 本地存储的在页外存储的可变长度列的数据量因行格式而异。 有关更多信息,请参见 第15.10节“InnoDB行格式”

  • 不同的存储格式使用不同数量的页眉和尾部数据,这会影响行的可用存储量。

行大小限制示例
  • 以下 InnoDB MyISAM 示例 演示了MySQL最大行大小限制为65,535字节 无论存储引擎如何,都会强制执行该限制,即使存储引擎可能能够支持更大的行。

    MySQL的> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
           c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
           f VARCHAR(10000), g VARCHAR(6000)) ENGINE=InnoDB CHARACTER SET latin1;
    ERROR 1118(42000):行大小太大。使用的最大行大小
    不计算BLOB的表类型是65535.这包括存储开销, 
    检查手册。您必须将某些列更改为TEXT或BLOB
    
    MySQL的> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
           c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
           f VARCHAR(10000), g VARCHAR(6000)) ENGINE=MyISAM CHARACTER SET latin1;
    ERROR 1118(42000):行大小太大。使用的最大行大小
    不计算BLOB的表类型是65535.这包括存储开销, 
    检查手册。您必须将某些列更改为TEXT或BLOB
    

    在下面的 MyISAM 示例中,更改列以 TEXT 避免65,535字节的行大小限制并允许操作成功,因为 BLOB 并且 TEXT 列仅向行大小贡献9到12个字节。

    MySQL的> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
           c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
           f VARCHAR(10000), g TEXT(6000)) ENGINE=MyISAM CHARACTER SET latin1;
    查询OK,0行受影响(0.02秒)
    

    对于 InnoDB 的操作成功, 因为更改列以 TEXT 避免MySQL 65,535字节行大小限制,并且 InnoDB 可变长度列的页外存储避免了 InnoDB 行大小限制。

    MySQL的> CREATE TABLE t (a VARCHAR(10000), b VARCHAR(10000),
           c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
           f VARCHAR(10000), g TEXT(6000)) ENGINE=InnoDB CHARACTER SET latin1;
    查询OK,0行受影响(0.02秒)
    
  • 可变长度列的存储包括长度字节,它们按行大小计算。 例如,一 VARCHAR(255) CHARACTER SET utf8mb3 列需要两个字节来存储值的长度,因此每个值最多可占用767个字节。

    创建表的语句 t1 成功,因为列需要32,765 + 2个字节和32,766 + 2个字节,这些字节的最大行大小为65,535字节:

    MySQL的> CREATE TABLE t1
           (c1 VARCHAR(32765) NOT NULL, c2 VARCHAR(32766) NOT NULL)
           ENGINE = InnoDB CHARACTER SET latin1;
    查询OK,0行受影响(0.02秒)
    

    创建表的语句 t2 失败,因为尽管列长度在65,535字节的最大长度内,但记录长度需要两个额外的字节,这会导致行大小超过65,535字节:

    MySQL的> CREATE TABLE t2
           (c1 VARCHAR(65535) NOT NULL)
           ENGINE = InnoDB CHARACTER SET latin1;
    ERROR 1118(42000):行大小太大。使用的最大行大小
    不计算BLOB的表类型是65535.这包括存储开销, 
    检查手册。您必须将某些列更改为TEXT或BLOB
    

    将列长度减少到65,533或更少可以使语句成功。

    MySQL的> CREATE TABLE t2
           (c1 VARCHAR(65533) NOT NULL)
           ENGINE = InnoDB CHARACTER SET latin1;
    查询OK,0行受影响(0.01秒)
    
  • 对于 MyISAM 表, NULL 列需要行中的额外空间来记录它们的值是否为 NULL NULL 列额外增加一位,向上舍入到最近的字节。

    创建表的语句 t3 失败,因为 除了可变长度列长度字节所需的空间之外还 MyISAM 需要 NULL 列的空间,导致行大小超过65,535字节:

    MySQL的> CREATE TABLE t3
           (c1 VARCHAR(32765) NULL, c2 VARCHAR(32766) NULL)
           ENGINE = MyISAM CHARACTER SET latin1;
    ERROR 1118(42000):行大小太大。使用的最大行大小
    不计算BLOB的表类型是65535.这包括存储开销, 
    检查手册。您必须将某些列更改为TEXT或BLOB
    

    有关 列存储的 信息 ,请参见 第15.10节“InnoDB行格式” InnoDB NULL

  • InnoDB 将行大小(对于本地存储在数据库页面中的数据)限制为略小于数据库页面的一半(4KB,8KB,16KB和32KB innodb_page_size 设置),对于64KB页面,略小于16KB。

    创建表的语句 t4 失败,因为定义的列超过了16KB InnoDB 页面 的行大小限制

    MySQL的> CREATE TABLE t4 (
           c1 CHAR(255),c2 CHAR(255),c3 CHAR(255),
           c4 CHAR(255),c5 CHAR(255),c6 CHAR(255),
           c7 CHAR(255),c8 CHAR(255),c9 CHAR(255),
           c10 CHAR(255),c11 CHAR(255),c12 CHAR(255),
           c13 CHAR(255),c14 CHAR(255),c15 CHAR(255),
           c16 CHAR(255),c17 CHAR(255),c18 CHAR(255),
           c19 CHAR(255),c20 CHAR(255),c21 CHAR(255),
           c22 CHAR(255),c23 CHAR(255),c24 CHAR(255),
           c25 CHAR(255),c26 CHAR(255),c27 CHAR(255),
           c28 CHAR(255),c29 CHAR(255),c30 CHAR(255),
           c31 CHAR(255),c32 CHAR(255),c33 CHAR(255)
           ) ENGINE=InnoDB ROW_FORMAT=DYNAMIC DEFAULT CHARSET latin1;
    ERROR 1118(42000):行大小太大(> 8126)。将某些列更改为TEXT或BLOB可能会有所帮助。
    在当前行格式中,0字节的BLOB前缀以内联方式存储。
    

C.10.5 Windows平台限制

以下限制适用于在Windows平台上使用MySQL:

  • 进程内存

    在Windows 32位平台上,默认情况下,在单个进程(包括MySQL)中使用超过2GB的RAM是不可能的。 这是因为Windows 32位的物理地址限制为4GB,Windows中的默认设置是在内核(2GB)和用户/应用程序(2GB)之间拆分虚拟地址空间。

    某些版本的Windows具有启动时设置,可通过减少内核应用程序来启用更大的应用程序。 或者,要使用超过2GB的空间,请使用64位版本的Windows。

  • 文件系统别名

    使用 MyISAM 表时,不能在Windows链接中使用别名链接到另一个卷上的数据文件,然后链接回主MySQL datadir 位置。

    此工具通常用于将数据和索引文件移动到RAID或其他快速解决方案。

  • 端口数量有限

    Windows系统有大约4,000个端口可用于客户端连接,并且在端口上的连接关闭后,需要两到四分钟才能重用端口。 在客户端以高速率连接到服务器和从服务器断开连接的情况下,所有可用端口可能会在关闭端口再次可用之前用完。 如果发生这种情况,即使MySQL服务器正在运行,它也似乎没有响应。 端口也可以由机器上运行的其他应用程序使用,在这种情况下,MySQL可用的端口数量较少。

    有关此问题的详细信息,请参阅 http://support.microsoft.com/default.aspx?scid=kb;en-us;196271

  • DATA DIRECTORY INDEX DIRECTORY

    Windows上仅支持 DATA DIRECTORY 选项 ,如 第15.6.3.6节“在数据目录外创建表空间”中所述 对于 和其他存储引擎, 在Windows和任何其他具有非功能 调用的 平台上将忽略 选项 选项 CREATE TABLE InnoDB MyISAM DATA DIRECTORY INDEX DIRECTORY CREATE TABLE realpath()

  • DROP DATABASE

    您不能删除另一个会话正在使用的数据库。

  • 不区分大小写的名称

    Windows上的文件名不区分大小写,因此MySQL数据库和表名在Windows上也不区分大小写。 唯一的限制是必须在给定语句中使用相同的大小写指定数据库和表名。 请参见 第9.2.2节“标识符区分大小写”

  • 目录和文件名

    在Windows上,MySQL Server仅支持与当前ANSI代码页兼容的目录和文件名。 例如,以下日语目录名称将无法在Western语言环境中使用(代码页1252):

    DATADIR = “C:/私たちのプロジェクトのデータ”
    

    同样的限制适用于SQL语句中引用的目录和文件名,例如数据文件路径名 LOAD DATA

  • \ 路径名分隔符

    Windows中的路径名组件由 \ 字符 分隔,该 字符也是MySQL中的转义字符。 如果您正在使用 LOAD DATA SELECT ... INTO OUTFILE ,请使用带有 / 字符的 Unix样式文件名

    mysql> LOAD DATA INFILE 'C:/tmp/skr.txt' INTO TABLE skr;
    mysql>SELECT * INTO OUTFILE 'C:/tmp/skr.txt' FROM skr;
    

    或者,您必须加倍 \ 角色:

    mysql> LOAD DATA INFILE 'C:\\tmp\\skr.txt' INTO TABLE skr;
    mysql>SELECT * INTO OUTFILE 'C:\\tmp\\skr.txt' FROM skr;
    
  • 管道问题

    管道在Windows命令行提示符下无法可靠地工作。 如果管道包含字符 ^Z / CHAR(24) ,Windows认为它遇到了文件结束并中止了程序。

    当您尝试应用二进制日志时,这主要是一个问题,如下所示:

    C:\> mysqlbinlog binary_log_file | mysql --user=root
    

    如果您在应用日志时遇到问题并怀疑是因为 ^Z / CHAR(24) 字符,则可以使用以下解决方法:

    C:\> 
    C:\>mysqlbinlog binary_log_file --result-file=/tmp/bin.sqlmysql --user=root --execute "source /tmp/bin.sql"
    

    后一个命令也可用于可靠地读取任何可能包含二进制数据的SQL文件。

原文