:: DEVELOPER ZONE
O código de bloqueio de tabelas no MySQL é livre de deadlock.
O MySQL utiliza bloqueio de tabelas (no lugar de bloqueio de registros ou
colnas) em todos os tipos de tabelas, exceto tabelas BDB, para obter
uma alta velocidade nos bloqueios. Para grandes tabelas, bloqueio de tabelas
é MUITO melhor que bloqueio de registros para a maioria das aplicações, mas
existem, é claro, algumas desvantagens.
Para tabelas BDB e InnoDB, O MySQL só utiliza bloqueio
de tabelas se você bloquear explicitamente a tabela com LOCK TABLES
ou executar um comando quer irá modificar todos os registros na tabela, como
ALTER TABLE. Para estes tipos de tabelas nós recomendamos a você não
utilizar LOCK TABLES.
No MySQL versão 3.23.7 ou superior , você pode inserir registros em tabelas
MyISAM ao mesmo tempo que outras threads estão lendo da mesma tabela.
Perceba que atualmente isto funciona somente se não existirem buracos depois
de registros apagados na tabela no momento que a inserção é feita. Quando
todos os buracos forem preenchidos com novos dados, inserções concorrentes
irão automaticamente ser habilitadas novamente.
O bloqueio de tabelas habilita várias threads para lerem de uma tabela ao mesmo tempo, mas se uma thread desejar escrever a uma tabela, ela primeiramente deve obter acesso exclusivo. Durante a atualização, todas outras threads que desejarem acessar esta tabela em particular irão esperar até que a atualização acabe.
Como atualizações em tabelas normalmente são consideradas mais importantes
que SELECT, todas as instruções que atualizam uma tabela tem maior
prioridade que instruções que simplesmente recuperam informações. Isto deve
garantir que atualizações não fiquem na fila por terem sido passadas
várias consultas pesadas em uma tabela específica. (Você pode alterar
isto utilizando LOW_PRIORITY com a instrução que faz a atualização ou
HIGH_PRIORITY com a instrução SELECT.)
A partir do MySQL versão 3.23.7 pode-se utilizadar a variável
max_write_lock_count para forçar o MySQL a fornecer temporariamente a
todas as instruções SELECT, que esperam por uma tabela, uma prioridade
mais alta depois de um número específico de inserções em uma tabela.
O bloqueio de tabela não é, no entanto, muito bom sobre os seguintes cenários:
Um cliente emite uma SELECT que exige muito tempo para ser executada.
Outro cliente então executa um UPDATE na tabela usada. Este cliente terá que
esperar até que a SELECT seja terminada.
Outro cliente executa outra instrução SELECT na mesma tabela. Como
UPDATE tem maior prioridade que SELECT, esta SELECT
irá esperar pelo término da UPDATE. Ela também irá esperar pelo término
da primeira SELECT!
Uma thread está esperando por algo do tipo disco cheio, caso em que todas
as threads que desejam acessar a tabela com problema irão ser colocadas em estado
de espera até que mais espaço em disco seja disponível.
Algumas soluções possíveis para este problema são:
Tente deixar suas instruções SELECT sempre rápidas. Você pode ter que
criar algumas tabelas de resumo para fazer isto.
Inicie o mysqld com --low-priority-updates. Isto irá fornecer
a todas instruções que atualizam (modificam) uma tabela prioridade menor que
uma instrução SELECT. Neste caso a última instrução SELECT no
cenário anterior deveria executar antes da instrução INSERT.
Você pode fornecer a uma instrução INSERT, UPDATE ou DELETE
específica menor prioridade com o atributo LOW_PRIORITY.
Inicie o mysqld com um valor baixo para max_write_lock_count para
fornecer bloqueios de LEITURA depois de um certo número de bloqueios de
ESCRITA.
Você pode especificar que todas as atualizações de uma thread específica deve
ser feita utilizando prioridade baixa com o comando SQL:
SET SQL_LOW_PRIORITY_UPDATES=1. See Secção 5.5.6, “Sintaxe de SET”.
Você pode especificar que uma SELECT específica é muito importante com
o atributo HIGH_PRIORITY. See Secção 6.4.1, “Sintaxe SELECT”.
Se você tiver problemas com INSERT combinado com SELECT,
utilize as novas tabelas MyISAM, pois elas suportam SELECTs e
INSERTs concorrentes.
Se você utiliza principalmente instruções INSERT e SELECT
misturadas, o atributo DELAYED no INSERT provavelmente irá
resolver seus problemas. See Secção 6.4.3, “Sintaxe INSERT”.
Se você tiver problemas com SELECT e DELETE, a opção LIMIT
para DELETE pode ajudar. See Secção 6.4.5, “Sintaxe DELETE”.
© 1995-2005 MySQL AB. All rights reserved.
