Índice
Este apêndice lhe ajudará a portar o MySQL para outros sistemas operacionais. Primeiro verifique a lista de sistemas operacionais atualemente suportados. See Secção 2.2.3, “Sistemas Operacionais suportados pelo MySQL”. Se você criou uma nova portabilidade do MySQL, por favor, deixe nos conhecê-la para que possamos lista-la aqui e em nosso site web. (http://www.mysql.com/), recomendando-a a outros usuários.
Nota: se voce criou uma nova portabilidade para o MySQL, você está
livre para distribuí-la sob a licença GPL
, mas
isto não te dá os direitos autorais do MySQL.
Uma biblioteca thread Posix funcionando é necessária para o
servidor. No Solaris 2.5 nós usamos Pthreads da Sun (o suporte da
thread nativa na versão 2.4 e anterior não está boa o
suficiente), no Linux usamos LinuxThreads criada por Xavier Leroy,
<Xavier.Leroy@inria.fr>
.
A parte difícil de portar para uma nova variante Unix sem um bom
suporte a thread nativa é, provavelmente, portar par MIT-pthreads.
Veja mit-pthreads/README
e Programando em
Thhredas POSIX
(http://www.humanfactor.com/pthreads/).
Até o MySQL 4.0.2, a distribuição do MySQL incluiu uma versão ``remendada'' do Pthreads de Chris Provenzano do MIT (veja o site de MIT Pthreads em http://www.mit.edu/afs/sipb/project/pthreads/ e uma introdução a programação em http://www.mit.edu:8001/people/proven/IAP_2000/). Eles podem ser usadas por alguns sistemas operacionais que não têm threads POSIX. See Secção 2.3.6, “Notas MIT-pthreads”.
Também é possível usar outro pacote de threads no nível do usuário chamado FSU Pthreads (veja http://moss.csc.ncsu.edu/~mueller/pthreads/). Esta implementação está usada para portar para o SCO.
Veja os programas thr_lock.c
e
thr_alarm.c
no diretório
mysys
para alguns testes/exemplos destes
problemas.
Tanto o servidor quanto o cliente precisam de um compilador C++
funcionanado. Nós usamos gcc
em muitas
plataormas. Outros compiladores que sabemos que funciona são o
SPARCworksm Sun Forte, Irix cc
, HP-UX
aCC
, IBM AIX xlC_r
), Intel
ecc
e Compaq cxx
).
Para compilar apenas o cliente use ./configure
--without-server
.
Atualmente não hé nenhum suporte para compilação só do servidor, nem está em pauta a sua adição a menos que alguém tenha uma boa razão para isto.
Se você quiser/precisar de alterar qualquer
Makefile
ou o script do configure você também
precisará do GNU Automake e Autoconf. See
Secção 2.3.4, “Instalando pela árvore de fontes do desenvolvimento”.
Todos os passos necessários para refazer tudo desde os arquivos mais básicos.
/bin/rm */.deps/*.P /bin/rm -f config.cache aclocal autoheader aclocal automake autoconf ./configure --with-debug=full --prefix='your installation directory' # O makefile gerado acima precsa do GNU make 3.75 ou mais novo. # (chamado gmake abaixo) gmake clean all install init-db
Se você encontrar problemas com uma nova portabilidade, você ter que fazer alguma depuração do MySQL! See Secção E.1, “Depurando um Servidor MySQL”.
Nota: antes de iniciar a
depuração do mysqld
, obtenha primeiro os
programas de teste mysys/thr_alarm
e
mysys/thr_lock
para funcionar. Isto asegurará
que sus instalação da thread tem pelo menos uma chance remota de
funcionar.
Se você estiver usando uma funcionalidade que é muito nova no
MySQL, você pode tentar executar o mysqld
com
--skip-new
(que desabilitará todas novas
funcionalidades com pontecialidade de ero) ou com
--safe-mode
que desabilita várias otimizações
que podem criar problemas. See Secção A.4.1, “O Que Fazer Se o MySQL Continua Falhando”.
Se o mysqld
não quiser iniciar, você deve
verificar se você não tem qualquer arquivo
my.cnf
que interfere com sua configuração.
Você pode verificar seus argumento do my.cnf
com mysqld --print-defaults
e evitar usá-los
iniciando com mysqld --no-defaults ...
.
Se o mysqld
começa a consumir CPU ou memória
ou se ele ficar lento, você pode usar o mysqladmin
processlist status
para achar alguém que esteja
executando uma consulta que demore algum tempo. POde ser uma boa
idéia executar mysqladmin -i10 processlist
status
em alguma janela se você estiver tendo problemas
de desempenho ou problemas com novos clientes que não podem
conectar.
O comando mysqladmin debug
irá trazer alguma
informação sobre as em uso, memória usada e uso das consultas
no arquivo de log do mysql. Isto pode ajudar a resolver problemas.
Este comando também fornece informações úteis mesmo se você
não tiver compilado MySQL para depuração!
Se o problema é que algumas tabelas estão ficando maior e mais
lentas você deve tentar otimizar a tabela com OPTIMIZE
TABLE
ou myisamchk
. See
Capítulo 4, Administração do Bancos de Dados MySQL. Você também
deve tentar verificar as consultas lentas com
EXPLAIN
.
Você também deve ler a seção específica do SO neste manual para saber sobre problemas que podem ser únicos em seu ambiente. See Secção 2.6, “Notas específicas para os Sistemas Operacionais”.
Se você tiver um problema específico, você sempre pode tentar
depurar o MySQL. Para fazer isto você deve configurar o MySQL
com a opção --with-debug
ou
--with-debug=full
. Você pode verificar se o
MySQL foi compilado com depuração executando: mysqld
--help
. Se o parâmetro --debug
estiver listado entre as opções então você têm a
depuração habilitada. mysqladmin ver
também lista a versão do mysqld
como
mysql ... --debug
neste caso.
se você estiver usando gcc ou egcs, a configuração recomendada é:
CC=gcc CFLAGS="-O2" CXX=gcc CXXFLAGS="-O2 -felide-constructors \ -fno-exceptions -fno-rtti" ./configure --prefix=/usr/local/mysql \ --with-debug --with-extra-charsets=complex
Isto evitará problemas com a biblioteca
libstdc++
e com exceções C++ (muitos
compiladores têm problemas com exceções C++ no código da
thread) e compila uma versão MySQL com suporte para todos os
conjuntos caracter.
Se você suspeita de um erro despejo de memória, você pode
configurar o o MySQL com --with-debug=full
, que
irá instalar verificar de alocação de memória
(SAFEMALLOC
). No entanto, a execução com
SAFEMALLOC
é um pouco lenta, assim se você
tiver problemas de desempenho você deve iniciar o
mysqld
com a opção
--skip-safemalloc
. Isto disabilitará a
verificação de despejo de momória para cada chamada a
malloc()
e free()
.
Se o mysqld
parar de falhar quando você
compilar com --with-debug
, você provavelmente
encontrou um erro de compilação ou erro de tempo dentro do
MySQL. Neste caso você pode tentar adicionar
-g
às variáveis CFLAGS
e
CXXFLAGS
acima e não usar
--with-debug
. Se agora o
mysqld
morre, você pode pelo menos
executá-lo com gdb
ou usar o
gdb
no arquivo core para descobrir que
aconteceu.
Quando você configura o MySQL para depuração você habilita
automaticamente diversas funções de vericação de segurança
extra que monitora a saúde do mysqld
. Se
eles encontrarem algo ``inesperado'', uma entrada será encrita
no stderr
, que mysqld_safe
direciona para o log de erros! Isto também significa que se
você estiver tendo alguns problemas inexperados com o MySQL e
estiver usando uma distribuição fonte, a primeira coisa que
você deve fazer é configurar o MySQL para depuração! (A
segunda coisa é enviar uma mensagem para a lista de email do
MySQL e pedir ajuda. See Secção 1.7.1.1, “As Listas de Discussão do MySQL”. Por
favor, use o script mysqlbug
para todos os
relatos de bug e questões referentes a versão do MySQL que
você está usando!
Na distribuição do MySQL para Windows,
mysqld.exe
é, por padrão, compilado com
suporte a arquivos trace.
Se o servidor mysqld
não inicia ou se você
pode fazer o servidor mysqld
falhar
rapidamente, você pode tentar criar um arquivo trace para
encontrar o problema.
Para fazer isto você tem que ter um mysqld
compilado para depuração. Você pode verificar isto executando
mysqld -V
. Se o número da versão finaliza
com -debug
, ele está compilado com suporte a
arquivos trace.
Inicie o servidor mysqld
com um log trace em
/tmp/mysqld.trace
(ou
C:\mysqld.trace
no Windows):
mysqld --debug
No Windows você também deve usar o parâmetro
--standalone
para não iniciar o
mysqld
como um serviço:
Em uma janela de console faça:
mysqld --debug --standalone
Depois disso você pode usar a ferramenta de linha de comando
mysql.exe
em uma segunda janela de console
para reproduzir o problema. Você pode finalizar o servidor
mysqld
acima com mysqladmin
shutdown
.
Note que o arquivo trace será muito grande! Se você quiser ter um arquivo trace menor, você pode usar algo como:
mysqld
--debug=d,info,error,query,general,where:O,/tmp/mysqld.trace
que apenas exibe informações com a maioria das tags
interrassants em /tmp/mysqld.trace
.
Se você fizer um relatório de bug sobre isto, por favor só envie as linhas do trace para a lista de email apropriada quando algo parecee estar errado! Se você não puder localizar o local errado, você pode fazer um ftp do arquivo trace, junto com um relatório de bug completo, para ftp://support.mysql.com/pub/mysql/secret/ para que assim um desenvolvedor do MySQL possa dar uma olhada nele.
O arquivo trace é feito com o pacote DBUG de Fred Fish. See Secção E.3, “O Pacote DBUG”.
Na maioria dos sistemas você também pode iniciar o
mysqld
a partir do gdb
para obter mais informações se o mysqld
falhar.
Com uma versão antiga do gdb
no Linux você
deve usar run --one-thread
se você quiser
estar apto a depurar a thread mysqld
. Neste
caso você só pode ter uma thread ativa por vez. Nós
recomendamos que você atualize para gdb 5.1 ASAP já que a
depuração da thread funciona muito melhor com esta versão!
Ao executar o mysqld
com gdb, você deve
disabilitar a pilha de rastreamento com
--skip-stack-trace
para estar apto a conseguir
segmentation fault com gdb.
É muito difícil depurar o MySQL no gdb
se
você fizer muitas conexões o tempo todo já que
gdb
não libera a memória para threads
antigas. Você pode evitar este problema iniciando
mysqld
com -O thread_cache_size=
'max_connections +1'
. Na maioria dos casos só o uso
de -O thread_cache_size=5'
já ajuda muito!
Se você quiser um tiver um core dump no Linux quando o
mysqld
morre com um sinal SIGSEGV, você pode
iniciar o mysqld
com a opção
--core-file
. Este arquivo core pode ser usado
para fazer um rastreamento que pode lhe ajudar a descobrir
porque o mysqld
morreu:
shell> gdb mysqld core
gdb> backtrace full
gdb> exit
See Secção A.4.1, “O Que Fazer Se o MySQL Continua Falhando”.
Se você estiver usando gdb 4.17.x ou acima no Linux, você deve
instalar um arquivo .gdb
, com a seguinte
informação, em seu diretório atual:
set print sevenbit off handle SIGUSR1 nostop noprint handle SIGUSR2 nostop noprint handle SIGWAITING nostop noprint handle SIGLWP nostop noprint handle SIGPIPE nostop handle SIGALRM nostop handle SIGHUP nostop handle SIGTERM nostop noprint
Se você tiver problemas depurando threads com gdb, você deve fazer o download do gdb 5.x e experimentá-lo. A nova versão do gdb tem um tratamento de threads bem melhorado.
Aqui está um exemplo de como depurar o mysqld:
shell> gdb /usr/local/libexec/mysqld
gdb> run
...
backtrace full # Faça isto quando o mysqld falhar
Inclua a saída acima e uma email gerado com
mysqlbug
e envie-o para lista de email do
MySQL. See Secção 1.7.1.1, “As Listas de Discussão do MySQL”.
Se o mysqld
travar você pode usar algumas
ferramentas de sistema como strace
ou
/usr/proc/bin/pstack
para exeminar onde
mysqld
travou.
strace /tmp/log libexec/mysqld
Se você estiver usando a interface Perl DBI
,
você pode habilitar a informação de depuação usando o
método trace
ou definindo a variável de
ambiente DBI_TRACE
. See
Secção 12.5.2, “A interface DBI
”.
Em alguns sistemas operacionais, o log de erro irá conter um
stack trace se mysqld
finalizar
inesperadmente. Você pode usá-lo para descobrir onde (e talvez
por que) o mysqld
finalizou. See
Secção 4.10.1, “O Log de Erros”. Para obter um stack trace, você
não deve compilar o mysqld
com a opção
-fomit-frame-pointer
para gcc. See
Secção E.1.1, “Compilando o MYSQL para Depuração”.
Se o arquivo de erro conter algo como o seguinte:
mysqld got signal 11; The manual section 'Debugging a MySQL server' tells you how to use a stack trace and/or the core file to produce a readable backtrace that may help in finding out why mysqld died Attemping backtrace. You can use the following information to find out where mysqld died. If you see no messages after this, something went terribly wrong stack range sanity check, ok, backtrace follows 0x40077552 0x81281a0 0x8128f47 0x8127be0 0x8127995 0x8104947 0x80ff28f 0x810131b 0x80ee4bc 0x80c3c91 0x80c6b43 0x80c1fd9 0x80c1686
você pode descobrir onde o mysqld
finalizou
fazendo o seguinte:
Copie os números acima em um arquivo, por exemplo
mysqld.stack
.
Faça um arquivo de símbolos para o servidor
mysqld
:
nm -n libexec/mysqld > /tmp/mysqld.sym
Note que a maioria das distribuições binárias do MySQL
(exceto para o pacotes de "depuração" onde as
informações são incluídas dentro dos binários) já
possuem o arquivo acima, chamado
mysqld.sym.gz
. Neste caso você pode
simplesmente desempacotá-lo fazendo:
gunzip < bin/mysqld.sym.gz > /tmp/mysqld.sym
Execute resolve_stack_dump -s /tmp/mysqld.sym -n
mysqld.stack
.
Isto exibirá a onde o mysqld
finalizou.
Se isto não lhe ajuda a descobrir o porque o
mysqld
morreu, você deve fazer um relato
de erro e incluir a saída do comando acima no relatório.
Note no entanto que na maioria dos casos, termos apenas um
stack trace, não nos ajudará a encontrar a razão do
problema. Para estarmos apto a localizar o erro ou fornecer
um modo de contorná-lo, precisariamos, na maioria dos
casos, conhecer a consulta que matou o
mysqld
e de preferência um caso de teste
para que possamos repetir o problema! See
Secção 1.7.1.3, “Como relatar erros ou problemas”.
Note que antes de iniciarmos o mysqld
com
--log
você deve verificar todas as suas
tabelas com myisamchk
. See
Capítulo 4, Administração do Bancos de Dados MySQL.
Se o mysqld
morre ou trava, você deve
iniciar o mysqld
com --log
.
Quando o mysqld
morre de novo, você pode
examinar o fim do arquivo de log para a consulta que matou o
mysqld
.
Se você estiver usando --log
sem um nome de
arquivo, o log é armazenado no diretório do banco de dados
como 'nomemaquina'.log. Na maioria dos casos é a última
consulta no arquivo de log que matou mysqld
,
mas se possível você deve verificar isto reiniciando o
mysqld
e executando a consulta encontrada por
meio da ferramenta de linha de comando mysql
.
Se isto funcionar, você também deve testar todas as consultas
complicadas que não completaram.
Você também pode tentar o comando EXPLAIN
em todas as instruções SELECT
que levam
muito tempo para assegurar que o mysqld
está
usando índices apropriados. See Secção 5.2.1, “Sintaxe de EXPLAIN
(Obter informações sobre uma SELECT
)”.
Você pode encontrar as consultas que levam muito twempo para
executar iniciando o mysqld
com
--log-slow-queries
. See
Secção 4.10.5, “O Log para Consultas Lentas”.
Se você encontrar o texto mysqld restarted
no arquivo de registro de erro (normalmente chamado
hostname.err
) você provavelmente encontrou
uma consulta que provocou a falha no mysqld
.
Se isto acontecer você deve verificar todas as suas tabelas com
myisamchk
(see
Capítulo 4, Administração do Bancos de Dados MySQL) e testar a
consulta no arquivo de log do MySQL para ver se ela não
funcionou. Se você encontrar tal consulta, tente primeiro
atualizar para uma versão mais nova do MySQL. Se isto não
ajudar e você não puder encontrar nada no arquivo de mensagem
mysql
, você deve relatar o erro para uma
lista de email do MySQL. As listas de email estão descritas em
http://lists.mysql.com/,
que também possui os links para as listas de arquivos online.
Se você iniciou o mysqld
com
myisam-recover
, o MySQL verificará
automaticamente e tentará reparar as tabelas
MyISAM
se elas estiverem marcadas como 'não
fechadas apropriadamente' ou 'com falha'. Se isto acontecer, o
MySQL irá escrever uma entrada 'Warning: Checking
table ...'
no arquivo
nomemaquina.err
, a qual é seguida por
Warning: Repairing table
se a tabela precisar
ser reparada. Se você obter vários desses erros, sem que o
mysqld
finalize inesperadamente um pouco
antes, então algo está errado e precisa ser investigado
melhor. See Secção 4.1.1, “Opções de Linha de Comando do mysqld
”.
É claro que não é um bom sinal se o mysqld
morreu inesperadamente, mas neste caso não se deve invwestigar
as mensagens Checking table...
e sim tentar
descobrir por que o mysqld
morreu.
Se você têm tabelas corrompidas ou se o
mysqld
sempre falha depois de alguns comendos
de atualização, você pode testar se este erro é
reproduzível fazendo o seguinte:
Desligue o daemon MySQL (com mysqladmin
shutdown
).
Faça um backup das tabelas (para o caso da reparação fazer algo errado)
Verifique todas as tabelas com myisamchk -s
database/*.MYI
. Repare qualquer tabela errada com
myisamchk -r database/table.MYI
.
Faça um segundo backup das tabelas.
Remove (ou mova para outro local) qualquer arquivo de log antigo do diretório de dados se você precisar de mais espaço.
Inicie o mysqld
com
--log-bin
. See
Secção 4.10.4, “O Log Binário”. Se você quiser encontrar uma
consulta que provoque uma falha no
mysqld
, você deve usar --log
--log-bin
.
Quando você obter uma tabela danificada, pare o
servidor mysql
.
Restaure o backup.
Reinicie o servidor mysqld
sem
--log-bin
Re-execute os comandos com mysqlbinlog
update-log-file | mysql
. O log de atualização
está salvo no diretório do banco de dados com o nome
nomemaquina-bin.#
.
Se as tabelas forem corrompidas novamente ou você puder
fazer o mysqld
finalizar com o comando
acima, vcê terá encontrado um erro reproduzível que deve
ser facilmente corrigido! Envie as tabelas e o log binário
por ftp para
ftp://support.mysql.com/pub/mysql/secret/
e coloque-o em nosso sistema de erros em
http://bugs.mysql.com/.
Se você é um consumidor com suporte, você também pode
enviar um email para <support@mysql.com>
para
alertar a equipe do MySQL sobre o problema e tê-lo
corrígido o mais rápido possível..
Você também pode usar o script
mysql_find_rows
para executar algumas das
instruções de atualização se você quiser estreitar o
problema.
Para estar apto a depurar um cliente MySQL com o pacote de
depuração integradom você deve configurar o MySQL com
--with-debug
ou
--with-debug=full
. See
Secção 2.3.3, “Opções típicas do configure
”.
Antes de executar um cliente, você deve configurar a variável de
ambiente MYSQL_DEBUG
:
shell>MYSQL_DEBUG=d:t:O,/tmp/client.trace
shell>export MYSQL_DEBUG
Isto faz com que os clientes gerem um arquivo trace em
/tmp/client.trace
.
Se você tiver problemas com seu próprio código cliente, você
deve tentar se conectar ao servidor e executar a sua consulta
usando um cliente que esteja funcionando. Faça isto executando o
mysql
no modo de depuração (assumindo que
você tenha compilado o MySQL com esta opção).
shell> mysql --debug=d:t:O,/tmp/client.trace
Isto irá fornecer informação útil no caso de você enviar um relatório de erro. See Secção 1.7.1.3, “Como relatar erros ou problemas”.
Se o seu cliente falhar em algum código aparentemente 'legal',
você deve verificar se o seu arquivo mysql.h
incluído corresponde com o seu arquivo da biblioteca mysql. Um
erro muito comum é usar um arquivo mysql.h
antigo de uma instalação MySQL antiga com uma nova biblioteca
MySQL.
O servidor MySQL e a maioria dos clientes MySQL são compilados com o pacote DBUG originalmente criado por Fred Fish. Quando se configura o MySQL para depuração, este pacote torna possível obter um arquivo trace sobre o que o programa está depurando. See Secção E.1.2, “Criando Arquivos Trace (Rastreamento)”.
Utiliza-se o pacote de depuração chamando o programa com a
opção --debug="..."
ou
-#...
.
A maioria dos programas MySQL tem uma string de depuração
padrão que será usada se você não especificar uma opção para
--debug
. O arquivo trace padrão é normalmente
/tmp/programname.trace
no Unix e
\programname.trace
no Windows.
A string de controle de depuração é uma sequência de campos separados por dois pontos como a seguir:
<field_1>:<field_2>:...:<field_N>
Cada campo consiste de um carcater de parâmetro obrigatório seguido por uma "," e lista de modificadores separdas por vírgula opcionais:
flag[,modifier,modifier,...,modifier]
Os carcteres de parâmetros atualmente reconhecidos são:
Parâmetro | Descrição |
d | Habilita a saída de macros DBUG_<N> para o estado atual. Pode ser seguido por uma lista de palavras chaves que selecionam a saída apenas para as macros DBUG com aquela palavra chave. Uma lista de palavras chaves vazia indica a saída para todas as macros. |
D | Atraso depois de cada linha de saída do depurados. O argumento é o
número de décimos de segundo do atraso, sujeito às
capacidades da máquina. Por exemplo,
-#D,20 atrasa em dois segundos |
f | Limita a depuração e/ou rastreamento, e perfilemento da lista de funções listadas. Note que uma lista nula disabilitará todas as funções. O parâmetro "d" ou "t" apropriado ainda deve ser dado, este parâmetro só limita as suas açõesse eles estiverem habilitados. |
F | Identifica o nome do arquivo fonte para cada linha de saída da depuração ou rastreamento. |
i | Identifica o processo com o PID ou a ID da thread para cada linha de saída da depuração ou rastreamento. |
g | Habilita a modelagem. Cria um arquivo chamado 'dbugmon.out' contendo informações que poder ser usadas para moldar o programa. Pode ser seguida por uma lista de palavras chaves que selecionam a modelagem apenas para as funções naquela lista. Uma lista nula indica que todas as funções serão consideradas. |
L | Identifica o número da linha do arquivo fonte para cada linha de saída da depuração ou rastreamento. |
n | Exibe a profundidade de aninhamento da função atual para cada linha de saída da depuração ou rastreamento. |
N | Número de cada linha de saída do dbug. |
o | Redireciona o fluxo de saída do depurador para um arquivo específico. A saída padrão é stderr. |
O | Igual a o , mas o arquivo é realmente descarregado
entre cada escrita. Quando necessário o arquivo é
fechado e reaberto entre cada escrita. |
p | Limita as ações do depurador para um processo específico. Um processo deve ser indentificado com a macro DBUG_PROCESS e corresponder a um dos itens especificados na lista de ações do depurador que devem ocorrer. |
P | Exibe o nome do processo atual para cada linha de saída da depuração ou rastreamento. |
r | Quando recebe um novo estado, não herda o nível de aninhamento da função do estado anterior. Útil quando a saída é iniciada na margem esquerda. |
S | Executa a função _sanity(_file_,_line_) a cada função depurada até que _sanity() retorne algo diferente de 0. (Geralmente usada com safemalloc para encontrar falhas de memória). |
t | Habilita a linhas do trace de chamada/saída de funções. Pode ser seguido por uma lista (contendo apenas um modificador) dando um o nível numérico máximo de rastreamento, além do que nenhuma saída será exibida, tanto para a depuração quanto para macros trace. O padrão é uma opção de tempo de compilação. |
Alguns exemplos de strings de controle do depurador que podem aparecer em uma linha de comando do shell (o "-#" é normalmente usado para introduzir uma string de controle a um aplicativo) são:
-#d:t -#d:f,main,subr1:F:L:t,20 -#d,input,output,files:n -#d:t:i:O,\\mysqld.trace
No MySQL, tags comuns de serem usadas (com a opção
d
) são:
enter
,exit
,error
,warning
,info
e loop
.
Atualmente o MySQL só suporta bloqueios de tabela para tipos
ISAM
/MyISAM
e
HEAP
, bloqueios a nível de página para
tabelas BDB
e bloqueio a nivel de registros
para tabelas InnoDB
. See
Secção 5.3.1, “Como o MySQL Trava as Tabelas”. Com tabelas
MyISAM
pode se misturar livremente
INSERT
e SELECT
sem travas,
se as instruções INSERT
s não são
confiltantes. (ex.: se eles são inseridos no fim da tabela em vez
de preencherem espaços liberados por dados/linhas deletados).
A partir da versão 3.23.33, você pode analisar a contenção do
bloqueio de tabela no seu sistema verificando as variáveis de
ambiente Table_locks_waited
e
Table_locks_immediate
.
Para decidir se você quer usar um tipo de tabela com bloqueio a nível de registro, você deverá olhar o que o aplicativo faz e o qual é o padrão de seleção/atualização dos dados.
Pontos a favor do bloqueios de registros:
Poucos conflitos de bloqueios ao acessar registros diferentes em muitas threads.
Poucas alterações para rollback.
Torna possível bloquear um único registro por um longo tempo.
Contras:
Gasta mais memória que bloqueios a nível de página ou tabela.
É mais lento que bloqueios a nível de página ou tabela quando usado em uma grande parte da tabela, pois deve-se fazer muito mais travamentos.
É difinitivamente muito pior que outras travas se você
frequentemente utiliza GROUP BY
em uma
grande parte dos dados ou é feita uma varredura de toda a
tabela.
Com nível de bloqueios mais altos pode-se também, com mais facilidade, suportar travas de diferentes tipos para sintonizar a aplicação já que a sobreposição de bloqueio é menos perceptível que para bloqueios a nível de registro.
Bloqueios de tabela são superiores a bloqueios a nível de página / registro nos seguintes casos:
Muitas leituras
Leituras e atualizações em chaves restritas; é onde atualiza ou deleta-se um registro que pode ser buscado com uma leitura de chave:
UPDATE nome_tbl SET coluna=valor WHERE unique_key# DELETE FROM nome_tbl WHERE unique_key=#
SELECT
combinado com
INSERT
(e muito poucas instruções
UPDATE
s e DELETE
s).
Muitas varreduras / GROUP BY
em toda a
tabela sem nenhuma escrita.
Outra opções além de bloqueios a nível de página / registro:
Versioning (como usamos no MySQL para inserções concorrentes) onde você pode ter um escrita e várias leituras ao mesmo tempo. Isto significa que o banco de dados/tabelas suporta diferentes viiews para os dados dependendo de quando se começa a acessá-lo. Outros nomes deste recurso são time travel, cóia na escrita ou cópia por demanda.
Cópia por demanda é em muitos casos muito melhor que bloqueio a nível de registro ou página; o piro caso, no entanto, usa muito mais memória que a usada em travamentos normais.
Em vez de se usar bloqueio de registro pode-se usar bloqueios no aplicativo (como get_lock/release_lock no MySQL). Isto só funciona em aplicaticos bem comportados.
Em muitos casos pode se fazer um palpite sobre qual tipo de bloqueio é melhor para a aplicação. mas geralmente é muito difícil dizer que um dado tipo de bloqueio é melhor que outro; tudo depende da aplicação e diferentes partes da aplicação podem exigir diferentes tipos de bloqueios.
Aqui estão algumas dicas sobre travamento no MySQL:
A maioria das aplicações web fazem diversos selects, muito poucas deleções, atualizaoes principalmente nas chaves e inserções em tabelas específicas. A configuração base do MySQL é bem sitonizada para esta finalidade.
Usuários concorrentes não são um problema se eles não misturam atualizações com seleções que precisam examinar muitas linhas na mesma tabela.
Se é misturado inserções e exclusões na mesma tabela então
INSERT DELAYED
pode ser de grande ajuda.
Pode se também usar LOCK TABLES
para aumentar
a velocidade (muitas atualizações com um travamento simples é
muito mais rápida que atualizações sem travamento). Separar as
coisas em tabelas diferentes também ajudará.
Se você tiver problemas de velocidade com travamento de tabelas
no MySQL, você pode estar apto a resolver isto convertendo alguma
de suas tabelas para tipos InnoDB
ou
BDB
. See Secção 7.5, “Tabelas InnoDB
”. See
Secção 7.6, “Tabelas BDB
ou BerkeleyDB
”.
A seção de otimização no manual cobre diversos aspectos de como sintonizar a sua aplicação. See Secção 5.2.13, “Mais Dicas sobre Otimizações”.
Tentamos usar os pacotes RTS thread com o MySQL mas nos deparamos com o seguinte problema:
Eles usam um versão antiga de diversas chamadas POSIX e é muito tedioso fazer ``wrappers'' para todas as funções. Estamos inclinados a pensar que seria mais fácil alterar a biblioteca de threads para a especificação POSIX mais nova.
Alguns ``wrappers'' já estão escritos. Veja
mysys/my_pthread.c
para maiores
informações.
Pelo menos o seguinte deve ser mudado:
pthread_get_specific
deve usar um argumento.
sigwait
deve usar dois argumentos. Diversas
funções (pelo menos pthread_cond_wait
,
pthread_cond_timedwait
) deve retornar o código
do erro. Agora eles retornam -1 e configuram
errno
.
Outro problema é que threads a nivel do usuario usam o sinal
ALRM
e isto aborta diversas das funções
(read
, write
,
open
...). O MySQL deve fazer uma nova tentativa
de interrupção em todos mas não é facil de se verifica isto.
O maior problema não solucionado é o seguinte:
Para conseguir alarmes de threads alteramos
mysys/thr_alarm.c
para esperar entre alarmes
com pthread_cond_timedwait()
, mas isto aborta
com o erro EINTR
. Tentamos depurar a biblioteca
thread para descobrirmos porque isto acontece, mas não podemos
encontrar nenhuma solução fácil.
Se alguém quiser experimentar o MySQL com RTS threads sugerimos o seguinte:
Altere as funções que o MySQL usa da biblioteca de threads para POSIX. Isto não deve levar tanto tempo.
Compile todas as bibliotecas com
-DHAVE_rts_threads
.
Compile thr_alarm
.
Se houver alguma pequena diferença na implementação, elas
devem ser corrigidas alterando
my_pthread.h
e
my_pthread.c
.
Execute thr_alarm
. Se ele executar sem
mensagens de ``aviso'', ``erro'' ou aborto, você está na
trilha certa. Aqui está uma execução bem sucedidad no
Solaris:
Main thread: 1 Thread 0 (5) started Thread: 5 Waiting process_alarm Thread 1 (6) started Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 1 (1) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 2 (2) sec Thread: 6 Simulation of no alarm needed Thread: 6 Slept for 0 (3) sec Thread: 6 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 4 (4) sec Thread: 6 Waiting process_alarm thread_alarm Thread: 5 Slept for 10 (10) sec Thread: 5 Waiting process_alarm process_alarm thread_alarm Thread: 6 Slept for 5 (5) sec Thread: 6 Waiting process_alarm process_alarm ... thread_alarm Thread: 5 Slept for 0 (1) sec end
MySQL é muito dependente do pacote de threads usado. Assim ao escolher uma boa plataforma para o MySQL, o pacote de threads é muito importante.
Existem pelo menos três tipos de pacotes de threads:
Threads de usuários em um processo único. A troca de threads é gerenciada com alarmes e a bilioteca thread gerencia todas as funções não segura as threads com travamento. Operações de leitura, excrita e operação são normalmente gerênciada com uma select específica da thread que troca para outra thread se a thread em execução tiver que esperar por dados. Se os pacotes de threads do usuário estão integrados com as bibliotecas padrão (threads FreeBSD e BSDI) o pacote da thread exige menos sobreposicao que pacotes de threads que têm que mapear todas as chamadas não seguras (MIT-pthreads, FSU Pthreads e RTS threads). Em alguns ambientes (SCO, por exemplo), todas as chamadas do sistema são seguras a threads e assim o mapeamento pode ser feito muito facilmente (FSU Pthreads em SCO). Desvantagem: Todas as chamadas mapeadas levam pouco tempo e é bem malicioso para tratar todas as situações. Também há, normalmente, algumas chamadas de sistema que não são tratados pelo pacote de thread (como MIT-threads e sockets). O agendamento de threads nem sempre é ótimo.
Threads de usuários em processos separados. A troca de threads é feita pelo kernel e todos os dados são compartilhados entre threads. O pacote de thread gerência as chamadas padrão de threads para permitir o compartilhamento de dadps entre threads. LinuxThreads é usado neste método. Desvantagem: Diversos processos. A criação de thrads é lenta. Se uma thread morrer as outras normalmente travarão e você você deverá matá-las antes de reiniciar. A troca de threads também tem um custo um pouco alto.
Threads de kernel. A troca de threads é feita pela biblioteca
de thread ou pelo kernele é muito rápida. Tudo é feito em
um processo, mas em alguns sistema, ps
pode
mostrar threads diferentes. Se uma thread abortar, todo o
processo é abortado. A maioria das chamadas do sistema são
seguras a threads e devem exigir muito pouca sobrecarga.
Solaris, HP-UX, AIX e OSF/1 têm threads de kernel.
Em alguns sistemas, threads do kernel são gerenciadas threads de usuário integrads em bibkliotecas de sistemas. Nestes casos a troca de thread pode ser feita pela biblioteca de threads e o kernel não têm real conhecimento da thread.
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.