MySQL INSERT DELAYED

pursuer.chen發表於2016-04-05

INSERT DELAYED 語法

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name [(col_name,...)]
    VALUES ({expr | DEFAULT},...),(...),...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]
或:

INSERT [LOW_PRIORITY | DELAYED | HIGH_PRIORITY] [IGNORE]
    [INTO] tbl_name
    SET col_name={expr | DEFAULT}, ...
    [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

 

用於INSERT語句的DELAYED選項是MySQL相對於標準SQL的擴充套件。如果您的客戶端不能等待INSERT完成,則這個選項是非常有用的。當您使用MySQL進行日誌編寫時,這是非常常見的問題。您也可以定期執行SELECT和UPDATE語句,這些語句花費的時間較長。

當一個客戶端使用INSERT DELAYED時,會立刻從伺服器處得到一個確定。並且行被排入佇列,當表沒有被其它執行緒使用時,此行被插入。

使用INSERT DELAYED的另一個重要的好處是,來自許多客戶端的插入被集中在一起,並被編寫入一個塊。這比執行許多獨立的插入要快很多。

使用DELAYED時有一些限制:

  1. INSERT DELAYED僅適用於MyISAM, MEMORY和ARCHIVE表。對於MyISAM表,如果在資料檔案的中間沒有空閒的塊,則支援同時採用SELECT和INSERT語句。在這些情況下,基本不需要對MyISAM使用INSERT DELAYED。
  2. INSERT DELAYED應該僅用於指定值清單的INSERT語句。伺服器忽略用於INSERT DELAYED...SELECT語句的DELAYED。
  3. 伺服器忽略用於INSERT DELAYED...ON DUPLICATE UPDATE語句的DELAYED。
  4. 因為在行被插入前,語句立刻返回,所以您不能使用LAST_INSERT_ID()來獲取AUTO_INCREMENT值。AUTO_INCREMENT值可能由語句生成。
  5. 對於SELECT語句,DELAYED行不可見,直到這些行確實被插入了為止。
  6. DELAYED在從屬複製伺服器中被忽略了,因為DELAYED不會在從屬伺服器中產生與主伺服器不一樣的資料。

注意,目前在佇列中的各行只儲存在儲存器中,直到它們被插入到表中為止。這意味著,如果您強行中止了mysqld(例如,使用kill -9)或者如果mysqld意外停止,則所有沒有被寫入磁碟的行都會丟失。

以下詳細描述了當您對INSERT或REPLACE使用DELAYED選項時會發生什麼情況。在這些描述中,“執行緒”指的是已接受了一個INSERT DELAYED語句的執行緒,“管理程式”指的是為某個特定的表處理所有INSERT DELAYED語句的執行緒。

  1. 當一個執行緒對一個表執行DELAYED語句時,會建立出一個管理程式執行緒(如果原來不存在),對用於本表的所有DELAYED語句進行處理。
  2. 執行緒會檢查是否管理程式以前已獲取了DELAYED鎖定;如果沒有獲取,則告知管理程式執行緒進行此項操作。即使其它執行緒對錶有READ或WRITE鎖定,也可以獲得DELAYED鎖定。但是管理程式會等待所有的ALTER TABLE鎖定或FLUSH TABLE鎖定,以確保表的結構是最新的。
  3. 執行緒執行INSERT語句,但不是把行寫入表中,而是把最終行的拷貝放入一個由管理程式執行緒管理的佇列中。執行緒會提示出現語法錯誤,這些錯誤會被報告到客戶端中。
  4. 因為在插入操作之前,INSERT返回已經完成,所以客戶端不能從伺服器處獲取重複記錄的數目,也不能獲取生成的行的AUTO_INCREMENT值。(如果您使用C API,則出於同樣的原因,mysql_info()函式不會返回任何有意義的東西。)
  5. 當行被插入表中時,二進位制日誌被管理程式執行緒更新。在多行插入情況下,當第一行被插入時,二進位制日誌被更新。
  6. 每次delayed_insert_limit行被編寫時,管理程式會檢查是否有SELECT語句仍然未執行。如果有,則會在繼續執行前,讓這些語句先執行。
  7. 當管理程式的佇列中沒有多餘的行時,表被解鎖。如果在delayed_insert_timeout時間內,沒有接收到新的INSERT DELAYED語句,則管理程式中止。
  8. 如果在某個特定的管理程式佇列中,有超過delayed_queue_size的行未被執行,則申請INSERT DELAYED的執行緒會等待,直到佇列中出現空間為止。這麼做可以確保mysqld不會把所有的儲存器都用於被延遲的儲存佇列。
  9. 管理程式執行緒會顯示在MySQL程式清單中,其命令列中包含delayed_insert。如果您執行一個FLUSH TABLES語句或使用KILL thread_id進行刪除,則會刪除此執行緒。不過,在退出前,執行緒會首先把所有排入佇列的行儲存到表中。在這期間,該執行緒不會從其它執行緒處接受任何新的INSERT語句。如果您在此之後執行一個INSERT DELAYED語句,則會建立出一個新的管理程式執行緒。

注意,如果有一個INSERT DELAYED管理程式正在執行,則這意味著INSERT DELAYED語句比常規的INSERT語句具有更高的優先權。其它更新語句必須等待,直到INSERT DELAYED語句佇列都執行完畢,或者管理程式執行緒被中止(使用KILL thread_id),或者執行了一個FLUSH TABLES時為止。

以下狀態變數提供了有關INSERT DELAYED語句的資訊:

狀態變數

意義

Delayed_insert_threads

管理程式執行緒的數目

Delayed_writes

使用INSERT DELAYED寫入的行的數目

Not_flushed_delayed_rows

等待被寫入的行的數目

您可以通過傳送一個SHOW STATUS語句,或者執行一個mysqladmin extended-status命令,來閱覽這些變數。

注意,當沒有使用表時,INSERT DELAYED比常規的INSERT要慢。對於伺服器來說,為每個含有延遲行的表操縱一個獨立的執行緒,也是一個額外的系統開銷。這意味著只有當您確認您需要時,才應使用INSERT DELAYED。

 

文章轉載來自:http://dev.mysql.com/doc/refman/5.6/en/insert-delayed.html

相關文章