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仅适用于MyISAM、MEMORY、ARCHIVE和BLACKHOLE表格。对于不支持的引擎,会DELAYED出现错误。INSERT DELAYED如果与已锁定的表一起使用, 则会发生错误,LOCK TABLES因为插入必须由单独的线程处理,而不是由持有锁的会话处理。对于
MyISAM表,如果数据文件中间没有空闲块,则支持concurrentSELECTandINSERTstatements。在这些情况下,您很少需要使用INSERT DELAYEDwithMyISAM。INSERT DELAYED应该只用于INSERT指定值列表的语句。服务器忽略DELAYEDforINSERT ... SELECT或INSERT ... ON DUPLICATE KEY UPDATE语句。因为该
INSERT DELAYED语句立即返回,所以在插入行之前,您不能使用LAST_INSERT_ID()来获取AUTO_INCREMENT该语句可能生成的值。DELAYEDSELECT行在实际插入之前 对语句不可见 。INSERT DELAYED只要 的值为 或,就作为简单INSERT(即没有DELAYED选项)处理。(在后一种情况下,该语句不会触发切换到基于行的日志记录,因此使用基于语句的格式进行记录。)binlog_formatSTATEMENTMIXEDbinlog_format这在使用基于行的二进制日志记录模式(设置为ROW) 时不适用,在该模式下,INSERT DELAYED语句始终使用DELAYED指定的选项执行,并记录为行更新事件。DELAYED在副本服务器上被忽略,因此在副本服务器上INSERT DELAYED被视为正常INSERT。这是因为DELAYED可能导致从站具有与源不同的数据。如果表被写锁定并用于修改表结构, 挂起
INSERT DELAYED的语句将丢失 。ALTER TABLEINSERT 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_insert中Command。如果您执行一条FLUSH TABLES语句或用 .kill 杀死它,它就会被杀死。但是,在退出之前,它首先将所有排队的行存储到表中。在此期间它不接受 来自其他线程的任何新语句。如果在此之后执行一条语句,则会创建一个新的处理程序线程。KILLthread_idINSERTINSERT DELAYED这意味着如果有处理程序正在运行,
INSERT DELAYED语句的优先级高于普通语句 。其他更新语句必须等到队列为空、有人终止处理程序线程(使用 )或有人执行.INSERTINSERT DELAYEDINSERT DELAYEDKILLthread_idFLUSH TABLES以下状态变量提供有关
INSERT DELAYED语句的信息。状态变量 意义 Delayed_insert_threads处理程序线程数 Delayed_writes写的行数 INSERT DELAYEDNot_flushed_delayed_rows等待写入的行数 您可以通过发出
SHOW STATUS语句或执行mysqladmin 扩展状态 命令来查看这些变量。