6.7.2 Синтаксис команд LOCK TABLES/UNLOCK TABLES
LOCK TABLES tbl_name [AS alias] {READ | [READ LOCAL] | [LOW_PRIORITY] WRITE}
[, tbl_name {READ | [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 section 4.5.5 Синтаксис команды KILL
.
Учтите, что нельзя блокировать любые таблицы, используемые совместно с
оператором INSERT DELAYED
, поскольку в этом случае команда INSERT
выполняется как отдельный поток.
Обычно нет необходимости блокировать таблицы, поскольку все единичные
команды UPDATE
являются неделимыми; никакой другой поток не может
взаимодействовать с какой-либо SQL-командой, выполняемой в данное время.
Однако в некоторых случаях предпочтительно тем или иным образом
осуществлять блокировку таблиц:
Используя пошаговые обновления (UPDATE customer SET
value=value+new_value
) или функцию LAST_INSERT_ID()
, применения команды
LOCK TABLES
во многих случаях можно избежать.
Некоторые проблемы можно также решить путем применения блокирующих функций
на уровне пользователя GET_LOCK()
и RELEASE_LOCK()
. Эти блоки хранятся в
хэш-таблице на сервере и, чтобы обеспечить высокую скорость, реализованы в
виде pthread_mutex_lock()
и pthread_mutex_unlock()
.
See section 6.3.6.2 Разные функции.
Чтобы получить дополнительную информацию о механизме блокировки,
обращайтесь к разделу section 5.3.1 Как MySQL блокирует таблицы.
Можно блокировать все таблицы во всех базах данных блокировкой READ
с
помощью команды FLUSH TABLES WITH READ LOCK
. See section 4.5.3 Синтаксис команды FLUSH
.
Это очень удобно для получения резервной копии файловой системы, подобной
Veritas, при работе в которой могут потребоваться заблаговременные копии
памяти.
Примечание: Команда LOCK TABLES
не сохраняет транзакции и автоматически
фиксирует все активные транзакции перед попыткой блокировать таблицы.