LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]
...
UNLOCK TABLES
Команда LOCK TABLES блокирует
указанные в ней таблицы для
данного потока. Команда UNLOCK
TABLES снимает любые блокировки,
удерживаемые данным потоком. Все
таблицы, заблокированные текущим
потоком, автоматически
разблокируются при появлении в
потоке иной команды LOCK
TABLES или при прекращении
соединения с сервером.
Чтобы использовать команду LOCK
TABLES в MySQL 4.0.2, необходимо иметь
глобальные привилегии LOCK
TABLES и SELECT для
заданных таблиц. В MySQL 3.23 для этого
необходимы привилегии
SELECT, INSERT,
DELETE и UPDATE для
рассматриваемых таблиц.
Основные преимущества
использования команды LOCK
TABLES состоят в том, что она
позволяет осуществлять эмуляцию
транзакций или получить более
высокую скорость при обновлении
таблиц. Ниже это разъясняется
более подробно.
Если в потоке возникает блокировка
операции READ для
некоторой таблицы, то только этот
поток (и все другие потоки) могут
читать из данной таблицы. Если для
некоторой таблицы в потоке
существует блокировка
WRITE, тогда только поток,
содержащий блокировку, может
осуществлять операции чтения
(READ) и записи
(WRITE) на данной таблице.
Остальные потоки блокируются.
Различие между READ LOCAL и
READ состоит в том, что
READ LOCAL позволяет
выполнять неконфликтующие команды
INSERT во время
существования блокировки. Однако
эту команду нельзя использовать
для работы с файлами базы данных
вне сервера MySQL во время данной
блокировки.
При использовании команды LOCK
TABLES необходимо блокировать
все таблицы, которые
предполагается использовать в
последующих запросах, употребляя
при этом те же самые псевдонимы,
которые будут в запросах! Если
таблица упоминается в запросе
несколько раз (с псевдонимами),
необходимо заблокировать каждый
псевдоним!
Блокировка WRITE обычно
имеет более высокий приоритет, чем
блокировка READ, чтобы
гарантировать, что изменения
обрабатываются так быстро, как
возможно. Это означает, что если
один поток получает блокировку
READ и затем иной поток
запрашивает блокировку
WRITE, последующие запросы
на блокировку READ будут
ожидать, пока поток WRITE
не получит блокировку и не снимет
ее. Можно использовать блокировки
LOW_PRIORITY WRITE, позволяющие
другим потокам получать
блокировки READ в то время,
как основной поток находится в
состоянии ожидания блокировки
WRITE. Блокировки
LOW_PRIORITY WRITE
могут быть использованы только
если есть уверенность, что в
конечном итоге будет период
времени, когда ни один из потоков
не будет иметь блокировки
READ.
Команда LOCK TABLES работает
следующим образом:
Сортирует все блокируемые таблицы в порядке, который задан внутренним образом, т.е. ``зашит'' (с точки зрения пользователя этот порядок не задан).
Блокировка WRITE
ставится перед блокировкой
READ, если таблицы
блокируются с блокировками
READ и WRITE.
Блокирует одну таблицу единовременно, пока поток не получит все блокировки.
Описанный порядок действий гарантирует, что блокирование таблицы не создает тупиковой ситуации. Однако есть и другие вещи, о которых необходимо отдавать себе отчет при работе по описанной схеме:
Использование для таблицы
блокировки LOW_PRIORITY WRITE
всего лишь означает, что MySQL будет
выполнять данную конкретную
блокировку, пока не появится поток,
запрашивающий блокировку
READ. Если поток получил
блокировку WRITE и
находится в ожидании блокировки
следующей таблицы из списка
блокируемых таблиц, то все
остальные потоки будут ожидать,
пока блокировка WRITE не
будет снята. Если это представляет
серьезную проблему для вашего
приложения, то следует подумать о
преобразовании имеющихся таблиц в
таблицы иного вида, поддерживающие
транзакции.
Поток, ожидающий блокировку
таблицы, можно безопасно
уничтожить с помощью команды
KILL. See Раздел 4.5.5, «Синтаксис команды KILL».
Учтите, что нельзя блокировать
любые таблицы, используемые
совместно с оператором INSERT
DELAYED, поскольку в этом случае
команда INSERT выполняется
как отдельный поток.
Обычно нет необходимости
блокировать таблицы, поскольку все
единичные команды UPDATE
являются неделимыми; никакой
другой поток не может
взаимодействовать с какой-либо
SQL-командой, выполняемой в данное
время. Однако в некоторых случаях
предпочтительно тем или иным
образом осуществлять блокировку
таблиц:
Если предполагается выполнить
большое количество операций на
группе взаимосвязанных таблиц,
то быстрее всего это сделать,
блокировав таблицы, которые вы
собираетесь использовать.
Конечно, это имеет свою обратную
сторону, поскольку никакой
другой поток управления не может
обновить таблицу с блокировкой
READ или прочитать
таблицу с блокировкой
WRITE. При блокировке
LOCK TABLES операции
выполняются быстрее потому, что
в этом случае MySQL не производит
запись на диск содержимого кэша
ключей для заблокированных
таблиц, пока не будет вызвана
команда UNLOCK TABLES
(обычно кэш ключей записывается
на диск после каждой SQL-команды).
Применение LOCK TABLES
увеличивает скорость
записи/обновления/удаления в
таблицах типа MyISAM.
Если вы используете таблицы, не
поддерживающие транзакций, то
при использовании программы
обработки таблиц необходимо
применять команду LOCK
TABLES для гарантии, что
никакой другой поток не
вклинился между операциями
SELECT и UPDATE.
Ниже показан пример, требующий
использования LOCK TABLES
для успешного выполнения
операций:
mysql>LOCK TABLES trans READ, customer WRITE;mysql>SELECT SUM(value) FROM trans WHERE customer_id=some_id;mysql>UPDATE customer SET total_value=sum_from_previous_statementWHERE customer_id=some_id; mysql>UNLOCK TABLES;
Без использования LOCK
TABLES существует вероятность
того, что какой-либо иной поток
управления может вставить новую
строку в таблицу trans
между выполнением операций
SELECT и UPDATE.
Используя пошаговые обновления
(UPDATE customer SET value=value+new_value)
или функцию LAST_INSERT_ID(),
применения команды LOCK
TABLES во многих случаях можно
избежать.
Некоторые проблемы можно также
решить путем применения
блокирующих функций на уровне
пользователя GET_LOCK() и
RELEASE_LOCK(). Эти блоки
хранятся в хэш-таблице на сервере
и, чтобы обеспечить высокую
скорость, реализованы в виде
pthread_mutex_lock() и
pthread_mutex_unlock(). See
Раздел 6.3.6.2, «Разные функции».
Чтобы получить дополнительную информацию о механизме блокировки, обращайтесь к разделу Раздел 5.3.1, «Как MySQL блокирует таблицы».
Можно блокировать все таблицы во
всех базах данных блокировкой
READ с помощью команды
FLUSH TABLES WITH READ LOCK. See
Раздел 4.5.3, «Синтаксис команды FLUSH ». Это очень удобно для
получения резервной копии
файловой системы, подобной Veritas,
при работе в которой могут
потребоваться заблаговременные
копии памяти.
Примечание: Команда LOCK
TABLES не сохраняет транзакции и
автоматически фиксирует все
активные транзакции перед
попыткой блокировать таблицы.
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.
© 1995-2005 MySQL AB. All rights reserved.
