Sintaxe LOCK TABLES
e 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 MariaDB 4.0.2 você precisa do privilégio global LOCK TABLES
e um privilégio SELECT
nas tabelas envolvidas No MariaDB 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 MariaDB 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 MariaDB 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
. Leia "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 MariaDB não irá descarregar a cache de tabelas bloqueadas até queUNLOCK 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 tabelasMyISAM
. - Se você estiver usando um mecanismo de armazenamento no MariaDB que não suporte transações, você deve usar
LOCK TABLES
se você quiser se assegurar que nenhuma outra thread venha entre umSELECT
e umUPDATE
. O exemplo mostrado aqui exigeLOCK 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 tabelatrans
entre a execução das instruçõesSELECT
eUPDATE
.
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. Leia "Funções Diversas".
Veja "Como o MariaDB 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
. Leia "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.