6.4.4 Синтаксис оператора INSERT DELAYED
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 section 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 API
mysql_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
следует применять
только тогда, когда в ней есть реальная необходимость!