Documentation Home

13.2.5.3 插入延迟语句

INSERT DELAYED ...

该语句的DELAYED选项 INSERT是标准 SQL 的 MySQL 扩展,可用于某些类型的表(例如MyISAM)。当客户端使用 INSERT DELAYED时,它会立即从服务器获得一个 okay,并且当该表未被任何其他线程使用时,该行将排队等待插入。

笔记

INSERT DELAYEDINSERT如果该表未以其他方式使用,则比正常速度慢。服务器还需要额外的开销来为每个有延迟行的表处理一个单独的线程。这意味着您应该 INSERT DELAYED仅在确实确定需要时才使用它。

从 MySQL 5.6.6 开始,INSERT DELAYED已弃用;希望在未来的版本中将其删除。使用INSERT (without DELAYED) 代替。

排队的行仅保存在内存中,直到它们被插入到表中。这意味着如果您强行终止 mysqld(例如,with kill -9)或者如果mysqld意外终止,则任何尚未写入磁盘的排队行都会丢失

使用 有一些限制 DELAYED

  • INSERT DELAYED仅适用于MyISAMMEMORYARCHIVEBLACKHOLE 表格。对于不支持的引擎,会 DELAYED出现错误。

  • INSERT DELAYED如果与已锁定的表一起使用, 则会发生错误,LOCK TABLES因为插入必须由单独的线程处理,而不是由持有锁的会话处理。

  • 对于MyISAM表,如果数据文件中间没有空闲块,则支持concurrent SELECTand INSERTstatements。在这些情况下,您很少需要使用INSERT DELAYEDwith MyISAM

  • INSERT DELAYED应该只用于INSERT指定值列表的语句。服务器忽略 DELAYEDfor INSERT ... SELECTINSERT ... ON DUPLICATE KEY UPDATE语句。

  • 因为该INSERT DELAYED 语句立即返回,所以在插入行之前,您不能使用 LAST_INSERT_ID()来获取 AUTO_INCREMENT该语句可能生成的值。

  • DELAYEDSELECT行在实际插入之前 对语句不可见 。

  • INSERT DELAYED只要 的值为 或,就作为简单INSERT(即没有DELAYED选项)处理。(在后一种情况下,该语句不会触发切换到基于行的日志记录,因此使用基于语句的格式进行记录。) binlog_formatSTATEMENTMIXED

    binlog_format这在使用基于行的二进制日志记录模式(设置为 ROW) 时不适用,在该模式下,INSERT DELAYED语句始终使用DELAYED指定的选项执行,并记录为行更新事件。

  • DELAYED在副本服务器上被忽略,因此在副本服务器上INSERT DELAYED被视为正常INSERT。这是因为DELAYED可能导致从站具有与源不同的数据。

  • 如果表被写锁定并用于修改表结构, 挂起INSERT DELAYED 的语句将丢失 。ALTER TABLE

  • INSERT DELAYED不支持视图。

  • INSERT DELAYED分区表不支持。

下面详细描述当您使用 或 DELAYED选项 时会发生什么。在此描述中, thread是接收 语句 的线程, handler是处理 特定表的所有语句的线程。 INSERTREPLACEINSERT DELAYEDINSERT DELAYED

  • 当线程为表执行语句时,如果不存在这样的处理程序,则会 DELAYED 创建一个处理程序线程来处理该表的所有语句。DELAYED

  • 线程检查处理程序之前是否已获取DELAYED锁;如果没有,它告诉处理程序线程这样做。即使其他线程对该表有锁或锁,DELAYED 也可以获得 锁。但是,处理程序会等待所有 锁或 语句完成,以确保表结构是最新的。 READWRITEALTER TABLEFLUSH TABLES

  • 线程执行 INSERT语句,但不是将行写入表,而是将最后一行的副本放入由处理程序线程管理的队列中。线程会注意到任何语法错误并报告给客户端程序。

  • 客户端无法从服务器获取重复行数或AUTO_INCREMENT 结果行的值,因为 INSERT在插入操作完成之前返回。(如果您使用 C API,该mysql_info()函数不会返回任何有意义的内容,原因相同。)

  • 当行被插入到表中时,二进制日志由处理程序线程更新。在多行插入的情况下,二进制日志会在插入第一行时更新。

  • 每次 delayed_insert_limit写入行时,处理程序都会检查是否有任何 SELECT语句仍在挂起。如果是这样,它允许这些在继续之前执行。

  • 当处理程序的队列中没有更多行时,表将解锁。如果在几秒钟INSERT DELAYED内没有收到新的语句 delayed_insert_timeout ,处理程序将终止。

  • delayed_queue_size如果特定处理程序队列中有 多个 行待处理,则请求线程INSERT DELAYED会一直等待,直到队列中有空间为止。这样做是为了确保 mysqld不会将所有内存用于延迟内存队列。

  • 处理程序线程显示在列中的 MySQL 进程列表 delayed_insertCommand。如果您执行一条FLUSH TABLES 语句或用 .kill 杀死它,它就会被杀死。但是,在退出之前,它首先将所有排队的行存储到表中。在此期间它不接受 来自其他线程的任何新语句。如果在此之后执行一条语句,则会创建一个新的处理程序线程。 KILL thread_idINSERTINSERT DELAYED

    这意味着如果有处理程序正在运行,INSERT DELAYED语句的优先级高于普通语句 。其他更新语句必须等到队列为空、有人终止处理程序线程(使用 )或有人执行. INSERTINSERT DELAYEDINSERT DELAYEDKILL thread_idFLUSH TABLES

  • 以下状态变量提供有关 INSERT DELAYED语句的信息。

    状态变量 意义
    Delayed_insert_threads 处理程序线程数
    Delayed_writes 写的行数INSERT DELAYED
    Not_flushed_delayed_rows 等待写入的行数

    您可以通过发出 SHOW STATUS语句或执行mysqladmin 扩展状态 命令来查看这些变量。