INSERT DELAYED ...
用于INSERT語句的DELAYED選項是MySQL相對于標準SQL的擴展。如果您的客戶端不能等待INSERT完成,則這個選項是非常有用的。當您使用MySQL進行日志編寫時,這是非常常見的問題。您也可以定期運行SELECT和UPDATE語句,這些語句花費的時間較長。
當一個客戶端使用INSERT DELAYED時,會立刻從服務器處得到一個確定。并且行被排入隊列,當表沒有被其它線程使用時,此行被插入。
使用INSERT DELAYED的另一個重要的好處是,來自許多客戶端的插入被集中在一起,并被編寫入一個塊。這比執行許多獨立的插入要快很多。
使用DELAYED時有一些限制:
· INSERT DELAYED僅適用于MyISAM, MEMORY和ARCHIVE表。對于MyISAM表,如果在數據文件的中間沒有空閑的塊,則支持同時采用SELECT和INSERT語句。在這些情況下,基本不需要對MyISAM使用INSERT DELAYED。請參見15.1節,“MyISAM存儲引擎”, 15.4節,“MEMORY (HEAP)存儲引擎”和15.8節,“ARCHIVE存儲引擎”。
· INSERT DELAYED應該僅用于指定值清單的INSERT語句。服務器忽略用于INSERT DELAYED...SELECT語句的DELAYED。
· 服務器忽略用于INSERT DELAYED...ON DUPLICATE UPDATE語句的DELAYED。
· 因為在行被插入前,語句立刻返回,所以您不能使用LAST_INSERT_ID()來獲取AUTO_INCREMENT值。AUTO_INCREMENT值可能由語句生成。
· 對于SELECT語句,DELAYED行不可見,直到這些行確實被插入了為止。
· DELAYED在從屬復制服務器中被忽略了,因為DELAYED不會在從屬服務器中產生與主服務器不一樣的數據。
注意,目前在隊列中的各行只保存在存儲器中,直到它們被插入到表中為止。這意味著,如果您強行中止了mysqld(例如,使用kill -9)或者如果mysqld意外停止,則所有沒有被寫入磁盤的行都會丟失。
以下詳細描述了當您對INSERT或REPLACE使用DELAYED選項時會發生什么情況。在這些描述中,“線程”指的是已接受了一個INSERT DELAYED語句的線程,“管理程序”指的是為某個特定的表處理所有INSERT DELAYED語句的線程。
· 當一個線程對一個表執行DELAYED語句時,會創建出一個管理程序線程(如果原來不存在),對用于本表的所有DELAYED語句進行處理。
· 線程會檢查是否管理程序以前已獲取了DELAYED鎖定;如果沒有獲取,則告知管理程序線程進行此項操作。即使其它線程對表有READ或WRITE鎖定,也可以獲得DELAYED鎖定。但是管理程序會等待所有的ALTER TABLE鎖定或FLUSH TABLE鎖定,以確保表的結構是最新的。
· 線程執行INSERT語句,但不是把行寫入表中,而是把最終行的拷貝放入一個由管理程序線程管理的隊列中。線程會提示出現語法錯誤,這些錯誤會被報告到客戶端中。
· 因為在插入操作之前,INSERT返回已經完成,所以客戶端不能從服務器處獲取重復記錄的數目,也不能獲取生成的行的AUTO_INCREMENT值。(如果您使用C API,則出于同樣的原因,mysql_info()函數不會返回任何有意義的東西。)
· 當行被插入表中時,二進制日志被管理程序線程更新。在多行插入情況下,當第一行被插入時,二進制日志被更新。
· 每次delayed_insert_limit行被編寫時,管理程序會檢查是否有SELECT語句仍然未執行。如果有,則會在繼續運行前,讓這些語句先執行。
· 當管理程序的隊列中沒有多余的行時,表被解鎖。如果在delayed_insert_timeout時間內,沒有接收到新的INSERT DELAYED語句,則管理程序中止。
· 如果在某個特定的管理程序隊列中,有超過delayed_queue_size的行未被執行,則申請INSERT DELAYED的線程會等待,直到隊列中出現空間為止。這么做可以確保mysqld不會把所有的存儲器都用于被延遲的存儲隊列。
· 管理程序線程會顯示在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。