LOCK TABLES nome_tabela [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} [, nome_tabela [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...] ... UNLOCK TABLES
LOCK TABLES
bloqueia tabelas para a thread
atual. UNLOCK TABLES
libera qualquer trava
existente para a thread atual. Todas as tabela que estão
bloqueadas pela thread atual são implicitamente desbloquadas
quando a thread executa um outro LOCK TABLES
,
ou quando a conexão ao servidor é fechada.
Para usar LOCK TABLES
no MySQL 4.0.2 você
precisa do privilégio global LOCK TABLES
e
um privilégio SELECT
nas tabelas envolvidas
No MySQL 3.23 você precisa ter os privilégios
SELECT
, insert
,
DELETE
e UPDATE
para as
tabelas.
A razão principal para utilizar LOCK TABLES
é para emular transações ou obter mais velocidade ao
atualizar tabelas. Isto é explicado em mais detalhes
posteriormente.
Se uma thread obtem uma trava de leitura
(READ
) em uma tabela, aquela thread (e todas
as outras threads) só poderão ler da tabela. Se uma thread
obter uma trava de escrita (WRITE
) na tabela,
apenas a thread que bloqueou poderá ler ou escrever na tabela.
Outras threads serão bloqueadas.
A diferença entre READ LOCAL
e
READ
é que READ LOCAL
permite que instruções INSERT
não
conflitantes sejam executadas enquanto a trava está ativa.
Isto, no entatnto, não pode ser usado se você for manipular o
arquivo de banco de dados fora do MySQL enquanto a trava estiver
ativa.
Quando você usa LOCK TABLES
, você deve
travar todas as tabelas que você for usar e utilizar o mesmo
alias que estiver utilizando em suas consultas! Se você estiver
usando uma tabela várias vezes em uma consulta (com aliases),
você deve obter um trava para cada alias.
Bloqueio de escrita (WRITE
) normalmente têm
maior prioridade que bloqueio de leitura
(READ
), para assegurar que atualizações
são processadas assim que possível. Isto significa que se uma
thread obtida um bloqueio de leitura (READ
) e
outra thread requisitar um bloqueio de escrita
(WRITE
), bloqueios de leitura
(READ
) subsequentes irão esperar até a
thread de escrita (WRITE
) tiver obtido a
trava e a liberado. Você pode usar travas LOW_PRIORITY
WRITE
para permitir que outras threads obtenham
bloqueios de leitura (READ
) enquanto a thread
estiver esperando pela trava de escrita
(WRITE
). Você só deve utilizar bloqueios
LOW_PRIORITY WRITE
se você estiver certo que
haverá um momento onde nenhuma thread terá bloqueio de leitura
(READ
).
LOCK TABLES
funciona da seguinte maneira:
Ordene todas as tabelas a serem travadas em uma ordem definida internamente (do ponto do usuário a ordem é indefinida).
Se uma tabela é bloqueada com uma trava de leitura e de escrita, coloque a trava de escrita antes da trava de leitura.
Bloqueie uma tabela por vez até que a thread obtenha todas as travas.
Esta política assegura que as tabelas sejam bloqueadas sem deadlock. Há no entanto outra coisa da qual é preciso estar ciente neste esquema:
Se cocê estiver usando uma trava de escita
LOW_PRIORITY WRITE
em uma tabela, significa
apenas que o MySQL irá esperar por esta trava particular até
que não haja mais treads fazendo um bloqueio de leitura
(READ
). Quando a thread tiver obtido a trava
de escrita (WRITE
) e está esperando ppo
obter o trava para a próxima tabela na lista de tabelas
bloqueadas, todas as outras threads irão esperar que a trva de
escrita (WRITE
) seja liberada. Se isto tornar
um sério problema com sua aplicação, você deve converter
algumas de suas tabellas para tabelas com segurança em
transações.
Você pode matar com segurança um thread que está esperando
por um bloqueio de tabela com KILL
. See
Secção 4.6.7, “Sintaxe de KILL
”.
Note que você não deve travar
nenhuma tabela que você esteja usando com INSERT
DELAYED
. Isto é porque este é o caso que o
INSERT
é feito por uma thread separada.
Normalmente, você não tem que travar tabelas, já que todas as
instruções UPDATE
são atomicas; nenhuma
outra thread pode interferir com qualquer outra executando uma
instrução SQL. Existem poucos casos em que você gostaria de
travar as tabelas de qualquer forma:
Se você for executar operações em um grupo de tabelas, é
muito mais rápido travar as tabelas que você for utilizar.
O lado ruim é que nenhuma outra thread pode atualizar uma
tabela travada para leitura (READ
)
(incluindo aquela que guarda o lock) e nenhuma outra thread
pode ler uma tabela bloqueada para escrita
(WRITE
) além daquele que guarda o lock.
A razão de algumas coisas serem rápidas sob LOCK
TABLES
é que o MySQL não irá descarregar a
cache de tabelas bloqueadas até que UNLOCK
TABLES
seja chamado (normalmente a cache de chaves
é descarregada a cada instrução SQL). Isto aumenta a
velocidade de inserção, atualização e deleção) em
tabelas MyISAM
.
Se você estiver usando um mecanismo de armazenamento no
MySQL que não suporte transações, você deve usar
LOCK TABLES
se você quiser se assegurar
que nenhuma outra thread venha entre um
SELECT
e um UPDATE
. O
exemplo mostrado aqui exige LOCK TABLES
para ser executado com segurança:
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_statement
->WHERE customer_id=some_id;
mysql>UNLOCK TABLES;
Sem LOCK TABLES
, existe uma chance que
outra thread possa inserir uma nova linha na tabela
trans
entre a execução das instruções
SELECT
e UPDATE
.
Utilizando atualizações incrementais (UPDATE customer
SET value=value+new_value
) ou a função
LAST_INSERT_ID()
i, você pode evitar o uso de
LOCK TABLES
em muitos casos.
Você também pode resolver alguns casos usando as funções de
bloqueio a nível de usuário GET_LOCK()
e
RELEASE_LOCK()
. Estas travas são salvas em
uma tabela hash no servidor e implementado com
pthread_mutex_lock()
e
pthread_mutex_unlock()
para alta velocidade.
See Secção 6.3.6.2, “Funções Diversas”.
Veja Secção 5.3.1, “Como o MySQL Trava as Tabelas”, para mais informações sobre política de bloqueios.
Você pode trocar todas as tabelas em todos os banco de dados
com trava de leitura com o comando FLUSH TABLES WITH
READ LOCK
. See Secção 4.6.4, “Sintaxe de FLUSH
”. Este é um
modo muito conveiente de tirar backups se você tiver um sistema
de arquivos, como Veritas, que pode tirar snapshots.
NOTE: LOCK
TABLES
mão é seguro com transações e fará um
commit implicitamente em qualquer transação ativa antes de
tentar travar as tabelas.
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.