INSERT DELAYED ...
Опция DELAYED
для команды INSERT
является специфической для MySQL
возможностью, которая очень полезна, если клиент не может ждать завершения
команды INSERT
. Такая проблема встречается часто - она возникает, когда
MySQL используется для ведения журналов (проще говоря, для логгинга) и при
этом периодически запускаются команды SELECT
и UPDATE
, для выполнения
которых требуется много времени. Оператор DELAYED
был введен в версию
MySQL 3.22.15. Он является расширением MySQL к ANSI SQL92.
INSERT DELAYED
работает только с таблицами типа ISAM
и MyISAM
. Следует
учитывать, что таблицы MyISAM
поддерживают одновременное выполнение SELECT
и INSERT
, поэтому если нет свободных блоков в середине файла данных, то
необходимость в применении INSERT DELAYED
возникает очень редко.
See Раздел 7.1, «Таблицы MyISAM
».
При использовании оператора INSERT DELAYED
клиент сразу же получает
успешный ответ от сервера, а запись будет добавлена в таблицу сразу же
после того, как эту таблицу перестанет использовать другой поток.
Еще одно существенное преимущество применения оператора INSERT DELAYED
заключается в том, что данные от многих клиентов собираются вместе и
записываются одним блоком. Это намного быстрее, чем несколько отдельных
операций вставки.
Обратите внимание: в настоящее время все записи, поставленные в очередь на
добавление, хранятся только в памяти до тех пор, пока они не будут
записаны на диск. Отсюда следует, что если выполнение mysqld
будет
завершено принудительно (kill -9
) или программа умрет, то все находящиеся
в очереди данные, которые не записаны на диск, будут потеряны!.
Ниже детально описано, что происходит при использовании опции DELAYED
в
командах INSERT
или REPLACE
. В этом описании ``поток'' понимается как
поток, принимающий команду INSERT DELAYED
, а ``обработчик'' - это поток,
который обрабатывает все команды INSERT DELAYED
в конкретной таблице.
При выполнении потоком команды
DELAYED
для таблицы создается поток-обработчик для обработки всех командDELAYED
в данной таблице, если подобный обработчик уже не существует.Данный поток проверяет, выполнил ли уже обработчик блокировку
DELAYED
; если нет, то он предписывает обработчику сделать это. БлокировкаDELAYED
может быть осуществлена даже в случае, если блокировкиREAD
илиWRITE
на данной таблице уже выполнены другими потоками. Однако обработчик будет ожидать всех блокировокALTER TABLE
и завершения всех командFLUSH TABLES
, чтобы убедиться в том, что структура таблицы соответствует последнему обновлению.Поток выполняет команду
INSERT
, но вместо записи строки в таблицу он ставит финальную копию этой строки в очередь, управляемую потоком-обработчиком. Поток отмечает все синтаксические ошибки и сообщает о них клиентской программе.Клиент не может уведомить о количестве дубликатов или значении
AUTO_INCREMENT
для данной результирующей строки; он также не может получить эти данные с сервера, поскольку командаINSERT
возвращает результат до полного завершения операции вставки. По той же причине ничего существенного не даст и использование функции C APImysql_info()
.-
Обновление журнала обновлений производится потоком-обработчиком после вставки строки в таблицу. В случае многострочной вставки обновление журнала обновлений производится при записи первой строки.
После записи каждых
delayed_insert_limit
строк, обработчик проверяет, не находятся ли в ожидании выполнения какие-либо командыSELECT
. Если да, то обработчик перед продолжением своей работы ``пропускает их вперед'' на выполнение.Если очередь обработчика больше не содержит строк, то с данной таблицы будет снята блокировка. Если в течение
delayed_insert_timeout
секунд не поступят никакие новые командыINSERT DELAYED
, то обработчик завершит свою работу.Если более, чем
delayed_queue_size
строк уже ожидают в очереди обработчика, то поток, запрашивающийINSERT DELAYED
, будет ждать, пока не освободится место в очереди. Таким образом можно иметь уверенность в том, чтоmysqld
не займет всю память сервера для хранения запросов данной очереди.Поток-обработчик будет наблюдаться в списке процессов MySQL со значением
delayed_insert
в столбцеCommand
. Поток-обработчик можно уничтожить запуском командыFLUSH TABLES
или командойKILL номер_потока
. Однако перед своим завершением он вначале сохранит в таблице все поставленные в очередь строки. В процессе сохранения он не будет принимать никаких новых командINSERT
от иного потока. При выполнении после этого командыINSERT DELAYED
будет создан новый поток-обработчик. Обратите внимание: отсюда следует, что командыINSERT DELAYED
имеют более высокий приоритет, чем обычные командыINSERT
, если уже существует запущенный обработчикINSERT DELAYED
! Другие команды обновления должны ожидать, пока не опустеет очередьINSERT DELAYED
или же пока кто-либо не прекратит выполнение потока-обработчика (с помощьюKILL номер_потока
) или не выполнит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
. Это означает, что команду INSERT DELAYED
следует применять
только тогда, когда в ней есть реальная необходимость!