XOOPS Brasil

 

Apêndice E. Portando para Outros Sistemas

Este apêndice lhe ajudará a portar o MySQL para outros sistemas operacionais. Primeiro verifique a lista de sistemas operacionais atualemente suportados. Veja mais informações sobre isto na Seçã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, .

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. Veja mais informações sobre isto na Seçã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 Seçã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 Seçã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.

E.1. Depurando um Servidor MySQL

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. Veja mais informações sobre isto na Seçã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. Veja mais informações sobre isto na Seção 2.6, “Notas específicas para os Sistemas Operacionais”.

E.1.1. Compilando o MYSQL para Depuração

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. Veja mais informações sobre isto na Seçã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.

E.1.2. Criando Arquivos Trace (Rastreamento)

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. Veja mais informações sobre isto na Seção E.3, “O Pacote DBUG”.

E.1.3. Depurando o mysqld no gdb

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

Veja mais informações sobre isto na Seçã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. Veja mais informações sobre isto na Seçã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. Veja mais informações sobre isto na Seção 12.5.2, “A interface DBI.

E.1.4. Usando Stack Trace

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. Veja mais informações sobre isto na Seçã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. Veja mais informações sobre isto na Seçã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:

  1. Copie os números acima em um arquivo, por exemplo mysqld.stack.

  2. 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
    
  3. 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 Seção 1.7.1.3, “Como relatar erros ou problemas”.

E.1.5. Usando Arquivos de Log para Encontrar a Causa dos Erros no mysqld

Note que antes de iniciarmos o mysqld com --log você deve verificar todas as suas tabelas com myisamchk. Veja mais informações sobre isto na 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. Veja mais informações sobre isto na Seçã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. Veja mais informações sobre isto na Seçã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 (Veja mais informações sobre isto na 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. Veja mais informações sobre isto na Seçã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.

E.1.6. Fazendo um Caso de Teste Se Ocorre um Corrompimento de Tabela

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 Seçã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 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.

E.2. Depurando um cliente MySQL.

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 Seçã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. Veja mais informações sobre isto na Seçã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.

E.3. O Pacote DBUG

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 Seçã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âmetroDescrição
dHabilita 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.
DAtraso 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
fLimita 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.
FIdentifica o nome do arquivo fonte para cada linha de saída da depuração ou rastreamento.
iIdentifica o processo com o PID ou a ID da thread para cada linha de saída da depuração ou rastreamento.
gHabilita 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.
LIdentifica o número da linha do arquivo fonte para cada linha de saída da depuração ou rastreamento.
nExibe a profundidade de aninhamento da função atual para cada linha de saída da depuração ou rastreamento.
NNúmero de cada linha de saída do dbug.
oRedireciona o fluxo de saída do depurador para um arquivo específico. A saída padrão é stderr.
OIgual a o, mas o arquivo é realmente descarregado entre cada escrita. Quando necessário o arquivo é fechado e reaberto entre cada escrita.
pLimita 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.
PExibe o nome do processo atual para cada linha de saída da depuração ou rastreamento.
rQuando 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.
SExecuta 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).
tHabilita 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.

E.4. Métodos de Lock

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 Seçã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 INSERTs 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 UPDATEs e DELETEs).

  • 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. Veja mais informações sobre isto na Seção 7.5, “Tabelas InnoDB. See Seçã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. Veja mais informações sobre isto na Seção 5.2.13, “Mais Dicas sobre Otimizações”.

E.5. Comentários Sobre Threads RTS

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
    

E.6. Diferença en Entre Alguns Pacotes de Threads

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.