Manual MySQL PT
Manual MySQL PT
Table of Contents
Chapter 1: Informações gerais sobre o MySQL 1
Se você tem alguma sugestão relacionada a acréscimos ou correções neste manual, por favor,
envie-a para a equiope do manual em [email protected].
Este é o manual de referência; ele não fornece instruções gerais sobre SQL ou conceitos de
bancos de dados relacionais. Se você deseja informações gerais sobre SQL, veja hundefinedi
[General-SQL], page hundefinedi. Para livros que focam mais especificamente em MySQL,
veja hundefinedi [MySQL-Books], page hundefinedi.
A pronúncia oficial do MySQL é “Mai Ess Que Ell” (e não MAI-SEQUEL). Mas tentamos
não corrigir as pessoas que dizem MAI-SEQUEL.
• C, C++, Eiffel, Java, Perl, PHP, Python e Tcl APIs. See hundefinedi [Clients], page hun-
definedi.
• Funciona em diversas plataformas. See hundefinedi [Which OS], page hundefinedi.
• Aceita diversos tipos de campos: inteiros de 1, 2, 3, 4 e 8 bytes com e sem sinal, FLOAT,
DOUBLE, CHAR, VARCHAR, TEXT, BLOB, DATE, TIME, DATETIME, TIMESTAMP, YEAR, SET,
and ENUM types. See hundefinedi [Column types], page hundefinedi.
• Joins muito rápidas usando uma multi-join de leitura única otimizada.
• Completo suporte a operadores e funções nas partes SELECT e WHERE das consultas. Por
exemplo:
mysql> SELECT CONCAT(first_name, " ", last_name) FROM nome_tabela
WHERE income/dependents > 10000 AND age > 30;
• Funções SQL são implementadas através de uma biblioteca de classes altamente
otimizada e com o máximo de performance. Geralmente não há nenhuma alocação de
memória depois da inicialização da pesquisa.
• Suporte pleno às cláusulas SQL GROUP BY e ORDER BY. Suporte para funções de agru-
pamento (COUNT(), COUNT(DISTINCT ...), AVG(), STD(), SUM(), MAX() e MIN()).
• Suporte para LEFT OUTER JOIN e RIGHT OUTER JOIN e sintaxes ANSI, SQL e ODBC.
• Você pode misturar tabelas de bancos de dados diferentes na mesma pesquisa (como
na versão 3.22).
• Um sistema de privilégios e senhas que é muito flexível, seguro e que permite verificação
baseada em estações/máquinas. Senhas são seguras porque todo o tráfico de senhas é
criptografado quando você se conecta ao servidor.
• Suporte ao ODBC (Open-DataBase-Connectivity) para Win32 (com fonte aberto). To-
das funções ODBC 2.5 e muitas outras. Por exemplo, você pode usar o MS Access para
conectar ao seu servidor MySQL. See hundefinedi [ODBC], page hundefinedi
• Tabelas de disco baseadas em árvores-B extremamente rápidas com compressão de
índices.
• São permitidos até 32 índices por tabela. Cada índice pode ser composto de 1 a 16
colunas ou partes de colunas. O tamanho máximo do índice é de 500 bytes (isto pode
ser alterado na compilação do MySQL). Um índice pode usar o prefixo de campo com
um tipo CHAR ou VARCHAR.
• Registros de tamanhos fixos ou variáveis.
• Tabelas hash em memória que são usadas como tabelas temporárias.
• Lida com bancos de dados enormes. Nós estamos usando MySQL com alguns bancos
de dados que contém 50.000.000 registros e nós sabemos de usuários que usam MySQL
com 60.000 tabelas e aproximadamente 5.000.000.000 de linhas.
• Todas as colunas têm valores padrão. Você pode usar INSERT para inserir um sub-
conjunto de colunas de tabelas; aquelas colunas que não possuem valores fornecidos
explicitamente usam os seus valores padrões.
• Utiliza o GNU Automake, Autoconf, e Libtool para portabilidade.
• Escrito em C e C++. Testado com um amplo faixa de compiladores diferentes.
• Um sistema de alocação de memória muito rápido e baseado em processo(thread).
8 Referência técnica para o MySQL versão 3.23.52
• Não existem furos ou problemas de memória. O MySQL foi testado com o Purify, um
detector de problemas de memória comercial.
• Inclui o myisamchk, um utilitário muito rápido para checagem, otimização e reparo de
tabelas. Toda a funcionalidade do myisamchk está, também, disponível pela interface
SQL. See hundefinedi [MySQL Database Administration], page hundefinedi.
• Suporte total para vários conjuntos de caracteres, que incluem ISO-8859-1 (Latin1),
big5, ujis e mais. Por exemplo, os caracteres Escandinavos ‘å’, ‘ä’ e ‘ö’ são permitidos
em nomes de tabelas e colunas.
• Todos os dados são armazenados no conjunto de caracteres escolhido. Todas as com-
parações em colunas de sequenciascaso-insensitivo.
• A ordenação é feita de acordo com o conjunto de caracteres escolhido (o modo sueco
por padrão). É possível alterar isso quando o servidor MySQL é iniciado. Para ver um
exemplo de várias ordenações avançadas, procure pelo código de ordenação Tcheca.
O MySQL suporta diversos conjuntos de caracteres que podem ser especificados em
tempo de compilação e execução.
• Apelidos em tabelas e colunas são disponíveis como definidos no padrão SQL92.
• DELETE, INSERT, REPLACE, e UPDATE retornam o número de linhas que foram alteradas
(afetadas). É possível retornar o número de linhas com padrão coincidentes configu-
rando um parâmetro quando estiver conectando ao servidor.
• Nomes de funções não comflitam com nomes de tabelas ou colunas. Por exemplo, ABS
é um nome de campo válido. A única restrição é que para uma chamada de função,
espaços não são permitidos entre o nome da função e o ‘(’ que o segue. See hundefinedi
[Reserved words], page hundefinedi.
• Todos os programas MySQL podem ser chamados com as opções --help ou -? para
obter ajuda online.
• O servidor pode apresentar mensagem de erros aos clientes em várias línguas. See
hundefinedi [Languages], page hundefinedi.
• Os clientes podem se conectar ao servidor MySQL usando sockets(tomadas) TCP/IP,
sockets Unix, ou Named Pipes (NT).
• O comando específico do MySQL SHOW pode ser usado para devolver informações sobre
bancos de dados, tabelas e índices. O comando EXPLAIN pode ser usado para determinar
como o otimizador resolve a consulta.
Cada release do MySQL foi sendo usado, e ocorrem problemas somente quando usuários
começam a usar as “áreas cinzentas.” Naturalmente, usuários externos não sabem o que
são as áreas cinzentas; esta seção tenta indicar aquelas que são conhecidas atualmente. As
descrições lidam com a Versão 3.23 do MySQL. Todos os erros conhecidos e relatados são
reparados na última versão, com a exceção dos bugs listados na seção de erros, os quais são
relacionados ao desenho. See hundefinedi [Bugs], page hundefinedi
O MySQL é escrito em múltiplas camadas e diferentes módulos independentes. Estes
módulos estão listados abaixo com indicações de quão bem-testado foi cada um deles.
O handler de tabelas ISAM — Estável
Gerencia armazenamento e restauração de todos os dados no MySQL Versão
3.22 e anteriores. Em todas versões do MySQL, nunca foi relatado um só erro
neste código. A única forma conhecida de corromper uma tabela é matar o
servidor no meio de uma atualização. Mesmo isto não é suficiente para destruir
qualquer dados que não possam ser recuperados, porque todos os dados são
atualizados para o disco entre cada query. Não existe nenhum relato de erros
sobre perda de dados causados por bugs no MySQL.
O handler de tabelas MyISAM — Estável
Este é novo na versão do MySQL 3.23. É amplamente baseado nos códigos de
tabelas ISAM mas possui diversos recursos novos e uteis.
O parser e o analisador léxico — Estável
Não existem relatos de erros neste sistema hà muito tempo.
O código C cliente — Estável
Não existem problemas conhecidos. Em versões mais antigas que a 3.20, ex-
istiam algumas limitações no tamanho do buffer de envio/recebimento. Como
na versão 3.21, o tamanho do buffer agora é dinâmico podendo chegar a um
padrão de 16M.
Programas clientes padrões — Estável
Inclui mysql, mysqladmin, mysqlshow, mysqldump, e mysqlimport.
SQL Básico — Estável
O manipulador do sistema de funções, da classe string e da memoria dinamica
do SQL basico. Não existem relatos de erros neste sistema.
Otimizador de pesquisas — Estável
Otimizador do Range — Estável
Otimizador de Join — Estável
Locking — Gamma
Esse módulo é muito dependente do sistema. Em alguns sistemas existem certos
problemas por utilizar o locking padrão do SO (fcntl(). Em alguns casos, você
pode executar o daemon do MySQL com o parâmetro --skip-locking. São
conhecidos alguns problemas ocorridos em alguns sistemas Linux e no SunOS
quando utiliza-se sistemas de arquivos montados em NFS.
Threads Linux — Estável
O maior problema encontrado neste módulo foi com a chamada fcntl(), que
é corrigida usando a opção --skip-locking com o mysqld. Algumas pessoas
10 Referência técnica para o MySQL versão 3.23.52
relataram travamentos com a versão 0.5. Se você planeja usar mais de 1000
conexões simultâneas, o LinuxThreads deverá ser recompilado. Embora seja
possível rodar todas essas conexões com o LinuxThreads padrão (de qualquer
forma, você nunca poderá ir acima de 1021 conexões), o espaço de pilha padrão
de 2MB deixa a aplicação instável, e iremos reproduzir um coredump depois de
criar 1021 conexões. See hundefinedi [Linux], page hundefinedi
Solaris 2.5+ pthreads — Estável
Utilizamos isto para todo nosso trabalho de produção.
MIT-pthreads (Outros Sistemas) — Estável
Não há nenhum erro relatado desde da versão 3.20.15 e nenhum erro conhecido
desde a cersão 3.20.16. Em alguns sistemas, há um "mal funcionamento" onde
algumas operacoes são muito lentas (uma parada de 1/20 segudos e feita entre
cada consulta). É claro que MIT-pthreads pode deixar tudo um pouco lento,
mas as instruções SELECT baseada em indice geralmente são feitas uma de cada
vez, então elas não precisão ser travadas com “mutex locking” nas threads.
Outras implementações de threads — Beta -
A portabilidade para outros sistemas ainda é muito nova e podem existir erros,
possivelmente no MySQL, mas a maioria na própria implementação das threads.
LOAD DATA ..., INSERT ... SELECT — Estável
Algumas pessoas achavam que haviam encontrado bugs aqui, mas geralmente
são mal-entendidos com relação ao funcionamento desses módulos. Por favor
confira o manual antes de relatar problemas!
ALTER TABLE — Estável
Pequenas alterações na versão 3.22.12.
DBD — Estável
Atualmente mantido por Jochen Wiedmann ([email protected]).
Obrigado!
mysqlaccess — Estável
Escrito e mantido por Yves Carlier ([email protected]). Obrigado!
GRANT — Estável
Grandes alterações feitas no MySQL Versão 3.22.12.
MyODBC (Usa ODBC SDK 2.5) — Gamma
Parece funcionar bem com muitos programas.
Replicação – Beta / Gamma
Ainda estamos trabalhando na replicação, portanto não espere que isso irá ser
sólido como uma rocha ainda. Por outro lado, alguns usuários MySQL já estão
usando isto com ótimos resultados.
Tabelas BDB – Beta
O código de Bancos de dados Berkeley é muito estável, mas nós ainda estamos
melhorando a interface entre o MySQL e as tabelas BDB, portando ele irá levar
algum tempo até ser testado como os outros tipos de tabelas foram.
Chapter 1: Informações gerais sobre o MySQL 11
Se sua tabela grande será somente leitura, você poderá usar o myisampack para unir e
comprimir várias tabelas em uma. mysisampack normalmente comprime uma tabela em
pelo menos 50%, portanto você pode obter, com isso, tabelas muito maiores. See hundefinedi
[myisampack], page hundefinedi
Uma opção é ignorar o limite de tamanho de arquivos do sistema operacional para arquivos
de dados MyISAM usando a opção RAID. See hundefinedi [CREATE TABLE], page hunde-
finedi.
Outra solução pode ser a biblioteca MERGE incluída, que lhe permite acessar uma coleção
de tabelas idênticas como se fosse apenas uma. See hundefinedi [MERGE], page hundefinedi
mysql> CREATE TABLE y2k (date date, date_time datetime, time_stamp timestamp);
Query OK, 0 rows affected (0.00 sec)
Isto mostra que os tipos DATE e DATETIME não apresentarão problemas com datas futuras
(eles irão conseguir trabalhar com datas até o ano 9999).
O tipo TIMESTAMP, que é usado para armazenar a hora atual, tem um alcance somente até
2030-01-01. TIMESTAMP tem um alcance de 1970 até 2030 em máquinas 32-bits (valor com
sinal). Em máquinas de 64-bits ele pode trabalhar com datas até 2106 (valor sem sinal).
Mesmo apesar do MySQL ser compatível com o ano 2000, é de sua responsabilidade forb-
necer datas que não sejam ambíguas. Veja hundefinedi [Y2K issues], page hundefinedi para
regras do MySQL para lidar com entrada de datas ambíguas (datas contendo valores de ano
com 2 dígitos)
Comprando um livro através dos hyperlinks fornecidos aqui você estará contribuindo para
o desenvolvimento do MySQL.
MySQL
Disponível em Barnes and Noble
Editor New Riders
Autor Paul DuBois
Data de Publicação 1st Edition December 1999
ISBN 0735709211
Páginas 800
Preço $49.99 US
Exemplos para Download samp_db distribution
Errata are available here
Revisado por Michael “Monty” Widenius, Moderador do MySQL.
Em MySQL, Paul DuBois introduz a você um guia completo para um dos mais populares
bancos de dados relacionais. Paul tem contribuído para a documentação online para o
MySQL e é um membro ativo da comunidade MySQL. O principal desenvolvedor do MySQL,
Monty Widenius, e uma rede de seus companheiros desenvolvedores revisaram o manuscrito,
e forneceram a Paul o tipo de discernimento que ninguém poderia fornecer.
Ao invés de simplesmente dar uma vião geral do MySQL, Paul o ensina grande parte de
seus conhecimentos. Através de duas tabelas exemplos utilizadas por todo o livro, ele
mostra soluções para problemas que você certamente irá encontrar. Ele o ajuda a integrar
MySQL, eficientemente, com ferramentas de terceiros, como PHP e Perl, habilitando-o a
gerar paginas Web dinamicas através de consultas a banco de dados. Ele o ensina a escrever
programas que acessam banco de dados MySQL, e também fornece um conjunto completo
de referências para tipos de campos, operadores, funções, sintaxe SQL, programando em
MySQL, API C, Perl DBI, e API PHP. MySQL simplesmente lhe dará informações que você
não encontrará em nenhum outro lugar.
C, A reference manual
Disponível em Barnes and Noble
Editor Prentice Hall
Autores Samuel P. Harbison, Guy L. Steele
Data de Publicação September 1994
ISBN 0133262243
Páginas 480
Preço $35.99
Uma nova e aprimorada revisão de referência à linguagem C. Este manual lhe introduz
noções de "C Limpo", escrevendo código C que pode ser compilado como um programa
C++, estilo de programação C que enfatiza comportamento apropriado, portabilidade, sus-
tentabilidade, e incorpora a emenda 1 do ISO C (1994) que especifica novas facilidades para
escrever programas em C portáveis e internacionais.
Algorithms in C
Disponível em Barnes and Noble
Editor Addison Wesley Longman, Inc.
Autores Robert Sedgewick
Data de Publicação April 1990
ISBN 0201514257
Páginas 648
Preço $45.75
Algorithms in C descreve uma variedade de algoritmos em algumas áreas de interesse, in-
cluindo: ordenação, pesquisa, processamento de strings e algorítmos geométricos, graficos e
matemáticos. O livro enfatiza técnicas fundamentais, fornecendo aos leitores as ferramentas
para executar, implementar e debugar úteis algorítmos com confiança.
Tutoriais e Manuais
MySQL Myths Debunked
MySQL usado no "mundo real".
http://www.4t2.com/mysql
Informações sobre a lista de discussão alemã do MySQL.
http://www2.rent-a-database.de/mysql/
MySQL handbook em alemão.
http://www.bitmover.com:8888//home/bk/mysql
Accesso web ao repositório BitKeeper do MySQL.
http://www.analysisandsolutions.com/code/mybasic.htm
Tutorial para iniciantes no MySQL em como instalar e configurar o MySQL
numa máquina Windows.
http://www.devshed.com/Server_Side/MySQL/
Vários tutorias sobre MySQL.
http://mysql.hitstar.com/
Manual do MySQL em chinês.
http://www.linuxplanet.com/linuxplanet/tutorials/1046/1/
Configurando um site web baseado em MySQL.
http://www.hotwired.com/webmonkey/backend/tutorials/tutorial1.html
Tutorial Perl-MySQL.
http://www.iserver.com/support/contrib/perl5/modules.html
Instalando novos módulos Perl que necessitam de módulos localmente instala-
dos.
http://www.hotwired.com/webmonkey/databases/tutorials/tutorial4.html
Tutorial PHP/MySQL.
http://www.useractive.com/
Tutorial para MySQL.
http://www.essencesw.com/Software/mysqllib.html
Novas bibliotecas cliente para o MAC OS Classic (Macintosh).
http://www.lilback.com/macsql/
Bibliotecas cliente para o MAC OS Classic (Macintosh).
http://sixk.maniasys.com/index_en.html
MySQL para a plataforma Amiga.
http://www.metahtml.com/
Metahtml: Um Linguagem Dinaimca de Programação para Aplicações WWW.
http://www.binevolve.com/
VelocityGen para Perl e Tcl.
http://hawkeye.net/
Hawkeye Internet Server Suite.
http://www.fastflow.com/
Network Database Connection para Linux
http://www.wdbi.net/
WDBI: Navegador web como um front end universal para banco de dados que
suportam MySQL.
http://www.webgroove.com/
WebGroove Script: compilador HTML e linguagem script do lado do servidor.
http://www.ihtml.com/
Uma linguagem script do lado do servidor.
ftp://ftp.igc.apc.org/pub/myodbc/README
Como usar o MySQL com ColdFusion no Solaris.
http://calistra.com/MySQL/
Administrador ODBC MySQL Calistra.
http://www.webmerger.com
Webmerger - Esta ferramenta CGI le arquivos e gera uma saida dinamica
baseada em um conjunto de tags simple. Drivers prontos para MySQL e Post-
greSQL através do ODBC.
http://phpclub.net/
PHPclub - Dicas e truques para o PHP.
http://www.penguinservices.com/scripts
Scripts MySQL e Perl.
http://www.widgetchuck.com
The Widgetchuck; Web site com ferramentas.
http://www.adcycle.com/
AdCycle - Software gerenciador de anuncios.
http://sourceforge.net/projects/pwpage/
pwPage - fornece uma ferramenta extremamente rápida e simples para a criação
de formulario de banco de dados. Isto é, se existe uma tabela de banco de
dados e uma pagina HTML foi construida usando poucas linhas pwPage pode
ser imediatamente usado para seleção, inserção, atualização, deleção de dados
da tabela e revisão do conteúdo da tabela selecionada.
http://www.omnis-software.com/products/studio/studio.html
OMNIS Studio é uma ferramenta de desenvolvimento rápido de aplicações
(RAD).
Chapter 1: Informações gerais sobre o MySQL 25
http://www.webplus.com
talentsoft Web+ 4.6 - uma completa e poderosa linguagem de desenvolvmento
para usar na criação de aplicações cliente/servidor com base na web sem escrever
programas CGI complicados, baixo-nivel e que consomem tempo.
http://www.stonekeep.com/pts/
PTS: Projeto de Sistema de Rastreamento.
http://tomato.nvgc.vt.edu/~hroberts/mot
Serviço e software de sistema de rastreamento.
http://www.cynergi.net/exportsql/
ExportSQL: Um script para exportar dados do Access95+.
http://SAL.KachinaTech.COM/H/1/MYSQL.html
Entrada MySQL SAL - Aplicações Ciêntificas no Linux (Scientific Applications
on Linux).
http://www.infotech-nj.com/itech/index.shtml
Uma empresa de consultoria que menciona o MySQL nos direitos da companhia.
http://www.pmpcs.com/
PMP Computer Solutions. Desenvolvedores de banco de dados usando MySQL
and mSQL.
http://www.aewa.org/
Airborne Early Warning Association.
http://www.dedserius.com/y2kmatrix/
Testador Y2K.
http://www.delec.com/is/products/prep/examples/BookShelf/index.html
DELECis - Uma Ferramenta que torna muito fácil a criação de documentação
de tabelas gerada automaticamente. Eles têm usado o MySQL como exemplo.
http://www.worldrecords.com
World Records - Um mecanismo de pesquisa para informações sobre música que
utiliza o MySQL e PHP.
http://www.webtechniques.com/archives/1998/01/note/
Um banco de dados de contatos usando MySQL e PHP.
http://modems.rosenet.net/mysql/
Calendário comunitário em PHP com interface Web.
http://www.odbsoft.com/cook/sources.htm
Pacote Perl para gerar páginas html de uma estrutura de tabelas SQL e in-
struções SQL de um formulário HTML.
http://www.gusnet.cx/proj/telsql/
Banco de dados básico de telefones usando DBI/DBD.
http://tecfa.unige.ch/guides/java/staf2x/ex/jdbc/coffee-break
Exemplos JDBC por Daniel K. Schneider.
http://www.spade.com/linux/howto/PostgreSQL-HOWTO-41.html
SQL BNF
http://www.ooc.com/
Object Oriented Concepts Inc; Aplicações CORBA com exemplos em fontes.
http://www.pbc.ottawa.on.ca/
DBWiz: Fornece um exemplo de como gerenciar cursores em VB.
http://keilor.cs.umass.edu/pluribus/
Pluribus é um mecanismo de busca gratuito que melhora a qualidade de seus
resultados com o tempo. Pluribus funciona através da gravação de qual das
paginas um usuario selecionou entre aquelas retornadas pela consulta. Um
usuario vota na página ao selecioná-la; Pluribus utiliza então o seu conhecimento
para melhorar a qualidade dos resultados quando outra pessoa envia a mesma
consulta (ou similar). Usa PHO e MySQL.
http://www.stopbit.com/
Stopbit -Um site de notícias sobre tecnologia usando MySQL e PHP.
http://www.linuxsupportline.com/~kalendar/
Gerenciador de datas para KDE - O gerenciador possui suporte monousuario
(baseado e arquivo) e multiusuario (banco de dados MySQL).
http://tim.desert.net/~tim/imger/
Exemplo de armazenamento/recuperação de imagens com MySQL e CGI.
http://www.penguinservices.com/scripts
Sistema de Carrinho de Compras Online.
Chapter 1: Informações gerais sobre o MySQL 29
http://www.city-gallery.com/album/
Old Photo Album - O album é um projeto de historico de fotografia com co-
laboraçção popular que gera todas a paginas através de dados armazendos em
banco de dados MySQL. As páginas são geradas dinamicamente através de uma
interface php3 com o conteúdo do banco de dados. Utiliza imagens e descrições.
As imagens são armazenadas em um servidor web para evitar armazena-los em
um banco de dados como BLOBs. Todas as outras informações são armazenadas
no no servidor MySQL compartilhado.
Existem também outros diversos sites Web que utilizam o MySQL. See hundefinedi [Users],
page hundefinedi. Envie sugestões para esta lista no email [email protected]. Estamos
pedindo que você disponibilize uma logomarca do MySQL em algum lugar de seu site se
você desejar ter sua página citada aqui. Isto também é válido para ter sua página adicionada
na pagina “ferramentas utilizadas” ou algo parecido.
a escrever seu relatório corretamente para que você não perca seu tempo fazendo coisas que
não irão ajudar-nos muito ou nada.
Nós encorajamos todo mundo a usar o script mysqlbug para gerar um relato de erros
(ou um relato sobre qualquer problema), se possível. mysqlbug pode ser encontrado no
diretório ‘scripts’ na distribuição fonte, ou, para uma distribuição binária, no diretório
‘bin’ no diretório de instalação do MySQL. Se você não puder utilizar o mysqlbug, você
pode continuar incluindo todas as informações necessárias listadas nesta seção.
O script mysqlbug lhe ajudará a gerar um relatório determinando muitas das seguintes
informações automaticamente, mas se alguma coisa importante estiver faltando, por favor
forneça-o junto de sua mensagem! Por favor leita esta seção com cuidado e tenha certeza
que todas as informações descritas aquie estão incluídas no seu relatório.
O lugar comum para relatar erros e problemas é [email protected]. Se você
fizer um caso com testes que demonstre o bug claramente, pode postá-lo na lista
[email protected]. Note que nesta lista você deverá postar somente um um relatório
completo, usando o script mysqlbug. Se você estiver trabalhando com o MySQL para
Windows, você deve incluir uma descrição do sistema operacional e a versão do MySQL.
Preferencialmente você deve testar o problema usando a última versão estável ou de
desenvolvimento do MySQL antes de postar ! Qualquer um deve conseguir repetir o
erro usando apenas “mysql test < script” no teste do caso incluso, ou executandoo do
shell ou utilizando scripts perl inclusos no relatorio de erro. Todos os erros postados na
lista bugs serão corrigidos ou documentados na próxima release do MySQL! Se foram
necessárias apenas pequenas alterações no código para resolver este problema, nós iremos
publicar um patch que corrige o problema.
Lembre-se que é possível responder a uma mensagem contendo muita informação, mas não
a uma contendo muito pouca. Frequentemente pessoas omitem fatos porque acreditam que
conhecem a causa do problema e assumem que alguns detalhes não importam. Um bom
principio é: Se você está em dúvida sobre declarar alguma coisa, declare-a ! É milhares de
vezes mais rápido e menos problemático escrever um pouco de linhas a mais no seu relatório
do que ser forçado a perguntar de novo e esperar pela resposta porque você não forneceu
informação sufiente da primeira vez.
Os erros mais comuns acontecem porque as pessoas não indicam o número da versão da
distribuição do MySQL que estão usando, ou não indicam em qual plataforma elas tem
o MySQL instalado (Incluindo o número da versão da plataforma). Essa informação é
muito relevante, e em 99% dos casos o relato de erro é inútil sem ela! Frequentemente nós
recebemos questões como, “Por que isto não funciona para mim?” então nós vemos que
aquele recurso requisitado não estava implementado naquela versão do MySQL, ou que o
erro descrito num relatório foi resolvido em uma versão do MySQL mais nova. Algumas
vezes o erro é dependente da plataforma; nesses casos, é quase impossível corrigir alguma
coisa sem conhecimento do sistema operacional e o número da versão da plataforma.
Lembre-se também de fornecer informações sobre seu compilador, se isto for relacionado
ao problema. Frequentemente pessoas encontram erros em compiladores e acreditam que o
problema é relacionado ao MySQL. A maioria dos compiladores estão sobre desenvolvimento
todo o tempo e tornam-se melhores a cada versão. Para determinar se o seu problema
depende ou não do compilador, nós precisamos saber qual compilador foi usado. Note que
todo problema de compilação deve ser estimado como relato de erros e, consequentemente
publicado.
34 Referência técnica para o MySQL versão 3.23.52
É de grande ajuda quando uma boa descrição do problema é incluída no relato do erro. Isto
é, um bom exemplo de todas as coisas que o levou ao problema e a correta descrição do
problema. Os melhores relatórios são aqueles que incluem um exemplo completo mostrando
como reproduzir o erro ou o problema See hundefinedi [Reproduceable test case], page hun-
definedi.
Se um programa produz uma mensagem de erro, é muito importante incluir essas mensagens
no seu relatório! Se nós tentarmos procurar por algo dos arquivos usando programas, é
melhor que as mensagens de erro relatadas sejam exatamente iguais a que o programa
produziu. (Até o caso deve ser observado!) Você nunca deve tentar lembrar qual foi a
mensagem de erro; e sim, copiar e colar a mensagem inteira no seu relatório!
Se você tem um problema com o MyODBC, você deve tentar gerar um arquivo para ras-
tremento de erros (trace) do MyODBC. See hundefinedi [MyODBC bug report], page hun-
definedi.
Por favor lembre-se que muitas das pessoas que lerão seu relatório podem usar um vídeo de
80 colunas. Quando estiver gerando relatórios ou exemplos usando a ferramenta de linha
de comando mysql, então deverá usar a opção --vertical (ou a instrução terminadora \G)
para saída que irá exceder a largura disponível para este tipo de vídeo (por exemplo, com
a instrução EXPLAIN SELECT; veja exemplo abaixo).
Por favor inclua a seguinte informação no seu relatório:
• O número da versão da distribuição do MySQL que está em uso (por exemplo, MySQL
Version 3.22.22). Você poderá saber qual versão vocês está executando, usando o
comando mysqladmin version. mysqladmin pode ser encontrado no diretório ‘bin’
sob sua instalação do MySQL.
• O fabricante e o modelo da máquina na qual você está trabalhando.
• O nome do sistema operacional e a versão. Para a maioria dos sistemas operacionais,
você pode obter esta informação executando o comando Unix uname -a.
• Algumas vezes a quantidade de memória (real e virtual) é relevante. Se estiver em
dúvida, inclua esses valores.
• Se você estiver usando uma distribuição fonte do MySQL, é necessário o nome e número
da versão do compilador usado. Se você estiver usando uma distribuição binária, é
necessário o nome da distribuição.
• Se o problema ocorre durante a compilação, inclua a(s) exata(s) mensagem(s) de erro(s)
e também algumas linhas do contexto envolvendo o código no arquivo onde o erro
ocorreu.
• Se o mysqld finalizou, você deverá relatar também a consulta que travou o mysqld.
Normalmente você pode encontrar isto executando mysqld com o log habilitado. See
hundefinedi [Using log files], page hundefinedi
• Se alguma tabela do banco de dados estiver relacionado ao problema, inclua a saída de
mysqldump --nodata nome_db nome_tbl1 nome_tbl2.... Isto é muito fácil de fazer
e é um modo poderoso de obter informações sobre qualquer tabela em um banco de
dados que irá ajudar-nos a criar uma situação parecida da que você tem.
• Para problemas relacionados à velocidade ou problemas com instruções SELECT, você
sempre deve incluir a saída de EXPLAIN SELECT ... e ao menos o número de linhas
que a instrução SELECT produz. Quanto mais informação você fornecer sobre a sua
Chapter 1: Informações gerais sobre o MySQL 35
situação, mais fácil será para alguém ajudar-lo! A seguir um exemplo de um relatório
de erros muito bom (ele deve ser postado com o script mysqlbug):
Exemplo de execução usando a ferramenta de linha de comando mysql (perceba o uso
do instrução terminadora \G para instruções cuja largura de saída deva ultrapassar 80
colunas):
mysql> SHOW VARIABLES;
mysql> SHOW COLUMNS FROM ...\G
<saida para SHOW COLUMNS>
mysql> EXPLAIN SELECT ...\G
<saida para EXPLAIN>
mysql> FLUSH STATUS;
mysql> SELECT ...;
<Uma pequena vers~ ao da saída do SELECT,
incluindo a hora em que a consulta foi executada>
mysql> SHOW STATUS;
<saida do SHOW STATUS>
• Se um erro ou problema ocorrer quando estiver executando o mysqld, tente fornecer um
script de entrada que irá reproduzir a anomalia. Este script deve incluir qualquer ar-
quivo de fonte necessário. Quanto mais próximo o script puder reproduzir sua situação,
melhor. Se você puder fazer uma série de testes repetidos, você poderá postá-lo para o
[email protected] para um tratamento de alta prioridade!
Se não puder fornecer o script, você ao menos deve incluir a saída de mysqladmin
variables extended-status processlist na sua mensagem para fornecer alguma
informação da performance do seus sistema.
•
Se você não puder produzir um caso de teste em algumas linhas, ou se a tabela de
testes for muito grande para ser enviada por email para a lista de mensagens (mais de
10 linhas), você deverá dar um dump de suas tabelas usando o mysqldump e criar um
arquivo ‘README’ que descreve seu problema.
Crie um arquivo comprimido de seus arquivos usando tar e gzip ou zip, e use o
ftp para transferir o arquivo para ftp://support.mysql.com/pub/mysql/secret/.
E envie uma pequena descrição do problema para [email protected].
• Se você achar que o MySQL produziu um resultado estranho para uma consulta, não
inclua somente o resultado, mas também sua opinião de como o resultado deve ser, e
uma conta descrevendo o base de sua opinião.
• Quando fornecer um exemplo do problema, é melhor usar os nomes de variáveis, nomes
de tabelas, etc. utilizados na sua situação atual do que enviar com novos nomes. O
problema pode ser relacionado ao nome da variável ou tabela! Esses casos são raros,
mas é melhor prevenir do que remediar. Além disso, será mais fácil para você fornecer
um exemplo que use sua situação atual, que é o que mais importa para nós. No caso
de ter dados que não deseja mostrar para outros, você pode usar o ftp para transferi-
lo para ftp://support.mysql.com/pub/mysql/secret/. Se os dados são realmente
confidenciais, e você não deseja mostrá-los nem mesmo para nós, então vá em frente e
providencie um exemplo usando outros nome, mas, por favor considere isso como uma
única chance.
36 Referência técnica para o MySQL versão 3.23.52
• Inclua, se possível, todas as opções fornecidas aos programas relevantes. Por exemplo,
indique as opções que você utiliza quando inicializa o daemon mysqld e aquelas que são
utilizadas para executar qualquer programa cliente MySQL. As opções para programas
como o mysqld e mysql, e para o script configure, são frequentemente chaves para
respostas e são muito relevantes! Nunca é uma má idéia incluí-las de qualquer forma!
Se você usa algum módulo, como Perl ou PHP por favor forneça o número da versão
deles também.
• Se sua questão é relacionada ao sistema de privilégios, por favor forneça a saída
de mysqlaccess, a saída de mysqladmin reload, e todas as mensagens de erro que
você obteve quando tentava conectar! Quando você testar seus privilégios, você deve
primeiramente executar mysqlaccess. Depois, execute mysqladmin reload version e
tente conectar com o programa que gerou o problema. mysqlaccess pode ser encon-
trado no diretório ‘bin’ sob seu diretório de instalação do MySQL.
• Se você tiver um patch para um erro, isso é bom, mas não assuma que o patch é
tudo que precisamos, ou que iremos usá-lo, se você não fornecer algumas informações
necessárias, como os casos de testes mostrando o erro que seu patch corrige. Nós
podemos encontrar problemas com seu patch ou nós podemos não entendê-lo ao todo;
se for assim, não podemos usá-lo.
Se nós não verificarmos exatamente o que o patch quer dizer, nós não poderemos usá-
lo. Casos de testes irão ajudar-nos aqui. Mostre que o patch irá cuidar de todas as
situações que possam ocorrer. Se nós encontrarmos um caso (mesmo que raro) onde o
patch não funcionaria, ele pode ser inútil.
• Palpites sobre o que o erro pode ser, porque ocorre, ou do que ele depende, geralmente
estão errados. Mesmo o time MySQL não pode adivinhar antecipadamente tais coisas
sem usar um debugger para determinar a causa real do erro.
• Indique na sua mensagem de e-mail que você conferiu o manual de referência e o arquivo
de mensagens para que outros saibam que você tentou solucionar o problema.
• Se você obter um parse error, por favor confira sua sintaxe com atenção! Se
você não conseguiu encontrar nada errado com ela, é extremamente provável
que que sua versão corrente do MySQL não suporte a consulta que você
está utilizando. Se você estiver usando a versão recente e o manual em
http://www.mysql.com/documentation/manual.php não cobrir a sintaxe que
você estiver usando, o MySQL não suporta sua consulta. Neste caso, suas unicas
opções são implementar você mesmo a sintaxe ou enviar uma mensagem para
[email protected] e perguntar por uma oferta para implementá-lo!
Se o manual cobrir a sintaxe que você estiver usando, mas você tiver uma versão mais
antiga do MySQL, você deverá conferir o histórico de alterações do MySQL para ver
quando a sintaxe foi implementada. Neste caso, você tem a opção de atualizar para
uma nova versão do MySQL. See hundefinedi [News], page hundefinedi.
• Se você tiver um problema do tipo que seus dados aparecem corrompidos ou você
obtem erros quando você acessa alguma tabela em particular, você deverá primeiro
checar depois tentar reparar suas tabelas com myisamchk ou CHECK TABLE e REPAIR
TABLE. See hundefinedi [MySQL Database Administration], page hundefinedi.
• Se você frequentemente obtém tabelas corrompidas, você deve ten-
tar encontrar quando e porque isto acontece! Neste caso, o arquivo
Chapter 1: Informações gerais sobre o MySQL 37
Se você é um cliente de nosso suporte, por favor envio o seu relatório de erros em
[email protected] para tratamento de alta prioritário, bem como para a lista de
mensagens apropriada para ver se mais alguém teve experiências com (e talvez resolveu) o
problema.
Para informações sobre relatar erros no MyODBC, veja hundefinedi [ODBC Problems],
page hundefinedi.
Para soluções a alguns problemas comuns, veja See hundefinedi [Problems], page hunde-
finedi.
Quando respostas são enviadas para você individualmente e não para a lista de mensagens, é
considerado boa etiqueta resumir as respostas e enviar o resumo para a lista de mensagens
para que outras possam ter o benefício das respostas que você recebeu que ajudaram a
resolver seu problema!
• Custos de Suporte (see hundefinedi [Cost], page hundefinedi) e seus benefícios (see
hundefinedi [Support], page hundefinedi)
• Custos do licenciamento comercial
processadores conta como uma máquina única, e não existem restrições sobre o número de
servidores MySQL que executam em uma máquina ou no número de clientes conectados
simultâneamente a um servidor executado naquela máquina!
Se você tiver alguma duvida se uma licença é necessária ou não para seu uso particular do
MySQL, por favor leia isto de novo e contate-nos. See hundefinedi [Contact information],
page hundefinedi.
Se você necessita de uma licença MySQL, o modo mais fácil para pagar por ele é usar o for-
mulário de licença no servidor securo da MySQL em https://order.mysql.com/. Outras
formas de pagamento são discutidas em hundefinedi [Payment information], page hunde-
finedi.
Perceba que uma licença única do MySQL cobre qualquer número de CPUs e servidores
mysqld em uma máquina! Não existe limite artificial no número de clientes que conectam
ao servidor em nenhum caso.
MySQL AB
BOX 6434
11382 STOCKHOLM, SWEDEN
+46-8-729 69 05
Se você desejar que nós lhe cobremos, pode usar o formulário de licenças e escrever “bill
us” no campo de comentário. Pode também enviar uma mensagem para [email protected]
(não [email protected]!) com as informações de sua empresa e pedir para que nós
envie a cobrança.
• Se você deseja que nós ajudemos a otimizar seu sistema, deve atualizar para um nível
mais alto de suporte.
Mesmo se estivermos muito convencidos que podemos resolver a maioria dos problemas de
uma maneira precisa, não podemos garantir uma solução rápida para quaisquer problemas
que você possa ter com os diferentes manipuladores de tabelas. Iremos entretanto fazer o
melhor possível para ajudá-lo a ter seu problemas resolvidos.
− Você pode usar comandos padrão do sistemas para fazer backups, renomear, apagar
e copiar tabelas. Por exemplo, para renomear uma tabela, renomeie os arquivos
‘.MYD’, ‘.MYI’ e ‘.frm’. para o nome da tabela correspondente.
• Em algumas instruções SQL, você pode acessar tabelas de diferentes bancos de dados
com a sintaxe nome_bd.nome_tbl. Alguns servidores SQL fornecem a mesma fun-
cionalidade mas chamam isto de User space. O MySQL não suporta tablespaces como
em: create table ralph.my_table...IN minha_tablespace.
• LIKE é permitido em campos numéricos.
• O uso de INTO OUTFILE e STRAIGHT_JOIN em uma instrução SELECT. See hundefinedi
[SELECT], page hundefinedi.
• A opção SQL_SMALL_RESULT em uma instrução SELECT.
• EXPLAIN SELECT para obter uma descrição de como as tabelas são ligadas.
• A utilização de nomes de índices, índices em um prefixo de um campo, e uso de INDEX
ou KEY em uma instrução CREATE TABLE. See hundefinedi [CREATE TABLE], page hunde-
finedi.
• O uso de TEMPORARY ou IF NOT EXISTS com CREATE TABLE.
• O uso de COUNT(DISTINCT lista) onde ’lista’ é maior que um elemento.
• O uso de CHANGE nome_campo, DROP nome_campo, ou DROP INDEX, IGNORE ou RENAME
em uma instrução ALTER TABLE. See hundefinedi [ALTER TABLE], page hundefinedi.
• O uso de RENAME TABLE. See hundefinedi [RENAME TABLE], page hundefinedi.
• Utilização de múltiplas cláusulas ADD, ALTER, DROP, ou CHANGE em uma instrução ALTER
TABLE.
• O uso de DROP TABLE com as palavras-chave IF EXISTS.
• Você pode remover (drop) múltiplas tabelas com uma instrução única DROP TABLE.
• A cláusula LIMIT da instrução DELETE.
• A cláusula DELAYED das instruções INSERT e REPLACE.
• A cláusula LOW_PRIORITY das instruções INSERT, REPLACE, DELETE e UPDATE.
• O uso de LOAD DATA INFILE. Em alguns casos essa sintaxe é compatível com o Oracle
LOAD DATA INFILE. See hundefinedi [LOAD DATA], page hundefinedi.
• As intruções ANALYZE TABLE, CHECK TABLE, OPTIMIZE TABLE, e REPAIR TABLE.
• A instrução SHOW. See hundefinedi [SHOW], page hundefinedi.
• Strings podem ser fechadas pelo ‘"’ ou ‘’’, não apenas pelo ‘’’.
• O uso do meta-caractere de escape ‘\’.
• A instrução SET OPTION. See hundefinedi [SET OPTION], page hundefinedi.
• Você não precisa nomear todos os campos selecionados na parte GROUP BY. Isto fornece
melhor performance para algumas consultas específicas, mas muito comuns. See hun-
definedi [Group by functions], page hundefinedi.
• Pode ser especificado ASC e DESC com o GROUP BY.
• Para tornar mais fácil para usuários que venham de outros ambientes SQL, o MySQL
suporta apelidos (aliases) para várias funções. Por exemplo, todas funções de string
suportam as sintaxes ANSI SQL e ODBC.
Chapter 1: Informações gerais sobre o MySQL 49
1.4.4.1 Sub-selects
Atualmente o MySQL suporta somente sub selects da forma INSERT ... SELECT ... e
REPLACE ... SELECT .... Entretanto, você pode usar a função IN() em outros contextos.
Em alguns casos você pode reescrever a query sem uma sub selects:
SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);
Isto pode ser reescrito como:
SELECT table1.* FROM table1,table2 WHERE table1.id=table2.id;
As consultas:
SELECT * FROM table1 WHERE id NOT IN (SELECT id FROM table2);
SELECT * FROM table1 WHERE NOT EXISTS (SELECT id FROM table2 where table1.id=table2.
Podem ser reescritas como:
SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id where table2.id
Para consulta aninhadas mais complexas você pode, geralmente, criar tabelas temporárias
para armazenar as consultas aninhadas. Em alguns casos, entretanto, essa opção não irá
funcionar. O mais frequentemente encontrado nestes casos surgem em instruções DELETE,
para o qual padrão SQL não suporta joins (exceto nas sub-selects). Para esta situação exis-
tem duas opções disponível enquanto consultas aninhadas forem suportadas pelo MySQL.
A primeira opção é usar uma linguagem de programação procedural (como Perl ou PHP)
para enviar uma query SELECT para obter as chaves primárias dos registros a serem dele-
tados, e depois usar estes valores para construir uma instrução DELETE DELETE FROM ...
WHERE ... IN (key1,key2, ...)).
Chapter 1: Informações gerais sobre o MySQL 51
A segunda opção é usar o interactive SQL para construir uma série de instruções DELETE
automaticamente, usando a extensão MySQL CONCAT() (em lugar do operador padrão ||.
For example:
SELECT CONCAT(’DELETE FROM tab1 WHERE pkid = ’, tab1.pkid, ’;’)
FROM tab1, tab2
WHERE tab1.col1 = tab2.col2;
Você pode colocar esta consulta em um arquivo script e redirecionar sua saída para o
interpretador de linha de comandos mysql, canalizando sua saída de volta a uma segunda
instância do interpretador:
prompt> mysql --skip-column-names mydb < myscript.sql | mysql mydb
O MySQL 4.0 suporta deleção de multi-tabelas que pode ser usado para apagar registros
de forma eficiente com base em informações de uma tabela ou mesmo de várias tabelas ao
mesmo tempo.
1.4.4.3 Transações
Como o MySQL, hoje em dia, suporta transações, a seguinte discussão só é válida se você
estiver usando os tipos de tabelas não transacionais. See hundefinedi [COMMIT], page hun-
definedi
Essa questão é normalmenta feita, pelos curiosos e críticos, “Por que o MySQL não é um
banco de dados transacional ?” ou “Por que o MySQL não suporta transações?”.
O MySQL tem feito uma descisão consciente para suportar outro paradigma para integri-
dade de dados, “operações atômicas.” É de nosso conhecimento e experiência que operações
atômicas oferecem integridade igual ou melhor com performance muito mais eficiente. Nós,
apesar de tudo, apreciamos e entendemos o paradigma de bancos de dados transacionais e
planejamos, nas próximas versões, introduzir tabelas com segurança transacional nos fun-
damentos de tabelas. Nós iremos dar a nossos usuários a possibilidade de decididir se eles
precisam da velocidade das operações atômicas ou se eles precisam usar recursos transa-
cionais na suas aplicações.
Como são utilizados recursos do MySQL para manter de forma rigorosa a integridade e
como estes recursos se comparam com o paradigma transacional?
Primeiro, no paradigma transacional, se as suas aplicações são escritas de uma forma que
é dependente na chamada de “rollback” em vez de “commit” em situações críticas, então
transações são mais convenientes. Além disso, transações asseguram que atualizações in-
acabadas ou atividades corrompidas não sejam executadas no banco de dados; o servidor
52 Referência técnica para o MySQL versão 3.23.52
oferece uma oportunidade para fazer um rollback automático e seu banco de dados é man-
tido.
O MySQL, na maioria dos casos, permite a você resolver potenciais problemas incluindo
simples conferências antes das atualizações e executando scripts simples que conferem incon-
sistências no banco de dados e, automaticamente, repara ou avisa caso isto ocorra. Perceba
que apenas usando o log do MySQL ou mesmo adicionando um log extra, pode-se corrigir
tabelas perfeitamente sem nenhuma perda de integridade.
Além disso, atualizações transacionais fatais podem ser reescritas para serem atômicas. De
fato podemos dizer que todos problemas de integridade que transações resolvem podem
ser feitas com LOCK TABLES ou atualizações atômicas, assegurando que você nunca irá ter
uma finalização automática da tabela, o que é um problema comum em bancos de dados
transacionais.
Nem mesmo transações podem prevenir todas as falhas se o servidor cair. Nestes casos
mesmo um sistema transacional pode perder dados. A diferença entre sistemas diferentes
é apenas em quão pequeno é o lapso de tempo em que eles podem perder dados. Nenhum
sistema é 100% seguro, somente “seguro o suficiente.” Mesmo o Oracle, com reputação de
ser o mais seguro bancos de dados transacionais, tem relatos de algumas vezes perder dados
nestas situações.
Para estar seguro com o MySQL, você apenas deve fazer backups e ter o log de atualizações
ligado. Com isto você pode se recuperar de qualquer situação possível com bancos de dados
transacionais. É sempre bom ter backups, independente de qual banco de dados você usa.
O paradigma transacional tem seus benefícios e suas desvantagens. Muitos usuários e
desenvolvedores de aplicações dependem da facilidade com a qual eles podem codificar
contornando problemas onde abortar parece ser, ou é necessário, e podem ter um pouco
mais de trabalho com o MySQL por terem que pensar diferente ou escrever mais. Se
você é novo no paradigma de operações atômicas ou tem mais familiaridade ou conforto
com transações, não acabe por concluir que o MySQL não tenha se preocupado com estes
assuntos. Confiança e integridade estão em nossas mentes. Estimativas recentes indicam
que existem mais de 1.000.000 de servidores mysqld operando atualmente, muitos dos quais
estão em ambientes de produção. São muito, muito raros os casos nos quais nossos usuários
perderam seus dados, e em quase todos os casos, erros dos usuários estão envolvidos. Isto
é, na nossa opinião, a melhor prova da estabilidade e segurança do MySQL.
Ultimamente, em situações onde integridade é de grande importância, as atuais cara-
cterísticas do MySQL permitem níveis transacionais ou melhor confiança e integridade.
Se você bloquear tabelas com LOCK TABLES todos as atualizações irão ser adiadas até qual-
quer verificação de integridade ser feita. Se você só obter um bloqueio de leitura (oposto ao
bloqueio de escrita), então leituras e inserções poderão ocorrer. Os novos registros inseridos
não poderão ser visualizados por nenhum dos clientes que tiverem um bloqueio de LEITURA
até eles liberarem estes bloqueios. Com INSERT DELAYED você pode enfileirar inserções em
uma fila local, até os bloqueios serem liberados, sem que o cliente prceise esperar pela
inserção completar. See hundefinedi [INSERT DELAYED], page hundefinedi
“Atomico”, no sentido em que nós mencionamos, não é mágico. Significa apenas que você
pode estar certo que enquanto cada atualização específica está sendo executada, nenhum
outro usuário pode interferir com ela, e nunca haverá um rollback automático (que pode
acontecer em sistemas baseados em transações se você não tiver muito cuidado). O MySQL
Chapter 1: Informações gerais sobre o MySQL 53
também assegura que nunca ocorrerá uma leitura suja. Você pode encontrar alguns ex-
emplos de como escrever atualizações atômicas na seção commit-rollbak. See hundefinedi
[Commit-rollback], page hundefinedi.
Estamos pensando muito sobre integridade e performance, e nós acreditamos que nosso
paradigma de operações atômicas permitem tanto confiança quanto uma performance ex-
tremamente alta, na ordem de tres a cinco vezes a velocidade do mais rápido e mais op-
timizado dos bancos de dados transacionais. Nós não deixamos as transações porque são
muito difíceis para serem feitas. A principal razão de trabalharmos com operações atômicas
ao invés de transações é que fazendo isto nós podemos aplicar muitas otimizações de veloci-
dade que de outra forma não seria possível.
Muitos de nossos usuários que tem a velocidade em mentee, não estão muito preocupados
com transações. Para eles transações não são importantes. Para aqueles usuários que estão
preocupados com ou tem curiosidade sobre transações no MySQL, existe um “MySQL
Way” como nós citamos acima. Para aqueles que dão mais importância a segurança do que
velocidade, recomendamos o uso das tabelas BDB ou InnoDB para todos seus dados críticos.
See hundefinedi [Table types], page hundefinedi.
Nota final: Atualmente nós estamos trabalhando em um esquema seguro de replicação o
qual acreditamos ser melhor que qualquer sistema de replicação comercial que conhecemos.
Este sistema irá trabalhar com confiança sobre o paradigma de operações atômicas não-
transacional. Mantenha-se informado.
See hundefinedi [JOIN], page hundefinedi. See hundefinedi [example-Foreign keys], page hun-
definedi.
A sintaxe FOREIGN KEY existe no MySQL somente para compatibilidade com os comandos
CREATE TABLE de outros fabricantes, ela não faz nada. A sintaxe FOREIGN KEY sem ON
DELETE ... é usada na maioria dos casos para documentação. Algumas aplicações ODBC
podem usar isto para produzir cláusulas WHERE automáticas, mas é normalmente ignorada.
FOREIGN KEY é algumas vezes usado para verificação, porém, esta verificação é desnecessária
na prática se os registros são inseridos nas tabelas na ordem correta. O MySQL suporta
somente estas cláusulas porque algumas aplicações dependem delas para existir (não levando
em consideração se elas funcionam ou não).
No MySQL, você pode trabalhar contornando o problema do ON DELETE... ainda não im-
plementado, adicionando as instruções DELETE apropriadas a aplicação quando você apagar
registros de uma tabela que possui uma chave estrangeira. Na prática isto é tão rápido (em
alguns casos, mais rápido) e muito mais portável do que o uso de chaves estrangeiras.
No futuro próximo, iremos extender a implementação de CHAVES ESTRANGEIRAS para que
ao menos a informação seja armazenada no arquivo de especifícações da tabela e possa ser
recuperada com mysqldump e ODBC. Em um estágio posterior, nós implementaremos as
chaves estrangeiras para aplicações que não podem ser facilmente codificadas para ignorá-la.
O único aspecto interessante das CHAVES ESTRANGEIRAS é que ela dá ao ODBC e alguns
outros programas clientes a habilidade de ver como a tabela é conectada e utilizá-la para
mostrar diagramas de conexão e ajudar na criação de aplicações.
MySQL logo irá armazenar definições de CHAVES ESTRANGEIRAS para que o cliente possa
pedi-la e receber uma resposta sobre como a conexão original foi feita. O formato atual dos
arquivos ‘.frm’ não tem lugar para elas. Em um estágio posterior nós iremos implementar
as chaves estrangeiras para aplicações que não podem ser codificadas para evitá-las.
1.4.4.7 Views
MySQL ainda não suporta views, mas planejamos implementá-las em torno da versão 4.1.
Views geralmente são muito úteis para permitir aos usuários acessar uma série de relações
como uma tabela (em modo leitura). Vários bancos de dados SQL não permitem atualizar
nenhum registro em uma view, mas você tem que fazer as atualizações em tabelas separadas.
Como o MySQL é normalmente usado em aplicações e sistemas web onde o autor da
aplicação tem total controle no uso de bancos de dados, a maioria de nossos usuários não
consideram view muito importante. (pelo menos nenhum teve interesse suficiente para
financiar a implementação de views).
Não é necessário o uso de views em MySQL para restringir acesso aos campos já que o
MySQL tem um sistema de privilégios bem sofisticado. See hundefinedi [Privilege system],
page hundefinedi.
Este método é, normalmente, muito mais rápido do que usar transações com possíveis
ROLLBACKs, mas nem sempre. A única situação em que esta solução não se aplica é quando
alguém mata as threads no meio de uma atualização. Neste caso, todos bloqueios serão
liberados mas algumas atualizações podem não ter sido executadas.
Você também pode utilizar funções para atualizar registros em uma única operação. Você
pode ter uma aplicação muito eficiente utilizando as seguintes técnicas:
• Modificar campos relativos aos seus valores atuais.
• Atualizar somentes aqueles campos que foram realmente alterados.
Por exemplo, quando estivermos fazendo atualizações em alguma informação de clientes,
atualizamos somente os dados do cliente que foram alterados e testamos somente aqueles
que não tiveram dados alterados ou dados que dependam dos dados alterados e que tenham
sido alterados comparados ao registro original. O teste para dados alterados é feito com a
cláusula WHERE na instrução UPDATE. Se o registro não for atualizado, daremos ao cliente
uma mensagem: "Alguns dos dados que você alterou foi alterado por outro usuário". Então
nós mostramos o registro antigo e o novo registro na tela para que o usuario possa decidir
qual versão ele pode usar.
Isto fornece algo que é parecido com bloqueio de colunas mas bem melhor, porque só
atualizamos algumas das colunas, usando valores que são relativos ao seus valores atuais.
Isto significa que instruções UPDATE se parecerão com isto:
UPDATE nometabela SET pay_back=pay_back+’mudança relativa’;
UPDATE customer
SET
data_corrente=’data_corrente’,
endereco=’novo endereco’,
telefone=’novo telefone’,
dinheiro_ele_nos_deve=dinheiro_ele_nos_deve+’novo_dinheiro’
WHERE
id_cliente=id AND endereco=’endereco antigo’ AND telefone=’telefone antigo’;
Como podemos ver, esta forma é muito eficiente e funciona mesmo se outro cliente tiver
alterado os valores nas colunas pay_back ou dinheiro_ele_nos_deve.
Em alguns casos, usuários tem necessitado de ROLLBACK e/ou LOCK TABLES com o propósito
de gerenciar identificadores únicos para algumas tabelas. Isto pode ser tratado de forma
muito mais eficiente usando um campo AUTO_INCREMENT e também a função SQL LAST_
INSERT_ID() ou a função da API C mysql_insert_id(). See hundefinedi [mysql_insert_
id()], page hundefinedi.
Na MySQL AB, nós nunca tivemos necessidade de bloqueio no nível de registros porque
nós sempre fomos capaz de programar evitando-os. Alguns casos realmente precisam de
bloqueio de registros, mas são poucos. Se você deseja bloqueio de registros, você pode usar
um campo de sinalização na tabela e fazer como se segue:
UPDATE nome_tabela SET row_flag=1 WHERE id=ID;
O MySQL retorna 1 para o número de registros atingidos se o registro for encontrado e
row_flag já não tinha 1 no registro original.
Você pode pensar como se o MySQL tivesse alterado a consulta acima para:
UPDATE nome_tabela SET row_flag=1 WHERE id=ID and row_flag <> 1;
58 Referência técnica para o MySQL versão 3.23.52
• Você só pode ter até 255 colunas ENUM e SET em uma tabela.
• safe_mysqld redireciona todas as mensagens de mysqld para o log mysqld. Um prob-
lema com isto é que se você executar o mysqladmin refresh para fechar e reabrir o
log, a stdout e a stderr continuam redirecionadas para o log antigo. Se você utiliza
--log extensivamente, deverá editar o safe_mysqld para logar em ‘’hostname’.err’
em vez de ‘’hostname’.log’; assim você pode facilmente utilizar o espaço do log antigo
apagando-o e executando mysqladmin refresh.
• Em instruções UPDATE, colunas são atualizadas da esquerda para a direita. Se você
referenciar a uma coluna atualizada, você irá obter o valor atualizado em vez do valor
original, por exemplo:
mysql> UPDATE nome_tabela SET KEY=KEY+1,KEY=KEY+1;
Isto atualiza KEY com 2 no lugar de 1.
• Você não pode usar tabelas temporárias mais que uma vez na mesma query. Por
exemplo, a seguinte instrução não funciona.
select * from tabela_temporaria, tabela_temporaria as t2;
• RENAME não funciona com tabelas temporárias (TEMPORARY).
• O otimizador pode lidar com o DISTINCT de forma diferente se você estiver usando col-
unas ’escondidas’ em uma join ou não. Em uma join, colunas escondidas são contadas
como parte do resultado (mesmo se elas não são mostradas) enquanto que em queries
normais colunas escondidas não participam na comparação DISTINCT. Nós provavel-
mente iremos alterar isto no futuro para nunca comparar as colunas escondidas quando
executando DISTINCT.
um exemplo disto é:
SELECT DISTINCT mp3id FROM band_downloads WHERE userid = 9 ORDER BY id
DESC;
e
SELECT DISTINCT band_downloads.mp3id, FROM band_downloads,band_mp3
WHERE band_downloads.userid = 9 AND band_mp3.id = band_downloads.mp3id
ORDER BY band_downloads.id DESC;
No segundo caso, você pode obter duas linhas idênticas no MySQL 3.23.x na série do
resultado (porque o campo escondido ’id’ pode variar).
Perceba que isto somente acontece em consultas onde você não tem colunas ORDER
BY no resultado, algo não permitido no ANSI SQL.
• Como o MySQL permite trabalhar com tipos de tabelas que não suportam transações
(e assim não pode fazer rollback em dados) algumas coisas funcionam um pouco
diferentes de outros servidores SQL em MySQL (Isto serve para garantir que o MySQL
nunca necessitará de um rollback para um comando SQL). Porém isto pode ser um
pouco estranho em casos que os valores dos campos devem ser verificados na aplicação,
mas isto ira fornacer um ótimo ganho de velocidade assim como permite ao MySQL
fazer algumas otimizações que de outro modo seriam muito difíceis para serem feitas.
Se você informar um valor incorreto em uma coluna, o MySQL, em vez de fazer um
rollback, aramzenará o melhor valor possível no campo.
− Se tentar armazenar um valor fora da faixa em uma coluna numérico, o MySQL
irá armazenar o menor ou maior valor possível no campo.
60 Referência técnica para o MySQL versão 3.23.52
− Se tentar armazenar uma string que não comece com um número em uma coluna
numérica, o MySQL irá armazenar 0 na coluna.
− Se você tentar armazenar NULL em uma coluna que não aceita valores
nulos, MySQL irá armazenar 0 ou ’’ (string vazia) na coluna. (Este
comportamento pode, entretanto, ser alterado com a opção de compilação
-DDONT USE DEFAULT FIELDS).
− O MySQL permite o armazenamento de alguns valores errados de data em campos
do tipo DATE e DATETIME. (Como 2000-02-31 ou 2000-02-00). Se a data estiver
totalmente errada, o MySQL irá armazenar a data 0000-00-00 no campo.
− Se você especificar um valor não suportado para um campo do tipo enum, ele será
alterado para o valor de erro ’empty string’, com valor numérico 0.
• Se você executar uma PROCEDURE em uma pesquisa que retorna uma série vazia, em
alguns casos a instrução PROCEDURE não irá transformar as colunas.
• Criação da tabela do tipo MERGE não verifiva se as tabelas envolvidas são de tipos
compatíveis.
• O MySQL ainda não pode lidar com valores NaN, -Inf e Inf em tipos double. Usá-los
causará problemas na exportação e importação de dados. Uma solução intermediária
é alterar NaN para NULL (se for possível) e -Inf e Inf para o valor double mínimo ou
máximo respectivo possível.
• LIMIT em números negativos são tratados como números grandes positivos.
• Se você usar ALTER TABLE para primeiro adicionar um índice UNIQUE a uma tabela usada
em uma tabela MERGE e então usar ALTER TABLE para adicionar um índice normal na
tabela MERGE, a ordem das chaves será diferente para as tabelas se existir uma chave
antiga não única na tabela. Isto é porque o ALTER TABLE coloca chaves UNIQUE antes
de chaves normais para ser possível detectar chaves duplicadas o mais cedo o possível.
Os seguintes erros são conhecidos em versões mais antigas do MySQL:
• Você pode pendurar um processo se você fizer um DROP TABLE em uma tabela entre
outras que esteja travada com LOCK TABLES.
• No caso seguinte você pode obter um descarrego de memória para o arquivo core:
− Tratamento de inserções com atraso tem deixado inserções pendentes na tabela.
− LOCK table com WRITE
− FLUSH TABLES
• Antes da versão 3.23.2 do MySQL um UPDATE que atualizava uma chave com um WHERE
na mesma chave podia falhar porque a chave era usada para procurar por registros e a
mesma linha poderia ter encontrado vários itens:
UPDATE nome_tabela SET KEY=KEY+1 WHERE KEY > 100;
Um modo de contornar este erro é utilizar:
mysql> UPDATE nome_tabela SET KEY=KEY+1 WHERE KEY+0 > 100;
Isto funcionará porque MySQL não utilizará indices em expressões com a cláusula
WHERE.
• Antes da versão 3.23 do MySQL, todos os tipos numéricos tratados como campos
de pontos fixos. Isto significa que você tem que especificar quantas casas decimais um
Chapter 1: Informações gerais sobre o MySQL 61
campo de ponto flutuante deve ter. Todos os resultados eram retornados com o numero
correto de casas decimais.
Para erros específicos na plataforma, vejas as seções sobre compilação e portabilidade.
modificando uma tabela que uma outra thread deseja acessar). No mSQL,
uma vez que uma conexão for estabelecida, todos outros devem esperar até
que a primeira tenha acabado, sem levar em consideração se a conexão está
executando uma query que é curta ou longa. Quando a primeira conexão
termina, a próxima pode ser atendida, enquanto todas as outras esperam
novamente e etc.
• Joins. O mSQL pode ficar patologicamente lento se você alterar a ordem
das tabelas em uma SELECT. Na suite de benchmark, o mSQL se mostrou
15000 vezes mais lento que o MySQL. Isto é devido a falta de um otimizador
join para ordenar tabelas na ordem otimizada no mSQL. Entretanto, se
você colocar as tabelas na ordem exata no mSQL2 e o WHERE for simples e
usar índice, o join vai ser relativamente rápido! See hundefinedi [MySQL
Benchmarks], page hundefinedi.
• ORDER BY e GROUP BY.
• DISTINCT.
• Usando tipos TEXT ou BLOB em campos.
Recursos SQL
• GROUP BY e HAVING. O mSQL não suporta completamente o GROUP BY. O
MySQL suporta completamente o GROUP BY com HAVING e as seguintes
funções: COUNT(), AVG(), MIN(), MAX(), SUM() e STD(). COUNT(*) é
otimizado para retornar rapidamente se o SELECT retornar de uma tabela,
nenhum outro campo é devolvido e não há uma cláusula WHERE. MIN() e
MAX() podem exigir argumentos.
• INSERT e UPDATE com cálculos. O MySQL pode fazer cálculos em uma
instrução INSERT ou UPDATE. Por exemplo:
mysql> UPDATE SET x=x*10+y WHERE x<20;
• Apelidos ou alias. MySQL tem suporte a apelidos para os campos.
• Qualificando nomes de colunas. No MySQL, se um nome de coluna é única
entre as tabelas usadas em uma query, você não tem que usar o qualifidador
completo.
• SELECT com funções. O MySQL tem várias funções (muitas para serem
listadas aqui; veja hundefinedi [Functions], page hundefinedi).
Eficiência no Armazenamento em Disco
Ou seja, quão pequena pode ser suas tabelas ?
Existem tipos muito precisos no MySQL, que possibilitam a criação de tabelas
que consumem muito pouco espaço em disco. Um exemplo de um tipo de
dados MySQL é o MEDIUMINT que ocupa 3 bytes. Se você tiver 100.000.000 de
registros, economizar um byte por registro pode ser m uito importante.
O mSQL2 possui uma variedade mais limitada para tipos de campos, portanto,
é mais complicado para obter pequenas tabelas.
Estabilidade
É difícil julgar objetivamente. Para uma discussão sobre estabilidade do
MySQL, veja em hundefinedi [Stability], page hundefinedi.
Chapter 1: Informações gerais sobre o MySQL 63
Nós não tempos experiência com a estabilidade do mSQL, portanto, não podemos
dizer nada sobre isto.
Preço Outro assunto importante é a licença. O MySQL possui uma licença mais
flexível que o mSQL, e também é mais barato que o mSQL. Qualquer produto
que você escolha usar, lembre-se de considerar ao menos o pagamento de uma
licença ou suporte por e-mail. (Você é obrigado a obter uma licença se incluir
o MySQL com um produto que vende.)
Interfaces Perl
O MySQL tem basicamente a mesma interface para o Perl que o mSQL com
alguns recursos adicionais.
JDBC (Java)
Atualmente, o MySQL tem vários drivers JDBC diferentes:
• O driver mm: Um driver JDBC tipo 4 por Mark Matthews
[email protected]. Este é distribuido sobre a LGPL.
• O driver Resin. Este é um driver JDBC comercial open source.
http://www.caucho.com/projects/jdbc-mysql/index.xtp
• O driver gwe: Uma interface JAVA fabricada pela GWE technologies (não
é mais suportado).
• O driver jms: Um driver gwe melhorado por xiaokun Kelvin ZHU
[email protected] (não é mais suportado).
• O driver twz: Um driver JDBC tipo 4 por Terrence W. Zellers
[email protected]. É comercial, porém livre para uso privado e
educacional (não é mais suportado).
O driver recomendado é o driver mm. O driver Resin também pode ser bom
(pelo menos nos benchmarks parece bom), mas nós não recebemos informações
suficientes sobre ele ainda.
Nós sabemos que o mSQL tem um driver JDBC, mas nós temos muito pouca
experiência com ele para comparar.
Desenvolvimento
MySQL tem uma equipe de desenvolvedores muito pequena, mas somos bem
rápidos codificando em C e C++. Como threads, funções, GROUP BY e outras
recursos ainda não estão implementada em mSQL, eles têm muitas coisas para
fazer. Para ter uma perspectiva para estas implementações você pode ar uma
olhada no arquivo de HISTÓRICO do mSQL do ultimo ano e compará-lo com a
seção Novidades do Manual de Referência do MySQL. (see hundefinedi [News],
page hundefinedi). É bem óbvio quem tem desenvolvido mais rapidamente.
Programas utilitários
Ambos mSQL e MySQL tem várias ferramentas interessantes de terceiros. Como
é muito fácil portar (do mSQL para MySQL), quase todas as aplicações interes-
santes que são disponíveis para mSQL também está disponível para MySQL.
O MySQL vem com um programa simples, msql2mysql que corrige diferenças
nas sintaxes entre o mSQL e o MySQL para as funções C API mais usadas.
Por exemplo, ele altera instancias de msqlConnect() para mysql_connect().
64 Referência técnica para o MySQL versão 3.23.52
mSQL Use a coluna _rowid. Observe que _rowid pode ser alterado varias vezes,
dependendo de alguns fatores.
Obtendo a hora em que uma coluna foi alterada
MySQL Adicionando uma coluna TIMESTAMP na tabela. Este campo é configurado auto-
maticamente para receber os valores de data e hora atuais se você não informar
algum valor ou fornecer um valor NULL.
mSQL Usa o coluna _timestamp.
Comparações de Valores NULL
MySQL O MySQL segue o ANSI SQL, portanto qualquer comparação com NULL é sem-
pre NULL.
mSQL No mSQL, NULL = NULL é verdadeiro. Você deve alterar =NULL para IS NULL
e <>NULL para IS NOT NULL quando portar códigos antigos do mSQL para o
MySQL.
Comparações de Strings
MySQL Normalmente, comparações de conjuntos de caracteres são feitas no estilo in-
dependente do caso com a forma de classificação determinada pelo conjunto
de caracteres atuais (ISO-8859-1 Latin1 por definição padrão). Se você não
gosta disto, declare seus campos com o atributo BINARY, que deixa as com-
parações serem realizadas de acordo com a ordenação ASCII usada na máquina
que hospeda o servidor MySQL.
mSQL Todas as comparações de conjuntos de caracteres são caso sensitivo com or-
denação na ordem ASCII.
Pesquisas Caso Insensitivo
MySQL LIKE é um operador caso-sensitivo ou caso-insensitivo, dependendo dos campos
envolvidos. Se possível, o MySQL usa índices se o argumento LIKE não iniciar
com um meta caracter.
mSQL Usar CLIKE.
Manipulando Espaços Excessivos
MySQL Remove todos os espaços no final de colunas CHAR e VARCHAR. Utilize uma
coluna TEXT se o comportamento citado não é desejado.
mSQL Mantém os espaços excessivos.
Cláusulas WHERE
MySQL O MySQL prioriza tudo (AND é avaliado antes de OR). Para obter o comparta-
mento do mSQL no MySQL, use parenteses (como visto no exemplo abaixo).
mSQL Avalia tudo da esquerda para a direita. Isto significa que alguns calculos lógicos
com mais de tres argumentos não pode ser expressados. Também significa que
você deve alterar algumas queries quando você atualizar para o MySQL. Você
pode fazer isto facilmente adicionando parênteses. Suponha que você tenha a
seguinte consulta mSQL:
Chapter 1: Informações gerais sobre o MySQL 67
mysql> SELECT * FROM tabela WHERE a=1 AND b=2 OR a=3 AND b=4;
Para fazer com que o MySQL avalie a sentença da maneira que o mSQL faria,
você deve adicionar parênteses:
mysql> SELECT * FROM tabela WHERE (a=1 AND (b=2 OR (a=3 AND (b=4))));
Controle de Acesso
MySQL Tem tabelas para armazenar opções de privilégios (permissões) por usuário,
máquina e banco de dados. See hundefinedi [Privileges], page hundefinedi.
mSQL Tem um arquivo ‘mSQL.acl’ em que você pode conceder privilégios de leitura/
escrita para usuários.
• O MySQL é codificado desde o ínicio para ser multi-thread enquando o PostgreSQL usa
processos. Troca de contexto e acesso a áreas comuns de armazenamento é muito mais
rápido entre threads do que entre processos separados, isto fornece ao MySQL uma
grande vantagem em velocidade em aplicações multi-usuárias e também torna muito
mais fácil para o MySQL obter vantagem total de sistemas de multiprocessamento
simétrico (SMP).
• O MySQL tem um sistema de privilégios muito mais sofisticado do que o PostgreSQL.
Enquanto o PostgreSQL suporta permissões somente para INSERT, SELECT e
UPDATE/DELETE por usuário em um banco de dados ou uma tabela, o MySQL permite
que você defina um conjunto completo de diferentes privilégios nos bancos de dados,
tabelas e campos. O MySQL também lhe permite especificar as combinações de
privilégios por máquina e usuários. See hundefinedi [GRANT], page hundefinedi.
• O MySQL suporta um protocol cliente/servidor comprimido que aumenta a perfor-
mance em conexões lentas.
• O MySQL trabalha com um conceito de “table handler”, e é o único banco de dados
relacional que conhecemos construído neste conceito. Isto permite diferentes tipos de
tabela em baixo nível serem trocadas no mecanismo SQL e cada tipo de tabela ser
otimizado para diferentes características de performace.
• Todos os tipos de tabelas MySQL (exceto InnoDB) são implementados como arquivos
(uma tabela por arquivo), que facilita muito o backup, mudança e deleção e mesmo
conexões simbólicas entre bancos de dados e tabelas, mesmo se o servidor estiver desli-
gado.
• Ferramentas para corrigir e otimizar tabelas MyISAM (o tipo de tabelas MySQL mais
comum). Um ferramenta de reparos só é necessária quando uma corrompimento fisico
do arquivo de dados acontece, normalmente por uma falha no equipamento. Elas
permitem que a maioria dos dados sejam recuperados.
• Atualizar o MySQL é indolor. Quando você estiver atualizando o MySQL, não precisará
de apagar/restaurar os seus dados, como você deve fazer na maioria das atualizações
do PostgreSQL.
Desvantagens do MySQL em comparação ao PostgreSQL:
• O suporte a transação no MySQL não é tão bem testado como no sistema PostgreSQL.
• Como o MySQL utiliza threads, os quais ainda não estão comple-
tos em vários Sistemas Operacionais, deve-se também usar binários de
http://www.mysql.com/downloads, ou cuidadosamente seguir nossas instruções em
http://www.mysql.com/doc/I/n/Installing_source.html para obter um binário
otimizado que funcione em todos os casos.
• Bloqueios de tabelas, usados pelas tabelas não transacionais MyISAM é, em muitos
casos, mais rápidos que bloqueios de páginas, bloqueios de registros ou versionamento.
A desvantagem entretanto é que se alguém não levar em consideração como funciona
o bloqueio de tabelas, simplesmente, uma única query que demora muito tempo para
executar, pode bloquear uma tabela para atualizações por um grande tempo. Isto
pode ser evitado quando for desenhar a aplicação. Se não, pode-se sempre trocar a
tabela e utilizar uma das tabelas do tipo transacional. See hundefinedi [Table locking],
page hundefinedi.
Chapter 1: Informações gerais sobre o MySQL 71
• Com o UDF (Funções definidas pelo usuário) pode-se extender o MySQL com funções
SQL normais e agregadas, mas isto ainda não é tão fácil e flexível como no PostgreSQL.
See hundefinedi [Adding functions], page hundefinedi.
• Atualizações e remoções que executam sobre multíplas tabelas são mais difíceis para
serem feitas no MySQL. Isto irá, entretanto, ser corrigido no MySQL 4.0 com DELETE
multi tabelas e UPDATE multi tabelas e no MySQL 4.1 com subselects.
O PostgreSQL atualmente oferece as seguintes vantagens sobre o MySQL:
Note que como conhecemos o mapa do MySQL, nós incluímos na seguinte tabela a versão
na qual o MySQL deve suportar o recurso. Infelizmente nós não podemos fazer isto em na
comparação anterior, porque nós não conhecemos o mapa do PostgreSQL.
Recurso versão MySQL
Subselects 4.1
Foreign keys (Chaves Estrangeiras) 4.0 e 4.1
Views 4.2
Stored procedures 4.1
Sistemas de tipos extensivos Sem planejamento
Unions 4.0
Full join 4.0 or 4.1
Triggers 4.1
Constrainst 4.1
Cursores 4.1 or 4.2
Tipos de indices extensivos como R-trees R-trees estao planejados
para 4.2
Tabelas com herança Sem planejamento
Outras razões para usar o PostgreSQL:
• O uso comum do PostgreSQL é mais próximo ao ANSI SQL em alguns casos.
• O PostgreSQL pode ficar mais rápido codificando coisas como stored procedures.
• PostgreSQL tem uma equipe de desenvolvedores maior que contribuem com o servidor.
Desvantagens do PostgreSQL comparado ao MySQL:
• A cláusula VACUUM() dificulta o uso do PostgreSQL em um ambiente 24/7.
• Somente tabelas transacionais.
• INSERT, DELETE UPDATE muito mais lentos.
Para uma lista completa de desvantagens, você deve também examinar a primeira tabela
nesta seção.
Por isto, nós, os desenvolvedores do MySQL gastamos várias horas para obter performance
máxima do PostgreSQL para os benchmarks, mas como não conhecemos PostgreSQL inti-
mamente, temos certeza que existem detalhes que podem ter sido esquecidos. Nós temos
na página de testes em nosso site a documentação de como fizemos os testes para que seja
fácil para qualquer um repetir e verificar nossos resultados.
Os testes comparativos são normalmente executados com e sem a opção --fast. Quando
executado com --fast nós estamos tentando usar todos os truques que o servidor pode
fazer para que o código execute o mais rápido possível. A idéia é que a execução normal
deve mostrar como o servidor deve trabalhar numa configuração padrão e a execução com
--fast mostra como o servidor comportaria se o desenvolvedor da aplicação usar extensões
no servidor para fazer sua aplicação executar mais rápida.
Quando executando com o PostgreSQL e --fast nós fazemos um VACUUM depois de quase
todos maiores UPDATE e DROP TABLE para deixar o banco de dados em forma perfeita para
as SELECTs seguintes. O tempo para VACUUM() é medido separadamente.
Quando executando com o PostgreSQL 7.1.1 não podemos, entretando, executar com --
fast porque durante o teste de INSERT, o postmaster (daemon do PostgreSQL) finalizou
e o banco de dados ficou tão corrompido que se tornou impossível reiniciar o postmaster.
Depois disto ter acontecido duas vezes, decidimos adiar o teste com o --fast até a próxima
versão do PostgreSQL. Os detalhes sobre a máquina na qual executamos o teste pode ser
encontrado na página de testes comparativos em nosso site.
Antes de irmos para os outros testes comparativos que conhecemos, gostariamos de fornecer
algumas informações sobre os testes:
É muito fácil escrever um teste demonstrando que ALGUM banco de dados é o melhor do
mundo, restringindo o teste apenas a alguma parte em que o banco de dados seja muito
bom e não testar outras partes que podem não ser. Se alguém publica os resultados com
uma simples figuração as coisas se tornam mais fáceis ainda.
Seria como nós medíssemos a velocidade do MySQL comparada ao PostgreSQL olhando
para o resumo de tempo dos testes do MySQL na nossa página. Desta forma o MySQL
poderia ser 40 vezes mais rápido que o PostgreSQL, algo que com certeza não é verdade.
Poderíamos deixar a coisa ainda pior se pegássemos o teste onde o PostgreSQL atuou pior
e falar que o MySQL é mais de 2000 vezes mais rápido que o PostgreSQL.
O caso é que o MySQL faz várias otimizações que o PostgreSQL não faz. É claro que isto
também é verdade do outro ladoa. Um otimizador SQL é uma coisa muito complexa e uma
empresa pode gastar anos apenas para deixar o otimizador cada vez mais rápido.
Se você estiver consultando os resultados dos testes procure por coisas que sua aplicação
utilize e use estes resultados apenas para decidir qual banco de dados será o melhor para a
sua aplicação. Os resultados dos testes comparativos também mostram onde um banco de
dados em particular não é bom e deve lhe fornecer uma noção sobre coisas que devem ser
evitadas e o que você deve fazer de outras maneiras.
Conhecemos dois testes comparativos que mostram o PostgreSQL com mais velocidade que
o MySQL. Os dois são testes multi-usuários, um teste que nós da MySQL AB ainda não
tivemos tempo para desenvolver e incluir no conjunto de testes comparativos principalmente
porque é uma enorme tarefa fazer isto de uma maneira justa para todos os bancos de dados.
Um é o teste comparativo pago da Great Bridge, o qual você pode ler a respeito em:
http://www.greatbridge.com/about/press.php?content_id=4.
Chapter 1: Informações gerais sobre o MySQL 73
Este é provavelmente o pior software de testes que já vimos alguem conduzir. Ele não só
foi preparado para testar exatamente o que o PostgreSQL tem de melhor, mas além disso
foi também injusto contra todos os outros bancos de dados envolvidos no teste.
NOTA: Sabemos que nem mesmo alguns dos principais desenvolvedores do PostgreSQL
gostam da maneira que a Great Bridge conduziu os testes comparativos, então não os
culpamos pela maneira que os testes foram realizados.
Este comparativo tem sido condenado em várias mensagens postadas em listas de discussões
portanto falaremos aqui apenas das coisas que estavam erradas com ele.
• Os testes foram executados com uma cara ferramenta comercial, que torna impossível
para uma empresa open source como nós confirmar os resultados , ou mesmo conferir
como os testes realmente foram feitos. A ferramenta nem mesmo é uma ferramenta
de testes comparativos de verdade, mas uma ferramenta de testes de aplicações e con-
figuração. Dizer que ela é uma ferramenta “padrão” de testes comparativos é esconder
a verdade.
• A própria Great Bridge admitiu que eles otimizaram os testes para o banco de dados
PostgreSQL (com VACUMM() antes dos testes) e preparou os testes, coisa que não foi feita
para nenhum dos outros bancos de dados envolvidos. Para dizer “Este processo otimiza
índices e libera um pouco de espaço em disco. Os índices otimizados aumentaram a
velocidade em alguns casos.” Nossos testes claramente indicam que a diferença em
executar várias selects em um banco de dados com e sem VACUUM() pode facilmente
diferenciar de um fator de dez.
• Os resultados dos testes também foram estranhos. A documenção do teste AS3AP
menciona que o teste faz “seleções, joins simples, projeções, agregados, atualizações de
uma tupla e atualizações em massa (bulk updates)”.
O PostgreSQL é bom fazendo SELECTs e JOINs (especialmente depois de um VACUUM(),
mas não atua tão bem em INSERTs ou UPDATEs. Os comparativos parecem indicar que
somente SELECTs foram feitos (ou muito poucas atualizações). Isto pode facilmente
explicar porque os resultados foram tão bons para o PostgreSQL neste teste. Os maus
resultados para o MySQL obviamente rebaixa este documento.
• Eles executaram o tão chamado benchmark de uma máquina Windows acessando uma
máquina Linux sobre ODBC, uma configuração que nenhum usuário de banco de dados
comum faria se estive executando uma aplicação pesada multi-usuária. Isto testou mais
o driver ODBC e o protocolo Windows usado entre os clientes do que o próprio banco
de dados.
• Executando o banco de dados contra o Oracle e o MS-SQL (A Great Bridge indicou
indiretamente os bancos de dados que eles usaram no teste), eles usaram o ODBC
no lugar do protocolo nativo. Qualquer um que já tenha usado o Oracle sabe que
aplicações reais devem usar a interface nativa e não ODBC. Fazer um teste através de
ODBC e reinvidicar que os resultados não teinham relação alguma com as situações de
uso na vida real não deve ser tomado como justo. Eles deveriam ter feito dois testes
com e sem ODBC para fornecer o fatos reais (depois de contratar expecialistas para
preparar os bancos de dados involvidos).
• A Great Bridge faz referencias aos testes TPC-C, mas não mencionam em lugar algum
que o teste que fizeram não foi realmente um teste TPC-C e eles nem mesmo estavam
permitidos a chamare-no de teste TPC-C. Um teste TPC-C só pode ser conduzido
74 Referência técnica para o MySQL versão 3.23.52
As coisas mudaram com o tempo e os testes acima não são mais relevantes. O MySQL
agora tem alguns diferentes manipuladores de tabela com diferente custo-benefício de ve-
locidade/concorrencia. See hundefinedi [Table types], page hundefinedi. Seria interessante
ver como os testes anteriores poderiam executar com os diferentes tipos de tabelas transa-
cionais no MySQL. É claro que o PostgreSQL também ganhou novos recursos desde que o
teste foi feito. Como o teste acima não foi publicamente disponível não existe forma para
nós sabermos como o banco de dados poderá atuar nos mesmos testes hoje.
Conclusão:
Os únicos benchmarks que existem hoje que qualquer um pode baixar e executar contra o
MySQL e o PostgreSQL são os testes MySQL. Nós, na MySQL, acreditamos que bancos de
dados com código aberto devem ser testados com ferramentas de código aberto! Este é o
único modo para assegurar que ninguém faça testes que não possam ser reproduzidos e os
use para alegar que um banco de dados é melhor que o outro. Sem conhecer todos os fatos
é impossível responder às alegações do testador.
O que achamos estranho é que todos os testes que temos visto sobre o PostgreSQL, que
é impossível de ser reproduzido, alega que o PostgreSQL é melhor na maioria dos casos
enquanto em nossos testes, que qualquer um pode reproduzir, mostra claramente o contrário.
Com isto nós não queremos dizer que o PostgreSQL não é bom em várias coisas (ele é!)
ou que ele não é mais rápido que o MySQL sobre certas condições. Nós só gostariamos
de ver um teste justo que seja realmente muito bom, para que então pudessemos ter uma
competição amigável!
Para maiores informações sobre nosso pacote de testes See hundefinedi [MySQL Bench-
marks], page hundefinedi.
Estamos trabalhando em um pacote de testes ainda melhor, incluindo testes multi usuários,
e uma melhor documentação do que os testes individuais realmente fazem e como adicionar
mais testes ao pacote.
A seção de novidades para a 4.0 inclui uma lista dos recursos que nós já implementamos na
árvore 4.0. See hundefinedi [News-4.0.x], page hundefinedi.
• Novo formato do arquivo de definição de tabela (arquivos .frm). Isto nos permitirá
que não tenhamos problemas de bits quando adicionarmos mais opções de tabelas. O
formato antigo .frm ainda poderá ser usado com o 4.0. Todas novas tabelas, entretanto,
usarão o novo formato.
O novo formato de arquivo permitirá adicionar novos tipos de colunas, mais opções
para chaves e suporte a Chave Estrangeira.
• mysqld como uma biblioteca. Isto terá a mesma interface como o cliente padrão MySQL
(com uma função extra para configurar apenas parâmetros de inicialização) mas será
mais rápido (sem sobrecarga do TCP/IP ou do socket), menor e mais fácil para usar
para produtos embutidos.
Poderemos definir em tempo de ligação se queremos usar o modelo cliente/servidor ou
uma aplicação isolada apenas definindo com qual biblioteca deve ser ligada.
O mysqld irá suportar todos recursos padrão do MySQL e podemos usá-lo num cliente
que suporte threads para executar diferentes consultas em cada thread.
• A replicação deve trabalhar com RAND() e variáveis de usuário @var.
• Backup Online com penalidade mínima de performance. O backup online irá facilitar
para adicionar um novo escravo de replicação sem ter que desligar o mestre.
• DELETE FROM nome_tabela irá retornar o número de linhas apagadas. Para execução
mais rápida use TRUNCATE nome_tabela.
• Permite que DELETE em tabelas MyISAM use o cache de registros. Para fazer isto,
precisaremos atualizar os threads de cache de registros quando atualizarmos o arquivo
.MYD
• Melhor replicação.
• Mais funções para pesquisas textuais. See hundefinedi [Fulltext Features to Appear in
MySQL 4.0], page hundefinedi.
• Elenco de conjuntos de caracteres e sintaxe para manipular multiplos conjunto.
• Permite usuários para alterar opções de inicialização sem parar o servidor.
• Ajuda para todos comandos no cliente.
• Conexões seguras (com SSL).
• Extender o otimizador para otimizar algumas consultas ORDER BY key_name DESC
• SHOW COLUMNS FROM nome_tabela (usado pelo cliente mysql para permitir expansões
de nomes de colunas) não deve abrir a tabela, mas somente o arquivo de definição. Isto
irá exigir menos memória e será mais rápido.
• Nova chave de cache
• Quando usar SET CHARACTER SET devemos traduzir a toda consulta e não somente
strings. Isto irá habilitar os usuários para usarem os caracteres traduzidos no banco de
dados, nome de colunas e tabelas.
• Adicionar uma interface portável sobre gethostbyaddr_r() para que possamos alterar
ip_to_hostname() para não bloquear outras threads enquanto faz consultas DNS.
• Adicionar o método record_in_range() para tabelas MERGE para ser possível escolher
o índice correto quando existir vários que possam ser escolhidas. Devemos também
Chapter 1: Informações gerais sobre o MySQL 77
• Se você executar um ALTER TABLE em uma tabela que é ligada simbolicamente a outro
disco, criar tabelas temporárias neste disco.
• Implementar um tipo DATE/DATETIME para manipular fusos horários corretamente para
lidarmos mais facilmente com datas em diferentes fusos horários.
• FreeBSD e MIT-pthreads; Deixar threads “dormindo” exigem processamento?
• Conferir se threads travadas exige processamento
• Corrigir o configure para que ele possa compilar todas as bibliotecas (como a MyISAM)
sem threads.
• Adicionar uma opção para periodicamente descarregar páginas chave para tabelas com
chaves atrasadas se elas não forem usadas em um certo espaço de tempo.
• Permitir “join” em partes de chaves (questão de otimização).
• INSERT SQL_CONCURRENT e mysqld --concurrent-insert para fazer inserções concor-
rentes no final do arquivo se o arquivo for travado para leitura.
• Armazenar definições de chaves ESTRANGEIRAS no arquivo ‘.frm’.
• Cascatear o DELETE
• Cursores do lado do servidor.
• Conferir se o lockd trabalha com kernels Linux mais modernos; Se não nós teremos
que corrigir o lockd! Para testar isto, inicie mysqld com --enable-locking e execute
os diferentes pacotes de testes fork*. Se eles não retornarem erros, lockd funciona.
• Permite variáveis SQL no LIMIT, como em LIMIT @a,@b.
• Permite atualização de variáveis nas instruções UPDATE. Por exemplo: UPDATE TABLE
foo SET @a=a+b,a=@a, b=@a+c
• Alterar quando variáveis de usuários são atualizadas para ique possam ser usadas com
GROUP BY, como no exemplo seguinte : SELECT id, @a:=count(*), sum(sum_col)/@a
FROM nome_tabela GROUP BY id.
• Não adicionar valores DEFAULT para as colunas. Isto retorna um erro quando se usa
um INSERT que não contenha uma coluna não tenham um DEFAULT.
• Cache de pesquisas e resultados. Isto deve ser feito como um módulo separado que
examina cada pesquisa e se a mesma estiver no cache o resultado memorizado deve
ser retornado. Quando alguém atualiza uma tabela deve se remover algumas queries
do cache. Isto deverá fornecer um grande incremento de velocidade em máquinas com
bastante memória onde pesquisas são muito repetidas (como aplicações WWW). Uma
idéia seria armazenar no cache somente pesquisas do tipo: SELECT CACHED ...
• Corrigir ‘libmysql.c’ para permitir dois comandos mysql_query() em uma linha sem
ler os resultados ou fornecer uma mensagem de erro quando alguém o fizer.
• Otimizar o tipo BIT para ocupar 1 bit (hoje BIT ocupa 1 char).
• Checar porque MIT-pthreads ctime() não funciona em alguns sistemas FreeBSD.
• Adicionar uma opção IMAGE para LOAD DATA INFILE para não atualizar campos
TIMESTAMP e AUTO_INCREMENT.
• Adicionar sintaxe LOAD DATE INFILE... UPDATE.
• Para tabelas com chaves primárias, se os dados contêm a chave primária, entradas
que combinem com a chave primária são atualizadas do resto das colunas. Entre-
tanto, colunas FALTANDO na entrada de dados não são mudadas.
Chapter 1: Informações gerais sobre o MySQL 79
• Para tabelas com chaves primárias que falta alguma parte da chave na entrada de
dados, ou que não tenha chave primária, a entrada é tratada como em LOAD DATA
INFILE ... REPLACE INTO.
• Fazer o LOAD DATA INFILE entender sintaxes do tipo:
LOAD DATA INFILE ’file_name.txt’ INTO TABLE nome_tabela
TEXT_FIELDS (text_field1, text_field2, text_field3)
SET table_field1=concatenate(text_field1, text_field2), table_field3=23
IGNORE text_field3
Isto pode ser usado para saltar colunas extras no arquivo texto, ou
atualizar colunas baseadas em express~
oes dos dados lidos...
• LOAD DATA INFILE ’file_name’ INTO TABLE ’nome_tabela’ ERRORS TO err_nome_
tabela Esta forma permite que quaisquer erros e avisos sejam logados na tabela
err nome tabela. Essa tabela deve ter uma estrutura como:
line_number - Número da linha no arquivo de dados
error_message - A mensagem de erro/aviso
e talvez
data_line - A linha do arquivo de dados
• Adicionar real suporte a VARCHAR (Já existe suporte para isto no MyISAM).
• Saída automática do mysql para o netscape.
• LOCK DATABASES. (com várias opções)
• Alterar ordenação para alocar memória em “grandes partes” para conseguir melhor
utilização de memória.
• Tipos DECIMAL e NUMERIC não podem ler números exponenciais; Field_
decimal::store(const char *from,uint len) deve ser reescrito para corrigir
isto.
• Funções: ADD TO SET(valor,conjunto) e REMOVE FROM SET(valor,conjunto)
• Adicionar uso de t1 JOIN t2 ON... e t1 JOIN t2 USING ... Atualmente, você só pode
usar esta sintaxe com LEFT JOIN.
• Adicionar suporte pleno para o tipo unsigned long long.
• Várias variáveis a mais para show status. Contadores para: Instruções
INSERT/DELETE/UPDATE. Registros lidos e atualizados. Selects em 1 tabela e selects
com joins. Número real de tabelas em uma select. Número de consultas ORDER BY e
GROUP BY.
• Se você abortar o mysql no meio de uma pesquisa, você deve abrir outra conexão e
matar a pesquisa antiga. Alternativamente, deve ser feita uma tentativa para detectar
isto no servidor.
• Adicionar uma interface de manioulação para as informações de tabelas para que se
possa usá-la como uma tabela de sistema. Pode se tornar um pouco lento se forem
requisitadas informações sobre todas as tabelas, mas muito flexível. SHOW INFO FROM
nome_tabela para informações básicas de tabelas devem também ser implementadas.
• Adicionar suporte para UNICODE.
• NATURAL JOIN e UNION JOIN
80 Referência técnica para o MySQL versão 3.23.52
• Permitir select A from crash_me left join crash_me2 using (A); Neste caso A é
assumido para vir da tabela crash me.
• Corrigir o ON e USING para funcionar com o tipo de união JOIN.
• CONNECT BY PRIOR ..., como Oracle, para psquisas em estruturas hierárquicas.
• mysqladmin copy database new-database. – Nececssita do comando COPY para ser
adicionado ao mysqld
• Lista de processos deve exibir número de consultas/thread.
• SHOW HOSTS exibirá informações sobre o cache de nomes de máquinas.
• Opções DELETE e REPLACE para a instrução UPDATE (esta opção apagará registros quando
um erro de chave duplicada for obtido durante a atualização.
• Alterar o formato de DATETIME para armazenar frações de segundos.
• Adicionar todos os tipos ANSI92 e ODBC 3.0 que ainda faltam.
• Alterar nomes de tabelas de strings vazias para NULL para colunas calculadas.
• Não usar ’Item copy string’ em valors numéricos para evitar conversão de número-
>string->número no caso de: SELECT COUNT(*)*(id+0) FROM nome_tabela GROUP BY
id
• Tornar possível o uso da nova biblioteca GNU regexp em vez da atual (A biblioteca
GNU deve ficar muito mais rápida do que a atual).
• Alterar o ALTER TABLE para que não aborte clientes que executam INSERT DELAYED.
• Corrigir quando as colunas referenciadas em uma cláusula UPDATE contém os valores
antigos antes da atualização iniciar.
• myisamchk, REPAIR e OPTIMIZE TABLE devem conseguir tratar casos onde os arquivos
de dados e/ou índices são links simbólicos.
• Adicionar simulação de pread()/pwrite() no Windows para habilitar inserções si-
multâneas.
• Um analisador de arquivos log que podem analisar informações sobre quais tabelas
são acessadas mais frequentemente, qual a frequência que joins de multi-tabelas são
executadas, etc. Ele deverá ajudar os usuários a identificar áreas ou projetos de tabelas
que poderão ser otimizadas para executar consultas muito mais eficientes.
• Adicionar SUM(DISTINCT)
• Adicionar funções de grupo ANY(),EVERY() e SOME(). Em ANSI SQL isto só fun-
ciona em colunas boleanas, mas nós podemos extendê-las para trabalhar em qualquer
coluna/expressão aplicando: valor == 0 -> FALSO e valor <> 0 -> TRUE.
• Corrigir o tipo para MAX(coluna) ser o mesmo que o tipo da coluna.
create table t1 (a DATE);
insert into t1 values (now());
create table t2 select max(a) from t1;
show columns from t2;
• Vir com uma nova sintaxe para uma expressão que irá fazer um UPDATE no registro se
ele existir e fazer um INSERT de um novo registro se o mesmo não existir. (Como o
REPLACE trabalha com INSERT / DELETE)
Chapter 1: Informações gerais sobre o MySQL 81
• Stored procedures. Atualmente isto não é tratado com muito importante já que as
stored procedures não estão muito bem padronizadas ainda. Outro problema é que
verdadeiras stored procedures dificultam muito o otimizador e em vários casos o resul-
tado é mais lento que antes. Nós iremos, por outro lado, adicionar uma linguagem de
atualização (atômica) simples que pode ser usada para escrever loops e semelhantes no
servidor MySQL.
• Alterar para o uso de semáforos quando contar threads. Devemos primeiro implementar
uma biblioteca de semáforos para a MIT-pthreads.
• N0ão atribuir novos valores AUTO_INCREMENT quando alguém configurar uma coluna
para 0. No lugar disto usar NULL.
• Adicionar suporte pleno para JOIN com parênteses.
• Como uma alternativa para uma thread / conexão gerencie uma fila de threads para
manipular as pesquisas.
• Permitir obter mais de um bloqueio com GET_LOCK. Quando isto for feito, serão,
também, tratados os possíveis deadlocks que essa alteração irá acarretar.
Tempo é fornecido de acordo com a quantidade de trabalho, e não tempo real.
2 Instalação do MySQL
Este capítulo descreve como obter e instalar o MySQL:
• Para uma lista de sites no quais você pode obter o MySQL, veja hundefinedi [Getting
MySQL], page hundefinedi.
• Para saber quais são as plataformas suportadas, veja em hundefinedi [Which OS],
page hundefinedi. Por favor perceba que nem todas as plataformas suportadas são
igualmente boas para executar o MySQL. Algumas são mais robustas e eficientes que
outras - ver hundefinedi [Which OS], page hundefinedi para detalhes.
• Várias versões do MySQL estão disponíveis em distribuições binárias e fonte. Nós
também fornecemos acesso público à nossa árvore fonte atual para aqueles que desejam
ver nossos desenvolvimentos mais recentes e nos ajudar a testar novos códigos. Para
determinar que versão e tipo da distribuição você deve usar, veja hundefinedi [Which
version], page hundefinedi. Se ainda restar dúvidas, use a distribuição binária.
• Instruções de instalação para distribuições binária e fonte são descritos em hundefinedi
[Installing binary], page hundefinedi e hundefinedi [Installing source], page hundefinedi.
Cada conjunto de instruções inclui uma seção sobre problemas específicos de sistemas
que você pode precisar.
• Para procedimentos pós-instalação, veja hundefinedi [Post-installation], page hunde-
finedi. Estes procedimentos podem ser aplicados caso você use uma distribuição binária
ou fonte do MySQL.
• MySQL-devel-VERSION.i386.rpm
Bibliotecas e arquivos include necessários se você desejar compilar outros clientes
MySQL, como nos módulos Perl.
• MySQL-VERSION.src.rpm
Este contém o código fonte para todos os pacotes acima. Ele também pode ser usado
para tentar construir RPMs para outras arquiteturas (por exemplo, Alpha ou SPARC).
Para ver todos os arquivo em um pacote RPM, execute:
shell> rpm -qpl MySQL-VERSION.i386.rpm
Para realizar uma instalação mínima padrão, execute:
shell> rpm -i MySQL-VERSION.i386.rpm MySQL-client-VERSION.i386.rpm
Para instalar somente o pacote cliente, execute:
shell> rpm -i MySQL-client-VERSION.i386.rpm
O RPM coloca dados em ‘/var/lib/mysql’. O RPM também cria as entradas apropriadas
em ‘/etc/rc.d/’ para iniciar o servidor automaticamente na hora do boot. (Isto significa
que se você realizou uma instalação anterior, talvez você deseje criar uma cópia do seu
arquivo de inicialialização instalado anteriormente se você fez alguma alteração no mesmo,
para que você não perca suas alterações.)
Depois de instalar o(s) arquivo(s) RPM, o daemon mysqld deve estar rodando e você já
deve poder iniciar o uso do MySQL. See hundefinedi [Post-installation], page hundefinedi.
Se alguma coisa der errado, você encontrar maiores informações no capítulo de instalação.
See hundefinedi [Installing binary], page hundefinedi.
que você deve especificar todos caminhos com ‘/’ em vez de ‘\’. Se você usar ‘\’, você
precisa especificá-lo dobrado, porque ‘\’ é o caractere escape no MySQL. See hundefinedi
[Option files], page hundefinedi.
Iniciado com o MySQL 3.23.38, a distribuição Windows inclui ambos binários, normal e o
MySQL-Max. O principal benefício de usar o binário normal mysqld.exe é que ele é um
pouco mais rápido e usa menos menos recursos.
Aqui está uma lista dos diferentes servidores MySQL que você pode usar:
mysqld Compilado com debugger integral e conferência automática de
alocação de memória, links simbólicos, BDB e tabelas InnoDB.
mysqld-opt Binário otimizado sem suporte para tabelas transacionais.
mysqld-nt Binário otimizado para Nt com suporte para named pipes. você
pode executar esta versão no Win98, mas neste caso não são cri-
ados named pipes e você deve ter TCP/IP instalado.
mysqld-max Binário otimizado com suporte para links simbólicos, tabelas BDB
e InnoDB.
mysqld-max-nt Como o mysqld-max, porém compilado com suporte para named
pipes.
Incluido a partir da versão 3.23.50, named pipes estará habilitado somente se o mysqld é
iniciado com a opção --enable-named-pipe
Todos os binários acima são otimizados para o processador Pentium Pro mas deve funcionar
em qualquer processador Intel >=i386.
Nota: Se você deseja utilizar as tabelas InnoDB, existem algumas opções de inicialização que
devem ser especificadas no seu arquivo ‘my.ini’ See hundefinedi [InnoDB start], page hun-
definedi
• BSDI 2.x com o pacote incluído MIT-pthreads. See hundefinedi [BSDI], page hunde-
finedi.
• BSDI 3.0, 3.1 e 4.x com threads nativas. See hundefinedi [BSDI], page hundefinedi.
• DEC Unix 4.x com threads nativas. See hundefinedi [Alpha-DEC-UNIX], page hunde-
finedi.
• FreeBSD 2.x com o pacote incluído MIT-pthreads. See hundefinedi [FreeBSD],
page hundefinedi.
• FreeBSD 3.x e 4.x com threads nativas. See hundefinedi [FreeBSD], page hundefinedi.
• HP-UX 10.20 com o pacote incluído MIT-pthreads. See hundefinedi [HP-UX 10.20],
page hundefinedi.
• HP-UX 11.x com as threads nativas. See hundefinedi [HP-UX 11.x], page hundefinedi.
• Linux 2.0+ com LinuxThreads 0.7.1+ ou glibc 2.0.7+. See hundefinedi [Linux],
page hundefinedi.
• Mac OS X Server. See hundefinedi [Mac OS X], page hundefinedi.
• NetBSD 1.3/1.4 Intel e NetBSD 1.3 Alpha (Necessita GNU make). See hundefinedi
[NetBSD], page hundefinedi.
• OpenBSD > 2.5 com threads nativas. OpenBSD < 2.5 com o pacote incluído MIT-
pthreads . See hundefinedi [OpenBSD], page hundefinedi.
• OS/2 Warp 3, FixPack 29 e OS/2 Warp 4, FixPack 4. See hundefinedi [OS/2], page hun-
definedi.
• SGI Irix 6.x com threads nativas. See hundefinedi [SGI-Irix], page hundefinedi.
• Solaris 2.5 e superior com threads nativas nas plataformas SPARC e x86. See hunde-
finedi [Solaris], page hundefinedi.
• SunOS 4.x com o pacote incluído MIT-pthreads. See hundefinedi [Solaris], page hun-
definedi.
• SCO OpenServer com o port recente do pacote FSU Pthreads. See hundefinedi [SCO],
page hundefinedi.
• SCO UnixWare 7.0.1. See hundefinedi [SCO Unixware], page hundefinedi.
• Tru64 Unix
• Win95, Win98, NT e Win2000. See hundefinedi [Windows], page hundefinedi.
Perceba que nem todas as plataformas são apropriadas para executar o MySQL. Os seguintes
fatores determinam se uma certa plataforma é apropriada para uma missão crítica pesada:
• Estabilidade geral da biblioteca thread. Uma plataforma pode ter excelente reputação,
entretanto, se a biblioteca thread é instável no código que é usado pelo MySQL, mesmo
se todo o resto for perfeito, o MySQL irá ser tão estável quanto a biblioteca thread.
• A habilidade do kernel e/ou a biblioteca thread tirar vantagem do SMP em sistemas
multi-processados. Em outras palavras, quando um proceesso cria uma thread, deve
ser possível para aquela thread executar em uma CPU diferente que o processo original.
• A habilidade do kernel e/ou a biblioteca thread executar várias threads que
adiquire/libera um bloqueio mutex sobre uma pequena região crítica frequentemente
sem trocas de contexto excessivos. Em outras palavras, se a implementação de
pthread_mutex_lock() requisitar a CPU muito rapidamente, isto irá afetar o MySQL
Chapter 2: Instalação do MySQL 89
tremendamente. Se esse detalhe não estiver sendo cuidado, adicionar CPUs extras
podem deixar o MySQL mais lento.
• Estabilidade e performance geral do sistema de arquivos.
• Habilidade do sistema de arquivos em lidar com arquivos grandes de forma eficiente,
se suas tabelas forem grandes.
• Nosso nível de experiência aqui na MySQL AB com a plataforma. Se nós conhecemos
bem uma plataforma, introduzimos otimizações/correçoes específicas para ela habili-
tadas na hora da compilação. Nós também podemos fornecer conselhos sobre como
configurar seu sistema otimizadamente para o MySQL.
• O volume de testes feitos internamente de configurações similares.
• O número de usuários que tem executado o MySQL com sucesso naquela plataforma em
configurações similares. Se esse número for alto, as chances de se ter alguma surpresa
específica da plataforma fica muito menor.
Baseado nos critérios acima, as melhores plataformas para a execução do MySQL até este
ponto são o x86 com SuSe Linux 7.1, kernel 2.4 e ReiserFS (ou qualquer distribuição Linux
similar) e Sparc com Solaris 2.7 ou 2.8. FreeBSD vem em terceiro, mas realmente temos
esperanças que ele irá se unir ao clube dos tops uma vez que a biblioteca thread está
melhorando. Nós também acreditamos que em certo ponto iremos estar aptos para incluir
todas as outras plataformas em que o MySQL compila e executa, mas não tão bem e com
o mesmo nível de estabilidade e performance, na categoria superior. Isto necessitará de
algum esforço da nossa parte em cooperação com os desenvolvedores dos componentes do
Sistema Operacional/Biblioteca que o MySQL depende. Se você tiver interesse em melhorar
algum de nossos componentes, está em uma posição para influenciar seu desenvolvimento,
e precisa de instruções mais detalhadas sobre o que o MySQL necessita para uma melhor
execução, envie um e-mail para [email protected].
Por favor, perceba que a comparação acima não é para dizer que um SO é melhor ou pior
que o outro em geral. Nós estamos falando sobre a escolha de um SO para um propósito
dedicado: executar o MySQL, e comparamos as plataformas levando isto em consideração.
Desta forma, o resultado desta comparação seria diferente se nós incluíssemos mais detalhes.
E em alguns casos, a razão de um SO ser melhor que o outro pode ser simplesmente
porque colocamos mais esforço nos testes e otimização para aquela plataforma em particular.
Estamos apenas colocando nossas observações para ajudá-lo na decisão de qual plataforma
usar o MySQL na sua configuração.
que você está usando (onde aenas o último número da versão é mais novo que o seu).
Nós temos tentado corrigir somente erros fatais e torná-los menores, com alterações
relativamente seguras para aquela versão.
A segunda decisão a ser feita é se você deseja usar uma distribuição fonte ou binária. Na
maioria dos casos provavelmente você deverá usar a distribuição binária, se alguma existir
para sua plataforma, será normalmente muito mais fácil para instalar do que a distribuição
em código fonte.
Nos seguites casos você provavelmente será mais bem servido com uma instalação baseada
em código fonte:
• Se você desejar instalar o MySQL em algum lugar expecífico. (O padrão das dis-
tribuições binárias é estar“pronto para rodar” em qualquer lugar, mas talvez você
deseje ainda mais flexibilidade).
• Para estar apto e satisfazer diferentes requisições dos usuários, estaremos fornecendo
duas versões binárias diferentes; Uma compilada com os manipuladores de tabelas não
transacionais (um binário rápido e pequeno) e um configurado com as mais importantes
opções extendidas como tabelas transacionais. Ambas versões são compiladas da mesma
distribuição fonte. Todos clientes MySQL nativos pode conectar com ambas versões do
MySQL.
A distribuição binária extendida é marcada com o sufixo -max e é configurada com as
mesmas opções de mysqld-max. mysqld-max. See hundefinedi [mysqld-max], page hun-
definedi.
Se você deseja usar o RPM MySQL-Max, primeiramente você deve instalar o RPM MySQL
padrão.
• Se você deseja configurar mysqld com alguns recursos extras que NÃO estão nas dis-
tribuições binárias. Segue abaixo a lista das opções extras mais comuns que você pode
querer usar:
• --with-berkeley-db
• --with-innodb
• --with-raid
• --with-libwrap
• --with-named-z-lib (Isto é feito para alguns dos binários)
• --with-debug[=full]
• A distribuição binária padrão é normalmente compilada com suporte para todos con-
juntos de caracteres e deve funcionar em uma variedade de processadores para a mesma
família do processador.
Se você precisar de um servidor MySQL mais rápido você pode querer recompilá-lo com
suporte para somente o conjunto de caracteres que você precisa, usar um compilador
melhor (como pgcc) ou usar opções de compiladores para usar otimizações para seu
processador.
• Se você encontrar um erro e relatá-lo para o time de desenvolvimento do MySQL você
provavelmente receberá um patch que será necessário aplicá-lo para a distribuição fonte
para ter o bug corrigido.
Chapter 2: Instalação do MySQL 91
• Se você deseja ler (e/ou modificar) o código C e C++ que é o MySQL, você pode obter
uma distribuição fonte. O código fonte é sempre o manual final. Distribuições fontes
também contem mais testes e exemplos que as distribuições binárias.
O esquema de nomes do MySQL usa números de versões que consistem de tres números e um
sufixo. Por exemplo, um nome de lançamento como mysql-3.21.17-beta é interpretado
da seguinte maneira:
• O primeiro número (3) descreve o formato dos arquivos. Todas releases da Versão 3
tem o mesmo formato de arquivo.
• O segundo número (21) é o nível da distribuição. Normalmente existem dois para serem
escolhidos. Um é o ramo estável (atualmente 23) e o outro é o ramo de desenvolvimento
(atualmente 4.0). Normalmente ambos são estáveis, mas a versão de desenvolvimento
pode acontecer coisas estranhas, faltar documentação em novos recursos, ou mesmo
não compilar em alguns sistemas.
• O terceiro número (17 é o número da versão do nível de distribuição. Este é incremen-
tado para cada nova distribuição. Normalmente você desejará a última versão para o
nível de publicação que tiver escolhido.
• O sufixo (beta) indica o nível de estabilidade da versão. Os possíveis sufixo são:
− alpha indica que a versão contém grandes seções de novos códigos que não foram
100% testados. Bugs conhecidos (normalmente não tem nenhum) devem estar
documentados na seção News. See hundefinedi [News], page hundefinedi. Existem
também novos comandos e extensões na maioria das publicações alpha. Desen-
volvimento ativo que podem envolver maiores alterações no código pode ocorrer
numa versão alpha, mas tudo será testado antes de fazer a publicação. Não podem
existir erros conhecidos em nenhuma publicação do MySQL.
− beta significa que todo o novo código foi testado. Não serão adicionados novos
recursos que podem causar algum tipo de corrompimento. Não deve existir bugs
conhecidos. Uma alteração de versão de alpha para beta ocorre quando não existir
nenhum relato de erro fatal com uma versão alpha por pelo menos um mês e não
planejarmos adicionar nenhum recurso que pode deixar algum antigo comando
menos confiável.
− gamma é o beta que já tem sido usado a algum tempo e parece funcionar bem.
Apenas pequenas correções são adicionadas. Isto é o que muitas empresas chamam
de release.
− Se não existir um sufixo, significa que esta versão já está sendo executada há
algum tempo em diferentes locais sem relatos de erros além dos específicos de
certas plataformas. Somente correções de erros críticos são adicionados ao release.
Isto é o que chamamos de uma distribuição estável.
Todas as versões do MySQL funcionam sobre nossos testes padrões e comparativos para
garantir que eles são relativamente seguros para o uso. Como os testes padrões são exten-
didos ao longo do tempo para conferir por todos os bugs antigos encontrados, o pacote de
testes continua melhorando.
Perceba que todas publicações de versões foram testadas pelo menos com:
92 Referência técnica para o MySQL versão 3.23.52
Você pode criar sua própria instalação binária da compilação dos fontes executando o script
‘scripts/make_binary_distribution’.
A versão estável atual é a 3.23; nós já mudamos o desenvolvimento em atividade para a
versão 4.0. Bugs contiuarão a ser corrigidos na versão estável. Não acreditamos em um
congelamento completo, pois isto abandona a correções de bugs e coisas que “devem ser
feitas.” “Alguma coisa congelada” significa que talvez possamos adicionar pequenas coisas
que “com certeza não afetará nada que já esteja funcionando.”
94 Referência técnica para o MySQL versão 3.23.52
Na maioria dos sistemas você irá obter um binário rápido e estável com essas opções.
96 Referência técnica para o MySQL versão 3.23.52
Se você tiver problemas, SEMPRE USE mysqlbug quando postar questões para
[email protected]. Mesmo se o problema não for um bug, mysqlbug recolhe
informações do sistema que facilitará aos outros resolverem seu problema. Por não suar
mysqlbug, você perde a vantagem de ter seu problema resolvido! Você irá encontrar
mysqlbug no diretório ‘scripts’ depois de desempacotar a distribuição. See hundefinedi
[Bug reports], page hundefinedi.
11. Se você deseja instalar suporte para a interface Perl DBI/DBD, veja hundefinedi [Perl
support], page hundefinedi.
12. Se você deseja que o MySQL inicie automaticamente quando você ligar sua máquina,
você pode copiar support-files/mysql.server para o local onde seu sistema tem seus
arquivos de incialização. Mais informações podem ser encontradas no próprio script
support-files/mysql.server e em hundefinedi [Automatic start], page hundefinedi.
Depois de tudo ter sido instalado, você deve iniciar e testar sua distribuição:
shell> /usr/local/mysql/bin/safe_mysqld --user=mysql &
Se o comando falhar imediatamente com mysqld daemon ended então você pode achar al-
guma informação no arquivo ‘diretório-dados-mysql/’nome_maquina’.err’. A razão
pode ser que você já possua outro servidor mysqld sendo executado. See hundefinedi [Mul-
tiple servers], page hundefinedi.
See hundefinedi [Post-installation], page hundefinedi.
Aqui LISTA é uma lista de conjuntos de caracteres separados por espaços, complex
para incluir todos caracteres que não podem ser carregados dinamicamente ou all
para incluir todos os conjuntos nos binários.
• Para configurar o MySQL com código para depuração, use a opção --with-debug:
shell> ./configure --with-debug
Isto inclui uma alocação segura de memória que pode encontrar alguns erros e fornecer
saída sobre o que está acontecendo. See hundefinedi [Debugging server], page hunde-
finedi.
• Se seus programas clientes usam threads, você precisará também compilar uma versão
thread-safe da biblioteca cliente do MySQL com as opções do configure --enable-
thread-safe-client. Isto irá criar uma biblioteca libmysqlclient_r com o qual
você deverá ligar suas aplicações que fazem uso de threads. See hundefinedi [Threaded
clients], page hundefinedi.
• Opções que pertençam a sistemas particulares podem ser encontrados na seção com de-
talhes específicos de sistemas neste manual. See hundefinedi [Operating System Specific
Notes], page hundefinedi.
5. Quando a construção estiver pronta, execute make install. Seja cuidadoso com isto
em uma máquina de produção; o comando pode sobrescrever sua versão atual insta-
lada. Se você tem outra instalação do MySQL, nós recomendamos que você execute
./configure com valores diferentes para as opções prefix, tcp-port e unix-socket-
path que as usadas pelo seu servidor em produção.
6. Seja rígido com sua nova instalação e tente fazer com que os novos recursos falhem.
Inicie executando make test. See hundefinedi [MySQL test suite], page hundefinedi.
7. Se você chegar ao estágio make e a distribuição não compilar, por favor relate-o para
[email protected]. Se você instalou as últimas versões das ferramentas GNU
exigidas, e elas falharam tentando processar nossos arquivos de configuração, por fa-
vor informe isto também. Entretanto, se você executar aclocal e obtêm um erro de
command not found não o reporte.Tenha certeza que todas as ferramentas necessárias
estejam instaladas e que sua variável PATH esteja corretamente configurada para que
sua shell possa encontrá-la.
8. Depois da operação inicial bk clone para obter a árvore fonte, você deve executar bk
pull periodicamente para obter as atualizações.
9. Você pode examinar o histórico de alterações para a árvore com todos os diffs usando
bk sccstool. Se você ver alguns diffs estranhos ou código sobre o qual você tenha
alguma dúvida, não hesite em enviar um e-mail para [email protected].
Além disso, se você pensar que tem uma idéia melhor em como fazer algo, envie um
email para o mesmo endereço com um patch. bk diffs irá produzir um patch para
você após fazer as alterações no código fonte. Se você não tiver tempo para codificar
sua idéia, apenas envie uma descrição.
10. BitKeeper tem um ótimo utilitário de ajudar que você pode acessar via bk helptool.
shell> rm config.cache
shell> make clean
Uma alternativa, seria executar make distclean
A lista abaixo descreve alguns dos problemas compilando o MySQL que tem sido encontra-
dos com mais frequencia:
• Se você obtêm erros quando ‘sql_yacc.cc’ como os mostrados abaixo, você provavel-
mente tem de falta de memória ou espaço de swap:
Internal compiler error: program cc1plus got fatal signal 11
ou
Out of virtual memory
ou
Virtual memory exhausted
O problema é que gcc necessita de grande quantidade de memória para compilar
‘sql_yacc.cc’ com funções inline. Tente executando configure com a opção --with-
low-memory:
shell> ./configure --with-low-memory
Esta opção adiciona -fno-inline na a linha de compilação se você estiver usando
gcc e -O0 se você estiver usando outro programa. Você deve tentar a opção --with-
low-memory mesmo se você tiver muita memória e espaço de swap que você ache ser
suficieente para não ocorrer erros. Este problema tem ocorrido mesmo em sistemas
com boas configurações de hardware e a opção --with-low-memory geralmente corrige
isto.
• Por padrão, configure escolhe c++ como o nome do compilador e GNU c++ liga com -
lg++. Se você estiver usando gcc, este comportamento pode causar problemas durante
a compilação, como o seguinte:
configure: error: installation or configuration problem:
C++ compiler cannot create executables.
Você podem também ter problemas durante a compilação relacionados à g++, libg++
ou libstdc++.
Uma causa destes problemas é que você pode não ter g++ ou você pode ter g++ mas não
ter o libg++ ou o libstdc++. De uma olhada no arquivo ‘config.log’. Ele deve conter
a razão exata do porque seu compilador c++ não funciona! Para trabalhar evitando
estes problemas, você pode usar gcc como seu compilador C++. Tente configurar a
variável de ambiente CXX para "gcc -O3". Por exemplo:
shell> CXX="gcc -O3" ./configure
Isto funciona porque gcc compila código fonte C++ tão bem quanto g++ faz, mas não
ifaz a ligação em libg++ ou libstdc++ por padrão.
Outra forma de corrigir estes problemas, com certeza, é instalando g++, libg++ e
libstdc++.
• Se sua compilação falhar com erros, como um dos seguintes, você deve atualizar sua
versão de make para GNU make:
making all in mit-pthreads
make: Fatal error in reader: Makefile, line 18:
Badly formed macro assignment
104 Referência técnica para o MySQL versão 3.23.52
or
make: file ‘Makefile’ line 18: Must be a separator (:
or
pthread.h: No such file or directory
O Solaris e o FreeBSD são conhecidos por terem alguns problemas com o make.
O GNU make versão 3.75 irá funcionar.
• Se você deseja definir algumas opções que devem ser usadas pelo seu compilador C ou
C++, adicione as opções para as variáveis de ambiente CFLAGS e CXXFLAGS. Você pode
também especificar os nomes do compilador a ser usado da mesma forma utilizando CC
e CXX. Exemplo:
shell> CC=gcc
shell> CFLAGS=-O3
shell> CXX=gcc
shell> CXXFLAGS=-O3
shell> export CC CFLAGS CXX CXXFLAGS
Olhe em hundefinedi [MySQL binaries], page hundefinedi para uma lista de definição
de opções que tenham sido úteis em vários sistemas.
• Se você recebeu uma mensagem de erro como esta, é necessário atualizar o compilador
gcc:
client/libmysql.c:273: parse error before ‘__attribute__’
O gcc 2.8.1 funciona, mas recomendamos o uso do gcc 2.95.2 ou egcs 1.0.3a em seu
lugar.
• Se você obtem erros como estes vistos abaixo enquanto estiver compilando o mysqld,
o configure não detectou corretamente o tipo do último argumento para accept(),
getsockname() ou getpeername():
cxx: Error: mysqld.cc, line 645: In this statement, the referenced
type of the pointer value "&length" is "unsigned long", which
is not compatible with "int".
new_sock = accept(sock, (struct sockaddr *)&cAddr, &length);
Para corrigir isto, edite o arquivo ‘config.h’ (que é gerado pelo configure). Procure
por estas linhas:
/* Define as the base type of the last arg to accept */
#define SOCKET_SIZE_TYPE XXX
Altere XXX para size_t ou int, dependendo de seu sistema operacional. (Perceba
que você deverá fazer isto cada vez que você executar configure, porque configure
regenera ‘config.h’.)
• O arquivo ‘sql_yacc.cc’ é gerado pelo ‘sql_yacc.yy’. Normalmente o processo de
construção não necessita criar ‘sql_yacc.cc’, porque o MySQL já vem com uma cópia
pré-gerada. Entretanto, se você necessita recriá-lo você pode encontrar este erro:
"sql_yacc.yy", line xxx fatal: default action causes potential...
Isto é um indício de que sua versão do yacc é deficiente. Provavelmente você precisará
instalar o bison (a versão GNU de yacc) e usá-lo no lugar do yacc.
• Se você necessita depurar mysqld ou um cliente MySQL, execute configure com a
opção --with-debug, então recompile e ligue seus clientes com a nova biblioteca cliente.
See hundefinedi [Debugging client], page hundefinedi.
Chapter 2: Instalação do MySQL 105
você pode pular este passo. (entretanto, mysql_install_db é realmente seguro de usar
e não irá atualizar nenhuma tabela que já exista, então se você não tem certeza do que
fazer, você pode sempre executar mysql_install_db.)
mysql_install_db cria seis tabelas (user, db, host, tables_priv, columns_priv e
func) no banco de dados mysql. Uma descrição dos privilégios iniciais é fornecido
em hundefinedi [Default privileges], page hundefinedi. De forma resumidao, estes
privilégios permitem que o usuário root faça qualquer coisa no MySQL, e permitem a
qualquer um a criar ou usar bancos de dados com o nome de ’test’ ou iniciando com
’test_’ .
Se você não configurar as tabelas de concessões, o seguinte erro irá aparecer no arquivo
log quando você não iniciar o servidor:
mysqld: Can’t find file: ’host.frm’
O erro acima pode também ocorrer com uma distribuição binária do MySQL se você não
iniciar o MySQL executando o ./bin/safe_mysqld! See hundefinedi [safe_mysqld],
page hundefinedi.
Você deve precisar executar mysql_install_db como root. Entretanto, se você
preferir, pode executar o servidor MySQL como um usuário (não-root) sem
privilégios, desde que o usuário possa ler e escrever arquivos no diretório de banco
de dados. Instruções para executar o MySQL como um usuário sem privilégios é
detalhado em hundefinedi [Alterando usuários MySQL], page hundefinedi
Se você tiver problemas com o mysql_install_db, veja hundefinedi [mysql_install_
db], page hundefinedi.
Existem algumas alternativas para executar o script mysql_install_db como ele é
fornecido na distribuição MySQL:
• Você pode querer editar o mysql_install_db antes de executá-lo, para alterar os
privilégios iniciais que são instalados nas tabelas de concessões. Isto é útil se você
deseja instalar o MySQL em várias máquinas com os mesmos privilégios. Neste
caso, é provável que você só precise adicionar algumas instruções INSERT extras
para as tabelas mysql.user e mysql.db.
• Se você deseja alterar algo na tabelas de concessões depois de instalá-las, você pode
executar mysql_install_db, então usar mysql -u root mysql para conectar às
tabelas de concessões como o usuário root e usar instruções SQL para modificá-las
diretamente.
• É possível recriar as tabelas de permissões completamente depois delas já terem
sido criadas. Você pode querer fazer isto se você já instalou as tabelas mas deseja
recriá-las depois das edições mysql_install_db.
Para maiores informações sobre estas alternativas, veja hundefinedi [Default privileges],
page hundefinedi.
2. Inicie o servidor MySQL assim:
shell> cd diretorio_instalacao_mysql
shell> bin/safe_mysqld &
Se você tiver problemas iniciando o servidor, veja hundefinedi [Starting server],
page hundefinedi.
108 Referência técnica para o MySQL versão 3.23.52
| db |
| func |
| host |
| tables_priv |
| user |
+--------------+
127.0.0.1 localhost
Este problema só ocorre em sistemas que não possuem uma biblioteca thread funcional e
para o qual o MySQL deve estar configurado para usar MIT-pthreads.
Se você não consegue iniciar o mysqld você pode tentar criar um arquivo para rastreamento
de erros (trace) para encontrar o problema. See hundefinedi [Making trace files], page hun-
definedi.
Se você estiver utilizando tabelas InnoDB, procure pelas opções especificas de inicialização
do InnoDB. See hundefinedi [InnoDB start], page hundefinedi.
Se você estiver usando tabelas BDB (Berkeley DB), você deve se familiarizar com as difer-
entes opções especificas de inicialização do BDB. hundefinedi [BDB start], page hundefinedi.
[mysql.server]
basedir=/usr/local/mysql
O script mysql.server entende as seguintes opções: datadir, basedir e pid-file.
A seguinte tabela mostra quais grupos de opções cada script de inicialização lê dos arquivos
de opções:
Script Grupos de opções
mysqld mysqld e server
mysql.server mysql.server, mysqld e server
safe_mysqld mysql.server, mysqld e server
See hundefinedi [Option files], page hundefinedi.
tabela MyISAM com ALTER TABLE nome_tabela TYPE=MyISAM ou com o script Perl mysql_
convert_table_format.
Os clientes versões 3.22 e 3.21 irão trabalhar sem quaisquer problemas com um servidor
versão 3.23.
As seguintes listas dizem o que você deve conferir quando atualizar para a versão 3.23:
• Todas tabelas que usam o conjunto de caracteres tis620 devem ser corrigidos com
myisamchk -r ou REPAIR TABLE.
• Se você fizer um DROP DATABASE em um banco de dados ligado simbolicamente, a ligação
e o banco de dados original serão apagados. (Isto não acontece na 3.22 porque ele não
detecta a chamada de sistema readlink).
• OPTIMIZE TABLE agora funciona somente para tabelas MyISAM. Para outros tipos de
tabelas, você pode usar ALTER TABLE para otimizar a tabela. Durante o OPTIMIZE
TABLE a tabela é, agora, bloqueada para outras threads.
• O cliente MySQL mysql é, agora, inicializado por padrão com a opção --no-named-
commands (-g). Esta opção pode ser desabilitada com --enable-named-commands
(-G). Isto pode causar problemas de imcompatibilidade em alguns casos, por exemplo,
em scripts SQL que usam comandos sem ponto e vírgula! Comandos longos continuam
funcionando.
• Se você estiver usando a ordem de classificação de caracteres alem~
a, você deve reparar
todas suas tabelas com isamchk -r, porque foram feitas alterações na sua ordem de
classificação!
• O tipo padrão de retorno de IF irá agora depender de ambos argumentos e não apenas
do primeiro argumento.
• AUTO_INCREMENT não irá funcionar com números negativos. A razão para isto é que
números negativos causaram problemas quando o -1 passa para 0. AUTO_INCREMENT é,
agora, tratado em um nível mais baixo para tabelas MyISAM e é muito mais rápido
que antes. Para tabelas MyISAM números antigos também não são mais reusados,
mesmo se você apagar algumas linhas da tabela.
• CASE, DELAYED, ELSE, END, FULLTEXT, INNER, RIGHT, THEN e WHEN agora são palavras
reservadas.
• FLOAT(X) agora é um tipo de ponto flutuante verdadeiro e não um valor com um
número fixo de decimais.
• Quando estiver declarando DECIMAL(tamanho,dec o argumento tamanho não inclui
mais um lugar para o símbolo do ponto decimal.
• Uma string TIME agora deve estar em um dos seguintes formatos: [[[DAYS]
[H]H:]MM:]SS[.fraction] ou [[[[[H]H]H]H]MM]SS[.fraction]
• LIKE agora compara strings usando as mesmas regras de comparação de caracteres de
’=’. Se você precisa do antigo compartamento, você pdoe compilar o MySQL com a
opção CXXFLGAS=-DLIKE_CMP_TOUPPER.
• REGEXP agora é caso insensitivo para strings normais (não binárias).
• Quando for necessário dar manutenção/reparar tabelas deve ser usado CHECK TABLE ou
myisamchk para tabelas MyISAM (.MYI) e isamchk para tabelas ISAM (.ISM).
• Se desejar que os arquivos mysqldump sejam compatíveis entre as versões 3.22 e 3.23
do MySQL, não deve ser usados as opções --opt ou --full com o mysqldump.
116 Referência técnica para o MySQL versão 3.23.52
• Confira todas suas chamadas à DATE_FORMAT() para ter certeza que exista um ‘%’ antes
de cada caractere formatador. (Versões mais antigas que o MySQL 3.22 aceitaivam esta
sintaxe.)
• mysql_fetch_fields_direct agora é uma função (era uma macro) e ela retorna um
ponteiro para um MYSQL_FIELD no lugar de um MYSQL_FIELD.
• mysql_num_fields() não pode mais ser usada em um objeto MYSQL* (agora é uma
função que obtem MYSQL_RES* como um argumento. Agora deve ser usado mysql_
field_count().
• No MySQL Versão 3.22, a saída de SELECT DISTINCT ... era na maioria das vezes
ordenada. Na Versão 3.23, você deve usar GROUP BY ou ORDER BY para obter a saída
ordenada.
• SUM() agora retorna NULL, em vez de 0 se não existir registros coincidentes. Isto é de
acordo com o ANSI SQL.
• Um AND ou OR com valores NULL agora retornam NULL no lugar de 0. Isto afetará, em
grande parte, pesquisas que usam NOT em uma expressão AND/OR como NOT NULL =
NULL. LPAD() e RPAD reduzirão a string resultante se ela for maior que o tamanho do
argumento.
não irá retornar erro do servidor, somente CR_UNKNOWN_ERROR (mas isto funciona para erros
de clientes) e o servidor usa a forma antiga da função password() para verificação, ao invés
da nova.
Se você NÃO estiver usando a opção --old-protocol para mysqld, você precisará fazer as
seguir alterações:
• Todo o código cliente deve ser recompilado. Se você usa o ODBC, deve obter o novo
driver MyODBC 2.x.
• O script scripts/add_long_password deve ser executado para converter o campo
Password na tabela mysql.user para CHAR(16).
• Todas as senhas devem ser reatribuidas na tabela mysql.user (para obter 62-bits no
lugar de senhas 31-bits).
• O formato das tabelas não foi alterado, então não é preciso converter nenhuma tabela.
A versão do MySQL 3.20.28 e superiores podem manipular o novo formato da tabela de
usuários sem afetar os clientes. Se você tem uma versão do MySQL mais nova que 3.20.28,
senhas não irão mais funcionar se você converter a tabela de usuaios. Por segurança, você
primeiro deve fazer uma atualização para a versão 3.20.28, pelo menos, e então atualizar
para a versão 3.21.
O novo código cliente trabalha com um servidor mysqld 3.20.x, portanto se houver proble-
mas com 3.21.x você deve usar o antigo servidor 3.20.x sem a necessidade de recompilar os
clientes novamente.
Se você não está usando a opção --old-protocol para o mysqld, antigos clientes irão emitr
a seguinte mensagem de erro:
ERROR: Protocol mismatch. Server Version = 10 Client Version = 9
A nova interface PERL DBI/DBD também suporta a antiga interface mysqlperl. A única
alteração que deve ser feita se você usa o mysqlperl é alterar os argumentos para a função
connect(). Os novos argumentos são: host, database, user, password (os argumentos
user e password foram alterados de lugar). See hundefinedi [Perl DBI Class], page hunde-
finedi.
As seguintes alterações podem afetar consultas em antigas aplicações:
• HAVING deve ser especificada antes de qualquer cláusula ORDER BY.
• Os parâmetros para LOCATE() foram trocados.
• Agora existem algumas palavras reservadasi novas. As mais notáveis são DATE TIME e
TIMESTAMP.
Por padrão, o mysqldump irá criar um arquivo cheio de declarações SQL. Você pode então
transferir o arquivo para a outra máquina e alimentá-la como uma entrada para o cliente
mysql.
Utilize mysqldump --help para ver quais opções estão disponíveis. Se você está movendo
os dados para uma versão mais nova do MySQL, você deve usar mysqldump --opt com a
nova versão para obter uma descarga rápida e compacta.
A mais fácil (mas não a mais rápida) forma para mover um banco de dados entre duas
máquinas é executar os seguintes comandos na máquina em que o banco de dados se en-
contra:
shell> mysqladmin -h ’nome da outra maquina’ create nome_bd
shell> mysqldump --opt nome_bd \
| mysql -h ’nome da outra maquina’ nome_bd
Se você deseja copiar um banco de dados de um máquina remota sobre uma rede lenta,
pode ser usado:
shell> mysqladmin create nome_bd
shell> mysqldump -h ’nome de outra maquina’ --opt --compress nome_bd \
| mysql nome_bd
O resultado pode também ser armazenado em um arquivo, depois transfira o arquivo para a
máquina destino e carregue o arquivo no banco de dados. Por exemplo você pode descarregar
um banco de dados para um arquivo na máquina origem desta forma:
shell> mysqldump --quick nome_bd | gzip > nome_bd.contents.gz
(O arquivo criado neste exemplo está compactado.) Transfria o arquivo contendo o conteúdo
do banco de dados para a máquina destino e execute estes comandos:
shell> mysqladmin create nome_bd
shell> gunzip < nome_bd.contents.gz | mysql nome_bd
Também pode ser usado mysqldump e mysqlimport para ajudar na transferência do banco de
dados. Para grandes tabelas, isto é muito mais rápido do que usar simplesmente mysqldump.
Nos comandos abaixo, DUMPDIR representa o caminho completo do diretório que você utiliza
para armazenar a saída de mysqldump.
Primeiro, crie o diretório para os arquivos de saída e descarregue o banco de dados:
shell> mkdir DUMPDIR
shell> mysqldump --tab=DUMPDIR nome_bd
Depois transfira os arquivo no diretório DUMPDIR para algum diretório correspondente na
máquina destino e carregue os arquivos no MySQL assim:
shell> mysqladmin create nome_bd # cria o banco de dados
shell> cat DUMPDIR/*.sql | mysql nome_bd # cria tabelas no banco de dados
shell> mysqlimport nome_bd DUMPDIR/*.txt # carrega dados nas tabelas
Não se esqueça de copiar o banco de dados mysql também, porque é nele que as tabelas
de permissões (user, db e host) são armazenadas. Você pode ter que executar comandos
como o usuário root do MySQL na nova máquina até que você tenha o banco de dados
mysql no lugar.
Depois de importar o banco de dados mysql para a nova máquina, execute mysqladmin
flush-privileges para que o servidor recarregue as informações das tabelas de permissões.
Chapter 2: Instalação do MySQL 119
Você também pode executar os comandos acima da linha de comando como root, mas
neste caso, os antigos limites voltarão a ser usados na próxima vez que o computador for
reiniciado.
Deve também ser adicionado ao /etc/my.cnf:
[safe_mysqld]
open-files-limit=8192
Os parâmetros acima permitem o MySQL criar até 8192 conexões + arquivos.
A constante STACK_SIZE na LinuxThreads controla o espaçamento das pilhas threads no
espaço de endereçamento. Ela necessita ser grande o bastante para que tenha espaço o
suficiente para a pilha de cada thread, mas pequena o bastante para manter a pilha de al-
guma thread executando dos dados globais mysqld. Infelizmente, a implementação Linux de
mmap(), como descobrimos em experiências, irá desmapear uma região já mapeada se você
solicitar o mapeamento de um endereço já em uso, zerando os dados de toda a página ao
invés de retoernar. um erro. Portanto a segurança do mysqld ou qualquer outra aplicação
baseada em threads depende do comportamento gentil do código que cria as threads. O
usuário deve tomar medidas para certirficar-se que o número de threads em funcionamento
em qualquer hora seja suficientemente baixo para que as pilhas das threads permaneçam
longe do monte global. Com mysqld você deve reforçar este comportamento "gentil" con-
figurando um valor razoável para a variável max_connections.
Se você mesmo construiu o MySQL e não deseja confusões corrigindo LinuxThreads, você
deve configurar max_connections para um valor máximo de 500. Ele ainda deve ser menor
se você tiver uma chave grande para o buffer, grandes tabelas heap, ou outras coisas que
fazem o mysqld alocar muita memória ou se você estiver executando um kernel 2.2 com o
patch de 2GB. Se você estiver usando nosso binário ou RPM versão 3.23.25 ou posterior,
você pode seguramente configurar max_connections para 1500, assumindo que não há
uma grande chave de buffer ou tabelas heap com grande quantidade de dados. Quanto
mais você reduz STACK_SIZE em LinuxThreads mais threads você pode criar seguramente.
Recomendamos os valores entre 128K e 256K.
Se você usa várias conexões simultâneas, você pode sofrer com um "recurso" do kernel
2.2 que penaliza um processo por bifurcar-se ou clonar um filho na tentativa de prevenir
um ataque de separação. Isto faz com que o MySQL não consiga fazer uma bom
escalonamento, quando o número de clientes simultâneos cresce. Em sistemas com CPU
única, temos visto isto se manifestar em uma criação muito lenta das threads, tornando
a conexão ao MySQL muito lenta. Em sistemas de múltiplas CPUs, temos observado
uma queda gradual na velocidade das consultas quando o número de clientes aumenta.
No processo de tentar encontrar uma solução, recebemos um patch do kernel de um de
nossos usuários, que alega fazer muita diferença para seu site. O patch está disponível
aqui (http://www.mysql.com/Downloads/Patches/linux-fork.patch). Atualmente
temos feito testes extensivos deste patch nos sistemas de desenvolvimento e produção.
A performance do MySQL obtem uma melhora significativa, sem causar problemas e
atualmente o recomendamos para nossos usuários que continuando trabalhando com
servidores muito carregados em kernels 2.2. Este detalhe foi corrigido no kernel 2.4,
portanto, se você não está satisfeito com a performance atual do seu sistema, melhor do
que aplicar um patch ao seu kernel 2.2, pode ser mais fácil simplesmente atualizar para o
2.4, que lhe dará também uma melhora em seu sistemas SMP em adição à correção do bug
discutido aqui.
Chapter 2: Instalação do MySQL 121
Estamos testando o MySQL no kernel 2.4 em uma máquina com 2 processadores e desco-
brimos que o MySQL escalona muito melhor - virtualmente, não há nenhuma perda de
desempenho no throughput das consultas até cerca de 1000 clientes, e o fator da escala do
MySQL (computado com a razão do throughput máximo para o thoughput de cada cliente.)
foi de 180%. Temos observado resultados similares em sistemas com 4 processadores - vir-
tualmente não há perda de desempenho quando o número de clientes é incrementado até
1000 e o fator da escala foi de 300%. Portanto para um servidor SMP muito carregado nós
definitivamente recomendamos o kernel 2.4. Nós descobrimos que é essencial executar o
processo mysqld com a mais alta prioridade possível no kernel 2.4 para obter performance
máxima. Isto pode ser feito adicionando o comando renice -20 $$ ao safe_mysqld. Nos
nossos testes em uma máquina com 4 processadores, o aumento da prioridade nos deu 60%
de aumento no throughput com 400 clientes.
Atualmente estamos tentando coletar mais informações sobre como o MySQL atua no kernel
2.4 em sistemas com 4 e 8 processadores. Se você tem acesso a um sistema deste porte e tem
feito alguns benchmarks, por favor envie um email para [email protected] com os resultados
- iremos incluí-los neste manual.
Existe outro detalhe que afeta muito a performance do MySQL, especialmente em sistemas
multi processados. A implementação de mutex em LinuxThreads na glibc-2.1 é muito ruim
para programas com várias threads que travam o mutex por um tempo curto. Em um
sistema SMP, ironicamente, se você liga o MySQL com LinuxThreads sem modificações,
removendo processadores da máquina, a performance do MySQL é melhorada em alguns
casos. Para corrigir este comportamento, disponibilizamos um patch para glibc 2.1.3, em
linuxthreads-2.1-patch
Com a glibc-2.2.2, o MySQL versão 3.23.36 irá usar o mutex adaptativo, que
é muito melhor,mesmo que o patch na glibc-2.1.3. Avisamos, entretando, que
sobre algumas condições, o código mutex no glibc-2.2.2 overspins, que preju-
dica a performance do MySQL. A chance desta condição pode ser reduzida
mudando a prioridade do processo mysqld para a prioridade mais alta. Nós
também corrigimos o comportamento overspin com um patch, disponível em
http://www.mysql.com/Downloads/Linux/linuxthreads-2.2.2.patch.here. Ele
combina a correção do overspin, número máximo de threads e espaçamento das pilhas
em um único patch. Você precisará aplicá-lo no diretório linuxthreads com patch -p0
</tmp/linuxthreads-2.2.2.patch. Acreditamos que será incluído de alguma forma nos
futuros lançamentos da glibc-2.2. De qualquer forma, se você ligar com glibc-2.2.2,
ainda será necessário corrigir STACK_SIZE e PTHREAD_THREADS_MAX. Temos esperanças que
os padrões serão corrigidos para valores mais aceitáveis para configurações pesadasa do
MySQL no futuro, então sua construção poderá ser reduzida a ./configure; make; make
install.
Recomendamos que você use os patches acima para construir uma versão estática especial
de libpthread.a e use-a somente para ligações estáticas com o MySQL. Sabemos que os
patches são seguros para o MySQL e pode melhorar significamente sua performance, mas não
podemos dizer nada sobre outras aplicações. Se você ligar outras aplicações coma a versão
modificada da biblioteca ou construir uma versão alterada compartilhada e instalá-la no seu
sistema, você estará fazendo por sua conta e risco e tenha atenção com outras aplicações
que dependem de LinuxThreads.
122 Referência técnica para o MySQL versão 3.23.52
Se você passar por problemas estranhos durante a instalação do MySQL ou com travamentos
de alguns utilitários comuns, é muito provável que eles são relacionados a problemas de
bibliotecas ou compilador. Se for este o caso, o uso de nosso binário será a solução.
Um problema conhecido com a distribuição binária é que com antigos sistemas Linux que
usam libc (como o RedHat 4.x ou Slackware), você obterá alguns problemas não fatais
com resolução de nomes. See hundefinedi [Binary notes-Linux], page hundefinedi.
Quando estiver usando LinuxThreads você verá um mínimo de três processos em execução.
Estes são de fato, threads. Existirá uma thread para o gerenciador LinuxThreads, uma
thread para lidar com conexões e uma thread para tartar de alarmes e sinais.
Perceba que o kernel Linux e a biblioteca LinuxThread pode por padrão ter apenas 1024
threads. Isto significa que você pode ter até 1021 conexões ao MySQL em um sistema sem
correção. A página http://www.volano.com/linuxnotes.html contém informações sobre
como contornar este limite.
Se você ver um processo mysqld daemon finalizado com ps, isto normalmente significa que
você encontrou um bug no MySQL ou que tenha uma tabela corrompida. See hundefinedi
[Crashing], page hundefinedi.
Para obter um descarga do core no Linux se o mysqld finalizar com um sinal SIGSEGV, você
pode iniciar o mysqld com a opção --core-file. Perceba que provavelmente você também
precisará aumentar o core file size adicionando ulimit -c 1000000 para safe_mysqld
ou iniciar safe_mysqld com --core-file-sizes=1000000, See hundefinedi [safe_mysqld],
page hundefinedi.
Se você estiver ligando seu próprio cliente MySQL e obter o erro:
ld.so.1: ./my: fatal: libmysqlclient.so.4: open failed: No such file or directory
Quando executá-los, o problema pode ser evitado com um dos seguintes métodos:
• Ligue o cliente com a seguinte opção (no lugar de -Lpath): -Wl,r/path-
libmysqlclient.so.
• Copie libmysqclient.so para ‘/usr/lib’.
• Adicione o caminho do diretório onde libmysqlclient.so está localizado para a
variável de ambiente LD_RUN_PATH antes de executar seu cliente.
Se você estiver usando o compilador Fujitsu (fcc / FCC) você terá alguns problemas com-
pilando o MySQL porque os arquivos de cabeçalho Linux são muito orientados ao gcc.
A seguinte linha configure deve funcionar com fcc/FCC:
CC=fcc CFLAGS="-O -K fast -K lib -K omitfp -Kpreex -D_GNU_SOURCE -DCONST=const -DNO_
Se você estiver usando um sistema baseado em libc (em vez de um sistema glibc2), você,
provavelmente, terá alguns problemas com resolução de nomes de máquinas e getpwnam()
com a versão binária. (Isto é porque o glibc infelizmente depende de algumas bibliotecas
externas para resolver nomes de máquinas e getpwent(), mesmo quando compilado com
-static). Neste caso, você provavelmente obterá a seguinte mensagem de erro quando
executar mysql_install_db:
Sorry, the host ’xxxx’ could not be looked up
ou o seguinte erro quando você tentar executar mysqld com a opção --user:
getpwnam: No such file or directory
Você pode resolver este problema usando de um dos modos seguintes:
• Obtenha uma distribuição fonte do MySQL (uma distribuição RPM ou tar.gz) e a
instale.
• Execute mysql_install_db --force; Isto não executará o teste resolveip no mysql_
install_db. O lado ruim é que você não poderá usar nomes de máquinas nas tabelas
de permissões; você deve usar números IP no lugar (exceto para localhost). Se você
estiver usando uma release antiga do MySQL que não suporte --force, você deve
remover o teste resolveip no mysql_install com um editor.
• Inicie mysqld com su no lugar de usar --user.
As distribuições binárias Linux-Intel e RPM do MySQL são configuradas para o máximo
de desempenho possível. Nós sempre tentamos usar o compilador mais rápido e estável
disponível.
Suporte MySQL ao Perl exige Perl Versão 5.004 03 ou mais novo.
Em algumas versões 2.2 do kernel Linux,você pode obter o erro Resource temporarily
unavailable quando você faz várias novas conexões para um servidor mysqld sobre
TCP/IP.
O problema é que o Linux tem um atraso entre o momento em que você fecha um socket
TCP/IP até que ele seja realmente liberado pelo sistema. Como só existe espaço para um
número finito de slots TCP/IP, você irá obter o erro acima se você tentar fazer muitas novas
conexões TCP/IP durante um pequeno tempo, como quando você executa o benchmark do
MySQL ‘test-connect’ sobre TCP/IP.
Nós enviamos emails sobre este problema várias vezes para diferentes listas de discussão
Linux mas nunca conseguimos resolver este problema apropriadamente.
A única ’correção’ conhecida , para este problema é usar conexões persistentes nos seus
clientes ou usar sockets, se você estiver executando o servidor de banco de dados e clientes
na mesma máquina. Nós experamos que o kernel Linux 2.4 corrija este problema no futuro.
Temos testado o MySQL no Alpha com nossos pacotes de benchmarks e testes, e ele parece
funcinar muito bem. A principal coisa que ainda não tivemos tempo de testar é como as
coisas funcionam com muitos usuários simultâneos.
Quando nós compilamos o binários MySQL padrões, nós estávamos usando SuSE 6.4, kernel
2.2.13-SMP, Compilador C Compaq (V6.2-504) e compilador C++ Compaq (V6.3-005) em
uma máquina Compaq DS20 com um processador Alpha EV6.
Você pode encontrar os compiladores acima em http://www.support.compaq.com/alpha-tools).
Usando estes compiladores, em vez do gcc, obtemos 9-14 % de melhora na performance
com MySQL.
Note que a linha de configuração otimiza o binário para a CPU atual; isto significa que
você só pode utilizar nosso binário se você tiver um processador Alpha EV6. Nós também
compilamos estaticamente para evitar problemas de bibliotecas.
CC=ccc CFLAGS="-fast" CXX=cxx CXXFLAGS="-fast -noexceptions -nortti" ./configure --p
Se você deseja usar egcs a seguinte linha de configuração funcionou para nós:
CFLAGS="-O3 -fomit-frame-pointer" CXX=gcc CXXFLAGS="-O3 -fomit-frame-pointer -felide
Alguns problemas conhecidos quando executamos o MySQL no Linux-Alpha:
• Debugar aplicações baseadas em threads como o MysQL não irá funcionar com gdb
4.18. Você deve fazer download e usar o gdb 5.0!
• Se você tentar ligar o mysqld estaticamente quando usar o gcc, a imagem resultante irá
descarregar um arquivo core no início. Em outras palavras, NÃO use --with-mysqld-
ldflags=-all-static com gcc.
Se você estiver usando a antiga versão shareware do MySQL versão 3.21 no Windows, o
comando acima irá falhar com um erro: parse error near ’SET OPTION password’. A
correção é feita atualizando a versão do MySQL, que está disponível livremente.
Com as versões atuais do MySQL você pode facilmente adicionar novos usuários e alterar
privilégios com os comandos GRANT e REVOKE. See hundefinedi [GRANT], page hundefinedi.
a isto. Para habilitar links simbólicos você deve colocar no seu arquivo my.cnf ou my.ini
a seguinte entrada:
[mysqld]
use-symbolic-links
No MySQL 4.0 nós habilitaremos links simbólicos por padrão. Então você deve usar a opção
skip-symlink se você desejar desabilitá-las.
Para corrigir isto, você deve criar um arquivo ‘\windows\hosts’ com a seguinte
informação:
127.0.0.1 localhost
ALTER TABLE
Enquanto você estiver executando uma cláusula ALTER TABLE, a tabela será
bloqueada para o uso por outras threads. Isto é relacionado com o fato de
que no Windows, você não pode apagar um arquivo que está sendo usado por
outras threads. (No futuro, iremos encontrar alguma forma de contornar este
problema.)
DROP TABLE em uma tabela que está em uso por uma tabela MERGE não irá funcionar.
O manipulador MERGE faz seu mapeamento de tabelas escondido do MySQL.
Como o Windows não permite apagar arquivos que estão abertos, você deve
primeiramente descarregar todas tabelas MERGE (com FLUSH TABLES) ou apagar
a tabela MERGE antes de apagar a tabela. Iremos corrigir isto quando intro-
duzirmos as VIEWs.
Aqui estão alguns assuntos em aberto para qualquer um que queira nos ajudar com a versão
Windows:
• Criar um servidor MYSQL.DLL mono-usuário. Isto deve incluir tudo de um servidor
MySQL padrão, exceto criação de threads. Isto deixará o MySQL muito mais fácil
para ser usado em aplicações que não necessitam de um verdadeiro cliente/servidor e
não necessitam acessar o servidor de outras máquinas.
• Adicionar alguns ícones agradáveis para o start e shutdown na instalação do MySQL.
• Criar uma ferramenta para gerenciar entradas de registro para as opções de inicialização
do MySQL. A leitura de entradas no registro já está codificada em ‘mysqld.cc’, mas
ela deve ser refeita para ser mais orientada a parâmetros. A ferramenta também deve
estar apta para atualizar o arquivo de opções ‘C:\my.cnf’ se o usuário preferir usa-lo
no lugar do registro.
• Quando registrar o mysqld como um serviço com --install (no NT) seria ótimo se
você também pudesse adicionar opções padrões na linha de comando. Para o momento,
a solução é listar os parâmetros no arquivo ‘C:\my.cnf’.
• Seria muito interessante conseguir matar o mysqld do gerenciador de tarefas. Para o
momento, deve ser usado o mysqladmin shutdown.
• Portar o readline para Windows para uso na ferramenta de linha de comando mysql.
• Versões GUI dos clientes MySQL padrões (mysql, mysqlshow, mysqladmin e
mysqldump) seria ótimo.
• Seria muito bom se as funções de leitura e escrita no socket em ‘net.c’ fosse inter-
rompíveis. Isto tornaria possível matar threads abertas com mysqladmin kill no
Windows.
• mysqld sempre inicia na localidade "C" e não na padrão. Gostariamos de ter o mysqld
usando a localização atual para a ordem de classificação.
• Implementar funções UDF com .DLLs.
• Adicionar macros para usar os métodos mais rápidos de incremento/decremento de
threads seguras fornecidos pelo Windows.
Chapter 2: Instalação do MySQL 133
Outros detalhes específicos do Windows são descritos no arquivo ‘README’ que acompanha
a distribuição MySQL-Windows.
ou
ou
para
O ‘Makefile’ do MySQL necessita o GNU make (gmake) para funcionar. Se você deseja
compilar o MySQL, antes você precisará instalar o GNU make.
Tenha certeza que sua configuração de resolução de nomes esteja correta. De outra forma
você vai ter atrasos na resolução ou falhas quando conectar ao mysqld.
Tenha certeza que a entrada localhost no arquivo ‘/etc/hosts’ esteja correta (de outra
forma você irá ter problemas conectando ao banco de dados). O arquivo ‘/etc/hosts’ deve
iniciar com a linha:
127.0.0.1 localhost localhost.seu.dominio
Se você notar que o configure irá usar MIT-pthreads, você deve ler as notas sobre o
MIT-pthreads. See hundefinedi [MIT-pthreads], page hundefinedi.
Se você obter um erro do make install dizendo que ele não consegue encontrar
‘/usr/include/pthreads’, o configure não percebeu que você necessita da
MIT-pthreads. Isto é corrigido com os seguintes comandos:
shell> rm config.cache
shell> ./configure --with-mit-threads
O FreeBSD é também conhecido por ter um limite muito baixo para o manipulador de
arquivos. See hundefinedi [Not enough file handles], page hundefinedi. Descomente a seção
ulimit -n no safe mysqld ou aumente os limites para o usuário mysqld no /etc/login.conf (e
reconstrua-o com cap mkdb /etc/login.conf). Também tenha certeza que você configurou
a classe apropriada para este usuário no arquivo de senhas (password) se você não es-
tiver usando o padrão (use: chpass nome usuario mysqld). See hundefinedi [safe_mysqld],
page hundefinedi
Se você tiver problemas com a data atual no MySQL, configurar a variável TZ provavelmente
ajudará. See hundefinedi [Environment variables], page hundefinedi.
Para obter um sistema seguro e estável você deve usar somente kernels FreeBSD que estejam
marcados com -STABLE.
Atualize para BSD/OS Versão 3.1. Se isto não for possível, instale BSDIpatch M300-038.
Use o seguinte comando quando configurar o MySQL:
shell> env CXX=shlicc++ CC=shlicc2 \
./configure \
--prefix=/usr/local/mysql \
--localstatedir=/var/mysql \
--without-perl \
--with-unix-socket-path=/var/mysql/mysql.sock
O comeando seguinte também funciona:
shell> env CC=gcc CXX=gcc CXXFLAGS=-O3 \
./configure \
--prefix=/usr/local/mysql \
--with-unix-socket-path=/var/mysql/mysql.sock
Você pode alterar as localizações dos diretórios se você desejar, ou apenas usar os padrões
não especificando nenhuma localização.
Se você tiver problemas com performance sob alta carga, tente usar a opção --skip-thread-
priority para mysqld! Isto irá executar todas as threads com a mesma prioridade; no BSDI
versão 3.1, isto fornece melhor performance (pelo menos até o BSDI corrigir seu organizador
de threads).
Se você obter o erro virtual memory exhausted enquanto estiver compilando, deve tentar
usar ulimit -v 80000 e executar make novamente. Se isto não funcionar e você estiver
usando bash, tente trocar para csh ou sh; alguns usuários BSDI relataram problemas com
bash e ulimit.
Chapter 2: Instalação do MySQL 139
configuration:
./configure --with-pthread \
--prefix=/source-control/mysql \
--with-named-thread-libs=-lpthread \
--with-low-memory
./configure --prefix=/usr/local \
--localstatedir=/var/mysql \
--sysconfdir=/etc/mysql \
--sbindir=’/usr/local/bin’ \
--libexecdir=’/usr/local/bin’ \
Chapter 2: Instalação do MySQL 143
--enable-thread-safe-client \
--enable-large-files
Acima estão as opções usadas para compilar a distribuição MySQL que pode ser encontrada
em http://www-frec.bull.com/.
Se você alterar o -O3 para -O2 na linha de configuração acima, você também deve remover
a opção -qstrict (isto é uma limitação no compilador C da IBM).
Se você estiver usando gcc ou egcs para compilar o MySQL, você DEVE usar a opção -fno-
exceptions, já que o manipulador de exceções no gcc/egcs não é seguro para threads! (Isto
foi testado com egcs 1.1). Existem também alguns problemas conhecidos com o assembler
da IBM que pode gerar código errado quando usado com gcc.
Nós recomendamos a seguinte linha do configure com egcs e gcc 2.95 no AIX:
CC="gcc -pipe -mcpu=power -Wa,-many" \
CXX="gcc -pipe -mcpu=power -Wa,-many" \
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti" \
./configure --prefix=/usr/local/mysql --with-low-memory
O -Wa,-many é necessário para o compilador ser bem sucedido. IBM está ciente deste
problema mas não está com pressa de corrigí-lo devido ao fato do problema poder ser
contornado. Nós não sabemos se o -fno-exceptions é necessário com gcc 2.9.5, mas
como o MySQL não utiliza exceções e a opção acima gera código mais rápido, recomendamos
que você sempre use esta opção com o egcs/gcc.
Se você tiver algum problema com código assembler tente alterar o -mcpu=xxx para o seu
processador. Normalmente power2, power ou powerpc podem ser usados, de uma maneira
alternativa você pode precisar usar 604 ou 604e. Não tenho certeza mas acredito que usar
"power" deve satisfazer a maioria dos casos, mesmo em uma máquina power2.
Se você não sabe qual é o seu processador, utilize o comando "uname -m", isto
irá fornecer a você uma string que parece com "000514676700", com um formato
de xxyyyyyymmss onde xx e ss são sempre 0s, yyyyyy é o ID único do sistema e
mm é o ID da CPU Planar. Uma tabela destes valores podem ser encontrados em
http://www.rs6000.ibm.com/doc_link/en_US/a_doc_lib/cmds/aixcmds5/uname.htm.
Isto irá lhe fornecer um tipo de máquina e um modelo de máquina que você pode usar
para determinar que tipo de cpu você tem.
Se você tiver problemas com sinais (MySQL finaliza sem notificação sob alta carga) você
pode ter encontrado um bug de SO com threads e sinais. Neste caso você pode dizer ao
MySQL para não usar sinais configurando-o com:
shell> CFLAGS=-DDONT_USE_THR_ALARM CXX=gcc \
CXXFLAGS="-felide-constructors -fno-exceptions -fno-rtti -DDONT_USE_THR_ALARM
./configure --prefix=/usr/local/mysql --with-debug --with-low-memory
Isto não afeta a performance do MySQL, mas tem o efeito colateral que você não pode
matar clientes que estão “dormindo” em uma conexão com mysqladmin kill ou mysqladmin
shutdown. Neste caso, o cliente morrerá quando ele chegar no próximo comando.
Em algumas versões do AIX, ligando com libbind.a faz o getservbyname descarregar core.
Isto é erro no AIX e deve ser relatado para a IBM.
Para o AIX 4.2.1 e gcc você tem que fazer as seguintes alterações.
Depois de configurar, edite o ‘config.h’ e ‘include/my_config.h’ e altere a linha que diz
144 Referência técnica para o MySQL versão 3.23.52
#define HAVE_SNPRINTF 1
para
#undef HAVE_SNPRINTF
E finalmente, no ‘mysqld.cc’ você precisa adicionar um protótipo para initgroups.
#ifdef _AIX41
extern "C" int initgroups(const char *,int);
#endif
no mysqld). Neste sistema, temos compilado o MySQL com a seguinte linha configure,
depois de substituir /bin/ld com a versão do OSF 4.0C:
CC=gcc CXX=gcc CXXFLAGS=-O3 ./configure --prefix=/usr/local/mysql
Com o compilador da Digital "C++ V6.1-029", o seguinte deve funcionar:
CC=cc -pthread
CFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all -arch host
CXX=cxx -pthread
CXXFLAGS=-O4 -ansi_alias -ansi_args -fast -inline speed -speculate all -arch host -n
export CC CFLAGS CXX CXXFLAGS
./configure --prefix=/usr/mysql/mysql --with-mysqld-ldflags=-all-static --disable-sh
Em algumas versões do OSF1, a função alloca() está quebrada. Corrija isto removendo a
linha no ‘config.h’ que define ’HAVE_ALLOCA’.
A função alloca() pode também ter um protótipo incorreto em /usr/include/alloca.h.
O alerta resultante deste erro pode ser ignorado.
configure irá usar a seguinte biblioteca thread automaticamente: --with-named-thread-
libs="-lpthread -lmach -lexc -lc".
Quando usar o gcc, você também pode tentar executar configure desta forma:
shell> CFLAGS=-D_PTHREAD_USE_D4 CXX=gcc CXXFLAGS=-O3 ./configure ....
Se você tiver problemas com sinais (MySQL finalzar inesperadamente sobre alta carga),
você pode ter encontrado um erro com threads e sinais no SO. Neste caso você pode dizer
ao MySQL para não usar sinais configurando-o com:
shell> CFLAGS=-DDONT_USE_THR_ALARM \
CXXFLAGS=-DDONT_USE_THR_ALARM \
./configure ...
Isto não afeta a performance do MySQL, mas tem efeitos colaterais que não permitem
finalizar clientes que estão “dormindo” em uma conexão com mysqladmin kill ou
mysqladmin shutdown. Neste caso o cliente irá morrer quando ele receber o próximo
comando.
Com gcc 2.95.2, você provavelmente encontrará o seguinte erro de compilação:
sql_acl.cc:1456: Internal compiler error in ‘scan_region’, at except.c:2566
Please submit a full bug report.
Para corrigir isto você deve alterar para o diretório sql e fazer um “corta e cola” da última
linha gcc, mas altere -O3 para -O0 (ou adicione -O0 imediatamente depois de gcc se você
não tiver algumas opção -O na sua linha de compilação.) Depois disto feito você deve apenas
voltar ao diretório superior e executar make novamente.
2. Você precisa do GCC versão 2.5.x para este produto e do sistema de desenvolvimento.
Eles são necessários nesta versão do SCO Unix. Você não pode usar apenas o sistema
GCC Dev.
3. Você deve obter o pacote FSU Pthreads e instalá-lo primeiro. Pode ser obtido em
http://www.cs.wustl.edu/~schmidt/ACE_wrappers/FSU-threads.tar.gz. Você
pode também obter um pacote precompilado de http://www.mysql.com/Downloads/SCO/FSU-threads
4. FSU Pthreads pode ser compilado com SCO Unix 4.2 com tcpip, ou OpenServer 3.0
ou OpenDesktop 3.0 (OS 3.0 ODT 3.0), com o Sistema de Desenvolvimento da SCO
instalado usando uma boa versão do GCC 2.5.x ODT ou OS 3.0, no qual você necessi-
tará de uma boa versão do GCC 2.5.x. Existem vários problemas sem uma boa versão.
Esta versão do produto necessita do sistema de Desenvolvimento SCO Unix. Sem ele,
você estará perdendo as bibliotecas e o editor de ligação necessário.
5. Para construir a FSU Pthreads no seu sistema, faça o seguinte:
a. Execute ./configure no diretório ‘threads/src’ e selecione a opção SCO
OpenServer. Este comando copia ‘Makefile.SCO5’ para ‘Makefile’.
b. Execute make.
c. Para instalar no diretório padrão ‘/usr/include’, use o usuário root, depois mude
para o diretório ‘thread/src’ e execute make install
6. Lembre de usar o GNU make quando estiver construindo o MySQL.
7. Se você não iniciou o safe_mysqld como root, você provavelmente só irá obter, por
padrão, os 110 arquivos abertos por processo. O mysqld irá gravar uma nota sobre isto
no arquivo log.
8. Com o SCO 3.2V5.0.5, você deve usar o FSU Pthreads versão 3.5c ou mais nova. Você
deve também usar o gcc 2.95.2 ou mais novo.
O seguinte comando configure deve funcionar:
shell> ./configure --prefix=/usr/local/mysql --disable-shared
9. Com SCO 3.2V4.2, você deve usar FSU Pthreads versão 3.5c ou mais nova. O seguinte
comando configure deve funcionar:
shell> CFLAGS="-D_XOPEN_XPG4" CXX=gcc CXXFLAGS="-D_XOPEN_XPG4" \
./configure \
--prefix=/usr/local/mysql \
--with-named-thread-libs="-lgthreads -lsocket -lgen -lgthreads" \
--with-named-curses-libs="-lcurses"
Você pode ter alguns problemas com alguns arquivos de inclusão. Neste
caso, você pode encontrar novos arquivos de inclusão específicos do SCO em
http://www.mysql.com/Downloads/SCO/SCO-3.2v4.2-includes.tar.gz. Você deve
descompactar este arquivo no diretório ‘include’ da sua árvore fonte do MySQL.
Notas de desenvolvimento SCO:
• O MySQL deve detectar automaticamente FSU Pthreads e ligar o mysqld com -
lgthreads -lsocket -lgthreads.
• As bibliotecas de desenvolvimento SCO são re-entrantes nas FSU Pthreads. A SCO
diz que suas bibliotecas de funções são re-entrantes, então elas devem ser re-entrantes
com as FSU-Pthreads. FSU Pthreads no OpenServer tentam usar o esquema SCO para
criar bibliotecas re-entrantes.
Chapter 2: Instalação do MySQL 149
• FSU Pthreads (ao menos a versão em http://www.mysql.com) vem ligada com GNU
malloc. Se você encontrar problemas com uso de memória, tenha certeza que o
‘gmalloc.o’ esteja incluído em ‘libgthreads.a’ e ‘libgthreads.so’.
• Na FSU Pthreads, as seguintes chamadas de sistema são compatíveis com pthreads:
read(), write(), getmsg(), connect(), accept(), select() e wait().
• O CSSA-2001-SCO.35.2 (O patch é listado de costume como patch de segurança
erg711905-dscr remap ver 2.0.0) quebra FSU threads e deixa o mysqld instável. Você
deve remove-lo se você deseja executar o mysqld em uma máquina OpenServer 5.0.6.
Se você deseja instalar o DBI no SCO, você deve editar o ‘Makefile’ em DBI-xxx e cada
subdiretório.
Note que o exemplo abaixo considera o gcc 2.95.2 ou mais novo:
OLD: NEW:
CC = cc CC = gcc
CCCDLFLAGS = -KPIC -W1,-Bexport CCCDLFLAGS = -fpic
CCDLFLAGS = -wl,-Bexport CCDLFLAGS =
LD = ld LD = gcc -G -fpic
LDDLFLAGS = -G -L/usr/local/lib LDDLFLAGS = -L/usr/local/lib
LDFLAGS = -belf -L/usr/local/lib LDFLAGS = -L/usr/local/lib
LD = ld LD = gcc -G -fpic
OPTIMISE = -Od OPTIMISE = -O1
OLD:
CCCFLAGS = -belf -dy -w0 -U M_XENIX -DPERL_SCO5 -I/usr/local/include
NEW:
CCFLAGS = -U M_XENIX -DPERL_SCO5 -I/usr/local/include
Isto é porque o carregador dinâmico Perl não irá carregar os módulos DBI se elas foram
compiladas com icc ou cc.
Perl trabalha melhor quando compilado com cc.
mysql>
O prompt lhe diz que o mysql está pronto para que você digite os comandos.
152 Referência técnica para o MySQL versão 3.23.52
são impreciso porque eles representam tempo de relógio (Não tempo de CPU ou de
máquina), e porque eles são afetados pelos fatores como a carga do servidor e latência
de rede. (Para resumir, a linha “rows in set” não é mostrada nos exemplos seguintes
deste capítulo.)
Palavras Chave podem ser entradas em qualquer caso de letra. As seguintes consultas são
equivalentes:
mysql> SELECT VERSION(), CURRENT_DATE;
mysql> select version(), current_date;
mysql> SeLeCt vErSiOn(), current_DATE;
Aqui está outra consulta. Ela demonstra que você pode usar o mysql como uma calculadora
simples:
mysql> SELECT SIN(PI()/4), (4+1)*5;
+-------------+---------+
| SIN(PI()/4) | (4+1)*5 |
+-------------+---------+
| 0.707107 | 25 |
+-------------+---------+
Os comandos mostrados até agora têm sido instruções relativamente pequenas, de uma
linha. Você pode também entrar com múltiplas instruções em uma única linha. Basta
finalizar cada uma com um ponto e vírgula:
mysql> SELECT VERSION(); SELECT NOW();
+--------------+
| version() |
+--------------+
| 3.22.20a-log |
+--------------+
+---------------------+
| NOW() |
+---------------------+
| 1999-03-19 00:15:33 |
+---------------------+
Um comando não necessita estar todo em uma única linha, então comandos extensos que
necessitam de várias linhas não são um problema. O mysql determina onde sua instrução
termina através do ponto e vírgula terminador, e não pelo final da linha de entrada. (Em
outras palavras, o myqsl aceita entradas de livre formato: Ele coleta linhas de entrada mas
não as executa até chegar o ponto e vírgula.)
Aqui está uma instrução simples usando múltiplas linhas:
mysql> SELECT
-> USER()
-> ,
-> CURRENT_DATE;
+--------------------+--------------+
| USER() | CURRENT_DATE |
+--------------------+--------------+
| joesmith@localhost | 1999-03-18 |
154 Referência técnica para o MySQL versão 3.23.52
+--------------------+--------------+
Neste exemplo, note como o prompt altera de mysql> para -> depois de você entrar a
primeira linha de uma consulta com múltiplas linhas. Isto é como o mysql indica que ainda
não achou uma instrução completa e está esperando pelo resto. O prompt é seu amigo,
porque ele fornece um retorno valioso. Se você usa este retorno, você sempre estará ciente
do que o mysql está esperando.
Se você decidir que não deseja executar um comando que está no meio do processo de
entrada, cancele-o digitando \c:
mysql> SELECT
-> USER()
-> \c
mysql>
Note o prompt aqui também. Ele troca para o mysql> depois de você digitar \c, fornecendo
retorno para indicar que o mysql está pronto para um novo comando.
A seguinte tabela mostra cada dos prompts que você pode ver e resume o que ele significa
sobre o estado em que o mysql se encontra:
Prompt Significado
mysql> Pronto para novo comando.
-> Esperando pela próxima linha de comando com múltiplas linhas.
’> Esperando pela próxima linha, coletando uma string que comece com uma aspas
simples (‘’’).
"> Esperando pela próxima linha, colentando uma string que comece com aspas
duplas (‘"’).
É muito comum instruções multi-linhas ocorrem por acidente quando você pretende publicar
um comando em uma única linha, mas esquece o ponto e vírgula terminador. Neste caso,o
mysql espera por mais entrada:
mysql> SELECT USER()
->
Se isto ocorrer com você (acha que entrou uma instrução mas a única resposta é um prompt
->), o mais provável é que o mysql está esperando pelo ponto e vírgula. Se você não
perceber o que o prompt está lhe dizendo, você pode parar por um tempo antes de entender
o que precisa fazer. Entre com um ponto e vírgula para completar a instrução, e o mysql
irá executá-la:
mysql> SELECT USER()
-> ;
+--------------------+
| USER() |
+--------------------+
| joesmith@localhost |
+--------------------+
O prompt ’> e "> ocorrem durante a coleta de strings. No MySQL, você pode escrever
strings utilizando os caracteres ‘’’ ou ‘"’ (por exemplo, ’hello’ ou "goodbye"), e o mysql
permite a entrada de strings que consomem múltiplas linhas. Quando você ver um prompt
’> ou ">, significa que você digitou uma linha contendo uma string que começa com um
caracter de aspas ‘’’ ou ‘"’ mas ainda não entrou com a aspas que termina a string. Isto
Chapter 3: Introdução ao MySQL: Um Tutorial MysQL 155
é bom se você realmente está entrando com uma string com múltiplas linhas, mas qual é
a probalidade disto acontecer ? Não muita. Geralmente, os prompts ’> e "> indicam que
você, por algum descuido, esqueceu algum caracter de aspas. Por exemplo:
mysql> SELECT * FROM minha_tabela WHERE nome = "Smith AND idade < 30;
">
Se você entrar esta sentença SELECT, apertar ENTER e esperar pelo resultado, nada irá
acontecer. Em vez de se perguntar o porquê desta query demorar tanto tempo, perceba a
pista fornecida pelo prompt ">. Ele lhe diz que o mysql espera pelo resto de uma string
não terminada. (Você ve o erro na declaração? Falta a segunda aspas na string "Smith.)
O que fazer neste ponto ? A coisa mais simples é cancelar o comando. Entretanto, você
não pode simplesmente digitar \c neste caso, porque o mysql o intrerpreta como parte da
string que está coletando! Digite o caracter de aspas para fechar (então o mysql sabe que
você fechou a string), então digite \c:
mysql> SELECT * FROM minha_tabela WHERE nome = "Smith AND idade < 30;
"> "\c
mysql>
O prompt volta para mysql>, indicando que o mysql está pronto para um novo comando.
É importante saber o que os prompts ’> e o "> significam, porque se você entrar sem
querer com uma string sem terminação, quaisquer linhas seguintes que forem digitadas
serão ignoradas pelo mysql — incluindo uma linha contendo QUIT! Isto pode ser um pouco
confuso, especialmente se você não sabe que você precisa fornecer as aspas finais antes poder
cancelar o comando atual.
de ser os mesmos e não precisam ser 20. Você pode escolher qualquer tamanho de 1 a 255,
o que você achar melhor. (Se você não fizer uma boa escolha e depois precisar de um campo
maior, o MySQL fornece o comando ALTER TABLE.)
O sexo dos animais podem ser representados em várias formas, por exemplo, "m" e "f" ou
mesmo "macho" e "f^ emea". É mais simples usar os caracteres "m" e "f".
O uso do tipo de dados DATE para as colunas birth e death são obviamente a melhor
escolha.
Agora que você criou uma tabela, a instrução SHOW TABLES deve produzir alguma saída:
mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| pet |
+---------------------+
Para verificar se sua tabela foi criada da forma que você esperava, utilize a instrução
DESCRIBE:
mysql> DESCRIBE pet;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| name | varchar(20) | YES | | NULL | |
| owner | varchar(20) | YES | | NULL | |
| species | varchar(20) | YES | | NULL | |
| sex | char(1) | YES | | NULL | |
| birth | date | YES | | NULL | |
| death | date | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
Você pode usar DESCRIBE a qualquer hora, por exemplo, se você esquecer os nomes das
colunas na sua tabela ou de que tipos elas são.
Como você está começando com uma tabela vazia, uma forma simples de povoá-la é criar
um arquivo texto contendo uma linha para cada um de seus animais, e depois carregar o
conteúdo do arquivo para a tabela com uma simples instrução.
Você pode criar um arquivo texto ‘pet.txt’ contendo um registro por linha, com valores
separado por tabulações e na mesma ordem em que as colunas foram listadas na instrução
CREATE TABLE. Para valores em falta (como sexo desconhecido ou data da morte para
animais que ainda estão vivos), você pode usar valores NULL. Para representá-lo em seu
arquivo texto, use \N. Por exemplo, o registro para Whistler the bird podem parecer com
isto (onde o espaço em branco entre os valores é um simples caractere de tabulação):
Whistler Gwen bird \N 1997-12-09 \N
Para carregar o arquivo texto ‘pet.txt’ na tabela pet, use este comando:
mysql> LOAD DATA LOCAL INFILE "pet.txt" INTO TABLE pet;
Você pode especificar o valor do separador de colunas e o marcador de final de linha explici-
tamente na instrução LOAD DATA se você desejar. Mas os valores omitidos são suficientes
para a instrução ler o arquivo ‘pet.txt’ corretamente.
Quando você desejar adicionar novos registros um a um, a instrução INSERT é usada. Na
sua forma mais simples, você fornece valores para cada coluna, na ordem em que as colunas
foram listadas na instrução CREATE TABLE. Suponha que Diane tenha um novo hamster
chamado Puffball. Você pode adicionar um registro utilizando uma instrução INSERT desta
forma:
mysql> INSERT INTO pet
-> VALUES (’Puffball’,’Diane’,’hamster’,’f’,’1999-03-30’,NULL);
Perceba que os valores de string e datas são especificados aqui como strings com aspas.
Com o INSERT você também pode inserir NULL diretamente para representar um valor em
falta. Não pode ser usado \N como você fez com LOAD DATA.
A partir deste exemplo, você deverá perceber que existem várias outras formas envolvidas
para carregar seus registros inicialmente utilizando diversas instruções INSERT do que uma
simples instrução LOAD DATA.
Comparações de strings normalmente são caso insensitivo, então você pode especificar o
nome como "bowser", "BOWSER", etc. O resultado da pesquisa será o mesmo.
Você pode especificar condições em qualquer coluna, não apenas no name. Por exemplo,
se você deseja saber quais foram os animais que nasceram depois de 1998, teste o campo
birth:
mysql> SELECT * FROM pet WHERE birth >= "1998-1-1";
+----------+-------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+-------+
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Puffball | Diane | hamster | f | 1999-03-30 | NULL |
+----------+-------+---------+------+------------+-------+
Você pode combinar condições, por exemplo, para encontrar cadelas (dog/f):
mysql> SELECT * FROM pet WHERE species = "dog" AND sex = "f";
+-------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+-------+--------+---------+------+------------+-------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+-------+--------+---------+------+------------+-------+
A consulta anterior utiliza o operador lógico AND (e). Existe também um operador OR (ou):
mysql> SELECT * FROM pet WHERE species = "snake" OR species = "bird";
+----------+-------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+-------+
| Chirpy | Gwen | bird | f | 1998-09-11 | NULL |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
| Slim | Benny | snake | m | 1996-04-29 | NULL |
+----------+-------+---------+------+------------+-------+
AND e OR podem ser misturados. Se você fizer isto, é uma ótima idéia usar parênteses para
indicar quais condições devem ser agrupadas:
mysql> SELECT * FROM pet WHERE (species = "cat" AND sex = "m")
-> OR (species = "dog" AND sex = "f");
+-------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+-------+--------+---------+------+------------+-------+
+----------+------------+
| Fluffy | 1993-02-04 |
| Claws | 1994-03-17 |
| Buffy | 1989-05-13 |
| Fang | 1990-08-27 |
| Bowser | 1989-08-31 |
| Chirpy | 1998-09-11 |
| Whistler | 1997-12-09 |
| Slim | 1996-04-29 |
| Puffball | 1999-03-30 |
+----------+------------+
Para saber quem são os donos dos animais, use esta consulta:
mysql> SELECT owner FROM pet;
+--------+
| owner |
+--------+
| Harold |
| Gwen |
| Harold |
| Benny |
| Diane |
| Gwen |
| Gwen |
| Benny |
| Diane |
+--------+
Entretanto, perceba que a query simplesmente retornou o campo owner de cada registro, e
alguns deles apareceram mais de uma vez. Para minimizar a saída, recupere cada registro
apenas uma vez, adicionando a palavra chave DISTINCT:
mysql> SELECT DISTINCT owner FROM pet;
+--------+
| owner |
+--------+
| Benny |
| Diane |
| Gwen |
| Harold |
+--------+
Você pode usar uma cláusula WHERE para combinar seleção de registros com seleção de
colunas. Por exemplo, para obter a data de nascimento somente dos gatos e cachorros,
utilize esta query:
mysql> SELECT name, species, birth FROM pet
-> WHERE species = "dog" OR species = "cat";
+--------+---------+------------+
| name | species | birth |
+--------+---------+------------+
| Fluffy | cat | 1993-02-04 |
| Claws | cat | 1994-03-17 |
Chapter 3: Introdução ao MySQL: Um Tutorial MysQL 163
O MySQL fornece várias funções que você pode usar para realizar cálculos em datas, por
exemplo, para calcular idades ou extrair partes de datas.
Para determinar quantos anos cada um do seus animais tem, compute a diferença do ano
da data atual e a data de nascimento (birth), depois subtraia se a o dia/mês da data atual
for anterior ao dia/mês da data de nascimento. A consulta seguinte, mostra, para cada
animal, a data de nascimento, a data atual e a idade em anos.
mysql> SELECT name, birth, CURRENT_DATE,
-> (YEAR(CURRENT_DATE)-YEAR(birth))
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
-> AS age
-> FROM pet;
+----------+------------+--------------+------+
| name | birth | CURRENT_DATE | age |
+----------+------------+--------------+------+
| Fluffy | 1993-02-04 | 2001-08-29 | 8 |
| Claws | 1994-03-17 | 2001-08-29 | 7 |
| Buffy | 1989-05-13 | 2001-08-29 | 12 |
| Fang | 1990-08-27 | 2001-08-29 | 11 |
| Bowser | 1989-08-31 | 2001-08-29 | 11 |
| Chirpy | 1998-09-11 | 2001-08-29 | 2 |
| Whistler | 1997-12-09 | 2001-08-29 | 3 |
| Slim | 1996-04-29 | 2001-08-29 | 5 |
| Puffball | 1999-03-30 | 2001-08-29 | 2 |
+----------+------------+--------------+------+
Aqui, YEAR() separa a parte do ano de uma data e RIGHT() separa os cinco caracteres
mais a direita que representam a parte da data MM-DD. A parte da expressão que compara
os valores MM-DD resulta em 1 ou 0, o qual ajusta a diferença do ano um ano abaixo se
CURRENT_DATE ocorrer mais cedo, no ano, que birth. A expressão completa é um tanto
deselegante, então um apelido (age) é usado para obter uma saída mais significativa.
Chapter 3: Introdução ao MySQL: Um Tutorial MysQL 165
A consulta funciona, mas o resultado pode ser mais compreensível se os registros forem
apresentados em alguma ordem. Isto pode ser feito adicionando uma cláusula ORDER BY
name para ordenar a saída pelo nome:
mysql> SELECT name, birth, CURRENT_DATE,
-> (YEAR(CURRENT_DATE)-YEAR(birth))
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
-> AS age
-> FROM pet ORDER BY name;
+----------+------------+--------------+------+
| name | birth | CURRENT_DATE | age |
+----------+------------+--------------+------+
| Bowser | 1989-08-31 | 2001-08-29 | 11 |
| Buffy | 1989-05-13 | 2001-08-29 | 12 |
| Chirpy | 1998-09-11 | 2001-08-29 | 2 |
| Claws | 1994-03-17 | 2001-08-29 | 7 |
| Fang | 1990-08-27 | 2001-08-29 | 11 |
| Fluffy | 1993-02-04 | 2001-08-29 | 8 |
| Puffball | 1999-03-30 | 2001-08-29 | 2 |
| Slim | 1996-04-29 | 2001-08-29 | 5 |
| Whistler | 1997-12-09 | 2001-08-29 | 3 |
+----------+------------+--------------+------+
Para ordenar a saída por age em vez de name, é só utilizar uma cláusua ORDER BY diferente:
mysql> SELECT name, birth, CURRENT_DATE,
-> (YEAR(CURRENT_DATE)-YEAR(birth))
-> - (RIGHT(CURRENT_DATE,5)<RIGHT(birth,5))
-> AS age
-> FROM pet ORDER BY age;
+----------+------------+--------------+------+
| name | birth | CURRENT_DATE | age |
+----------+------------+--------------+------+
| Chirpy | 1998-09-11 | 2001-08-29 | 2 |
| Puffball | 1999-03-30 | 2001-08-29 | 2 |
| Whistler | 1997-12-09 | 2001-08-29 | 3 |
| Slim | 1996-04-29 | 2001-08-29 | 5 |
| Claws | 1994-03-17 | 2001-08-29 | 7 |
| Fluffy | 1993-02-04 | 2001-08-29 | 8 |
| Fang | 1990-08-27 | 2001-08-29 | 11 |
| Bowser | 1989-08-31 | 2001-08-29 | 11 |
| Buffy | 1989-05-13 | 2001-08-29 | 12 |
+----------+------------+--------------+------+
Uma consulta similar pode ser usada para determinar a idade na morte para animais que
morreram. Para determinar quais são os animais, confira se o valor de death não é NULL.
Depois para estes com valores não-NULL, compute a diferença entre os valores dos campos
death e birth:
mysql> SELECT name, birth, death,
-> (YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5))
-> AS age
-> FROM pet WHERE death IS NOT NULL ORDER BY age;
166 Referência técnica para o MySQL versão 3.23.52
+--------+------------+------------+------+
| name | birth | death | age |
+--------+------------+------------+------+
| Bowser | 1989-08-31 | 1995-07-29 | 5 |
+--------+------------+------------+------+
A query usa death IS NOT NULL em vez de death != NULL porque NULL é um valor especial.
Isto será explicado depois. See hundefinedi [Working with NULL], page hundefinedi.
E se você desejar saber quais animais fazem aniversário no próximo mês? Para este tipo
de cálculo, ano e dia são irrelevantes; você simplesmente deseja extrair a parte do mês da
coluna birth. O MySQL fornece diversas funções para extrair partes da data, como em
YEAR(), MONTH() e DAYOFMONTH(). MONTH é a função apropriada aqui. Para ver como ela
funciona, execute uma consulta simples que mostre o valor de birth e MONTH(birth):
mysql> SELECT name, birth, MONTH(birth) FROM pet;
+----------+------------+--------------+
| name | birth | MONTH(birth) |
+----------+------------+--------------+
| Fluffy | 1993-02-04 | 2 |
| Claws | 1994-03-17 | 3 |
| Buffy | 1989-05-13 | 5 |
| Fang | 1990-08-27 | 8 |
| Bowser | 1989-08-31 | 8 |
| Chirpy | 1998-09-11 | 9 |
| Whistler | 1997-12-09 | 12 |
| Slim | 1996-04-29 | 4 |
| Puffball | 1999-03-30 | 3 |
+----------+------------+--------------+
Encontrar animais com aníversário no próximo mês também é fácil. Suponha que o mês
atual é abril. Então o valor do mês é 4 e você procura por animais nascidos em Maio (mês
5) assim:
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
+-------+------------+
| name | birth |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
Existe uma pequena complicação se o mês atual é Dezembro, é claro. Você não pode apenas
adicionar um para o número do mês (12) e procurar por animais nascidos no mês 13, porque
não existe tal mês. O certo seria procurar por animais nascidos em Janeiro (mês 1).
Você pode também escrever uma consulta para que funcione sem importar qual é o mês
atual. Assim você não têm quee usar um número de mês em particular na consulta. DATE_
ADD() permite adicionar um intervalo de tempo para uma data fornecida. Se você adicionar
um mês para o valor de NOW(), então extrair a parte do mês com MONTH(), o resultado é o
mês no qual você deseja procurar por aniversários:
mysql> SELECT name, birth FROM pet
-> WHERE MONTH(birth) = MONTH(DATE_ADD(NOW(), INTERVAL 1 MONTH));
Chapter 3: Introdução ao MySQL: Um Tutorial MysQL 167
Uma maneira diferente para realizar a mesma tarefa é adicionar 1 para obter o mês seguinte
ao atual (depois de usar a função módulo (MOD) para o valor do mês retornar 0 se ele for
12):
mysql> SELECT name, birth FROM pet
-> WHERE MONTH(birth) = MOD(MONTH(NOW()), 12) + 1;
Perceba que MONTH retorna um número entre 1 e 12. E MOD(alguma_coisa,12) retorna um
número entre 0 e 11. Então a adição tem que ser feita depois do MOD(), senão iríamos de
Novembro (11) para Janeiro (1).
• Expressões regulares caso sensitivo, mas você pode usar uma classe de caracteres para
combinar maíusculas/minúsculas se você desejar. Por exemplo, ‘[aA]’ combina o ‘a’
minúsculo ou maiúsculo e ‘[a-zA-Z]’ combina qualquer letra em ambos casos.
• O padrão combina se ele ocorre em algum lugar no valor sendo testado. (Padrões SQL
combinam somente se eles combinarem com todo o valor.)
• Para fazer com que um padrão deva combinar com o começo ou o fim de um valor
sendo testado, utilize ‘^’ no começo ou ‘$’ no final do padrão.
Para demonstrar como expressões regulares extendidas funcionam, as consultas com LIKE
mostradas acima foram reescritas abaixo usando REGEXP.
Para encontrar nomes começando com ‘b’, utilize ‘^’ para combinar com o começo do nome:
mysql> SELECT * FROM pet WHERE name REGEXP "^b";
+--------+--------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+------------+
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
+--------+--------+---------+------+------------+------------+
Antes da versão 3.23.4 do MySQL, REGEXP era caso sensitivo, e a consulta anterior não iria
retornar nenhum registro. Para combinar letras ‘b’ maiúsculas e minúsculas, utilize esta
consulta:
mysql> SELECT * FROM pet WHERE name REGEXP "^[bB]";
A partir do MySQL 3.23.4, para forçar uma comparação REGEXP com caso sensitivo, utilize
a palavra-chave BINARY para tornar uma das strings em uma string binárias. Esta consulta
irá combinar somente com ‘b’s minúsculos no começo de um nome:
mysql> SELECT * FROM pet WHERE name REGEXP BINARY "^b";
Para encontrar nomes finalizados com ‘fy’, utilize ‘$’ para combinar com o final do nome:
mysql> SELECT * FROM pet WHERE name REGEXP "fy$";
+--------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | cat | f | 1993-02-04 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+--------+--------+---------+------+------------+-------+
Para encontrar nomes contendo um ‘w’ minúsculo ou maiúsculo, utilize esta consulta:
mysql> SELECT * FROM pet WHERE name REGEXP "w";
+----------+-------+---------+------+------------+------------+
| name | owner | species | sex | birth | death |
+----------+-------+---------+------+------------+------------+
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Bowser | Diane | dog | m | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen | bird | NULL | 1997-12-09 | NULL |
+----------+-------+---------+------+------------+------------+
Como uma expressão regular extendida encontra padrões coincidentes se eles ocorrem em
qualquer lugar no valor comparado, não é necessário utiliar, na consulta anterior, nenhum
170 Referência técnica para o MySQL versão 3.23.52
metacaracter em nenhum dos lados do padrão para fazê-lo coincidir com todo o valor, como
seria feito se fosse utilizado o padrão SQL.
Para encontrar nomes contendo exatamente cinco caracteres, utilize ‘^’ e ‘$’ para combinar
com o começo e fim do nome e cinco instâncias de ‘.’ entre eles.
mysql> SELECT * FROM pet WHERE name REGEXP "^.....$";
+-------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+-------+--------+---------+------+------------+-------+
Você pode também escrever a consulta anterior utilizando o operador ‘{n}’ “repete-n-vezes”:
mysql> SELECT * FROM pet WHERE name REGEXP "^.{5}$";
+-------+--------+---------+------+------------+-------+
| name | owner | species | sex | birth | death |
+-------+--------+---------+------+------------+-------+
| Claws | Gwen | cat | m | 1994-03-17 | NULL |
| Buffy | Harold | dog | f | 1989-05-13 | NULL |
+-------+--------+---------+------+------------+-------+
Perceba o uso de GROUP BY para agrupar todos os registros para cada owner (dono). Sem
ele, você teria uma mensagem de erro:
mysql> SELECT owner, COUNT(owner) FROM pet;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause
COUNT() e GROUP BY são úteis para personalizar seus dados de diversas maneiras. Os
seguintes exemplos mostram diferentes maneiras para realizar operações de censo nos ani-
mais.
Número de animais por espécie:
mysql> SELECT species, COUNT(*) FROM pet GROUP BY species;
+---------+----------+
| species | COUNT(*) |
+---------+----------+
| bird | 2 |
| cat | 2 |
| dog | 3 |
| hamster | 1 |
| snake | 1 |
+---------+----------+
Número de animais por sexo:
mysql> SELECT sex, COUNT(*) FROM pet GROUP BY sex;
+------+----------+
| sex | COUNT(*) |
+------+----------+
| NULL | 1 |
| f | 4 |
| m | 4 |
+------+----------+
(Nesta saída, NULL indica sexo desconhecido.)
Número de animais combinando espécie e sexo:
mysql> SELECT species, sex, COUNT(*) FROM pet GROUP BY species, sex;
+---------+------+----------+
| species | sex | COUNT(*) |
+---------+------+----------+
| bird | NULL | 1 |
| bird | f | 1 |
| cat | f | 1 |
| cat | m | 1 |
| dog | f | 1 |
| dog | m | 2 |
| hamster | f | 1 |
| snake | m | 1 |
+---------+------+----------+
Não é necessário selecionar uma tabela inteira quando estiver usando COUNT(). Por exemplo,
a consulta anterior, quando realizada apenas procurando por cachorros e gatos, se parece
com isto:
172 Referência técnica para o MySQL versão 3.23.52
+---------+-------------+------+-----+---------+-------+
A coluna Field (campo) indica o nome da coluna, Type é o tipo de dados para a coluna,
Null indica se a coluna pode conter valores nulos (NULL), key indica se a coluna é indexada
ou não e Default especifica o valor padrão da coluna.
Se você tem índices em uma tabela, SHOW INDEX FROM tbl_nome traz informações sobre eles.
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | A | 3.45 |
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | B | 1.45 |
| 0003 | C | 1.69 |
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+--------+-------+
+---------+
176 Referência técnica para o MySQL versão 3.23.52
| article |
+---------+
| 4 |
+---------+
Outra solução é ordenar todos os registros por preço de forma descendente e obtenha so-
mente o primeiro registro utilizando a cláusula específica do MySQL LIMIT:
SELECT article, dealer, price
FROM shop
ORDER BY price DESC
LIMIT 1
NOTA: Se existir diversos ítens mais caros (por exemplo, cada um por 19,95) a solução
LIMIT mostra somente um deles !
+---------+-------+
| article | price |
+---------+-------+
| 0001 | 3.99 |
| 0002 | 10.99 |
| 0003 | 1.69 |
| 0004 | 19.95 |
+---------+-------+
Chapter 3: Introdução ao MySQL: Um Tutorial MysQL 177
INSERT INTO tmp SELECT article, MAX(price) FROM shop GROUP BY article;
UNLOCK TABLES;
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0001 | B | 3.99 |
| 0002 | A | 10.99 |
| 0003 | C | 1.69 |
| 0004 | D | 19.95 |
+---------+--------+-------+
O último exemplo pode, é claro, ser feito de uma maneira mais eficiente fazendo a separação
da coluna concatenada no cliente.
178 Referência técnica para o MySQL versão 3.23.52
+---------+--------+-------+
| article | dealer | price |
+---------+--------+-------+
| 0003 | D | 1.25 |
| 0004 | D | 19.95 |
+---------+--------+-------+
+----+-------+--------+-------+
| id | style | color | owner |
+----+-------+--------+-------+
| 4 | dress | orange | 2 |
| 5 | polo | red | 2 |
| 6 | dress | blue | 2 |
+----+-------+--------+-------+
O MySQL ainda não otimiza quando você pesquisa em duas chaves diferentes combinadas
com OR (Pesquisa em uma chave com diferentes partes OR é muito bem otimizadas).
SELECT field1_index, field2_index FROM test_table WHERE field1_index = ’1’
OR field2_index = ’1’
180 Referência técnica para o MySQL versão 3.23.52
A razão é que nós ainda não tivemos tempos para fazer este tratamento de uma maneira
eficiente no caso geral. (A manipulação do AND é, em comparação, completamente geral e
funciona muito bem).
No momento você pode resolver isto de maneira eficiente usando uma tabela TEMPORÁRIA.
Este tipo de otimização é também muito boa se você estiver utilizando consultas muito
complicadas no qual o servidor SQL faz as otimizações na ordem errada.
CREATE TEMPORARY TABLE tmp
SELECT field1_index, field2_index FROM test_table WHERE field1_index = ’1’;
INSERT INTO tmp
SELECT field1_index, field2_index FROM test_table WHERE field2_index = ’1’;
SELECT * from tmp;
DROP TABLE tmp;
A maneira descrita acima para resolver esta consulta é uma união (UNION) de duas consultas.
que retornará:
+------+-------+------+
| year | month | days |
+------+-------+------+
| 2000 | 01 | 3 |
| 2000 | 02 | 2 |
+------+-------+------+
O exemplo acima calcula quantos dias diferentes foram usados para uma combinação
fornecida de mês/ano, com remoção automática de entradas duplicadas.
/* For Twin 2 */
left join twin_data as td2 on p2.id = td2.id and p2.tvab = td2.tvab
left join informant_data as id2 on p2.id = id2.id and p2.tvab = id2.tvab
left join harmony as h2 on p2.id = h2.id and p2.tvab = h2.tvab
left join lentus as l2 on p2.id = l2.id and p2.tvab = l2.tvab,
person_data as p1,
person_data as p2,
postal_groups as pg
where
/* p1 gets main twin and p2 gets his/her twin. */
/* ptvab is a field inverted from tvab */
p1.id = tp.id and p1.tvab = tp.tvab and
p2.id = p1.id and p2.ptvab = p1.tvab and
/* Just the sceening survey */
tp.survey_no = 5 and
/* Skip if partner died before 65 but allow emigration (dead=9) */
(p2.dead = 0 or p2.dead = 9 or
(p2.dead = 1 and
(p2.death_date = 0 or
(((to_days(p2.death_date) - to_days(p2.birthday)) / 365)
>= 65))))
and
(
/* Twin is suspect */
(td.future_contact = ’Yes’ and td.suspect = 2) or
/* Twin is suspect - Informant is Blessed */
(td.future_contact = ’Yes’ and td.suspect = 1 and id.suspect = 1) or
/* No twin - Informant is Blessed */
(ISNULL(td.suspect) and id.suspect = 1 and id.future_contact = ’Yes’) or
/* Twin broken off - Informant is Blessed */
(td.participation = ’Aborted’
and id.suspect = 1 and id.future_contact = ’Yes’) or
/* Twin broken off - No inform - Have partner */
(td.participation = ’Aborted’ and ISNULL(id.suspect) and p2.dead = 0))
and
l.event = ’Finished’
/* Get at area code */
and substring(p1.postal_code, 1, 2) = pg.code
/* Not already distributed */
and (h.nurse is NULL or h.nurse=00 or h.doctor=00)
/* Has not refused or been aborted */
and not (h.status = ’Refused’ or h.status = ’Aborted’
or h.status = ’Died’ or h.status = ’Other’)
order by
tvid;
Algumas explicações:
184 Referência técnica para o MySQL versão 3.23.52
--debug[...]=
Se o MySQL está configurado com --with-debug, você pode usar esta opção
para obter um arquivo de rastreamento indicando o que o mysqld está fazendo.
See hundefinedi [Criando arquivos de rastreamento], page hundefinedi.
--delay-key-write-for-all-tables
Não atualiza buffers das chaves entre escritas em nenhuma tabela MyISAM. See
hundefinedi [Parâmetros do servidor], page hundefinedi.
--enable-locking
Habilita o bloqueio do sistema. Perceba que se usar esta opção em um sistema
que não possui um lockd() completamente funcional (como no Linux) você pode
fazer com que o mysqld entre em deadlock.
--enable-named-pipe
Habilita suporte para named pipes (somente no NT/Win2000/XP).
-T, --exit-info
Esta é uma máscara binária com diferêntes parâmetros que pode ser usada para
depurar o servidor mysqld; Esta opção não deve ser usada por alguém que não
a conheça muito bem!
--flush Atualiza todas as alterações no disco depois de cada comando SQL. Normal-
mente o MySQL só faz a escrita de todas as alterações no disco depois de cada
comando SQL e deixa o sistema operacional lidar com a sincronização com o
disco. See hundefinedi [Falhas], page hundefinedi.
-?, --help
Mostra uma pequena ajuda e sai.
--init-file=arquivo
Lê comandos SQL do arquivo especificado na inicialização.
-L, --language=...
Mensagens de erro do cliente na língua especificada. Pode ser fornecido como
um caminho completo. See hundefinedi [Línguas], page hundefinedi.
-l, --log[=arquivo]
Log de conexões e consultas ao arquivo. See hundefinedi [Log de consultas],
page hundefinedi.
--log-isam[=arquivo]
Log de todas alterações ISAM/MyISAM no arquivo (usado somente quando
estiver depurando bancos ISAM/MyISAM).
--log-slow-queries[=arquivo]
Log de todas as consultas que levam mais de long_query_time segundos de
execução para um arquivo. See hundefinedi [Log de consultas lentas], page hun-
definedi.
--log-update[=arquivo]
Log de atualizações para file.# onde # é um número único se não for fornecido.
See hundefinedi [Log de atualização], page hundefinedi.
188 Referência técnica para o MySQL versão 3.23.52
--log-long-format
Log de algumas informações extra ao log de atualizações. Se você estiver usando
--log-slow-queries então consultas que não estão usando índices são logadas
ao log de consultas lentas.
--low-priority-updates
Operações de alterações das tabelas (INSERT/DELETE/UPDATE) irão ter priori-
dade menor do que as selects. Isto também pode ser feito usando {INSERT |
REPLACE | UPDATE | DELETE} LOW_PRIORITY ... para baixar a prioridade de
somente uma consulta, ou SET OPTION SQL_LOW_PRIORITY_UPDATES=1 para al-
terar a prioridade em uma única thread. See hundefinedi [Bloqueio de tabelas],
page hundefinedi.
--memlock
Bloqueia o processo mysqld na memória. Isto funciona somente se o seu sistema
suportar a chamada de sistema mklockall() (como no Solaris). Isto pode
ajudar se você tiver um problema no qual o sistema operacional faz com que o
mysqld faça a troca em disco.
--myisam-recover [=opç~ ao[,opç~
ao...]]] onde opç~ ao é qualquer combinaç~ ao
de DEFAULT, BACKUP, FORCE ou QUICK. Você também pode configurar isto ex-
plicitamente para "" se você deseja desabilitar esta opção. Se esta opção for
usada, o mysqld irá conferir na abertura se a tabela está marcada como que-
brada ou se a tabela não foi fechada corretamente. (A última opção funciona
somente se você estiver executando com --skip-locking). Se este for o caso
mysqld irá executar uma conferência na tabela. Se a tabela estiver corrompida,
o mysqld irá tentar repará-la.
As seguintes opções afetam no funcionamento da reparação.
DEFAULT O mesmo que não fornecer uma opção para --myisam-
recover.
BACKUP Se os dados da tabela foram alterados durante a recuperação,
salve um backup do arquivo de dados ‘nome_tabela.MYD’
como ‘nome_tabela_dia_hora.BAK’.
FORCE Execute a recuperação mesmo se perdermos mais de uma
linha do arquivo .MYD.
QUICK Não confira as linhas na tabela se não existir nenhum bloco
apagado.
Antes da tabela ser reparada automaticamente, o MySQL irá adicionar uma
nota no log de erros. Se você desejar que a recuperação da maioria das
coisas não tenha a intervenção de algum usuário, devem ser usadas as opções
BACKUP,FORCE. Isto irá forçar um reparo de uma tabela mesmo se alguns
registros forem apagados, mas ele manterá o arquivo de dados antigo como um
backup para que você possa examinar posteriormente o que aconteceu.
--pid-file=path
Encaminha para o arquivo pid usado pelo safe_mysqld.
-P, --port=...
Número da porta para conexões TCP/IP.
Chapter 4: Administração de Bancos de Dados MySQL 189
-o, --old-protocol
Utilize o protocolo 3.20 para compatibilidade com alguns clientes muito antigos.
See hundefinedi [Upgrading-from-3.20], page hundefinedi.
--one-thread
Use somente uma thread (para depuração sobre Linux). See hundefinedi [De-
bugging server], page hundefinedi.
-O, --set-variable var=opç~ ao
Fornece um valor para uma variável. --help lista as variáveis. Você
pode encontrar uma descrição completa para todas as variáveis na seção
SHOW VARIABLES deste manual. See hundefinedi [SHOW VARIABLES],
page hundefinedi. A seção de sintonia dos parâmetros do servidor inclui
informações sobre como otimizá-los. See hundefinedi [Server parameters],
page hundefinedi.
--safe-mode
Salta alguns estágios de otimização. Implica --skip-delay-key-write.
--safe-show-database
Não mostra os bancos de dados nos quais o usuário não tenha privilégios.
--safe-user-create
Se isto estiver ativo, um usuário não pode criar novos usuários com o comando
GRANT, se o usuário não ter o privilégio de INSERT na tabela mysql.user ou
em alguma coluna desta tabela.
--skip-concurrent-insert
Desliga a habilidade de selecionar e inserir ao mesmo tempo em tabelas MyISAM.
(Isto só é usado se você achar que encontrou um erro neste recurso).
--skip-delay-key-write
Ignore a opção delay_key_write para todas as tabelas. See hundefinedi
[Parâmetros do servidor], page hundefinedi.
--skip-grant-tables
Esta opção faz com que o servidor não use o sistema de privilégio. Isto dá a
todos acesso pleno a todos os bancos de dados! (Você pode dizer a um servidor
em execução para iniciar a usar as tabelas de permissão novamente executando
mysqladmin flush-privileges ou mysqladmin reload.)
--skip-host-cache
Nunca utiliza cache para nomes de máquina para resoluções de nomes mais
rápidos, mas pesquisa o servidor DNS em todas conexões. See hundefinedi
[DNS], page hundefinedi
--skip-locking
Não utilizar bloqueio de sistema. Para usar isamchk ou myisamchk você deve
desligar o servidor. See hundefinedi [Stability], page hundefinedi. Perceba que
na Versão 3.23 do MySQL pode ser usado REPAIR e CHECK para reparar/conferir
tabelas MyISAM.
190 Referência técnica para o MySQL versão 3.23.52
--skip-name-resolve
Nomes de máquinas não são resolvidos. Todos os valores da coluna Host nas
tabelas de permissões devem conter números IP ou localhost. See hundefinedi
[DNS], page hundefinedi.
--skip-networking
Não escutair conexões TCP/IP. Toda interação com mysqld deve ser feito
através de sockets Unix. Esta opção é altamente recomendada para sistemas
onde requisições locais são permitidas. See hundefinedi [DNS], page hundefinedi
--skip-new
Não utilizar rotinas novas, possívelmente erradas. Implica --skip-delay-key-
write. Isto também configura o tipo de tabela padrão como ISAM. See hunde-
finedi [ISAM], page hundefinedi.
--skip-symlink
Não apague ou renomeie arquivos de ligação simbólica para o diretório de dados.
--skip-safemalloc
Se o MySQL é configurado com --with-debug=full, todos os programas irão
verificar a memória por erros para cada alocação e liberação de memória. Como
esta consistência é muito lenta, você pode evitá-la, quando você não precisar
de verificar a memória, usando esta opção.
--skip-show-database
Não permite o comando ’SHOW DATABASE’, a menos que o usuário tenha
privilégio process.
--skip-stack-trace
Não gravar rastreamentos de pilha. Esta opção é útil quando você estiver exe-
cutando o mysqld sob um depurador. See hundefinedi [Depurando o servidor],
page hundefinedi.
--skip-thread-priority
Desabilita o uso de prioridade das threads para um tempo de resposta mais
rápido.
--socket=path
Arquivo socket para usar em conexões locais no lugar do padrão
/tmp/mysql.sock.
--sql-mode=opç~
ao[,opç~ao[,opç~
ao...]]
Opção pode ser qualquer combinação de: REAL_AS_FLOAT, PIPES_AS_CONCAT,
ANSI_QUOTES, IGNORE_SPACE, SERIALIZE, ONLY_FULL_GROUP_BY. Ela também
pode ficar vazia ("") se você desejar limpá-la.
Especificar todas as opções acima é o mesmo que usar –ansi. Com estas opções,
pode se ligar somente os modos SQL necessários. See hundefinedi [Modo ANSI],
page hundefinedi.
transaction-isolation= { READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ
| SERIALIZABLE }
Configura o nível de isolação da transação padrão. See hundefinedi [SET
TRANSACTION], page hundefinedi.
Chapter 4: Administração de Bancos de Dados MySQL 191
-t, --tmpdir=caminho
Encaminha para arquivos temporários. Ele pode ser útil se o seu diretório
padrão /tmp está em uma partição muito pequena para armazenar tabelas tem-
porárias.
-u, --user=nome_usuário
Executar o servidor mysqld como o usuário nome_usuário. Esta opção é obri-
gatória quando o mysqld é iniciado como usuário root.
-V, --version
Gera saída com a informação da versão e sai.
-W, --warnings
Imprime avisos como Aborted connection... no arquivo .err. See hunde-
finedi [Erros de comunicação], page hundefinedi.
[mysqld]
port=3306
socket=/tmp/mysql.sock
set-variable = key_buffer_size=16M
set-variable = max_allowed_packet=1M
[mysqldump]
quick
Aqui está um típico arquivo de opções do usuário
[client]
# A senha seguinte será enviada para todos clientes MySQL
password=minha_senha
[mysql]
no-auto-rehash
Chapter 4: Administração de Bancos de Dados MySQL 193
set-variable = connect_timeout=2
[mysqlhotcopy]
interactive-timeout
Se você tem uma distribuição fonte, você encontrará arquivos de exemplo de configuração
chamados ‘my-xxxx.cnf’ no diretório ‘support-files’. Se você tem uma distribuição
binária olhe no diretório de instalação ‘DIR/support-file’, onde DIR é o caminho para o
diretório de instalação (normalmente ‘/usr/local/mysql’). Atualmente existem arquivos
de configuração para sistemas pequenos, médios, grandes e enormes. Você pode copiar
‘my-xxxx.cnf’ para seu diretório home (renomeie a cópia para ‘.my.cnf’ para experimen-
tar.
Todos os clientes MySQL que suportam arquivos de opções aceitam opções:
–no-defaults Não lê nenhum arquivo de opções.
–print-defaults Imprima o nome do programa e todas opções.
–defaults-file=caminho-para- Utilize somente o arquivo de configuração es-
arquivo-padrão pecíficado.
–defaults-extra-file=caminho-para- Leia este arquivo de configuração depois do arquivo
arquivo-padrão de configuração global mas antes do arquivo de con-
figuração do usuário.
Perceba que as opções acima devem vir primeiro na linha de comando para funcionar!
--print-defaults pode, no entanto, ser usado logo depois dos comandos --defaults-
xxx-file.
Notas para desenvolvedores: O tratamento de arquivos de opções é implementado simples-
mente processando todos as opções coincidentes (isto é, opções no grupo apropriado) antes
de qualquer argumento da linha de comando. Isto funciona bem para programas que usam
a última instância de uma opção que é especificada diversas vezes. Se você tem um pro-
grama antigo que trata opções especificadas várias vezes desta forma mas não lê arquivos
de opções, você só precisa adicionar duas linhas para lhe dar esta capacidade. Verifique o
código fonte de qualquer um dos clientes MySQL padrão para ver como fazer isto.
Nos scripts shell você pode usar o comando ‘my_print_defaults’ para analisar os arquivos
config:
Uma maneira de ter um novo servidor executando é iniciando-o com um socket e porta
diferentes, como segue:
shell> MYSQL_UNIX_PORT=/tmp/mysqld-new.sock
shell> MYSQL_TCP_PORT=3307
shell> export MYSQL_UNIX_PORT MYSQL_TCP_PORT
shell> scripts/mysql_install_db
shell> bin/safe_mysqld &
O apêndice das variáveis de ambiente incluem uma lista de outras variáveis de ambiente que
você pode usar e que afetam o mysqld. See hundefinedi [Variáveis de ambiente], page hun-
definedi.
A forma descrita acima é a maneira mais rápida e suja que normalmente é usado para
testes. A melhor coisa é que com isto todas as conexões que você faz na shell acima irão
automaticamente ser direcionadas para o novo servidor.
Se você precisar fazer isto permanentemente, você deve criar um arquivo de opções para cada
servidor. See hundefinedi [Arquivos de opção], page hundefinedi. No script de inicialização
que é executado no tempo de boot (mysql.server) você deve especificar ambos os servidores:
safe_mysqld --default-file=path-to-option-file
Pelo menos as seguines opções devem ser diferentes por servidor:
port=#
socket=path
pid-file=path
As seguintes opções devem ser diferentes, se elas forem usadas:
log=path
log-bin=path
log-update=path
log-isam=path
bdb-logdir=path
Se você precisar de mais performance, você também pode diferenciar:
tmpdir=path
bdb-tmpdir=path
See hundefinedi [Opções de linha de comando], page hundefinedi.
Se você estiver instalando versões binárias do MySQL (arquivos .tar) e iniciá-los
com ./bin/safe_mysql então na maioria dos casos a única opção que você precisa
adicionar/alterar são os argumentos socket e port do safe_mysqld.
Se você deseja executar múltiplos servidores, a forma mais fácil é compilá-los com diferentes
portas TCP/IP e arquivos socket para que ambos não escutem na mesma porta TCP/IP
ou arquivo socket. See hundefinedi [mysqld_multi], page hundefinedi.
Considere que um servidor existente está configurado para a porta e arquivo socket padrões.
Então configure o novo servidor com o comando configure assim:
shell> ./configure --with-tcp-port=número_porta \
--with-unix-socket-path=nome_arquivo \
--prefix=/usr/local/mysql-3.22.9
Aqui número_porta e nome_arquivo deve ser diferente que o número da porta e o caminho
do arquivo socket padrões e o valor --prefix deve especificar um diretório de instalação
diferente daquele usado pelo servidor existente.
Você pode conferir o socket usado por qualquer servidor MySQL em execução com este
comando:
shell> mysqladmin -h hostname --port=número porta variáveis
Se você especificar “localhost” como o nome da máquina, mysqladmin irá por padrão usar
sockets Unix no lugar de TCP/IP.
Se você tem um servidor MySQL executando na porta que você usou, você obterá uma lista
de algumas das variáveis configuráveis mais importantes no MySQL, incluindo o nome do
socket.
Não é necessário recompilar um novo servidor MySQL apenas para iniciar com uma porta
ou socket diferentes. Você pode alterar a porta e o socket a ser usado especificando-os no
tempo de execução como opções para o safe_mysqld:
shell> /path/to/safe_mysqld --socket=nome_arquivo --port=número_porta
mysqld_multi pode também utilizar o safe_mysqld (ou mysqld) como um argumento e
passar as opções de um arquivo de configuração para o safe_mysqld e mysqld.
Se você executar o novo servidor no mesmo diretório do banco de dados que o outro servidor
com o log habilitado, você também deve especificar o nome dos arquivos log para o safe_
mysqld com --log, --log-update, ou --log-slow-queries. Se não, ambos servidores
podem tentar escrever no mesmo arquivo de log.
AVISO: Normalmente você nunca deve ter dois servidores que atualizam dados no mesmo
banco de dados! Se seu SO não suporta bloqueio de sistema a prova de falhas, isto pode
provocar surpresas indesejáveis.
Se você deseja usar outro diretório de banco de dados para o segundo servidor, você pode
usar a opção --datadir=caminho para o safe_mysqld.
NOTE também, que iniciando vários servidores MySQL (mysqlds) em diferentes máquinas
e deixá-los acessar um diretório de dados sob NFS, é normalmente uma MÁ IDÉIA! O
problema é que o NFS se tornará um gargalo, tornando o sistema lento. Ele não se destina
para este tipo de uso. E você ainda não terá como ter certeza que dois ou mais mysqlds
não estão interferindos uns com os outros. No momento não existe nenhuma plataforma
que faria, com 100% de segurança, o bloqueio de arquivos (daemon
Quando você for conectar a um servidor MySQL que esteja executando com uma porta
diferente daquela que foi compilada no seu cliente, você pode usar um dos seguintes métodos:
196 Referência técnica para o MySQL versão 3.23.52
Checklist:
− Tente mysql -u root. Se você conseguir conectar com sucesso ao servidor sem
a solicitação de uma senha, você tem problemas. Qualquer um pode conectar
ao seu servidor MySQL como o usuário root com privilégios plenos! Revise as
instruções de instalação do MySQL, prestando atenção particularmente ao item
sobre configuração da senha do usuário root.
− Utilize o comando SHOW GRANTS e confira para ver quem tem acesso a o que. Re-
mova aqueles privilégios que não são necessários utilizando o comando REVOKE.
• Não mantenha nenhuma senha de texto puro no seu banco de dados. Quando seu
computador fica comprometido, o intruso pode obter a lista completa de senhas e
utilizá-las. No lugar utilize a função MD5() ou qualquer função de embaralhamento de
via única.
• Não escolha senhas de dicionários. Existem programas especiais para quebrá-las.
Mesmo senhas como “xfish98” não sao boas. Muito melhor seria “duag98” que contém
a mesma palavra ’fish mas digitada uma letra a esquerda em um teclado QWERTY
convencional. Outro método seria usar “Mhall” que é obtido dos primeiros caracteres
de cada palavra na frase “Mary has a litle lamb”. Isto é fácil de lembrar e digitar, mas
dificulta que alguém que não a conheça a advinhe.
• Invista em um firewall. Ele protege você de pelo menos 50% de todos os tipos de
exploits em qualquer software. Coloque o MySQL atrás do firewall ou em uma zona
desmilitarizada (DMZ).
Checklist:
− Tente examinar suas portas da Internet utilizando alguma ferramenta como o nmap.
O MySQL utiliza a porta 3306 por padrão. Esta porta não deve ser acessível
para máquinas não confiáveis. Outra maneira simples para conferir se sua porta
do MySQL está aberta ou não é tentar o seguinte comando de alguma máquina
remota, onde nome_máquina é o nome da máquina ou o endereço IP de seu servidor
MySQL:
shell> telnet nome_máquina 3306
Se você obter uma conexão e alguns caracteres, a porta está aberta e deve ser
fechada no seu firewall ou roteador, a menos que você realmente tenha uma boa
razão para mantê-la aberta. Se o telnet apenas parar ou a conexão for recusada,
tudo está bem; a porta está bloqueada.
• Não confie em nenhum dado incluídos pelos seus usuários. Eles podem tentar enganar
seu código entrando com caracteres especiais ou sequencias de escape nos formulários
Web, URLS ou qualquer aplicação que você construa. Tenha certeza que sua aplicação
continua segura se um usuário entrar com algo do tipo “; DROP DATABASE mysql;”.
Este é um exemplo extremo, mas grandes falhas de segurança ou perda de dados podem
ocorrer como o resultado de hackers utilizando técnicas similares, se você não estiver
preparado para eles.
Também lembre de conferir dados numéricos. Um erro comum é proteger somente as
strings. Em alguns casos as pessoas pensam que se um banco de dados contém somente
dados disponíveis publicamente, ele não precisa ser protegido. Isto não é verdade. No
mínimo ataques do tipo denial-of-service podem ser feitos nestes bancos de dados. A
maneira mais simples para proteger deste tipo de ataque é usar apóstrofos em torno
198 Referência técnica para o MySQL versão 3.23.52
das contantes numéricas: SELECT * FROM tabela WHERE ID=’234’ em vez de SELECT *
FROM table WHERE ID=234. O MySQL automaticamente converte esta string para um
número e corta todos os símbolos não-numéricos dela.
Checklist:
− Todas aplicações Web:
• Tente inserir ‘’’ e ‘"’ em todos seus formulários Web. Se você obter qualquer
tipo de erro do MySQL, investigue o problema imediatamente.
• Tente modificar qualquer URL dinâmica adicionando %22 (‘"’), %23 (‘#’) e %27
(‘’’) na URL.
• Tente modificar os tipos de dados nas URLs dinâmicas de numérico para
caractere contendo caracteres dos exemplos anteriores. Sua aplicação deve ser
segura contra estes ataques e similares.
• Tente inserir caracteres, espaços e símbolos especiais no lugar de número nos
campos numéricos. Sua aplicação deve removê-los antes de passá-los para o
MySQL ou sua aplicação deve gerar um erro. Passar valores não verificados
ao MySQL é extramente perigoso!
• Confira o tamanho dos dados antes de passá-los ao MySQL.
• Considere ter sua aplicação conectando ao banco de dados utilizando um
usuário diferente doq ue o que é utilizado com propósitos administrativos.
Não forneça às suas aplicações mais privilégios de acesso do que elas necessi-
tam.
− Usuários do PHP:
• Confira a função addslashes. No PHP 4.0.3, uma função mysql_escape_
string() está disponível e é baseada na função com o mesmo nome da API
C do MySQL.
− Usuários do API C do MySQL:
• Confira a chamada API mysql_escape_string().
− Usuários do MySQL:
• Confira os modificadores escape e quote para consultas streams.
− Usuários do Perl DBI:
• Confira o método quote() ou utilize aspas simples ou duplas.
− Usuários do Java JDBC:
• Utilize um objeto PreparedStatement e aspas simples ou duplas.
• Não transmita dados sem criptografia na Internet. Estes dados são acessíveis para
todos que tenham o tempo e habilidade para interceptá-lo e usá-lo para seu propósito
próprio. No lugar, utilize um protocolo de criptografia como o SSL ou SSH. O MySQL
suporta conexões SSL interno desde a versão 3.23.9. O repasse de portas do SSH pode
ser usado para criar um tunel criptografado (e com compressão) para a comunicação.
• Aprenda a usar os utilitários tcpdump e strings. Para a maioria dos casos você
pode conferir se o fluxo de dados do MySQL está ou não criptografado utilizando um
comando parecido com este:
shell> tcpdump -l -i eth0 -w - src or dst port 3306 | strings
Chapter 4: Administração de Bancos de Dados MySQL 199
(Isto funciona sobre Linux e deve funcionar com pequenas modificações sob outros
sistemas.) Alerta: Se você não ver dados não significa sempre que esteja criptografado.
Se você necessita de alta segurança, você deve consultar um especialista em segurança.
Estas opções configuram o servidor para iniciar como o usuário designado quando você o
inicia manualmente ou usando safe_mysqld ou mysql.server. Para maiores detalhes,
veja hundefinedi [Changing MySQL user], page hundefinedi.
• Não suportar links simbólicos para tabelas (Isto pode ser desabilitado com a opção --
skip-symlink. Isto é muito importante caso você execute o mysqld como root, assim
qualquer um que tenha acesso à escrita aos dados do diretório do mysqld podem apagar
qualquer arquivo no sistema! See hundefinedi [Symbolic links to tables], page hunde-
finedi.
• Verfique se o usuário Unix que executa o mysqld é o único usuário com privilégios de
leitura/escrita nos diretórios de bancos de dados.
• Não forneça o privilégio process para todos os usuários. A saída de mysqladmin
processlits mostra as consultas atualmente em execução, portanto qualquer usuário
que consiga executar este comando deve ser apto a ver se outro usuário entra com uma
consulta do tipo UPDATE user SET password=PASSWORD(’n~ ao_seguro’).
O mysqld reserva uma conexão extra para usuários que tenham o privilégio process,
portanto o usuário root do MySQL pode logar e verificar alguns detalhes mesmo se
todas as conexões normais estiverem em uso.
• Não conceda o privilégio file a todos os usuários. Qualquer usuário que possua este
privilégio pode gravar um arquivo em qualquer lugar no sistema de arquivos com os
privilégios do daemon mysqld! Para tornar isto um pouco mais seguro, todos os ar-
quivos gerados com SELECT ... INTO OUTFILE são lidos por todos, e não se pode so-
brescrever arquivos existentes.
O privilégio file pode também ser usado para ler qualquer arquivo acessível para o
usuário Unix com o qual o servidor está sendo executado. Pode ocorrer abusos como,
por exemplo, usar LOAD DATA para carregar o arquivo ‘/etc/passwd’ em uma tabela,
que pode então ser lido com SELECT.
• Se você não confia em seu DNS, você deve utilizar números IP no lugar de nomes de
máquinas nas tabelas de permissão. De qualquer forma, você deve ter muito cuidado
ao criar entradas de concessão utilizando valores de nomes de máquinas que contenham
metacaractes!
• Se você deseja restrigir o número de conexões para um único usuário, você pode faze-lo
configurando a variável max_user_connections no mysqld.
privilégios que o usuário tenha direito a conceder, você deve dar ao usuário o
seguinte privilégio:
GRANT INSERT(user) on mysql.user to ’usuarior’h́ostname’;
Isto irá assegurar que o usuário não poderá alterar nenhuma coluna de
privilégios diretamente, mas tem que usar o comando GRANT para conceder
direitos para outros usuários.
--skip-grant-tables
Esta opção desabilita no servidor o uso do sistema de privilégios. Isto dá a
todos os usuários acesso total a todos os bancos de dados! (Você pode dizer a
um servidor em execução para para uar as tabelas de permissões executando
mysqladmin flush-privileges ou mysqladmin reload.)
--skip-name-resolve
Nomes de máquinas não são resolvidos. Todos os valores da coluna Host nas
tabelas de permissões devem ser números IP ou localhost.
--skip-networking
Não permitir conexões TCP/IP sobre a rede. Todas as conexões para mysqld
devem ser feitas via Sockets Unix. Esta opção não é possível em sistemas que
usam MIT-pthreads, porque o pacote MIT-pthreads não suporta sockets Unix.
--skip-show-database
Com esta opção a instrução SHOW DATABASES não retorna nada.
O servidor utiliza as tabelas user, db e host no banco de dados mysql em ambos estágios
do controle de acesso. Os campos nestas tabelas de permissão são detalhados abaixo:
Nome da Tabela User db host
Campos de escopo Host Host Host
User Db Db
Password User
Cmapos de Select_priv Select_priv Select_priv
privilégio
Insert_priv Insert_priv Insert_priv
Update_priv Update_priv Update_priv
Delete_priv Delete_priv Delete_priv
Index_priv Index_priv Index_priv
Alter_priv Alter_priv Alter_priv
Create_priv Create_priv Create_priv
Drop_priv Drop_priv Drop_priv
Grant_priv Grant_priv Grant_priv
References_priv
Reload_priv
Shutdown_priv
Process_priv
File_priv
No segundo estágio do controle de acesso (verificação da solicitação), o servidor pode, se a
solicitação involver tabelas, consultar adicionalmente as tabelas tables_priv e columns_
priv. Os campos nestas tabelas são mostrados abaixo:
Nome da tabela tables_priv columns_priv
Campos de Host Host
escopop
Db Db
User User
Table_name Table_name
Column_name
Campos de Table_priv Column_priv
privilégio
Column_priv
Outros campos Timestamp Timestamp
Grantor
Cada tabela de permissões contêm campos de escopo e campos de privilégios.
Chapter 4: Administração de Bancos de Dados MySQL 203
Campos de escopo determinam o escopo de cada entrada nas tabelas, isto é, o contexto
no qual a entrada se aplica. Por exemplo, uma entrada na tabela user com valores Host
e User de ’thomas.loc.gov’ e ’bob’ devem ser usados para autenticar conexões feitas
ao servidor por bob da máquina thomas.loc.gov. De maneira similar, uma entrada na
tabela db com campos Host, User e Db de ’thomas.loc.gov’, ’bob’ e ’reports’ devem
ser usados quando bob conecta da máquina thomas.loc.gov para acessar o banco de dados
reports. As tabelas tables_priv e columns_priv contem campos de escopo indicando as
combinações de tabelas ou tabela/coluna para o qual cada entrada se aplica.
Para propósitos de verificação de acessos, comparações de valores Host são caso insensitivo,
valores User, Password, Db e Table_name são caso sensitivo. Valores Column_name são caso
insensitivo no MySQL versão 3.22.12 ou posterior.
Campos de privilégios indicam os privilégios concedidos por uma entrada na tabela, isto é,
quais operações podem ser realizadas. O servidor combina as informações de várias tabelas
de concessão para formar uma descrição completa dos privilégios de um usuário. As regras
usadas para fazer isto são descritas em hundefinedi [Request access], page hundefinedi.
Campos de escopo são strings, declaradas como mostrado abaixo; os valores padrão para
cada é a string vazia:
Nome do Tipo
Campo
Host CHAR(60)
User CHAR(16)
Password CHAR(16)
Db CHAR(64) (CHAR(60) para as tabelas tables_priv e columns_priv)
Table_name CHAR(60)
Column_name CHAR(60)
Nas tabelas user, db e host, todos campos de privilégios são declarados como
ENUM(’N’,’Y’) --- cada um pode ter um valor de ’N’ ou ’Y’ e o valor padrão é ’N’.
Nas tabelas tables_ e columns_priv, os campos de privilégios são declarados como campos
SET:
Nome da Tabela Nome Campo Possíveis elementos do conjunto
tables_priv Table_priv ’Select’, ’Insert’, ’Update’, ’Delete’,
’Create’, ’Drop’, ’Grant’, ’References’,
’Index’, ’Alter’
tables_priv Column_priv ’Select’, ’Insert’, ’Update’, ’References’
columns_priv Column_priv ’Select’, ’Insert’, ’Update’, ’References’
De maneira resumida, o servidor utiliza as tabelas de permissões desta forma:
• Os campos de escopo da tabela user determinam quando permitir ou aceitar conexões.
Para conexões permitidas, qualquer privilégio concedido em uma tabela user indica
o privilégio global (superusuário) do usuário. Estes privilégios se aplicam a todos os
bancos de dados no servidor.
• As tabelas db e host são usadas juntas:
− Os campos de escopo da tabela db determinam quais usuários podem acessar de-
terminados bancos de dados de máquinas determinadas. Os campos de privilégios
determinam quais operações são permitidas.
204 Referência técnica para o MySQL versão 3.23.52
− A tabela host é usada como uma extensão da tabela db quando você quer que
uma certa entrada na tabela db seja aplicada a diversas máquinas. Por exemplo,
se você deseja que um usuário esteja apto a usar um banco de dados a partir de
diversas máquinas em sua rede, deixe o campo Host vazio no registro da tabela
db, então popule a tabela Host com uma entrada para cada uma das máquinas.
Este mecanismo é descrito com mais detalhes em hundefinedi [Request access],
page hundefinedi.
• As tabelas tables_priv e columns_priv são similares à tabela db, porém são mais
finas: Elas se aplicam ao nível de tabelas e colunas em vez do nível dos bancos de
dados.
Perceba que os privilégios administrativos (reload, shutdown e etc) são especificados so-
mente na tabela user. Isto ocorre porque operações administrativas são operações no
próprio servidor e não são específicas e não específicas dos bancos de dados, portanto não
existe razão para listar tais privilégios nas outras tabelas de permissão. De fato, somente
a tabela user necessita ser consultada para determinar se você pode ou não realizar uma
operação administrativa.
O privilégio file também só é especificado na tabela user. Ele não é um privilégio admin-
istrativo, mas sua habilidade para ler ou escrever arquivo no servidor é independtende do
banco de dados que você está acessando.
O servidor mysqld le o conteúdo das tabelas de permissões uma vez, quando é iniciado.
Alterações nas tabelas de permissões tem efeito como indicado em hundefinedi [Privilege
changes], page hundefinedi.
Quando você modifica o conteúdo das tabelas de permissões, é uma boa idéia ter certeza que
suas alterações configuraram os privilégios da forma desejada. Para ajuda no diagnostico
de problemas, veja hundefinedi [Access denied], page hundefinedi. Para conselhos sobre
asssuntos de segurança, See hundefinedi [Security], page hundefinedi.
Uma ferramenta de diagnóstico útil é o script mysqlaccess, que Yves Carlier fornece na
distribuição MySQL. Chame mysqlaccess com a opção --help para descobrir como ele
funciona. Perceba que o mysqlaccess confere o acesso usando somente as tabelas user, db
e host. Ele não confere privilégios no nível de tabelas ou colunas.
O mysql utiliza valores padrão para parâmetros de conexão que não são passados pela linha
de comando:
• O nome padrão da máquina (hostname) é localhost.
• O nome de usuário padrão é o mesmo nome do seu usuário no Unix.
• Nenhuma senha é fornecida se faltar o parâmetro -p.
Então, para um usuário Unix joe, os seguintes comandos são equivalentes:
shell> mysql -h localhost -u joe
shell> mysql -h localhost
shell> mysql -u joe
shell> mysql
Outros clientes MySQL comportam-se de forma similar.
Em sistemas Unix, você pode especificar valores padrões diferentes para serem usados
quendo você faz uma conexão, assim você não precisa digitá-los na linha de comando sempre
que chamar o programa cliente. Isto pode ser feito de várias maneiras:
• Podem ser especificados parâmetros de conexão na seção [client] do arquivo de con-
figuração ‘.my.cnf’ no seu diretório home. A seção relevante do arquivo deve se parecer
com isto:
[client]
host=nome_máquina
user=nome_usuário
password=senha_usuário
See hundefinedi [Option files], page hundefinedi.
• Você pode especificar parâmetros de conexão utilizando variáveis de ambiente. O nome
de máquina pode ser especificado para o mysql utilizando a variável MYSQL_HOST. O
nome do usuário MySQL pode ser especificado utilizando USER (isto é somente para
Windows). A senha pode ser especificada utilizando MYSQL_PWD (mas isto não é seguro;
veja a próxima seção). See hundefinedi [Environment variables], page hundefinedi.
Valores de Password que não estão em branco são apresentados como senhas criptografadas.
O MySQL não armazena senhas na forma de texto puro para qualquer um ver. Em vez disso,
a senha fornecida por um usuário que está tentando se conectar é criptografada (utilizando a
função PASSWORD()). A senha criptografada é então usada quando o cliente/servidor estiver
conferindo se a senha é correta (Isto é feito sem a senha criptografada sempre trafegando
sobre a conexão.) Perceba que do ponto de vista do MySQL a senha criptografada é a
senha REAL, portanto você não deve passá-la para ninguém! Em particular, não forneça a
usuários normais acesso de leitura para as tabelas no banco de dados mysql!
Os exemplos abaixo mostram várias combinações de valores de Host e User nos registros
da tabela user aplicando a novas conexões:
Valor em host Valor em user Conexões casadas com o registro
’thomas.loc.gov’ ’fred’ fred, conectando de thomas.loc.gov
’thomas.loc.gov’ ’’ Qualquer usuário, conectando de
thomas.loc.gov
’%’ ’fred’ fred, conectando a partir de qualquer máquina
’%’ ’’ Qualquer usuário, conectando a partir de qual-
quer máquina
’%.loc.gov’ ’fred’ fred, conectando de qualquer máquina do
domínio loc.gov
’x.y.%’ ’fred’ fred, conectando de x.y.net,
x.y.com,x.y.edu, etc. (Isto provavel-
mente não é útil)
Chapter 4: Administração de Bancos de Dados MySQL 209
Aqui está outro exemplo. Suponha que a tabela user fosse assim:
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| % | jeffrey | ...
| thomas.loc.gov | | ...
+----------------+----------+-
A tabela ordenada pareceria com isto:
+----------------+----------+-
| Host | User | ...
+----------------+----------+-
| thomas.loc.gov | | ...
| % | jeffrey | ...
+----------------+----------+-
Uma conexão a partir de thomas.loc.gov feita por jeffrey coincide com a primeira en-
trada, no entanto, uma conexão de whitehouse.gov fetia por jeffrey coincidiria com a
segunda entrada na tabela.
Um erro comum é pensar que para um determinado usuário, todas as entradas que citam
explicitamente este usuário serão usadas primeiro quando o usuário tentar encontrar uma
combinação para a conexão. Simplesmente isto não é verdade. O exemplo anterior ilustra
isto, onde uma conexão de thomas.loc.gov feita por jeffrey combina primeiro não com
a entrada contendo ’jeffrey’ no valor do campo user, mas sim pela entrada sem o nome
de usuário!
Se você tiver problemas conectando ao servidor, imprima a tabela user e ordene-a na
manualmente para ver onde se deu o primeiro coincidência de valores.
• Os metacaracteres ‘%’ e ‘_’ podem ser usados nos campos Host e Db de ambas tabelas.
• O valor ’%’ em Host na tabela db significa “qualquer máquina.” Um valor em branco
em Host na tabela db significa “consulte a tabela host para informação adicional.”
• O valor ’%’ ou em branco no campo Host na tabela host significa “qualquer máquina.”
• O valor ’%’ ou em branco no campo Db de ambas as tabelas significa “qualquer banco
de dados.”
• O valor em branco no campo User em ambas tabelas coincide com o usuário anônimo.
As tabelas db e host são lidas e ordenadas quando o servidor inicia (ao mesmo tempo que
ele lê a tabela user). A tabela db é ordenada nos campos de escopo Host, Db e User e a
tabela host é ordenada nos campos de escopo Host e Db. Assim como na tabela user, a
ordenação coloca os valores mais específicos no início e os menos específicos por último, e
quando o servidor procura por entradas coincidentes, ele usa a primeira combinação que
encontrar.
As tabelas tables_priv e columns_priv concedem privilégios específicos para tabelas e
campos. Valores nos campos escopo podem ser especificados como a seguir:
• Os meta caracteres ‘%’ e ‘_’ podem ser usados no campo Host de ambas tabelas.
• O valor ’%’ ou em branco no campo Host em ambas tabelas significam “qualquer
máquina”
• Os campos Db, Table_name e Column_name não podem conter meta caracteres ou serem
brancos em ambas tabelas.
As tabelas tables_priv e columns_priv são ordenadas nos campos Host, DB e User. Isto
é parecido com a ordenação da tabela db, no entanto, a ordenação é mais simples porque
somente o campo Host pode conter meta caracteres.
O processo de verificação da requisição é descrito abaixo. (Se você já está familiarizado
com o código de verificação de acesso, você irá perceber que a descrição aqui é um pouco
diferente do algorítimo usado no código. A descrição é equivalente ao que o código realmente
faz; ele só é diferente para tornar a explicação mais simples.)
Para requisições administrativas (shutdown, reload, etc.), o servidor confere somente a
entrada da tabela user, porque ela é a única tabela que especifica privilégios administra-
tivos. O acesso é concedido se o registro permitir a operação requisitada ou negado caso
o contrário. Por exemplo, se você deseja executar mysqladmin shutdown mas a entrada
em sua tabela user não lhe concede o privilégio shutdown, o acesso é negado mesmo sem
consultar as tabelas db ou host. (elas não contém o campo Shutdown_priv, portanto não
existe esta necessidade.)
Para requisições relacionadas aos bancos de dados (insert, udpdate, etc.), o servidor primeiro
confere os privilégios globais do usuário consultando as entradas da tabela user. Se a
entrada permitir a operação requisitada, o acesso é concedido. Se os privilégios globais na
tabela user são insuficientes, o servidor determina os privilégios específicos de banco de
dados para o usuário consultando as tabelas db e host:
1. O servidor consulta a tabela db por uma combinação nos campos Host, Db e User. Os
campos Host e User são comparados com o nome da máquina e o nome do usuário que
faz a requisição. O campo Db é comparado com o banco de dados que o usuário deseja
acessar. Se não existir entradas coincidentes para o Host e User, o acesso é negado.
212 Referência técnica para o MySQL versão 3.23.52
2. Se existir uma combincação com a entrada da tabela db e seu campo Host não estiver
em branco, aquela entrada define os privilégios especificos do banco de dados do usuario.
3. Se o registro coincidente da tabela db tiver o campo Host em branco, significa que a
tabela host enumera quais máquinas são permitidas acessar o banco de dados. Neste
caso, uma consulta adicional é feita na tabela host para encontrar uma valores coinci-
dentes nos campos Host e Db. Se nenhuma entrada na tabela host coincide, o acesso
é negado. Se existir uma coincidência, os privilégios específicos de bancos de dados
para o usuário são computados como a interseção (não a união!) dos privilégios nas
entradas das tabelas db e host, isto é, os privilégios que são ’Y’ em ambas entradas.
(Desta forma você pode conceder privilégios gerais em entradas na tabela db e então
restringi-los em uma base de máquina a máquina utilizando as entradas da tabela
host.)
Depois de determinar os privilégios específicos do banco de dados concedido pelas entradas
nas tabelas db e host, o servidor os adiciona aos privilégios globais concedidos pela tabela
user. Se o resultado permitir a operação requisitada, o acesso será concedido. De outra
forma, o servidor consulta os privilégios de tabelas e campos do usuario nas tabelas tables_
priv e columns_priv e os adiciona aos privilégios do usuário. O acesso será permitido ou
negado baseado no resultado.
Expresso em termos booleanos, a descrição precedente de como os privilégios de um usuário
são calculados podem ser resumido assim:
global privileges
OR (database privileges AND host privileges)
OR table privileges
OR column privileges
Ele pode não ser aparente porque, se os privilégios da entrada global de user são inicialmente
insuficientes para a operação requisitada, o servidor adiciona estes privilégios mais tarde aos
privilégios específicos de banco de dados, tabelas e colunas. A razão é que uma requisição
pode exigir mais que um tipo de privilégio. Por exemplo, se você executar uma instrução
INSERT ... SELECT, você precisa dos privilégios insert e select. Seu privilégio pode ser
tal que a entrada da tabela user concede um privilégio e a entrada da tabela db concede
o outro. Neste caso, você tem os privilégios necessários para realizar a requisição, mas o
servidor não pode obtê-los de ambas as tabelas por si próprio; os privilégios concedidos
pelas entradas em ambas as tabelas de ser combinados.
A tabela host pode ser usada para manter uma lista dos servidores seguros.
Na Tcx, a tabela host contém uma lista de todas as máquina na rede local. A elas são
concedidos todos os privilégios.
Você pode também usar a tabela host para indicar máquinas que não são seguras. Suponha
que você tenha uma máquina public.your.domain que está localizada em uma área pública
que você não considera segura. Você pode permitir o acesso a todas as máquinas de sua
rede exceto a esta máquina usando entradas na tabela host desta forma:
+--------------------+----+-
| Host | Db | ...
+--------------------+----+-
| public.your.domain | % | ... (todos os privilégios configurados para ’N’)
| %.your.domain | % | ... (todos os privilégios configurados para ’Y’)
Chapter 4: Administração de Bancos de Dados MySQL 213
+--------------------+----+-
Naturalmente, você deve sempre testar suas entradas nas tabelas de permissões (por ex-
emplo, usar o mysqlaccess para ter certeza que os privilégios de acesso estão atualmente
configurados da forma que você imagina.
deve colocar uma entrada com o valor ’%’ na coluna Host da tabela user e reiniciar
o mysqld com a opção --log na máquina onde é executado o servidor. Depois tente
conectar a partir da máquina cliente, a informação no log do MySQL irá indicar como
você está realmente conectando. (Então troque o ’%’ na tabela user com o nome da
máquina mostrado pelo log. De outra forma você teria um sistema que seria inseguro.)
Outra razão para este erro no Linux pode ser porque você está utilizando uma versão
binária do MySQL que é compilada com uma versão diferente da glibc que você está
usando. Neste caso você deve atualizar seu SO/Glibc ou fazer o download da versão
fonte do MySQL e compilá-la. Um RPM fonte é, normalmente, fácil de compilar e
instalar, logo, isto não é um grande problema.
• Se você obter uma mensagem de erro onde o nome da máquina não é exibido ou, no
lugar do nome da máquina existir um IP, mesmo se você tenta a conexão com um nome
de máquina:
shell> mysqladmin -u root -pxxxx -h some-hostname ver
Access denied for user: ’root´ (Using password: YES)
Isto significa que o MySQL obteve algum erro quando tentava resolver o IP para um
nome de maquina. Neste caso você pode executar mysqladmin flush-hosts para zerar
o cache DNS interno. See hundefinedi [DNS], page hundefinedi.
Algumas soluções permanentes são:
− Tente descobrir o que está errado com seu servidor DNS e corrija os erros.
− Especifique números IPs no lugar de nomes nas tabelas de privilégios do MySQL.
− Inicie o mysqld com --skip-name-resolve.
− Inicie o mysqld com --skip-host-cache.
− Conecte à localhost se você estiver executando o servidor e o cliente na mesma
máquina.
− Coloque os nomes das máquinas clientes em /etc/hosts.
• Se mysql -u root test funciona mas mysql -h nome_servidor -u root test resultar
em Access denied, então você pode não ter o nome correto para a sua máquina na
tabela user. Um problema comum é quando o valor de Host na entrada da tabela
user especifica um nome de máquina não qualificado, mas as rotinas de resolução de
nomes de seu sistema retornam um nome qualificado completo do domínio (ou vice-
versa). Por exemplo, se você tem uma entrada com o nome ’tcx’ na tabela user, mas
seu DNS diz ao MySQL que o nome da máquina é ’tcx.subnet.se’, a entrada não
irá funcionar. Tente adicionar um registro à tabela user que contenha o número IP
de sua máquina como o valor da coluna Host. (Uma alternativa, seria adicionar um
registro à tabela user com o valor de Host contendo um metacaracter, por exemplo,
’tcx.%’. Entretanto, o uso de nomes de máquinas terminando com ‘%’ é inseguro e
não é recomendado!)
• Se mysql -u nome_usuário test funciona mas mysql -u nome_usuário outro_bd não
funconar, você não possui uma entrada para outro_bd listado na tabela db.
• Se mysql -u nome_usuário nome_bd funciona quando executado no próprio servidor,
mas mysql -u nome_máquina -u nome_usuário nome_bd não funciona quando execu-
tado em outra máquina cliente, você não possui o nome da máquina cliente listado na
tabela user ou na tabela db.
216 Referência técnica para o MySQL versão 3.23.52
• Se você não estiver entendendo porque obtem Access denied, remova da tabela user
todas as entradas da coluna Host que contenham meta caracteres (entradas que con-
tenham ‘$’ ou ‘_’). Um erro muito comum é inserir uma nova entrada com Host=’%’ e
User=’algum usuário’, pensando que isto irá permitir a você especificar localhost
para conectar da mesma máquina. A razão disto não funcionar é que os privilégios
padrões incluem uma entrada com Host=’localhost’ e User=’’. Como esta entrada
tem o valor ’localhost’ em Host que é mais específica que ’%’, ela é usada no lugar
da nova entrada quando se conectar de localhost! O procedimento correto é inserir
uma segunda entrada com Host=’localhost’ e User=’algum_usuário’, ou remover
a entrada com Host=’localhost’ e User= ’’.
• Se você obter o seguinte erro, você pode ter um problema com a tabela db ou a tabela
host:
Access to database denied
Se a entrada selecionada da tabela db tiver um valor vazio na coluna Host, tenha certeza
que exista uma ou mais entradas correspondentes na tabela host especificando quais
máquinas aplicam-se à tabela db.
Se você obter o erro quando estiver utilizando comandos SQL SELECT ... INTO
OUTFILE ou LOAD DATA INFILE, a entrada na tabela user provavelmente não tem o
privilégio file habilitado.
• Lembre-se que programas clientes irão usar parâmetros de conexões especificados em
arquivos de configuração ou variáveis ambientais. See hundefinedi [Environment vari-
ables], page hundefinedi. Se parecer que algum cliente está enviando parâmetros errados
para a conexão e você não os especificou na linha de comando, verifique seu ambiente e
o arquivo ‘.my.cnf’ no seu diretório home. Você pode também conferir os arquivos de
configurações do servidor MySQL, apesar de não ser interessante gravar configurações
de cliente nestes arquivos. See hundefinedi [Option files], page hundefinedi. Se você
obter a mensagem de acesso negado (Access denied) quando estiver executando um
cliente sem opções, tenha certeza que você não especificou uma senha antiga em nenhum
de seus arquivos de opções! See hundefinedi [Option files], page hundefinedi.
• Se você fizer alterações para as tabelas de permissões diretamente (utilizando uma in-
strução INSERT ou UPDATE) e suas alterações parecem ser ignoradas, lembre que você
deve usar uma instrução FLUSH PRIVILEGES ou executar um comando mysqladmin
flush-privileges para o servidor ler novamente as tabelas com os privilégios. De
outra forma, suas alterações não farão efeito até que o servidor seja reiniciado. Lembre-
se que depois de configurar a senha de root com um comando UPDATE, não será
necessário especificar a senha até que você atualize os privilégios, pois o servidor ainda
não saberá que você alterou a senha!
• Se você tiver problemas de acesso com Perl, PHP, Python ou um programa ODBC,
tente conectar ao servidor com mysql -u nome_usuário nome_bd ou mysql -u nome_
usuário -psua_senha nome_bd. Se você consegue conectar com o cliente mysql, existe
algum problema com seu programa e não o acesso aos privilégios (Note que não espaço
entre -p e a senha; você também pode utilizar a sintaxe --password=sua_senha para
especificar a senha. Se você utilizar a opção -p sozinha, o MySQL irá lhe solicitar a
senha.)
• Para testar, iniciae o daemon mysqld com a opção --skip-grant-tables. Então você
Chapter 4: Administração de Bancos de Dados MySQL 217
Os privilégios para uma tabela ou coluna são formados através do OU lógico dos privilégios
em cada um dos quatro níveis de privilégios. Por exemplo, se a tabela mysql.user especifica
que um usuário tem um privilégio global select, isto não pode ser negado por uma entrada
no nível de banco de dados, tabela ou coluna.
Os privilégios para uma coluna podem ser calculados da seguinte forma:
privilégios globais
OR (privilégios de banco de dados AND privilégios de máquina)
OR privilégios de tabela
OR privilégios de coluna
Na maioria dos casos, os direitos a um usuário são atribuídos em apenas um dos níveis de
privilégios, portanto a vida normalmente não é tão complicada como mostrado acima. Os
detalhes do procedimento de verificação dos privilégios são apresentados em hundefinedi
[Privilege system], page hundefinedi.
Se você concede privilégios para uma combinação de usuário e máquina que não existem
na tabela mysql.user, um registro é adicionado e permanece lá até ser removido com um
comando DELETE. Em outras palavras, GRANT pode criar registros na tabela user, mas
REVOKE não as removerá; para removê-las você deve usar a instrução explícita DELETE.
Na Versão 3.22.12 ou posterior do MySQL, se um novo usuário é criado ou se você possui
privilégios de concessão globais, a senha do usuário será especificada utilizando a cláusula
IDENTIFIED BY, se uma for dada. Se o usuário já possui uma senha, ela é trocada pela nova.
CUIDADO: Se você criar um novo usuário mas não especificar uma cláusula IDENTIFIED
BY, o usuário não possuirá uma senha. Isto não é seguro.
Senhas podem também ser configuradas com o comando SET PASSWORD. See hundefinedi
[SET OPTION], page hundefinedi.
Se você conceder privilégios para um banco de dados, uma entrada na tabela mysql.db é
criada se necessário. Quando todos os privilégios para o banco de dados forem removidos
com REVOKE, este registro é removido.
Se um usuário não tem privilégios em uma tabela, a tabela não é mostrada quando o usuário
solicita uma lista de tabelas (com a instrução SHOW TABLES por exemplo).
A cláusula WITH GRANT OPTION dá ao usuário habilidade de fornecer à outros usuários quais-
quer privilégios que ele tenha em um nível específico de privilégio. Você deve ter cuidado
ao fornecer o privilégio grant, pois dois usuários podem se unir para unir privilégios!
Você não pode conceder a outro usuário um privilégio que não possua; o privilégio grant
possibilita fornecer somente os privilégios que possuir.
Esteja ciente que quando conceder a um usuário o privilégio grant em um nível particular de
privilégios, qualquer privilégio que o usuário já possua (ou seja fornecido no futuro!) nesse
nível também pode ser concedido por este usuário. Suponha que você conceda a um usuário
o privilégio insert em um banco de dados. Se você conceder o privilégio select no banco de
dados e especificar WITH GRANT OPTION, o usuário além de poder repassar o privilégio select
poderá também repassar o insert. Se você concede o privilégio update para o usuário no
banco de dados, o usuário poderá conceder os privilégios insert, select e update.
Você não deve conceder privilégios alter a um usuário comum. Se você fizer isto, o usuário
pode tentar enganar o sistema de privilégios renomeando tabelas!
220 Referência técnica para o MySQL versão 3.23.52
Perceba que se você estiver utilizando privilégios de tabelas ou colunas, mesmo que para
apenas um usuário, o servidor examina os privilégios de tabelas e colunas para todos os
usuários e isto irá deixar o MySQL um pouco mais lento.
Quando o mysqld inicia, todos os privilégios são lidos na memória. Privilégios de bancos de
dados, tabelas e colunas são iniciados um vez, e privilégios ao nível de usuário fazem efeito na
próxima vez que o usuário conectar. Modificações nas tabelas de permissões que você realiza
utilizando GRANT ou REVOKE são percebidas pelo servidor imediatamente. Se você modificar
as tabelas de permissões manualmente (utilizando INSERT, UPDATE, etc), você deve executar
uma instrução FLUSH PRIVILEGES ou executar mysqladmin flush-privileges para dizer
ao servidor para recarregar as tabelas de permissões. See hundefinedi [Privilege changes],
page hundefinedi.
As maiores diferenças entre o ANSI SQL e versões MySQL de GRANT são:
• No MySQL privilégios são fornecidos para uma combinação de usuário e máquina e
não somente para um usuário.
• O ANSI SQL não possui privilégios no nível global ou de bancos de dados, e não
suporta todos os tipos de privilégios que o MySQL suporta. O MySQL não suporta os
privilégios TRIGGER, EXECUTE ou UNDER do ANSI SQL.
• Os privilégios do ANSI SQL são estruturadados em uma maneira hierárquica. Se você
remover um usuário, todos os privilégios do usuário são removidos. No MySQL os
privilégios concedidos não são removidos automaticamente, mas você deve removê-los
se necessário.
• Se no MySQL você possuir o privilégio INSERT em somente parte das colunas em uma
tabela, você pode executar instruções INSERT na tabela; As colunas em que você não
tem o privilégio INSERT irão receber seus valores padrões. O SQL ANSI necessita que
você tenha o privilégio INSERT em todas as colunas.
• Quando você remove uma tabela no ANSI SQL, todos os privilégios para a tabela são
removidos. Se você remover um privilégio no SQL ANSI, todos os privilégios que foram
concedidos baseado neste privilégio são também removidos. No MySQL, privilégios só
podem ser removidos com comandos REVOKE explícitos ou manipulando as tabelas de
permissões do MySQL.
• Senhas MySQL não tem nenhuma relação com senhas Unix. Não existe nenhuma
associação entre a senha em que você utiliza para logar-se a uma máquina Unix e a
senha que é utilizada para acessar um banco de dados na mesma máquina.
• O MySQL criptografa senhas utilizando um algorítimo diferente que o utilizado pelo
processo de login do Unix. Veja as descrições das funções PASSWORD() e ENCRYPT()
em hundefinedi [Miscellaneous functions], page hundefinedi. Perceba que mesmo que
a senha é armazenada ’embaralhada’, o conhecimento da sua senha ’embaralhada’ é o
suficiente para conseguir se conectar ao servidor MySQL!
Usuários MySQL e seus privilégios são criados normalmente com o comando GRANT, See
hundefinedi [GRANT], page hundefinedi.
Quando você se conecta a um servidor MySQL com um cliente de linha de comando
você pode especificar a senha com --password=sua-senha. See hundefinedi [Connecting],
page hundefinedi.
mysql --user=monty --password=guess nome_do_banco
Se você deseja que o cliente lhe solicite a senha, deve ser especificado o parâmetro --
password sem nenhum argumento
mysql --user=monty --password nome_do_banco
ou no formato curto:
mysql -u monty -p nome_do_banco
Perceba que no último exemplo a senha não é ’nome do banco’.
Se você deseja usar a opção -p para fornecer uma senha você deve fazer assim:
mysql -u monty -pguess nome_do_banco
Em alguns sistemas, a chamada da biblioteca que é utilizada pelo MySQL para solicitar por
uma senha corta automaticamente a senha para 8 caracteres. Internamente o MySQL não
limita o tamanho limite da senha.
Alterações nos privilégios globais e alterações de senhas fazem efeito na próxima vez que o
cliente conectar.
admin Um usuário que possa conectar de localhost sem uma senha e que é
concedido os privilégios administrativos reload e process. Isto permite ao
usuário a execução dos comandos mysqladmin reload, mysqladmin refresh
e mysqladmin flush-*, bem como o mysqladmin processlist. Nenhum
privilégio relacionado aos bancos de dados é concedido. (Depois eles podem
ser adicionados utilizando instruções GRANT adicionais.)
dummy Um usuário que pode conectar sem uma senha, mas somente na máquina local.
Os privilégios globais são todos configurados para ’N’ --- o tipo de privilégio
USAGE permite a criação de um usuário sem privilégios. Considera-se que você
irá conceder privilégios específicos de bancos de dados mais tarde.
TO meunomedeusuario@"%.meudominio.com"
IDENTIFIED BY ’minhasenha’;
Para realizar a mesma coisa modificando diretamente as tabelas de permissões, faça isto:
mysql> INSERT INTO user VALUES (’%.meudominio, ’meunomedeusuario’
PASSWORD(’minhasenha’),...);
mysql> FLUSH PRIVILEGES;
Você pode também utilizar xmysqladmin, mysql_webadmin e mesmo xmysql para inserir,
alterar e atualizar valores nas tabelas de permissões. Você pode encontrar estes utilitários
em Diretório de Colaboradores do Website do MySQL.
esta versão do ps, seria imprudência assumir que não existe outro método para observar
o ambiente de processos. See hundefinedi [Environment variables], page hundefinedi.
Em resumo, os métodos mais seguros seriam que o programa cliente solicitasse a senha ou
especificar a senha em um arquivo ‘.my.cnf’ corretamente protegido.
ou
Quanto mais chaves tiver, mais demorado será. Como no comando BACKUP TABLE, atual-
mente só funciona com tabelas MyISAM.
O comando retorna uma tabela com as seguintes colunas:
Coluna Valor
Table Nome da Tabela
Op Sempre “restore”
Msg type Um dos seguintes: status, error, info ou warning.
Msg text A mensagem.
opç~
ao = QUICK | FAST | MEDIUM | EXTENDED | CHANGED
CHECK TABLE funciona somente em tabelas MyISAM. Em tabelas MyISAM é a mesma coisa
que executar myisamchk -m nome_tabela na tabela.
Se você não especificar nenhuma opção, MEDIUM é usado.
Verifica se existem erros na(s) tabela(s). Para as tabelas MyISAM as estatísticas das chaves
são atualizadas. O comando retorna uma tabela com as seguintes colunas:
Coluna Valor
Table Nome da Tabela.
Op Sempre “check”.
Msg type Um dos seguintes: status, error, info, or warning.
Msg text A mensagem.
Note que você pode obter várias linhas de informações para cada tabela conferida. A última
linha irá ser do tipo Msg_type status e normalmente deve estar OK. Se você não obteve OK
ou Not checked, deve ser executado, normalmente, um reparo da tabela. See hundefinedi
[Table maintenance], page hundefinedi. Not checked significa que a tabela de um dado
TIPO disse ao MySQL que não havia nenhuma necessidade de verificá-la.
Os diferentes tipos de consistências continuam para os seguintes:
Tipo Significado
QUICK Não busca os registros verificando ligações incorretas.
FAST Só confere tabelas que não foram fechadas corretamente.
CHANGED Só verifica as tabelas que foram alteradas desde a última conferência
ou que não foram fechadas corretamente.
MEDIUM Busca os registros para verificanado que ligações removidas estão ok.
Isto também calcula uma chave de conferência para os registros e ver-
ifica isto com um checksum calculado para as chaves.
EXTENDED Faz uma busca completa nas chaves para todas as chaves em cada
registro. Isto assegura que a tabela está 100% consistente, mas pode
demorar muito tempo para executar!
Para tabelas MyISAM de tamanho dinâmico, uma verificação iniciada sempre fará uma veri-
ficação MEDIUM. Para registros de tamanho estático nós saltamos a busca de registros para
QUICK e FAST já que os registros estão raramente corrompidos.
Você pode combinar opções de consistência como em:
Chapter 4: Administração de Bancos de Dados MySQL 231
REPAIR TABLE repara uma tabela possivelmente corrompida. O comando retorna uma tabela
com as seguintes colunas:
Coluna Valor
Table Nome da Tabela
Op Sempre “repair”
Msg type Um dos seguintes: status, error, info ou warning.
Msg text A mensagem.
Perceba que você pode obter várias linhas de informações para cada tabela recuperada. A
ultima linha será de Msg_type status e normalmente deve exibir OK. Se o retorno não for
OK, você pode tentar reparar a tabela com myisamchk -o, já que REPAIR TABLE ainda não
implementa todas as opções de myisamchk. Futuramente iremos torná-lo mais flexível.
Se o parâmetro QUICK for especificado o MySQL tentará REPARAR somente a árvore de
índices.
Se você utilizar EXTENTED o MySQL criará o índice, registro a registro em vez de criar um
índice de uma vez com ordenação; Isto pode ser melhor que a ordenação em chaves de
tamanho fixo se você tiver grandes chaves do tipo char() que compactam muito bem.
-V ou --version
Exibe a versão do myisamchk e sai.
-w ou, --wait
No lugar de gerar um erro se a tabela estiver bloqueada, espere até que a tabela
fique livre antes de continuar. Perceba que se você estiver utilizando mysqld na
tabela com --skip-locking, a tabela só pode ser trancada por outro comadno
myisamchk.
--character-sets-dir=...
Diretório onde conjuntos de caracteres são armazenados.
--set-character-set=name
Altere o conjunto de caracteres usado pelo índice
.t ou --tmpdir=path
Caminho para armazenar arquivos temporários. Se isto não for configurado,
myisamchk irá usar a variável de ambiente TMPDIR para isto.
-q ou --quick
Reparo rápido sem modificar o arquivo de dados. Pode ser fornecido um se-
gundo -q para forçar o myisamchk para modificar o arquivo de dados original
no caso de chaves duplicadas.
-u ou --unpack
Descompacta arquivo empacotado com o myisampack.
em grandes arquivos, você deve decidir primeiro quanta memória deseja usar. O valor
padrão é utilizar somente 3MB para correções. Utilizando valores maiores, o myisamchk
pode operar mais rapidamente. Por exemplo, se você tiver mais que 32M de memória
RAM, você pode utilizar opções tais como esta (em adição às várias outras que podem ser
especificadas):
shell> myisamchk -O sort=16M -O key=16M -O read=1M -O write=1M ...
Utilizando -O sort=16M provavelmente é suficiente para a maioria dos casos.
Certiffique-se que o myisamchk utiliza arquivos temporários em TMPDIR. Se TMPDIR aponta
para um sistema de arquivos em memória, você pode facilmente obter erros de memória.
Se isto acontecer, configure TMPDIR para apontar para algum diretório com mais espaço e
reinicie o myisamchk.
Quando reparando, o myisamchk também precisará de bastante espaço em disco:
• Dobra-se o tamanho do arquivo de registros (o original e uma cópia). Este espaço não
é necessário se for feito um reparo com --quick, já que neste caso somente o arquivo
de índices será recriado. Este espaço é necessário no mesmo disco que se encontra o
arquivo de registros original!
• Espaço para o novo arquivo de índice que substitui o antigo. O arquivo de índices antigo
é truncando no início, portanto, normalmente este espaço é ignorado. Este espaço é
necessário no mesmo disco que o arquivo de índice original!
• Quando utilizando --recover ou --sort-recover (mas não quando usando --safe-
recover, será necessário espaço para um buffer de ordenação de: (maior_chave
+ tamanho_do_ponteiro_de_registro)*número_de_registros * 2. Você pode
conferir o tamanho das chaves e o tamanho do ponteiro de registro com myisamchk
-dv tabela. Este espaço é alocado no disco temporário (especificado por TMPDIR ou
--tmpdir=#).
Se você tiver um problema com espaço em disco durante o reparo, pode-se tentar usar
--safe-recover em vez de --recover.
Este capítulo descreve como checar e lidar com dados corrompidos nos bancos de dados
MySQL. Se suas tabelas corromperem com frequência deve ser encontrada a razão para
isto! See hundefinedi [Falhas], page hundefinedi.
A seção de tabelas MyISAM contêm motivos do porque uma tabela pode estar corrompida.
See hundefinedi [MyISAM table problems], page hundefinedi.
Quando se realizar recuperação devido a falhas, é importante entender que cada tabela
nome_tabela em um banco de dados corresponde a tres arquivos no diretório do banco de
dados:
Arquivo Propósito
‘nome_tabela.frm’ Arquivo com definições da tabela (form)
‘nome_tabela.MYD’ Arquivo de dados
‘nome_tabela.MYI’ Arquivo de índices
Cada um destes três tipos de arquivos está sujeito a corrupção de várias formas, mas
problemas ocorrem mais frequentemente em arquivos de dados e índices.
O myisamchk trabalha criando uma cópia do arquivo de dados ‘.MYD’ linha a linha. Ele
termina o estágio de reparos removendo o antigo arquivo ‘.MYD’ e renomeando o novo arquivo
com nome original. Se for utilizada a opção --quick, myisamchk não cria um arquivo
‘.MYD’ temporário, mas assume que o arquivo ‘.MYD’ está correto e somente gera um novo
arquivo índice sem mexer no arquivo de dados. Isto é seguro, pois o myisamchk detecta
automaticamente se o arquivo ‘.MYD’ está corrompido e aborda o reparo neste caso. Você
pode também fornecer duas opções --quick para o myisamchk. Neste caso, o myisamchk
não aborta em alguns erros (como chaves duplicadas) mas tenta resolvê-los modificando o
arquivo ‘.MYD’. Normalmente o uso de duas opções --quick é útil somente se você tiver
muito pouco espaço em disco para realizer um reparo normal. Neste caso você deve pelo
menos fazer um backup antes de executar o myisamchk.
obter mais informações, pode adicionar a opção --verbose (-v). Isto faz o
myisamchk continuar a percorrer a tabela até um máximo de 20 erros. Em
utilização normal, um simples myisamchk (sem argumentos além do nome da
tabela) é suficiente.
myisamchk -e -i nome_tabela
Como o comando anterior, mas a opção -i diz ao myisamchk para exibir algumas
informações estatísticas também.
Se não estiverem, você precisa alterar os arquivos, eles também devem ter a permissão de
escrita para você.
Se você estiver utilizando o MySQL versão 3.23.16 e superior, você pode (e deve) usar os
comandos CHECK e REPAIR para conferir e corrigir tabelas MyISAM. See hundefinedi [CHECK
TABLE], page hundefinedi. See hundefinedi [REPAIR TABLE], page hundefinedi.
A seção do manual sobre manutenção de tabelas inclui as opções para isamchk/myisamchk.
See hundefinedi [Table maintenance], page hundefinedi.
A seguinte seção são para os casos onde o comando acima falhar ou se você desejar usar os
recursos extendidos que o isamchk e myisamchk fornecem.
Se você for reparar uma tabela da linha de comandos, deve primeiro desligar o servidor
mysqld. Perceba que quando você executa mysqladmin shutdown em um servidor remoto,
o servidor mysqld irá continuar funcionando por um tempo depois do mysqladmin retornar,
até que todas as queries parem e todas as chaves sejam descarregadas no disco.
Estágio 1: Verificando suas tabelas
Execute myisamchk *.MYI ou myisamchk -e *.MYI se você tiver tempo disponível. Utilize
a opção -s (silencioso) para suprimir informações desnecessárias.
Se o servidor mysqld parar, deve ser utilizada a opção --update para dizer ao myisamchk
marcar a tabela como ’checada’.
Você deve reparar somente as tabelas em que o myisamchk indicar um erro. Para tais
tabelas, vá para o estágio 2.
Se você obter erros estranhos na verficação (como nos erros out of memory), ou se o
myisamchk quebrar, vá para o estágio 3.
Estágio 2: Reparo simples e seguro
NOTA: Se você deseja que os reparos sejam mais rápidos, devem ser usadas as opções: -O
sorf_buffer=# -O key_buffer=# (onde # seria 1/4 da memória disponível) para todos
comandos isamchk/myisamchk.
Primeiro, tente usar myisamchk -r -q nome_tabela (-r -q significa “modo de recuperação
rápida”). Ele tentará reparar o arquivo de índice sem mexer no arquivo de dados. Se
o arquivo de dados estiver normal e os links apagados apontam nas localizações corretas
dentro do arquivo de dados, isto deve funcionar e a tabela será corrigida. Inicie o reparo da
próxima tabela. Outra maneira seria utilizar os seguintes procedimentos:
1. Faça um backup do arquivo de dados antes de continuar.
2. Utilize myisamchk -r nome_tabela (-r significa modo de “recuperação”). Isto re-
moverá registros incorretos e deletados do arquivo de dados e reconstroi o arquivo
de índices.
3. Se o passo anterior falhar, utilize myisamchk --safe-recover nome_tabela. O modo
de recuperação segura utiliza um metódo de recuperação antiga que trata de alguns
casos que o modo de recuperação comum não consegue (porém é mais lento).
Se você obter erros estranhos no reparo (como em erros out of memory), ou se o myisamchk
falhar, vá para o estágio 3.
Estágio 3: Reparo difícil
Você só deve atingir este estágio se o primeiro bloco de 16K do arquivo de índice estiver
destruído ou conter informações incorretas, ou se o arquivo de índice não existir. Neste
caso, é necessário criar um novo arquivo de índice. Faça como a seguir:
242 Referência técnica para o MySQL versão 3.23.52
A partir do MySQL Versão 3.23.13, você pode conferir tabelas MyISAM com o comando
CHECK TABLE. See hundefinedi [CHECK TABLE], page hundefinedi. Você pode reparar
tabelas com o comando REPAIR TABLE. See hundefinedi [REPAIR TABLE], page hunde-
finedi.
É uma boa idéia verificar as tabelas regularmente em vez de esperar que ocorram problemas.
Para propósitos de manutenção você pode utilizar o myisamchk -s para verificar as tabelas.
A opção -s (abreviação de --silent) faz com que o myisamchk execute em modo silencioso,
exibindo mensagens somente quando ocorrem erros.
É também uma boa idéia verificar as tabelas quando o servidor inicia. Por exemplo, sempre
que a máquina reinicia no meio de uma atualização, você normalmente precisará conferir
todas as tabelas que podem ter sido afetadas. (Isto é uma“tabela com falhas esperadas”.)
Você pode adicionar um teste ao safe_mysqld que executa myisamchk para conferir todas
tabelas que foram modificadas durante as últimas 24 horas se existir um arquivo ‘.pid’
(process ID) antigo depois do último reboot. (O arquivo ‘.pid’ é criado pelo mysqld quando
ele inicia e removido quando ele termina normalmente. A presença de um arquivo ‘.pid’
durante a inicialização do sistema indica que o mysqld terminou de forma anormal.)
Um teste ainda melhor seria verificar qualquer tabela cuja a data da última modificação é
mais recente que a do arquivo ‘.pid’.
Você também deve verificar suas tabelas regularmente durante a operação normal do sis-
tema. Na MySQL AB, nós executamos uma tarefa agendada cron para conferir todas
nossas tabelas importantes uma vez por semana utilizando uma linha com esta no arquivo
‘crontab’:
35 0 * * 0 /diretório/do/myisamchk --fast --silent /diretório/de/dados/*/*.MYI
Isto exibe informações sobre tabelas com falhas para que possamos examiná-las e repará-las
quando necessário.
Como nós não estamos tendo tabelas com falhas inesperadas (tabelas corrompidas por razões
diferentes de problemas de hardware) por vários anos (isto realmente é verdade), uma vez
por semana é mais que suficiente para nós.
Nós recomendamos que para iniciar, você execute myisamchk -s a cada noite em todas as
tabelas que foram atualizadas durantes as últimas 24 horas, até que você confie no MySQL
como nós confiamos.
Normalmente você não precisará de tanta manutenção em suas tabelas MySQL. Se você
estiver alterando tabelas com registros de tamanho dinâmico (tabelas com colunas VARCHAR,
BLOB ou TEXT) ou tem tabelas com vários registros apagados você pode desejar de tempos
em tempos (uma vez ao mês?) desfragmentar/recuperar espaço das tabelas.
Você pode fazer isto utilizando OPTIMIZE TABLE nas tabelas em questão ou se você puder
desligar o servidor mysqld por um tempo faça:
isamchk -r --silent --sort-index -O sort_buffer_size=16M */*.ISM
myisamchk -r --silent --sort-index -O sort_buffer_size=16M */*.MYI
244 Referência técnica para o MySQL versão 3.23.52
table description:
Key Start Len Index Type
1 2 8 unique double
2 15 10 multip. text packed stripped
3 219 8 multip. double
4 63 10 multip. text packed stripped
5 167 2 multip. unsigned short
6 177 4 multip. unsigned long
7 155 4 multip. text
8 138 4 multip. unsigned long
9 177 4 multip. unsigned long
193 1 text
Exemplo da saída de myisamchk -d -v :
MyISAM file: company
Record format: Fixed length
File-version: 1
Creation time: 1999-10-30 12:12:51
Recover time: 1999-10-31 19:13:01
Status: checked
Data records: 1403698 Deleted blocks: 0
Chapter 4: Administração de Bancos de Dados MySQL 245
table description:
Key Start Len Index Type Rec/key Root Blocksize
1 2 8 unique double 1 15845376 1024
2 15 10 multip. text packed stripped 2 25062400 1024
3 219 8 multip. double 73 40907776 1024
4 63 10 multip. text packed stripped 5 48097280 1024
5 167 2 multip. unsigned short 4840 55200768 1024
6 177 4 multip. unsigned long 1346 65145856 1024
7 155 4 multip. text 4995 75090944 1024
8 138 4 multip. unsigned long 87 85036032 1024
9 177 4 multip. unsigned long 178 96481280 1024
193 1 text
Exemplo da saída de myisamchk -eis:
Checking MyISAM file: company
Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4
Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4
Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4
Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3
Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3
Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3
Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3
Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3
Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4
Total: Keyblocks used: 98% Packed: 17%
index 2:
index 3:
index 4:
index 5:
index 6:
index 7:
index 8:
index 9:
No recordlinks
- check index reference
- check data record references index: 1
Key: 1: Keyblocks used: 97% Packed: 0% Max levels: 4
- check data record references index: 2
Key: 2: Keyblocks used: 98% Packed: 50% Max levels: 4
- check data record references index: 3
Key: 3: Keyblocks used: 97% Packed: 0% Max levels: 4
- check data record references index: 4
Key: 4: Keyblocks used: 99% Packed: 60% Max levels: 3
- check data record references index: 5
Key: 5: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 6
Key: 6: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 7
Key: 7: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 8
Key: 8: Keyblocks used: 99% Packed: 0% Max levels: 3
- check data record references index: 9
Key: 9: Keyblocks used: 98% Packed: 0% Max levels: 4
Total: Keyblocks used: 9% Packed: 17%
Aqui estão os tamanhos dos arquivos de dados e índices para a tabela utilizada nos exemplos
anteriores:
-rw-rw-r-- 1 monty tcx 317235748 Jan 12 17:30 company.MYD
-rw-rw-r-- 1 davida tcx 96482304 Jan 12 18:35 company.MYM
Chapter 4: Administração de Bancos de Dados MySQL 247
Explicações para os tipos de informações que o myisamchk produz são fornecidas abaixo. O
“keyfile” é o arquivo de índices. “Registro” e “linha” são sinônimos:
ISAM file Nome do arquivo (índice) ISAM.
Isam-version
Versão do formato ISAM. Atualmente sempre 2.
Creation time
Quando o arquivo de dados foi criado.
Recover time
Quando foi a última vez que o arquivo de índices/dados foi reconstruído.
Data records
Quantos registros existem na tabela.
Deleted blocks
Quantos blocos apagados continuam alocando espaço. Você pode otimizar sua
tabela para minimizar este espaço. See hundefinedi [Otimização], page hunde-
finedi.
Datafile: Parts
Para formato de registros dinâmicos, isto indica quantos blocos de dados exis-
tem. Para uma tabela otimizada sem registros fragmentados, isto é o mesmo
que Data records.
Deleted data
Quantos bytes de dados deletados não recuperados existem. Você pode otimizar
sua tabela para minimizar este espaço. See hundefinedi [Otimização], page hun-
definedi.
Datafile pointer
O tamanho do ponteiro do arquivo de dados, em bytes. Ele normalmente possui
2, 3, 4 ou 5 bytes. A maioria das tabelas trabalham com 2 bytes, mas isto
ainda não pode ser controlado pelo MySQL ainda. Para tabelas fixas, isto é
um endereço de registro. Para tabelas dinâmicas, isto é um endereço de byte.
Keyfile pointer
O tamanho de um ponteiro de arquivo de índices, em bytes. Ele normalmente
possui 1, 2 ou 3 bytes. A maioria das tabelas trabalham com 2 bytes, mas isto
é calculado automaticamente pelo MySQL. Ele é sempre um endereço de bloco.
Max datafile length
Qual tamanho o arquivo de dados (arquivos .MYD) pode atingir, em bytes.
Max keyfile length
Qual tamanho o arquivo de índices (.MYI pode atingir, em bytes.
Recordlength
Quanto espaço cada registro ocupa, em bytes.
Record format
O formato utilizado para armazenar as linhas da tabelas. Os exemplos vistos
abaixo utilizam Fixed length (tamanho fixo). Outros valores possíveis são
Compressed(compactado) e Packed(empacotado).
248 Referência técnica para o MySQL versão 3.23.52
table description
Uma lista de todas as chaves na tabela. Para cada chave, alguma informação
de baixo nível é apresentada:
Key O Número desta chave.
Start Onde, no registro, esta parte do índice inicia.
Len Qual o tamanho desta parte do índice. Para números empacotados,
isto deve sempre ser o tamanho total da coluna. Para strings, deve
ser mais curto que o tamanho total da coluna indexada, porque
você pode indexar um prefixo de uma coluna string.
Index unique ou multip. (multiplos). Indica se um valor pode ou não
exisitir várias vezes neste índice.
Type Que tipo de dados esta parte do índice tem. Isto é um tipo de
dados ISAM com as opções packed, stripped ou empty.
Root Endereço do bloco de índice raiz.
Blocksize
O tamanho de cada bloco de índice. O tamanho padrão é 1024,
mas o valor pode ser alterado na compilação.
Rec/key Este é um valor estatístico utilizado pelo otimizador. Ele diz quan-
tos registros existem por valor para esta chave. Uma chave única
sempre tem um valor de 1. Ele pode ser atualizado depois que
uma tabela é carregada (ou muito alterada) com myisamchk -a. Se
isto não for completamente atualizado, um valor padrão de 30 é
fornecido.
No primeiro exemplo acima, a nona chave é uma chave multi partes com duas
partes.
Keyblocks used
Qual o percentual de bloco de chaves são usados. Como a tabela usada nos
exemplos foi reorganizada com myisamchk, os valores são muito altos (muito
próximos do máximo teórico).
Packed O MySQL tenta empacotar chaves com um sufixo comum. Isto pode ser us-
ado somente para chaves CHAR/VARCHAR/DECIMAL. Para strings grandes como
nomes, isto pode reduzir significativamente o espaço utilizado. No terceiro ex-
emplo acima, a quarta chave possui 10 caracteres e uma redução de 60% no
espaço é obtida.
Max levels
Qual a profundidade da árvore-B para esta chave. Grandes tabelas com chaves
longas resultam em valores altos.
Records Quantos registros existem na tabela.
M.recordlength
A média de tamanho do registro. Para tabelas com registros de tamanho fixo,
isto é o tamanho exato do registro.
Chapter 4: Administração de Bancos de Dados MySQL 249
Packed O MySQL corta espaços do final de strings. O valor Packed indica o percentual
de economia alcançado fazendo isto.
Recordspace used
Qual percentual do arquivo de dados é usado.
Empty space
Qual percetual do arquivo de dados não é usado.
Blocks/Record
Número médio de blocos por registro (isto é, de quantos links um registro frag-
mentado é composto). Sempre será 1 para tabelas de formato fixo. Este valor
deve permanecer o mais próximo possível de 1.0. Se ele aumentar, você pode
reorganizar a tabela com myisamchk. See hundefinedi [Otimização], page hun-
definedi.
Recordblocks
Quantos blocos (links) são utilizados. Para formatos fixos, este é o mesmo que
o número de registros.
Deleteblocks
Quantos blocos (links) foram excluídos.
Recorddata
Quantos bytes no arquivo de dados são usados.
Deleted data
Quantos bytes no arquivo de dados foram apagados (sem uso).
Lost space
Se um registro é atualizado para um tamanho menor, algum espaço é perdido.
Isto é a soma de todas estas perdas, em bytes.
Linkdata Quando o formato de tabela dinâmica é utilizado, fragmentos de registros são
ligados com ponteiros (4 a 7 bytes cada). Linkdata é a soma do montante de
armazenamento utilizado por todos estes ponteiros.
Se uma tabela foi compactada com myisampack, mysiamchk -d exibe informações adicionais
sobre cada coluna da tabela. Veja hundefinedi [myisampack], page hundefinedi, para um
exemplo desta informação e uma descrição do que ela significa.
pode utilizar OPTIMIZE TABLE para reclamar o espaço inutilizado e para desfragmentar o
arquivo de dados.
No momento OPTIMIZE TABLE só funciona em tabelas MyISAM e BDB. Para tabelas BDB,
OPTIMIZE TABLE é atualmente mapeado para ANALIZE TABLE. See hundefinedi [ANALYZE
TABLE], page hundefinedi.
Você pode ter a otimização de tabelas trabalhando em outros tipos de tabelas iniciando
o mysqld com --skip-new ou --safe-mode, mas neste caso, OPTIMIZE TABLE é mapeado
apenas para ALTER TABLE.
OPTIMIZE TABLE funciona da seguinte forma:
• Se a tabela tem registros excluídos ou dividos, repara a tabela.
• Se as páginas de índice não estão ordenas, ordene-as.
• Se as estatísticas não estão atualizadas (e o reparo não pode ser feito ordenando o
índice), atualize-as.
OPTIMIZE TABLE para tabelas MyISAM é equivalente a executar myisamchk --quick
--check-changed-tables --sort-index --analyze na tabela.
Perceba que a tabela estará bloqueada durante o tempo em que OPTIMIZE TABLE estiver
executando.
Se você tiver o privilégio process, você pode ver e matar qualquer thread. Caso contrário,
você pode ver e matar somente suas próprias threads.
Você também pode usar os comandos mysqladmin processlist e mysqladmin kill para
examinar e matar threads.
Quando você utiliza um KILL, um sinal (flag) kill especifico é configurado para a thread.
Na maioria dos casos pode levar algum tempo para a thread morrer pois o sinal kill só é
checado em intervalos específicos.
• Nos loops SELECT, ORDER BY e GROUP BY, o sinal é checado depois de ler um bloco de
registros. Se o sinal kill está habilitado a instrução é abortada.
• Na execução de um ALTER TABLE o sinal kill é conferido antes de cada bloco de registros
ser lido da tabela original. Se o sinal kill foi habilitado, o comando é abortado e a tabela
temporária apagada.
• Ao fazer um UPDATE TABLE and DELETE TABLE, o sinal de kill é conferido depois de
que cada bloco é lido e depois de cada atualização ou remoção de registro. Se o sinal
kill está habilitado, a instrução é abortada. Note que se você não estiver utilizando
transações, as alterações não irão ser desfeitas!
• GET_LOCK() irá aborar com NULL.
• Uma thread INSERT DELAYED irá rapidamente descarregar todos registros que estiverem
em memória e morrer.
• Se a thread estiver no manipulador de bloqueio de tabelas (status: Locked), o bloqueio
de tabela será abortado rapidamente.
• Se a thread estiver esperando por espaço livre em disco numa chamada write, a escrita
é abortada com uma mensagem de espaço em disco insuficiente.
| Handler_delete | 462604 |
| Handler_read_first | 105881 |
| Handler_read_key | 27820558 |
| Handler_read_next | 390681754 |
| Handler_read_prev | 6022500 |
| Handler_read_rnd | 30546748 |
| Handler_read_rnd_next | 246216530 |
| Handler_update | 16945404 |
| Handler_write | 60356676 |
| Key_blocks_used | 14955 |
| Key_read_requests | 96854827 |
| Key_reads | 162040 |
| Key_write_requests | 7589728 |
| Key_writes | 3813196 |
| Max_used_connections | 0 |
| Not_flushed_key_blocks | 0 |
| Not_flushed_delayed_rows | 0 |
| Open_tables | 1 |
| Open_files | 2 |
| Open_streams | 0 |
| Opened_tables | 44600 |
| Questions | 2026873 |
| Select_full_join | 0 |
| Select_full_range_join | 0 |
| Select_range | 99646 |
| Select_range_check | 0 |
| Select_scan | 30802 |
| Slave_running | OFF |
| Slave_open_temp_tables | 0 |
| Slow_launch_threads | 0 |
| Slow_queries | 0 |
| Sort_merge_passes | 30 |
| Sort_range | 500 |
| Sort_rows | 30296250 |
| Sort_scan | 4650 |
| Table_locks_immediate | 1920382 |
| Table_locks_waited | 0 |
| Threads_cached | 0 |
| Threads_created | 30022 |
| Threads_connected | 1 |
| Threads_running | 1 |
| Uptime | 80380 |
+--------------------------+------------+
Variável Signficado
Aborted_clients Número de conexões abortadas porque o cliente morreu
sem fechar a conexão corretamente. See hundefinedi [Er-
ros de Comunicação], page hundefinedi.
256 Referência técnica para o MySQL versão 3.23.52
| have_raid | YES |
| have_ssl | NO |
| init_file | |
| interactive_timeout | 28800 |
| join_buffer_size | 131072 |
| key_buffer_size | 16776192 |
| language | /my/monty/share/english/ |
| large_files_support | ON |
| log | OFF |
| log_update | OFF |
| log_bin | OFF |
| log_slave_updates | OFF |
| long_query_time | 10 |
| low_priority_updates | OFF |
| lower_case_table_names | 0 |
| max_allowed_packet | 1048576 |
| max_binlog_cache_size | 4294967295 |
| max_connections | 100 |
| max_connect_errors | 10 |
| max_delayed_threads | 20 |
| max_heap_table_size | 16777216 |
| max_join_size | 4294967295 |
| max_sort_length | 1024 |
| max_tmp_tables | 32 |
| max_write_lock_count | 4294967295 |
| myisam_recover_options | DEFAULT |
| myisam_sort_buffer_size | 8388608 |
| net_buffer_length | 16384 |
| net_read_timeout | 30 |
| net_retry_count | 10 |
| net_write_timeout | 60 |
| open_files_limit | 0 |
| pid_file | /my/monty/data/donna.pid |
| port | 3306 |
| protocol_version | 10 |
| record_buffer | 131072 |
| query_buffer_size | 0 |
| safe_show_database | OFF |
| server_id | 0 |
| skip_locking | ON |
| skip_networking | OFF |
| skip_show_database | OFF |
| slow_launch_time | 2 |
| socket | /tmp/mysql.sock |
| sort_buffer | 2097116 |
| table_cache | 64 |
| table_type | MYISAM |
| thread_cache_size | 4 |
| thread_stack | 65536 |
260 Referência técnica para o MySQL versão 3.23.52
| tmp_table_size | 1048576 |
| tmpdir | /tmp/ |
| version | 3.23.29a-gamma-debug |
| wait_timeout | 28800 |
+-------------------------+---------------------------+
Cada opção é descrita abaixo. Valores para tamanhos de buffer, comprimento e tamanho
de pilha são fornecidos em bytes. Você pode especificar valores com sufixos ‘K’ ou M para
indicar o valor em kilobytes ou megabytes. Por exemplo, 16M indica 16 Megabytes. Não
importa se os sufixos estão em letras maiúsuculas ou minúsculas; 16M e 16m são equivalentes:
ansi_mode.
Está ligado (ON) se o mysqld foi iniciado com --ansi. See hundefinedi [Modo
ANSI], page hundefinedi.
back_log O número de requisições de conexões que o MySQL pode suportar. Isto entra
em cena quando a thread principal do MySQL recebe MUITAS solicitações de
conexões em um espaço curto de tempo. Eles tomam algum tempo (porém
muito pouco) da a thread principal para conferir a conexão e iniciar uma nova
thread. O valor back_log indica quantas requisições podem ser empilhadas du-
rante este breve tempo antes do MySQL parar de responder a novas requisições.
Você isó precisa aumentá-lo se espera um número alto de conexões em um curto
período de tempo
Em outras palavras, este valor é o tamanho da fila de escuta para novas conexões
TCP/IP. Seu sistema operacional tem o próprio limite para o tamanho desta
fila. A página do manual Unix da chamada de sistema listen(2) deve fornecer
maiores detalhes. Confira a documentação do seus SO para saber o valor
máximo para esta variável. Tentativas de configurar back_log maior do que o
limite de seu sistema operacional serão ineficazes.
basedir O valor da opção --basedir.
bdb_cache_size
O buffer que é alocado para o cache de índice e registros de tabelas BDB. Se
você não utiliza tabelas BDB, deve iniciar o mysqld com a opção --skip-bdb
para evitar desperdício de memória para este cache.
bdb_log_buffer_size
O buffer que é alocado para o cache de índice e registros de tabelas BDB. Se
você não utiliza tabelas BDB, deve configurá-la com 0 ou iniciar o mysqld com
a opção --skip-bdb para evitar desperdício de memória para este cache.
bdb_home O valor para a opção --bdb-home.
bdb_max_lock
O número máximo de bloqueios (1000 por padrão) que podem ser feitas em uma
tabela BDB. Você deve ser aumentá-la se obter erros do tipo: bdb: Lock table
is out of available locks ou Got error 12 from ... quando são necessárias
longas transações ou quando o mysqld precisar examinar vários registros para
calcular a pesquisa.
bdb_logdir
O valor da opção --bdb-logdir.
Chapter 4: Administração de Bancos de Dados MySQL 261
bdb_shared_data
Está ligada (ON) se você estiver utilizando --bdb-shared-data.
bdb_tmpdir
O valor da opção --bdb-tmpdir.
binlog_cache_size. O tamanho do cache para armazenar instruç~ oes
SQL para o log binário durante uma transação. Se você geralmente utiliza
transações grandes, multi-instruções, você pode aumentar este valor para obter
mais performance. See hundefinedi [COMMIT], page hundefinedi.
character_set
O conjunto de caracteres padrão.
character_sets
Os conjuntos de caracteres suportados.
concurrent_inserts
Se ON (ligado, por padrão), o MySQL permitirá o uso de INSERT em tabelas
MyISAM ao mesmo tempo em que são executadas consultas SELECT. Você pode
desligar esta opção iniciando mysqld com --safe ou --skip-new.
connect_timeout
O número de segundos que o servidor mysqld espera para um pacote de conexão
antes de responder com Bad handshake.
datadir O valor da opção --datadir.
delay_key_write
Se habilitado (valor padrão), o MySQL utilizará a opção delay_key_write
com CREATE TABLE. Isto siginifica que o buffer de chaves das tabelas com
esta opção não serão descarregadas a cada atualização do índice, mas somente
quando a tabela é fechada. Isto irá aumentar bem a velocidade de escrita em
chaves, mas voc6e deve adicionar verificação automática de todas as tabelas
com myisamchk --fast --force se você usá-lo. Note que se você iniciar o
mysqld com a opção --delay-key-write-for-all-tables siginifica que to-
das as tabelas serão tratadas como se fossem criadas com a opção delay_key_
write. Você pode limpar esta configuração iniciando mysqld com --skip-new
ou --safe-mode.
delayed_insert_limit
Depois de inserir delayed_insert_limit registros, o agente que cuida de
INSERT DELAYED ira conferir se exitem instruções SELECT pendentes. Se sim,
ele permite a execução destas antes de continuar.
delayed_insert_timeout
Quanto tempo uma thread INSERT DELAYED deve esperar por instruções INSERT
antes de terminar.
delayed_queue_size
Qual tamanho deve ser alocado para a fila (em linhas) para lidar com INSERT
DELAYED. Se a fila encher, algum cliente que executar INSERT DELAYED irá
esperar até existir espaço na fila novamente.
262 Referência técnica para o MySQL versão 3.23.52
max_binlog_size
Disponível a partir da 3.23.33. Se uma escrita ao log binário (replicação) exceder
o valor fornecido, rotacione os logs. Você não pode configurá-lo para menos de
1024 bytes ou mais que 1 GB. O valor padrão é 1 GB.
max_connections
O Número de clientes simultâneos permitidos. Aumentar este valor aumente
o número de descritores de arquivos que o mysqld necessita. Veja abaixo os
comentários sobre os limites de descritores de arquivos. See hundefinedi [Muitas
conexões], page hundefinedi.
max_connect_errors
Se houver mais que este número de conexões interrompidas a partir de uma
máquina está máquina terá as próximas conexões bloqueadas. Você pode des-
bloquar uma máquina com o comadno FLUSH HOSTS.
max_delayed_threads
Não inicie mais do que este número de threads para lidar com instruções INSERT
DELAYED. Se você tentar inserir dados em uma nova tabela depois que todas as
threads INSERT DELAYED estiverem em uso, o registro será inserido como se o
atributo DELAYED não fosse especificado.
max_heap_table_size
Não permita criação de tabelas heap maiores que este valor.
max_join_size
Joins que provavelmente forem ler mais que max_join_size registros retornam
um erro. Configure este valor se os seus usuários tendem a realizar joins que
não possuem uma cláusula WHERE, que tomam muito tempo, e retornam milhões
de registros.
max_sort_length
O número de bytes utilizados para ordenar valores BLOB ou TEXT (somente os
primeiros max_sort_lenght bytes de cada valor são usados; o resto é ignorado).
max_user_connections
O valor máximo de conexões ativas para um único usuário (0 = sem limite).
max_tmp_tables
(Esta opção ainda não faz nada.) Número máximo de tabelas temporárias que
um cliente pode manter abertas ao mesmo tempo.
max_write_lock_count
Depois desta quantidade de bloqueios de escrita, permite que alguns bloqueios
de leitura sejam executados.
myisam_recover_options
O valor da opção --myisam-recover.
myisam_sort_buffer_size
O buffer que é alocado ao ordenar o índice quando estiver fazendo um REPAIR
ou estiver criando índices com CREATE INDEX ou ALTER TABLE.
Chapter 4: Administração de Bancos de Dados MySQL 265
myisam_max_extra_sort_file_size.
Se a criação do arquivo temporário para criação rápida de índices fosse este
valor maior que quando for usado o cache de chaves, de preferência ao método
de cache de chaves. Isto é usado principalmente para forçar que longas chaves
de caracteres em tabelas grandes usem o método de cache de chaves mais lenta
para criar o índice. NOTE que este parâmetro é fornecido em megabytes!
myisam_max_sort_file_size
O tamanho máximo do arquivo temporário que é permitido ao MySQL usar en-
quanto recria os índices (durante REPAIR, ALTER TABLE ou LOAD DATA INFILE).
Se o tamanho do arquivo for maior que isto, o índice será criado através do
cache de chaves (que é mais lento). NOTE que este parâmetro é fornecido em
megabytes!
net_buffer_length
O buffer de comunicações é configurado para este tamanho entre queries. Isto
não deve ser alterado normalmente, mas se você tem muito pouca memória,
pode configurá-lo para o tamanho esperado de uma consulta. (Isto é, o tamanho
experado das instruções SQL enviadas pelos clientes. Se as instruções excederem
este valor, o buffer é aumentado automaticamente, até max_allowed_packet
bytes.)
net_read_timeout
Número de segundos para esperar por mais dados de uma conexão antes de abor-
tar a leitura. Perceba que quando nós não esperamos dados de uma conexão, o
tempo máximo de espera é definido pelo write_timeout. Veja também slave_
read_timeout.
net_retry_count
Se uma leitura na porta de comunicações for interrompida, tente novamente
net_retry_count vezes antes de parar. Este valor deve ser bem alto no FreeBSD
já que interrupções internas são enviadas para todas as threads.
net_write_timeout
Número de segundos para esperar pela escrita de um bloco em uma conexão
antes de abortar a escrita.
open_files_limit
Se não for 0, então o mysqld usará este valor para reservar descritores de ar-
quivos para usar com setrlimit(). Se este valor for 0 então o mysqld irá reser-
var max_connections*5 ou max_connections + table_cache*2 (que é maior)
número de arquivos. Você deve tentar aumentar isto se o mysqld fornecer a
você o erro ’Too many open files’ (Muitos arquivos abertos).
protocol_version
A versão do protocolo usada pelo servidor MySQL.
266 Referência técnica para o MySQL versão 3.23.52
record_buffer
Cada thread que faz uma leitura sequencial aloca um buffer deste tamanho para
cada tabela lida. Se você fizer várias leituras sequenciais, você pode desejar
aumentar este valor.
record_rnd_buffer
Ao ler registros na ordem depois de uma ordenação, os registros são lidos através
deste buffer para evitar pesquisas em disco. Se não for configurado, recebe o
valor de record_buffer.
query_buffer_size
A alocação inicial do buffer de consultas. Se a maioria de suas consultas são
grandes (como quando se insere blobs), você deve aumentiá-lo!
safe_show_databases
Não exibe bancos de dados nos quais o usuário não tem nenhum privilégios. Isto
pode melhorar a segurança se você se preocupa com o fato das pessoas estarem
aptas a ver quais bancos de dados outros usuários possuem. Veja também
skip_show_databases.
server_id
O valor da opção --server-id.
skip_locking
Está desligado (OFF) se o mysqld usar bloqueio externo.
skip_networking
Está ligado (ON) se somente permitimos conexões locais (socket).
skip_show_databases
Isto previne usuários de fazerem SHOW DATABASES se eles não possuirem o
privilégio PROCESS_PRIV. Isto pode aumentar a segurança se você se preocupa
com o fato das pessoas poderem ver quais bancos de dados outros usuários
possuem. Veja também safe_show_databases.
slave_read_timeout
Número de segundos para esperar por mais dados de uma conexão de
mestre/escravo antes de abortar a leitura.
slow_launch_time
Se a criação de threads demorar mais que este valor (em segundos), o contador
Slow_launch_threads será incrementado.
socket O socket Unix utilizado pelo servidor.
sort_buffer
Cada thread que precisar fazer uma ordenação aloca um buffer deste tamanho.
Aumente este valor para operações ORDER BY ou GROUP BY mais rápidas. See
hundefinedi [Arquivos temporários], page hundefinedi.
table_cache
O número de tabelas abertas para todas as threads. Aumentar este valor au-
menta o número de descritores de arquivos que o mysql necessita. O MySQL
precisa de dois descritores de arquivos para cada tabela única aberta. Veja
Chapter 4: Administração de Bancos de Dados MySQL 267
table_type
O tipo padrão de tabelas.
thread_cache_size
Quantas threads devem ser mantidas em cache para reutilização. Quando um
cliente desconecta, as threads dos clientes são colocadas no cache se não existir
mais de thread_cache_size threads que antes. Todas novas threads serão
obtidas primeiramente do cache, e só quando o cache estiver vazio uma nova
thread é criada. Esta variável pode ser aumentada para melhorar a performance
se você tiver várias conexões novas. (Normalmente isto não dá uma melhora
de performance notável se você possuir uma boa implementação de threads.)
Examinando as diferenças entre Connections e Threads_create pode ser visto
o quão eficente é o cache de threads atual.
thread_concurrency
No Solaris, mysqld irá chamar thr_setconcurrency() com este valor. thdr_
setconcurre=() permite que a aplicação forneça ao sistema de threads uma
dica com o número desejado de threads que devem ser executados ao mesmo
tempo.
thread_stack
O tamanho da pilha para cada thread. Vários dos limites detectados pelo
teste crash-me são dependentes deste valor. O padrão é grande o suficiente
para operações normais. See hundefinedi [Benchmarks do MySQL], page hun-
definedi.
tmp_table_size
Se uma tabela temporária em memória exceder este tamanho, o MySQL irá
a convertê-la automaticamente para uma tabela MyISAM em disco. Aumente o
valor de tmp_table_size se você fizer várias consultas GROUP BY avançadas e
você tiver muita memória.
wait_timeout
O número de segundos que o servidor espera pela atividade em uma conexão
antes de fechá-la. Veja também interactive_timeout.
A seção do manual que descreve a sintonia do MySQL contém algumas informações de como
sintonizar as variáveis acima. See hundefinedi [Parâmetros do servidor], page hundefinedi.
SHOW CREATE TABLE irá citar os nomes de colunas e tabelas de acordo com a
opção SQL_QUOTE_SHOW_CREATE. hundefinedi [SET OPTION SQL_QUOTE_SHOW_CREATE],
page hundefinedi.
[client]
character-sets-dir=/usr/local/mysql/share/mysql/charsets
onde o caminho aponta para onde os conjuntos de caracteres dinâmicos do MySQL são
armazenados.
Pode-se forçar o cliente a usar conjuntos de caracteres específicos especificando:
[client]
default-character-set=nome-conjunto-caracteres
mas normalmente isto nunca será necessário.
myisamchk
Utilitário para descrever, conferir, otimizar e reparar tabelas MySQL. Como o
myisamchk tem muitas funções, eles são descritos em seu próprio capítulo. See
hundefinedi [Administração do Banco de Dados MySQL], page hundefinedi.
make_binary_distribution
Cria uma edição binária de um MySQL compilado. Isto pode ser enviado por
FTP para ‘/pub/mysql/Incoming’ em support.mysql.com para a conveniência
de outros usuários MySQL.
274 Referência técnica para o MySQL versão 3.23.52
msql2mysql
Um script shell que converte programas mSQL para MySQL. Ele não consegue
lidar com todos os casos, mas é um bom começo quando uma conversão for
necessária.
mysqlaccess
Um script que confere os privilégios de acesso para uma combinação de máquina,
usuário e banco de dados.
mysqladmin
Utilitário para realizar operações administrativas, como a criação ou remoção
de bancos de dados, recarga das tabelas de permissões, descarga de tabelas ao
disco e reabertura de arquivos log. mysqladmin pode também ser utilizado para
exibir informações de versão, processos e estado do servidor. See hundefinedi
[mysqladmin], page hundefinedi.
mysqlbug O script para relatar erros no MySQL. Este script deve sempre ser utilizado
quando for necessário preencher um relatório de erros para a lista do MySQL.
mysqld O servidor (daemon) SQL. Deve sempre estar em execução.
mysqldump
Descarrega um banco de dados MySQL em um arquivo no formato de in-
struções SQL ou como arquivos texto separado por tabulações. Versão melho-
rada do freeware produzido originalmente por Igor Romanenko. See hundefinedi
[mysqldump], page hundefinedi.
mysqlimport
Importa arquivos texto em suas respectivas tabelas utilizando LOAD DATA
INFILE. See hundefinedi [mysqlimport], page hundefinedi.
mysqlshow
Exibe informações sobre bancos de dados, tabelas, colunas e índices.
mysql_install_db
Cria as tabelas de permissões do MySQL com os privilégios padrões. Este
comando normalmente é executado somente na primeira vez quando o MySQL
é instalado em um sistema.
replace Um programa utilitário que é utilizado pelo msql2mysql, mas também pode
ser utilizado para aplicações gerais. replace altera strings em arquivos ou na
entrada padrão. Utiliza uma máquina de estado finito para coincidir primeira-
mente com strings maiores. Pode ser utilizado para trocar strings. Por exemplo,
este comando troca a e b nos arquivos fornecidos:
shell> replace a b b a -- arquivo1 arquivo2 ...
O script safe_mysqld é gravável, portanto ele deve estar apto para iniciar um servidor que
foi instalado de uma fonte ou uma versão binária do MySQL, mesmo se o servidor estiver
instalado em localizações um pouco diferentes. safe_mysqld espera uma destas condições
ser verdadeira:
• O servidor e o banco de dados pode ser encontrado relativo ao diretório de onde o
safe_mysqld foi chamado. safe_mysqld procura dentro de seu diretório de trabalho
pelos diretórios ‘bin’ e ‘data’ (para distribuições binárias) ou pelos diretórios ‘libexec’
e ‘var’ (para distribuições baseadas em código fonte). Esta condição deve ser satisfeita
se você executar o safe_mysqld a partir do seu diretório da instalação do MySQL (por
exemplo, ‘/usr/local/mysql’ para uma distribuição binária).
• Se o servidor e os bancos de dados não forem encontrados relativos ao diretório de
trabalho, safe_mysqld tenta localizá-lo utilizando caminhos absolutos. Localizações
típicas são ‘/usr/local/libexec’ e ‘/usr/local/var’. As localizações atuais foram
determinadas quando a distribuição foi construída da qual vem o safe_mysqld. Eles
dever estar corretas se o MySQL foi instalado na localização padrão.
Como o safe_mysqld tentará encontrar o servidor e o banco de dados relativo a seu diretório
de trabalho, você pode instalar uma distribuição binária do MySQL em qualquer lugar,
desde de que o safe_mysqld seja iniciado a partir do diretório da instalação:
shell> cd diretório_instalaç~ ao_mysql
shell> bin/safe_mysqld &
Se o safe_mysqld falhar, mesmo se invocado a partir do diretório de instalação do MySQL,
você pode modificá-lo para usar o caminho para o mysqld e as opções de caminho que
seriam corretas para seu sistema. Perceba que se você atualizar o MySQL no futuro, sua
versão modificada de safe_mysqld será sobrescrita, portanto, você deve fazer uma cópia de
sua versão editada para que você a possa reinstalar.
encontrados serão iniciados, parados ou listados. Perceba que você não deve ter nenhum
espaço em branco na lista GNR. Qualquer coisa depois de um espaço em branco é ignorado.
mysqld_multi suporta as seguintes opções:
--config-file=...
Arquivo de configuração alternativo. NOTA: Isto não irá afetar as próprias
opções do programa (grupo [mysqld_multi]), mas somente grupos [mysqld#].
Sem esta opção tudo será procurado a partir do arquivo my.cnf.
--example
Fornece um exemplo de um arquivo de configuração.
--help Exibe esta ajuda e sai.
--log=...
Arquivo Log. Deve ser informado o caminho completo e o nome do arquivo log.
NOTA: se o arquivo existir, tudo será anexado.
--mysqladmin=...
Binário mysqladmin a ser usado para o desligamento do servidor.
--mysqld=...
Binário mysqld a ser usado. Lembre-se que você também pode fornecer safe_
mysqld a esta opção. As opções são passadas ao mysqld. Apenas tenha certeza
que o mysqld está localizado na sua variável de ambiente PATH ou corrija o
safe_mysqld.
--no-log Imprime na saída padrão em vez do arquivo log. Por padrão o arquivo log
sempre fica ligado.
--password=...
Senha do usuário para o mysqladmin.
--tcp-ip Conecta ao(s) servidor(es) MySQL através de porta TCP/IP no lugar de socket
UNIX. Isto afeta a ação de desligar e relatar. Se um arquivo socket estiver
faltando, o servidor pode ainda estar executando, mas só pode ser acessado
através da porta TCP/IP. Por padrão a conexão é feita através de socket UNIX.
--user=...
Usuário MySQL para o mysqladmin.
--version
Exibe o número da versão e sai.
Algumas notas sobre mysqld_multi:
• Tenha certeza que o usuário MySQL, que finalizar os serviços mysqld (e.g. utilizando o
mysqladmin) tem a mesma senha e usuário para todos os diretórios de dados acessados
(para o banco de dados ’mysql’). E tenha certeza que o usuário tem o privilégio
’Shutdown priv’ ! Se você possui diversos diretórios de dados e vários bancos de dados
’mysql’ com diferentes senhas para o usuário ’root’ do MySQL, você pode desejar
criar um usuário comum ’multi-admin’ para cada um que utilize a mesma senha (veja
abaixo). Exemplo de como fazer isto:
278 Referência técnica para o MySQL versão 3.23.52
[mysqld_multi]
mysqld = /usr/local/bin/safe_mysqld
mysqladmin = /usr/local/bin/mysqladmin
user = multi_admin
password = multipass
[mysqld2]
socket = /tmp/mysql.sock2
port = 3307
pid-file = /usr/local/mysql/var2/hostname.pid2
datadir = /usr/local/mysql/var2
language = /usr/local/share/mysql/english
user = john
[mysqld3]
socket = /tmp/mysql.sock3
port = 3308
pid-file = /usr/local/mysql/var3/hostname.pid3
datadir = /usr/local/mysql/var3
language = /usr/local/share/mysql/swedish
user = monty
[mysqld4]
socket = /tmp/mysql.sock4
port = 3309
pid-file = /usr/local/mysql/var4/hostname.pid4
datadir = /usr/local/mysql/var4
language = /usr/local/share/mysql/estonia
user = tonu
[mysqld6]
socket = /tmp/mysql.sock6
port = 3311
pid-file = /usr/local/mysql/var6/hostname.pid6
datadir = /usr/local/mysql/var6
language = /usr/local/share/mysql/japanese
user = jani
See hundefinedi [Arquivo de opções], page hundefinedi.
sobre o myisampack, mas tudo dito sobre myisampack também pode ser verdadeiro para o
pack_isam.
myisampack trabalha compactando cada coluna na tabela separadamente. A informação
necessária para descompactar colunas é lida em memória quando a tabela é aberta. Isto
resulta em uma performance muito melhor quando estiver acessando registros individuais,
porque você precisará descompactar somente um registro, não um bloco muito maior do
disco como faz o Stacker no MS-DOS. Normalmente, myisampack compacta o arquivo de
dados 40%-70%.
O MySQL utiliza mapeamento de memória (nmap()) em tabelas compactadas e retorna ao
uso normal de leitura e escrita se nmap() não funcionar.
Atualmente existem duas limitações com myisampack:
• Depois da compactação, a tabela deve trabalhar somente para leitura.
• myisampack também pode compactar colunas BLOB ou TEXT. O antigo pack_isam não
pode fazer isto.
A correção destas limitações está em nossa lista de pendencias (TODO), mas com baixa
prioridade.
myisampack é chamado desta forma:
shell> myisampack [opç~ oes] nome_arquivo ...
Cada nome arquivo deve ter o nome de um arquivo de índice (‘.MYI’). Se você não se
encontra em um diretório de bancos de dados, você deve especificar o caminho completo
para o arquivo. Pode-se omitir a extensão ‘.MYI’.
myisampack suporta as seguintes opções:
-b, --backup
Realiza um backup da tabela como nome_tabela.OLD.
-#, --debug=debug_options
Log da saída de depuração. A string debug_options geralmante é
’d:t:o,nome_arquivo’.
-f, --force
Força a compactação da tabela mesmo se ela se tornar maior ou se o arquivo
temporário existir. myisampack cria um arquivo temporário chamado ‘nome_
tabela.TMD’ enquanto ele compacta a tabela. Se você matar o myisampack o
arquivo ‘.TMD’ não pode ser removido. Normalmente, myisampack sai com um
erro se ele descobrir que ‘nome_tabela.TMD’ existe. Com --force, myisampack
compacta a tabela de qualquer maneira.
-?, --help
Exibe uma mensagem de ajuda e sai.
-j nome_tabela_grande, --join=nome_tabela_grande
Une todas as tabelas nomeadas na linha de comando em uma única tabela nome_
tabela_grande. Todas tabelas que forem combinadas DEVEM ser idênticas
(mesmos nomes de colunas e tipos, alguns índices, etc.).
-p #, --packlength=#
Especifica o comprimento do tamanho de armazenamento, em bytes. O valor
deve ser 1, 2 ou 3. (myisampack armazena todas as linhas com ponteiros de
Chapter 4: Administração de Bancos de Dados MySQL 281
table description:
Key Start Len Index Type Root Blocksize Rec/key
282 Referência técnica para o MySQL versão 3.23.52
46 479 1
47 480 1
48 481 79
49 560 79
50 639 79
51 718 79
52 797 8
53 805 1
54 806 1
55 807 20
56 827 4
57 831 4
shell> ls -l station.*
-rw-rw-r-- 1 monty my 127874 Apr 17 19:00 station.MYD
-rw-rw-r-- 1 monty my 55296 Apr 17 19:04 station.MYI
-rw-rw-r-- 1 monty my 5767 Apr 17 19:00 station.frm
table description:
Key Start Len Index Type Root Blocksize Rec/key
1 2 4 unique unsigned long 10240 1024 1
2 32 30 multip. text 54272 1024 1
3 6 4 no zeros, zerofill(1) 2 9
4 10 1 3 9
5 11 20 table-lookup 4 0
6 31 1 3 9
7 32 30 no endspace, not_always 5 9
8 62 35 no endspace, not_always, no empty 6 9
9 97 35 no empty 7 9
10 132 35 no endspace, not_always, no empty 6 9
11 167 4 zerofill(1) 2 9
12 171 16 no endspace, not_always, no empty 5 9
13 187 35 no endspace, not_always, no empty 6 9
14 222 4 zerofill(1) 2 9
15 226 16 no endspace, not_always, no empty 5 9
16 242 20 no endspace, not_always 8 9
17 262 20 no endspace, no empty 8 9
18 282 20 no endspace, no empty 5 9
19 302 30 no endspace, no empty 6 9
20 332 4 always zero 2 9
21 336 4 always zero 2 9
22 340 1 3 9
23 341 8 table-lookup 9 0
24 349 8 table-lookup 10 0
25 357 8 always zero 2 9
26 365 2 2 9
27 367 2 no zeros, zerofill(1) 2 9
28 369 4 no zeros, zerofill(1) 2 9
29 373 4 table-lookup 11 0
30 377 1 3 9
31 378 2 no zeros, zerofill(1) 2 9
32 380 8 no zeros 2 9
33 388 4 always zero 2 9
34 392 4 table-lookup 12 0
35 396 4 no zeros, zerofill(1) 13 9
36 400 4 no zeros, zerofill(1) 2 9
37 404 1 2 9
38 405 4 no zeros 2 9
39 409 4 always zero 2 9
40 413 4 no zeros 2 9
41 417 4 always zero 2 9
42 421 4 no zeros 2 9
43 425 4 always zero 2 9
44 429 20 no empty 3 9
45 449 30 no empty 3 9
46 479 1 14 4
47 480 1 14 4
48 481 79 no endspace, no empty 15 9
49 560 79 no empty 2 9
50 639 79 no empty 2 9
51 718 79 no endspace 16 9
Chapter 4: Administração de Bancos de Dados MySQL 285
52 797 8 no empty 2 9
53 805 1 17 1
54 806 1 3 9
55 807 20 no empty 3 9
56 827 4 no zeros, zerofill(2) 2 9
57 831 4 no zeros, zerofill(1) 2 9
A informação exibida pelo myisampack é descrita abaixo:
normal O número de colunas para qual nenhum empacotamento extra é utilizado.
empty-space
O número de colunas contendo valores que são somente espaços; estes ocuparão
apenas 1 bit.
empty-zero
O número de colunas contendo valores que são somente 0’s binários; ocuparão
1 bit.
empty-fill
O número de colunas inteiras que não ocupam a faixa completa de bytes de
seu tipo; estes são alteradas para um tipo menor (por exemplo, uma coluna
INTEGER pode ser alterada para MEDIUMINT).
pre-space
O número de colunas decimais que são armazenadas com espaços a esquerda.
Neste caso, cada valor irá conter uma contagem para o número de espaços.
end-space
O número de colunas que tem muitos espaços espaços extras. Neste caso, cada
valor conterá uma contagem para o número de espaços sobrando.
table-lookup
A coluna tem somente um pequeno número de valores diferentes, que são con-
vertidos para um ENUM antes da compressão Huffman.
zero O número de colunas em que todos os valores estão zerados.
Original trees
O número inicial de árvores Huffman.
After join
O número de árvores Huffman distintas que sobram depois de unir árvores para
poupar espaço de cabeçalho.
Depois que uma tabela foi compactada, myisamchk -dvv exibe informações adicionais sobre
cada campo:
Type O tipo de campo deve conter as seguites descrições:
constant Todas linhas tem o mesmo valor.
no endspace
Não armazena espaços no fim.
286 Referência técnica para o MySQL versão 3.23.52
no endspace, not_always
Não armazena espaços no fim e não faz compactação de espaços
finais para todos os valores.
no endspace, no empty
Não armazena espaços no fim. Não armazena valores vazios.
table-lookup
A coluna foi convertida para um ENUM.
zerofill(n)
Os n bytes mais significativos no valor são sempre 0 e não são
armazenados.
no zeros Não armazena zeros.
always zero
Valores zero são armazenados em 1 bit.
Huff tree A árvore Huffman associada com o campo.
Bits O número de bits usado na árvore Huffman.
Depois de ter executado pack_isam/myisampack você deve executar o isamchk/myisamchk
para recriar o índice. Neste momento você pode também ordenar os blocos de índices
para criar estatísticas necessárias para o otimizador do MySQL trabalhar de maneira mais
eficiente.
myisamchk -rq --analyze --sort-index nome_tabela.MYI
isamchk -rq --analyze --sort-index nome_tabela.ISM
Depois de instalar a tabela compactada no diretório de banco de dados MySQL você deve
fazer mysqladmin flush-tables para forçar o mysqld a iniciar usando a nova tabela.
Se você desejar descompactar uma tabela compactada, você pode fazer isto com a opção
--unpack para o isamchk ou myisamchk.
myisamchk
Utilitário para descrever, verificar, otimizar e reparar tabelas MySQL. Como
o myisamchk tem várias funções, ele é descrito em seu próprio capítulo. See
hundefinedi [Administracão de Banco de Dados MySQL], page hundefinedi.
make_binary_distribution
Gera uma distribuição binária do MySQL compilado. Ela pode ser enviado por
FTP para ‘/pub/mysql/Incoming’ em support.mysql.com para a conveniência
de outros usuários MySQL.
msql2mysql
Um script shell que converte programas mSQL para MySQL. Ele não lida com
todos os casos, mas ele fornece um bom inicio para a conversão.
mysqlaccess
Um script que verifica os privilégios de acesso para uma combinação de nome
de máquina, usuário e banco de dados.
mysqladmin
Utilitário para realizar operações administrativas, tais como criação ou remoção
de bancos de dados, recarga das tabelas de permissões, descarga de tabelas em
disco e reabertura dos arquivos log. mysqladmin também pode ser usado para
exibir informações de versão, processos e estado do servidor. See hundefinedi
[mysqladmin], page hundefinedi.
Chapter 4: Administração de Bancos de Dados MySQL 289
mysqlbug O script para relatar erros no MySQL. Este script deve ser usado sempre que
for for relatar algum bug para a lista MySQL.
mysqld O daemon SQL. Deve estar sempre em execução.
mysqldump
Descarrega um banco de dados MySQL em um arquivo como instruções SQL
ou como arquivo texto separado por tabulação. Versão aprimorada do free-
ware escrito originalmente por Igor Romanenko. See hundefinedi [mysqldump],
page hundefinedi.
mysqlimport
Importa arquivos texto em suas tabelas respectivas utilizando LOAD DATA
INFILE. See hundefinedi [mysqlimport], page hundefinedi.
mysqlshow
Exibe informações sobre bancos de dados, tabelas, colunas e índices.
mysql_install_db
Cria as tabelas de permissões do MySQL com os privilégios padrões. Isto é
normalmente executado somente uma vez, quando estiver instalando o MySQL
em um sistema.
replace Um programa utilitário que é usado pelo msql2mysql, mas que também pode ser
aplicável mais genericamente. replace altera conjuntos de caracteres. Utiliza
uma máquina de estado finito para comparar strings maiores primeiro. Pode
ser usada para trocar conjuntos de caracteres. Por exemplo, este comando troca
a e b nos arquivos dados:
shell> replace a b b a -- arquivo1 arquivo2 ...
-?, --help
Exibe esta ajuda e sai.
290 Referência técnica para o MySQL versão 3.23.52
-A, --no-auto-rehash
Sem reprocessamento automático. O ’rehash’ deve ser usado se o usuário desejar
que o cliente mysql complete as tabelas e campos. Esta opção é usada para
acelerar a inicialização do cliente.
-B, --batch
Exibe resultados com o caractere de tabulação como o separador, cada registro
em uma nova linha. Não utiliza o arquivo de histórico.
--character-sets-dir=...
Diretório onde os conjuntos de caracteres estão localizados.
-C, --compress
Utiliza compactação no protocolo cliente/servidor.
-#, --debug[=...]
Log de Depuração. O padrão é ’d:t:o,/tmp/mysql.trace’.
-D, --database=...
Qual banco de dados usar. Isto geralmente é util em um arquivo my.cnf.
--default-character-set=...
Configura o conjunto de caracters padrão.
-e, --execute=...
Executa o comando e sai. (Saída parecida com --batch)
-E, --vertical
Exibe a saída de uma consulta (linhas) verticalmente. Sem esta opção você
também pode forçar esta saída terminando suas instruções com \G.
-f, --force
Continue mesmo se for obtido um erro SQL.
-g, --no-named-commands
Comandos nomeados serão desabilitados. Utilize somente a forma \*, ou use
comandos nomeados apenas no começo da linha terminada com um ponto-e-
vírgula (;). Desde a versão 10.9, o cliente agora inicia com esta opção habilitada
por padrão! Com a opção -g, entretando, comandos de formato longo contin-
uarão funcionando na primeira linha.
-G, --enable-named-commands
Comandos nomeados são habilitados. Comandos de formato longo são aceitos
assim como os comandos reduzidos \*.
-i, --ignore-space
Ignore caractere de espaço depois de nomes de funções.
-h, --host=...
Conectar à máquina especificada.
-H, --html
Produza saída HTML.
Chapter 4: Administração de Bancos de Dados MySQL 291
-L, --skip-line-numbers
Não escreva número da linha para os erros. Útil quando se deseja comparar
arquivos com resultados que incluem mensagens de erro.
--no-pager
Desabilita paginação e impressão na saída padrão. Veja também a ajuda inter-
ativa (\h).
--no-tee Desabilita arquivo de saída. Veja também a ajuda interativa (\h).
-n, --unbuffered
Descarrega e atualiza o buffer depois de cada pesquisa.
-N, --skip-column-names
Não escrever nomes de colunas nos resultados.
-O, --set-variable var=option
Fornece um valor a uma variável. --help lista as variáveis.
-o, --one-database
Atualiza somente o banco de dados padrão. Isto é útil para evitar atualização
em outros bancos de dados no log de atualizações.
--pager[=...]
Tipo de saída. O padrão é sua variável de ambiente PAGER. Paginadores válidos
são: less, more, cat [>nome arquivo], etc. Veja também a ajuda interativa (\h).
Esta opção não funciona no modo batch. A opção pager funciona somente no
UNIX.
-p[password], --password[=...]
Senha a ser usada ao conectar ao servidor. Se uma senha não é fornecida
na linha de comando, lhe será solicitado uma. Perceba que se você utilizar o
formato curto -p você não pode ter um espaço entre a opção e a senha.
-P --port=...
Número da porta TCP/IP para usar na conexão.
-q, --quick
Não faz cache do resultado, imprime linha a linha. Isto pode deixar o servidor
mais lento se a saída for suspendida. Não usa arquivo de histórico.
-r, --raw Exibe valores de colunas sem conversão de escapes. Utilizado com --batch
-s, --silent
Opção para ser mais silencioso.
-S --socket=...
Arquivo socket para ser utilizado na conexão.
-t --table
Saída no formato de tabela. Isto é padrão no modo não-batch.
-T, --debug-info
Exibe alguma informação de depuração na saída.
292 Referência técnica para o MySQL versão 3.23.52
--tee=...
Anexa tudo no arquivo de saída. Veja também a ajuda interativa (\h). Não
funciona no modo batch.
-u, --user=#
Usuário para login diferente do usuário atual do sistema.
-U, --safe-updates[=#], --i-am-a-dummy[=#]
Permite somente que UPDATE e DELETE utilizem chaves. Veja abaixo para
maiores informações sobre esta opção. Você pode zerar esta opção se possui-la
no arquivo my.cnf utilizando --safe-updates=0.
-v, --verbose
Modo verbose (-v -v -v fornece o formato de saída da tabela).
-V, --version
Gera saída com informação de versão e sai.
-w, --wait
Espera e repete em vez de sair se a conexão estiver inacessível.
Você também pode configurar as seguntes variáveis com -O ou --set-variable:
Nome variável Padrão Descrição
connect timeout 0 Número de seguntos antes de esgotar o
tempo da conexão
max allowed packet 16777216 Tamanho máximo do pacote para en-
viar/receber do servidor
net buffer length 16384 Tamanho do buffer para comunicação
TCP/IP e socket
select limit 1000 Limite automático para SELECT quando
utilizar --i-am-a-dummy
max join size 1000000 Limite automático para registros em uma
join quando utilizar --i-am-a-dummy.
Se você digitar ’help’ na linha de comando, mysql irá exibir os comandos que ele suporta:
mysql> help
MySQL commands:
help (\h) Display this text.
? (\h) Synonym for ‘help’.
clear (\c) Clear command.
connect (\r) Reconnect to the server. Optional arguments are db and host.
edit (\e) Edit command with $EDITOR.
ego (\G) Send command to mysql server, display result vertically.
exit (\q) Exit mysql. Same as quit.
go (\g) Send command to mysql server.
nopager (\n) Disable pager, print to stdout.
notee (\t) Don’t write into outfile.
pager (\P) Set PAGER [to_pager]. Print the query results via PAGER.
print (\p) Print current command.
quit (\q) Quit mysql.
rehash (\#) Rebuild completion hash.
Chapter 4: Administração de Bancos de Dados MySQL 293
source (\.) Execute a SQL script file. Takes a file name as an argument.
status (\s) Get status information from the server.
tee (\T) Set outfile [to_outfile]. Append everything into given outfile.
use (\u) Use another database. Takes database name as argument.
Das opções acima, o pager é o único que só funciona no UNIX.
O comando status lhe fornece algumas informações sobre a conexão e o servidor que está
utilizando. Se você estiver executando no modo --safe-updates, status irá também
imprimir os valores para as variáveis mysql que afetam suas consultas.
Uma opção útil para iniciantes (introduzido no MySQL versão 3.23.11) é o --safe-updates
(ou --i-am-a-dummy para usuários que alguma vez executaram um DELETE FROM nome_
tabela mas esqueceram da cláusula WHERE). Quando utilizar esta opção, o mysql envia o
seguinte comando ao servidor MySQL quando abrir a conexão.
SET SQL_SAFE_UPDATES=1,SQL_SELECT_LIMIT=#select_limit#,
SQL_MAX_JOIN_SIZE=#max_join_size#"
onde #select_limit# e #max_join size# são variáveis que podem ser configuradas da
linha de comando mysql. See hundefinedi [SET OPTION], page hundefinedi.
O efeito da opção acima é:
• Você não tem permissão de utilizar uma instrução UPDATE ou DELETE se você não possuir
uma chave na parte WHERE. Pode-se, entretanto, forçar um UPDATE/DELETE utilizando
LIMIT:
UPDATE nome_tabela SET campo_nao_chave=# WHERE campo_nao_chave=# LIMIT 1;
• Todos resultados maiores são limitados automaticamente a #select_limit# linhas.
• SELECT’s que provavelmente precisarão examinar mais que #max_join_size
combinaçoes de linhas serão abortadas.
Algumas dicas úteis sobre o cliente mysql:
Alguns dados são muito mais legíveis quando exibido verticalmente, em vez da saída do
tipo caixa horizontal comum. Por exemplo: Textos longos, que incluem várias linhas, são
muito mais fáceis de serem lidos com saída vertical.
mysql> select * from mails where length(txt) < 300 limit 300,1\G
*************************** 1. row ***************************
msg_nro: 3068
date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Monty
reply: [email protected]
mail_to: "Thimble Smith" <[email protected]>
sbj: UTF-8
txt: >>>>> "Thimble" == Thimble Smith writes:
Thimble> Hi. I think this is a good idea. Is anyone familiar with UTF-
8
Thimble> or Unicode? Otherwise I’ll put this on my TODO list and see what
Thimble> happens.
Regards,
Monty
file: inbox-jani-1
hash: 190402944
1 row in set (0.09 sec)
• Para o log, você pode utilizar a opção tee. O tee pode ser iniciado com a opção --
tee=..., ou pela linha de comando de maneira interativa com o comando tee. Todos
os dados exibidos na tela serão anexados no arquivo fornecido. Isto também pode ser
muito útil para propósitos de depuração. O tee pode ser desabilitado da linha de
comando com o comando notee. Executando tee novamente o log é reiniciado. Sem
um parâmetro o arquivo anterior será usado. Perceba que tee irá atualizar os resultados
dentro do arquivo depois de cada comando, pouco antes da linha de comando reaparecer
esperando pelo próximo comando.
• Navegar ou pesquisar os resultados no modo interativo em algum programa do UNIX
como o less, more ou outro similar, é agora possível com a opção --pager[=...]. Sem
argumento, o cliente mysql irá procurar pela variável de ambiente PAGER e configurar
pager para este valor. pager pode ser iniciado a partir da linha de comando interativa
com o comando pager e desabilitado com o comando nopager. O comando recebe um
argumento opcional e e o pager será configurado com ele. O comando pager pode ser
chamado com um argumento, mas isto requer que a opção --pager seja usada, ou o
pager será usado com a saída padrão. pager funciona somente no UNIX, uma vez
que é utilizado a função popen(), que não existe no Windows. No Windows a opção
tee pode ser utilizada, entretanto ela pode não ser cômoda como pager pode ser em
algumas situações.
• Poucas dicas sobre pager: Você pode usá-lo para gravar em um arquivo:
mysql> pager cat > /tmp/log.txt
e os resultados irão somente para um arquivo. Você também pode passar qualquer
opções para os programas que você deseja utilizar com pager:
mysql> pager less -n -i -S
Note a opção ’-S’ exibida acima. Você pode achá-la muito útil quando navegar pelos
resultados; experimente com a opção com saída a horizontal (finalize os comandos com
’\g’, ou ’;’) e com saída vertical (final dos comandos com ’\G’). Algumas vezes um
resultado com um conjunto muito largo é difícil ser lido na tela, com a opção -S para
less, você pode navegar nos resultados com o less interativo da esquerda para a direita,
evitando que linhas maiores que sua tela continuem na próxima linha. Isto pode tornar
o conjunto do resultado muito mais legível. você pode alterar o modo entre ligado e
desligado com o less interativo com ’-S’. Veja o ’h’(help) para mais ajuda sobre o less.
• Por último (a menos que você já entendeu este assunto com os exemplos acima ;) você
pode combinar maneiras muito complexas para lidar com os resultados, por exemplo,
o seguinte enviaria os resultados para dois arquivos em dois diferentes diretórios, em
dois discos diferentes montados em /dr1 e /dr2, e ainda exibe o resultado na tela via
less:
mysql> pager cat | tee /dr1/tmp/res.txt | tee /dr2/tmp/res2.txt | less -
n -i -S
Chapter 4: Administração de Bancos de Dados MySQL 295
• Você também pode combinar as duas funções acima; tenha o tee habilitado, o pager
configurado para ’less’ e você estará apto a navegar nos resultados no less do unix e
ainda ter tudo anexado em um arquivo ao mesmo tempo. A diferença entre UNIX tee
usado com o pager e o tee embutido no cliente mysql é que o tee embutido funciona
mesmo se você não tiver o comando UNIX tee disponível. O tee embutido também loga
tudo que é exibido na tela, e o UNIX tee usado com pager não loga completamente.
Por último o tee interativo é mais cômodo para trocar entre os modos on e off, quando
você desejar logar alguma coisa em um arquivo, mas deseja estar apto para desligar o
recurso quando necessário.
slave-start
Inicia thread de replicação no slave.
slave-stop
Termina a thread de replicação no slave.
status Fornece uma mensagem curta sobre o estado do servidor.
variables
Exibe variáveis disponíveis.
version Obtêm informação de versão do servidor.
Todos comandos podem ser reduzidos para seu prefixo único. Por exemplo:
shell> mysqladmin proc stat
+----+-------+-----------+----+-------------+------+-------+------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-------+-----------+----+-------------+------+-------+------+
| 6 | monty | localhost | | Processlist | 0 | | |
+----+-------+-----------+----+-------------+------+-------+------+
Uptime: 10077 Threads: 1 Questions: 9 Slow queries: 0 Opens: 6 Flush tables: 1
O resultado do comando mysqladmin status possui as seguintes colunas:
Uptime Número de segundos que o servidor MySQL está funcionando.
--compress
Utilize compressão no protocolo server/cliente.
-?, --help
Exibe esta mensagem de ajuda e sai.
-B, --databases
Para verificar diversos bancos de dados. Perceba a diferença no uso; Neste caso
nenhuma tabela será fornecida. Todos os argumentos são tratados como nomes
de bancos de dados.
--default-character-set=...
Configura o conjunto de caracteres padrão.
-F, --fast
Verifica somente as tabelas que não foram fechadas corretamente
-f, --force
Continue mesmo se nós obtermos um erro de sql.
-e, --extended
Se você estiver utilizando esta opção com CHECK TABLE, irá garantir que a
tabela está 100 por cento consistente, mas leva bastante tempo.
Se você utilizar esta opção com REPAIR TABLE, ele irá executar um comando
de reparos na tabela, que não só irá demorar muito tempo para executar, mas
também pode produzir muitas linhas de lixo.
-h, --host=...
Conecta à máquina.
-m, --medium-check
Mais rápido que verificação extendida, mas encontra somente 99.99 de todos os
erros. Deve resolver a maioria dos casos.
-o, --optimize
Otimizador de tabelas
-p, --password[=...]
Senha para usar ao conectar ao servidor. Se a senha não for fornecida será
solicitada no terminal.
-P, --port=...
Número de porta para usar para conexão.
-q, --quick
Se esta opção for utilizada com CHECK TABLE, evita a busca de registros
verificando links errados. Esta é a conferência mais rápida.
Se você estiver utilizando esta opção com REPAIR TABLE, ela tentará reparar
somente a árvore de índices. Este é o método de reparo mais rápido para uma
tabela.
-r, --repair
Pode corrigir quase tudo exceto chaves únicas que não são únicas.
Chapter 4: Administração de Bancos de Dados MySQL 299
-s, --silent
Exibe somente mensagens de erro.
-S, --socket=...
Arquivo socket para usar na conexão.
--tables Sobrepõe a opção --databases (-B).
-u, --user=#
Usuário para o login, se não for o usuário atual.
-v, --verbose
Exibe informação sobre os vários estágios.
-V, --version
Exibe informação sobre a versão e sai.
--allow-keywords
Permite criação de nomes que colunas que são palavras chaves. Isto funciona
utilizando o nome da tabela como prefixo em cada nome de coluna.
-c, --complete-insert
Utilize instruções de insert completas (com nomes de colunas).
-C, --compress
Compacta todas as informações entre o cliente e o servidor se ambos suportarem
a compactação.
-B, --databases
Para descarregar diversos bancos de dados. Perceba a diferença no uso. Neste
caso nenhuma tabela é fornecida. Todos argumentos são estimados como nomes
de bancos de dados. USE nome_bd; será incluído na saída antes de cada banco
de dados novo.
--delayed
Insere registros com o comando INSERT DELAYED.
-e, --extended-insert
Utiliza a nova sintaxe multilinhas INSERT. (Fornece instruções de inserção mais
compactas e mais rápidas.)
-#, --debug[=option_string]
Rastreia a utilização do programa (para depuração).
--help Exibe uma mensagem de ajuda e sai.
--fields-terminated-by=...
--fields-enclosed-by=...
--fields-optionally-enclosed-by=...
--fields-escaped-by=...
--lines-terminated-by=...
Estas opções são usadas com a opção -T e tem o mesmo significado que as
cláusulas correspondentes em LOAD DATA INFILE See hundefinedi [LOAD DATA],
page hundefinedi.
-F, --flush-logs
Atualiza o arquivo de log no servidor MySQL antes de iniciar a descarga.
-f, --force,
Continue mesmo se obter um erro de SQL durantes uma descarga de tabela.
-h, --host=..
Descarrega dados do servidor MySQL na máquina especificada. A máquina
padrão é localhost.
-l, --lock-tables.
Bloqueia todas as tabelas antes de iniciar a descarga. As tabelas são bloqueadas
com READ LOCAL para permitir inserções concorrentes no caso de tabelas MyISAM.
-n, --no-create-db
’CREATE DATABASE /*!32312 IF NOT EXISTS*/ nome bd;’ não será colo-
cado na saída. A linha acima será adicionada se a opção --databases ou --all-
databases for fornecida.
Chapter 4: Administração de Bancos de Dados MySQL 301
-t, --no-create-info
Não grava informações de criação de tabelas (A instrução CREATE TABLE.)
-d, --no-data
Não grava nenhuma informação de registros para a tabela. Isto é muito útil se
você desejar apenas um dump da estrutura da tabela!
--opt O mesmo que --quick --add-drop-table --add-locks --extended-insert
--lock-tables. Fornece a descarga mais rápida para leitura em um servidor
MySQL.
-pyour_pass, --password[=sua_senha]
A senha para usar quando conectando ao servidor. Se não for especificado a
parte ‘=sua_senha’, o mysqldump irá perguntar por uma senha.
-P port_num, --port=porta_num
O número da porta TCP/IP usado para conectar a uma máquina. (Isto é usado
para conexões a máquinas diferentes de localhost, na qual sockets Unix são
utilizados.)
-q, --quick
Não utiliza buffers para as consultas, descarrega diretamente para saída padrão.
Utilize mysql_use_result() para fazer isto.
-r, --result-file=...
Direcione a saída para um determinado arquivo. Esta opção deve ser usada no
MSDOS porque previne a conversão de nova linha ’\n’ para ’\n\r’ (nova linha
+ retorno de carro).
-S /path/to/socket, --socket=/caminho/para/arquivo_socket
O arquivo socket que será utilizado quando conectar à localhost (que é a
máquina padrão).
--tables Sobrepõe a opção --databases (-B).
-T, --tab=path-to-some-directory
Cria um arquivo nome_tabela.sql, que contém os comandos SQL CREATE
e um arquivo nome_tabela.txt, que contém os dados, para cada tabela dada.
NOTA: Isto só funcionará se mysqldump for executado na mesma máquina do
daemon mysqld. O formato do arquivo .txt é feito de acordo com as opções
--fields-xxx e --lines--xxx.
-u user_name, --user=user_name
O nome do usuário do MySQL para usar ao conectar ao servidor. O valor
padrão é seu nome de usuário no Unix.
-O var=option, --set-variable var=option
Confirgura o valor de uma variável. As variáveis possíveis são listadas abaixo.
-v, --verbose
Modo verbose. Exibe mais informações sobre o que o programa realiza.
-V, --version
Exibe informações de versão e sai.
302 Referência técnica para o MySQL versão 3.23.52
-w, --where=’where-condition’
Descarrega somente registros selecionados. Perceba que as aspas são obri-
gatórias:
"--where=user=’jimf’" "-wuserid>1" "-wuserid<1"
-O net_buffer_length=#, where # < 16M
Quando estiver criando instruções de inserções em múltiplas linhas (com a opção
--extended-insert ou --opt), mysqldump irá criar linhas até o tamanho de
net_buffer_length. Se você aumentar esta variável, você também deve se
assegurar que a variável max_allowed_packet no servidor MySQL é maior que
a net_buffer_length.
O uso mais comum do mysqldump é provavelmente para fazer backups de bancos de dados
inteiros. See hundefinedi [Backup], page hundefinedi.
mysqldump --opt banco_dados > arquivo-backup.sql
Você pode ler de volta no MySQL com:
mysql banco_dados < arquivo-backup.sql
ou
mysql -e "source /patch-to-backup/backup-file.sql" banco_de_dados
Entretanto, é muito útil também popular outro servidor MySQL com informações de um
banco de dados:
mysqldump --opt banco_dados | mysql ---host=máquina-remota -C banco_dados
É possível descarregar vários bancos de dados com um comando:
mysqldump --databases banco_dados1 [banco_dados2 banco_dados3...] > meus_
bancosdedados.sql
Se desejar descarregar todos os bancos de dados, pode-se utilizar:
mysqldump --all-databases > todos_bancos_dados.sql
mysqlhotcopy nome_bd./regex/
mysqlhotcopy suporta as seguintes opções:
-?, --help
Exibe uma tela de ajuda e sai
-u, --user=#
Usuário para fazer login no banco de dados
Chapter 4: Administração de Bancos de Dados MySQL 303
-p, --password=#
Senha para usar ao conectar ao servidor
-P, --port=#
Porta para usar ao conectar ao servidor local
-S, --socket=#
Qual socket usar ao conectando a um servidor local
--allowold
Não aborta se o alvo já existir (renomeie-o para old)
--keepold
Não apaga alvos anteriores (agora renomeados) quando pronto
--noindices
Não inclui arquivos de índices na cópia para deixar o backup menor e mais
rápido. Os índices podem ser recostruídos mais tarde com myisamchk -rq..
--method=#
Metódo para copiar (cp ou scp).
-q, --quiet
Seja silencioso exceto em erros
-n, --dryrun
Relata ações sem realizá-las
--regexp=#
Copia todos bancos de dados com nomes que coincidem com a expressão regular
--suffix=#
Sufixo para nomes de bancos de dados copiados
--checkpoint=#
Insere entrada de ponto de controle um uma bd.tabela especificada
--flushlog
Atualiza logs uma vez que todas as tabelas estiverem bloqueadas.
--tmpdir=#
Diretório Temporário (em vez de /tmp).
Você pode utilizar perldoc mysqlhotcopy para obter uma documentação mais completa
de mysqlhotcopy.
mysqlhotcopy lê os grupos [client] e [mysqlhotcopy] dos arquivos de opções.
Para poder executar mysqlhotcopy é necessário acesso de escrita ao diretório de backup,
privilégio SELECT nas tabelas que desejar copiar e o privilégio Reload no MySQL (para
poder executar FLUSH TABLES).
304 Referência técnica para o MySQL versão 3.23.52
-l, --lock-tables
Bloqueia TODAS as tabelas para escrita antes de processar qualquer arquivo
texto. Isto garante que todas as tabelas são sincronizadas no servidor.
-L, --local
Lê arquivos de entrada do cliente. Por padrão, é assumido que os arquivos texto
estão no servidor se você conectar à localhost (máquina padrão).
-pyour_pass, --password[=sua_senha]
Senha para conectar ao servidor. Se você não especificar a parte ‘=sua_senha’,
o mysqlimport irá pedir por uma senha.
-P port_num, --port=port_num
O número da porta TCP/IP para usar quando conectar a uma máquina. (isto
é usado para conexões a máquinas diferentes de localhost, onde são utilizados
sockets Unix).
-r, --replace
As opções --replace e --ignore controlam o tratamento de registros de en-
trada que duplicam registros existentes em valores de chaves únicas. Se você es-
pecificar --replace, novos registros substituirão registros que tiverem o mesmo
valor na chave unica. Se você especificar --ignore, registros de entrada que
duplicariam um registro existente em um valor de chave única são saltados. Se
você não especificar nenhuma das duas opções, um erro ocorrerá quando um
valor de chave duplicado for encontrado e o resto do arquivo texto será ignorado.
-s, --silent
Modo silencioso. Gera saída somente quando ocorrer algum erro.
-S /path/to/socket, --socket=/path/to/socket
O arquivo socket para usar ao conectar à localhost (máquina padrão).
-u user_name, --user=user_name
O nome de usuário MySQL para usar ao conectar ao servidor. O valor padrão
é seu nome de usuário atual no Unix.
-v, --verbose
Modo verbose. Gera mais informações na saída.
-V, --version
Exibe informação sobre a versão e sai.
Abaixo um exemblo da utilização de mysqlimport:
$ mysql --version
mysql Ver 9.33 Distrib 3.22.25, for pc-linux-gnu (i686)
$ uname -a
Linux xxx.com 2.2.5-15 #1 Mon Apr 19 22:21:09 EDT 1999 i586 unknown
$ mysql -e ’CREATE TABLE imptest(id INT, n VARCHAR(30))’ test
$ ed
a
100 Max Sydow
101 Count Dracula
.
306 Referência técnica para o MySQL versão 3.23.52
w imptest.txt
32
q
$ od -c imptest.txt
0000000 1 0 0 \t M a x S y d o w \n 1 0
0000020 1 \t C o u n t D r a c u l a \n
0000040
$ mysqlimport --local test imptest.txt
test.imptest: Records: 2 Deleted: 0 Skipped: 0 Warnings: 0
$ mysql -e ’SELECT * FROM imptest’ test
+------+---------------+
| id | n |
+------+---------------+
| 100 | Max Sydow |
| 101 | Count Dracula |
+------+---------------+
Por exemplo:
Chapter 4: Administração de Bancos de Dados MySQL 307
shell> perror 64 79
Error code 64: Machine is not on the network
Error code 79: Can not access a needed shared library
perror pode ser usado para exibir uma descrição de um código de erro do sistema, ou um
código de erro do manipulador de tabelas MyISAM/ISAM. As mensagens de erro são na
maioria dependentes do sistema.
Ele contém informações indicando quando o mysqld foi iniciado e parado e também os
erros críticos encontrados durante a execução. Se o mysqld finalizar inexperadamente e o
safe_mysqld precisar reiniciar o mysqld, o safe_mysqld irá escrever uma linha restarted
mysqld neste arquivo. Este log também armazena alertas de tabelas que necessitam ser
verificadas automaticamente ou reparadas.
Em alguns sistemas operacionais, o log de erro irá conter registros de pilha de onde o mysqld
finalizou. Isto pode ser usado para saber onde e como o mysqld morreu. See hundefinedi
[Utilizando registros de pilha], page hundefinedi.
O log de atualização é inteligente pois registra somente instruções que realmente alteram
dados. Portanto, um UPDATE ou um DELETE com uma cláusula WHERE que não encontre
nenhum registro não é escrito no log. Ele salta até instruções UPDATE que atribui a uma
coluna o mesmo valor que ela possuia.
O registro da atualização é feito imediatamente após uma consulta estar completa mas antes
que as bloqueios sejam liberados ou que algum commit seja feito. Isto garante que o log
seja escrito na ordem de execução.
Se você desejar atualizar um banco de dados a partir de arquivos de logs de atualização,
você pode fazer o seguinte (assumindo que seus logs de atualização estejam nomeados na
forma ‘nome_arquivo.###’):
shell> ls -1 -t -r nome_arquivo.[0-9]* | xargs cat | mysql
ls é utilizado para obter todos os arquivos de log na ordem correta.
Isto pode ser útil se você tiver que recorrer a arquivos de backup depois de uma falha e
desejar refazer as atualizações que ocorreram entre a hora do backup e a falha.
Para saber quais arquivos binários foram usados, o mysqld irá criar também um arquivo
de índice para o log binário que contém o nome de todos os arquivos de log binário usados.
Por padrão este arquivo tem o mesmo nome que o arquivo de log binário, com a extensão
’.index’. Você pode alterar o nome do arquivo de índice do log binário com a opção
--log-bin-index=[nome_arquivo].
Se estiver sendo usado replicação, os arquivos de log binário antigos não devem ser apagados
até ter certeza que nenhum escravo irá mais precisar deles. Uma forma de fazer isto é o
utilizar mysqladmin flush-logs uma vez por dia e então remover qualquer log com mais
de 3 dias.
Você pode examinar o arquivo de log binário com o comando mysqlbinlog. Por exemplo,
você pode atualizar um servidor MySQL a partir de um log binário como mostrado a seguir:
mysqlbinlog arquivo-log | mysql -h nome_servidor
Você também pode utilizar o programa mysqlbinlog para ler o log binário diretamente de
um servidor MySQL remoto !
mysqlbinlog --help irá lhe fornecer mais informações de como usar este programa!
Se você estiver utilizando BEGIN [WORK] ou SET AUTOCOMMIT=0, você deve utilizar o log
binário do MySQL para backups no lugar do antigo log de atualização.
O Log binário é feito imedatamente depois que uma consulta terminar mas antes que os
bloqueios sejam liberados ou algum commit seja feito. Isto garante que o log seja feito na
ordem de execução.
Todas atualizações (UPDATE, DELETE ou INSERT) que alteram uma tabela transacional (como
tabelas BDB) são armazenadas no cache até um COMMIT. Quaisquer atualizações a uma
tabela não transacional são armazenadas no log binário de uma vez. Todas as threads
irão, no início, alocar um buffer de binlog_cache_size para registrar consultas. Se uma
conaulta é maior que o registro, a thread irá criar um arquivo temporário para lidar com a
mesma. O arquivo temporário será apagado quando a thread terminar.
O max_binlog_cache_size pode ser usado para restringir o tamanho total usado para
armazenar uma consulta multi-transacional.
Se você estiver utilizando o log de atualização ou o binário, inserções concorrentes não
funcionarão juntas com CREATE ... INSERT e INSERT ... SELECT. Isto é para garantir que
você possa recriar uma cópia exata de suas tabelas aplicando o log em um backup.
O log para queries lentas pode ser usado para encontrar queries que levam muito tempo
para executar e que devem ser candidatas a otimização. Com um log muito grande, isto
pode ser uma tarefa difícil. Você pode utilizar o log de consultas lentas através do comando
mysqldumpslow para obter um resumo das consultas que aparecem no log.
Se a opção --log-long-format estiver sendo usada, então as consultas que não estiverem
utilizando índices serão escritas. See line options-snt [Opções de linha de comando], page
line options-pg.
4.10.1 Introdução
Um motivo de se usar replicação é para ganhar robustez e velocidade. No caso de robustez
você pode ter dois sistemas e pode fazer um troca para o backup se tiver problemas com o
mestre. A velocidade extra é alcançada enviando uma parte de consultas que não sejam de
atualização para o servidor de replicação. É claro que isto funciona somente se consultas
que não fazem atualizações forem em maior número, o que é o caso normal.
A partir da versão 3.23.15, o MySQL suporta replicação de uma via internamente. Um
servidor atua como o mestre, enquando o outro atua como escravo. Note que um servidor
pode exercer a função do mestre em um momento e de escravo em outro. O servidor mestre
mantêm um log binário de atualizações (See hundefinedi [Log binário], page hundefinedi.)
e um arquivo índice para logs binários para manter os registro da rotatividade dos logs. O
escravo, na conexão, informa ao mestre onde parou desde a última atualização propagada
com sucesso, realiza a atualização e então para e espera o mestre informar sobre novas
atualizações.
Note que se você estiver replicando um banco de dados, todas atualizações neste banco de
dados deve ser feito através do mestre !
Outro benefício de utilizar replicação é que pode-se obter backups intantâneos do sis-
tema fazendo backups no escravo em vez de fazê-los no mestre. See hundefinedi [Backup],
page hundefinedi.
server-id deve ser diferente para cada servidor participante da replicação. Se você
não especificar um server-id, ele será configurado para 1 se você não definiu master-
host, senão ele será configurado para 2. Perceba que no caso da omissão de server-id
o mestre irá recusar conexões de todos os escravos, e o escravo recusará a conexão a
um mestre. Assim, omitindo server-id é bom somente para um backup com um log
binário.
8. Coloque os dados copiados anteriormente no seu diretório de dados no(s) escravo(s).
Tenha certeza que os privilégios nos arquivos e diretórios estão corretos. O usuário que
executa o MySQL deve estar apto para ler e escrever nos bancos de dados, da mesma
forma que no mestre.
9. Restart the slave(s).
Depois de completados os procedimentos acima, o(s) escravo(s) devem se conectar ao mestre
e pegar todas as atualizações que ocorreram desde que o backup foi restaurado.
Se você esqueceu de configurar o server-id no escravo você irá obter o seguinte erro no
arquivo de log:
Warning: one should set server_id to a non-0 value if master_host is set.
The server will not act as a slave.
Se você esqueceu fazer isto no mestre, os escravos não vão conseguir se conectar ao mestre.
Se um escravo não está apto para replicar por alguma razão, você encontrará a mensagem
de erro no arquivo de log de erros no escravo.
Uma vez que um escravo está replicando, você encontrará um arquivo chamado master.info
no mesmo diretório do seu log de erros. O arquivo master.info é usado pelo escravo para
manter o registro de quanto foi processado do log binário do mestre. Não remova ou edite
o arquivo, a menos que você realmente saiba o que está fazendo. Mesmo neste caso, é mais
aconselhável usar o comando CHANGE MASTER TO.
• Comandos FLUSH não são armazenados no log binário e por isso, não são replicadas para
os escravos. Normalmente isto não é um problema já que FLUSH não altera nada. Entre-
tanto, isto significa que se você atualizar as tabelas de privilégios do MySQL diretamente
sem usar a instrução GRANT e replicar o banco de dados de privilégios do MySQL, você
deve fazer um FLUSH PRIVILEGES nos escravos para fazer com que os novos privilégios
tenham efeito.
• A partir da versão 3.23.29 tabelas temporárias são replicadas corretamente com a ex-
cessão do caso no qual o servidor escravo é desligado (não apenas a thread escrava da
replicação), e algumas tabelas temporárias estão abertas e são usadas nas atualizações
subsequentes. Para lidar com este problema, iantes de desligar o escravo, execute SLAVE
STOP e então verifique a variável Slave_open_temp_tables para ver se ela é 0, então
execute mysqladmin shutdown. Se o número não for 0, reinicie a thred escrava com
SLAVE START e veja se você terá mais sorte na próxima vez. Existirá uma solução
melhor, mas teremos que esperá-la até a versão 4.0. Em versões anteriores, tabelas
temporárias não eram replicadas corretamente - nós recomendamos que você atualize
sua versão ou execute SET SQL_LOG_BIN=0 nos seus clientes antes de todas as consultas
com tabelas temporárias.
• O MySQL suporta somente um mestre e vários escravos. Na versão 4.x adicionaremos
um algorítimo de votação para trocar automaticamente o mestre se alguma coisa estiver
errada com o mestre atual. Iremos também introduzir processos agentes para ajudar
a fazer o balanceamento de carga enviando consultas com SELECTS para diferentes
escravos.
• A partir da versão 3.23.26 é seguro conectar servidores em um relacionamento circular
com log-slave-updates habilitado. Perceba, entretanto, que várias queries não irão
funcionar corretamente neste tipo de configuração a menos que o código do cliente seja
escrito para tomar cuidado dos potenciais problemas que podem ocorrer em diferentes
sequências em servidores diferentes.
Isto significa que você pode fazer uma configuração parecida com o seguinte:
A -> B -> C -> A
Esta configuração funcionará se você fizer somente atualizações não conflitantes entre
as tabelas. Em outras palavras, se você inserir dados em A e C, você nunca poderá
inserir uma linha em A que pode ter uma chave conflitante com uma linha inserida em
C. Você também não deve atualizar as mesmas linhas em dois servidores se a ordem
em que as atualizações são aplicadas importar.
Note que o formato de log foi alterado na Versão 3.23.26 portanto escravos anteriores
a versão 3.23.26 não conseguirão ler estes logs.
• Se houver um erro em uma consulta no escravo, a thread escrava irá terminar e uma
mensagem irá aparecer no arquivo .err. Você deve então conectar a um escravo man-
ualmente, corrigir a causa do erro (por exemplo, tabela não existente), e então executar
o comando sql SLAVE START (disponível a partir da versão 3.23.16). Na versão 3.23.15,
será necessário reiniciar o servidor.
• Se a conexão para o mestre for perdida, o escravo irá tentar conectar de novo imedi-
atamente e no caso de falhas, a cada master-connect-retry (padrão 60) segundos.
Por causa disto, é seguro desligar o mestre, e então reiniciá-lo depois de um tempo. O
escravo também está apto para lidar com interrupções de rede.
316 Referência técnica para o MySQL versão 3.23.52
• Desligar o escravo (corretamente) também é seguro, pois mantém sinais de onde parou.
Desligamentos incorretos podem produzir problemas, especialmente se o cache de disco
não foi sincronizado antes do sistema morrer. Seu sistema de tolerância a falhas será
melhorado se você possuir um bom No-Break ou UPS.
• Se o mestre está escutando em uma porta não padrão, você também deve especificá-la
com o parâmetro master-port no my.cnf.
• Na versão 3.23.15, todas as tabelas e bancos de dados serão replicados. A partir da
versão 3.23.16, você pode restringir a replicação para um conjunto de bancos de dados
com diretivas replicate-do-db no my.cnf ou apenas excluir um conjunto de bancos
de dados com replicate-ignore-db. Até a versão 3.23.23, existia um bug que não
lidava corretamente com LOAD DATA INFILE se você fizesse isto em um banco de dados
que foi excluido da replicação.
• A partir da Versão 3.23.16, SET SQL_LOG_BIN = 0 irá desligar a replicação (binárias)
no mestre e SET SQL_LOG_BIN=1 irá ligá-la novamente - você deve possuir o privilégio
process para fazer isto.
• A partir da versão 3.23.19, você pode limpar vestígios de replicações anteriores quando
algo estiver errada acontecer e você deseja iniciar corretamnete com os comandos FLUSH
MASTER e FLUSH SLAVE. Na versão 3.23.26 nós os renomeamos respectiviamente para
RESET MASTER e RESET SLAVE para deixar claro o que eles fazem. As variantes antigas
FLUSH ainda funcionam, para manter compatibilidade.
• A partir da versão 3.23.21, você pode utilizar LOAD TABLE FROM MASTER para backup
de rede e configurar inicialmente a replicação. Recentemente, recebemos vários relatos
de bugs relacionados e estamos investigando, portanto nós recomendamos que você o
utilize somente para testes até que se torne mais estável.
• A partir da versão 3.23.23, você pode alterar os mestres e ajustar a posição do log com
CHANGE MASTER TO.
• A partir da versão 3.23.23, você pode dizer ao mestre que atualizações em determinados
bancos de dados não devem ser registradas no log binário com binlog-ignore-db.
• A partir da versão 3.23.26, você pode utilizar replicate-rewrite-db para dizer ao
escravo para fazer atualizações de um banco de dados no mestre para outro com um
nome diferente no escravo.
• A partir da versão 3.23.28, você pode utilizar PURGE MASTER LOGS TO ’log-name’ para
se livrar de logs antigos enquanto o escravo estiver funcionando.
Opção Descrição
log-bin=nome_arquivo Grava em um log binário de atualizações em uma lo-
calização específica. Perceba que se você fornecer
um parâmetro com uma extensão (por exemplo, log-
bin=/mysql/logs/replication.log ) as versões até 3.23.24
não irão funcionar direito durante a replicação se você fizer
FLUSH LOGS. O problema é corrigido na versão 3.23.25. Se
você estiver utilizando este tipo de nome de log, FLUSH LOGS
será ignorado no log binário. Para limpar o log, execute FLUSH
MASTER, e não se esqueça de executar FLUSH SLAVE em todos
os escravos. Na versão 3.23.26 e em versões posteriores você
deve utilizar RESET MASTER e RESET SLAVE
log-bin-index=filename Como o usuário pode disparar o comando FLUSH LOGS, pre-
cisamos saber qual log está ativo no momento e quais foram
foram rotacionados e em qual sequência. Esta informação é
armazenada no arquivo de índice do log binário. O padrão é
‘nome máquina‘.index. Você pode utilizar esta opção se de-
seja se rebelar.
Exemplo: log-bin-index=db.index.
sql-bin-update-same Se configurado, atribuir um valor a SQL_LOG_BIN irá atribuir
automaticamente ao parâmetro SQL_LOG_UPDATE o mesmo va-
lor e vice versa.
binlog-do-db=nome_bd Diz ao mestre que ele deve logar as atualizações para o log
binário se o banco de dados atual for ’nome bd’. Todos os
outros bancos de dados são ignorados. Note que se você uti-
lizar esta opção você deve se assegurar que só poderá ser feito
atualizações no banco de dados atual.
Exemplo: binlog-do-db=nome_bd.
binlog-ignore-db=nome_ Diz ao mestre que atualizações onde o banco de dados at-
bd ual é ’nome bd’ não devem ser armazenadas no log binário.
Perceba que se você usar esta opção você deve ter certeza que
você somente atualizará o banco de dados atual.
Exemplo: binlog-ignore-db=nome_bd
A tabela seguinte contém as opções que você opde utilizar para SLAVE:
Opção Descrição
master-host=máquina Nome da máquina mestre ou endereço IP para replicação. Se
não for configurada a thread do escravo não será iniciada.
Exemplo: master-host=db-master.mycompany.com.
318 Referência técnica para o MySQL versão 3.23.52
replicate-ignore- Diz à thread escrava não replicar uma tabela específica. Para
table=nome_bd.nome_ especificar mais de uma tabela a ser ignorada, utilize a diretiva
tabela múltiplas vezes, uma vez para cada tabela. Isto irá funcionar
para atualizações cruzadas em bancos de dados, em contraste
com replicate-ignore-db.
Exemplo: replicate-ignore-table=nome_bd.nome_
tabela.
Chapter 4: Administração de Bancos de Dados MySQL 319
CHANGE MASTER TO
MASTER_HOST=’master2.mycompany.com’,
MASTER_USER=’replication’,
MASTER_PASSWORD=’bigs3cret’,
MASTER_PORT=3306,
MASTER_LOG_FILE=’master2-bin.001’,
MASTER_LOG_POS=4;
PURGE MASTER LOGS TO Disponível a partir da versão 3.23.28. Apaga todos os logs da
’nome_log replicação que estiverem listados no índice de log anteriores ao
log especificado e também os remove do índice de log, portanto
o log fornecido agora vem em primeiro. Exemplo:
PURGE MASTER LOGS TO ’mysql-bin.010’
Este comando não fará nada e irá falhar retornando um erro
caso você tenha um escravo ativo que esteja lendo um dos logs
que você estiver tentando apagar. Entretanto, se você possui
um escravo inativo e limpar um dos logs que ele desejar ler,
o escravo não conseguirá replicar no momento que iniciar. O
comando é seguro para ser executado enquanto os escravos
estiverem replicando - você não precisa pará-los.
Primeiro, você deve conferir todos os escravos com SHOW
SLAVE STATUS para ver qual log estão sendo usados, então
faça uma listagem dos logs no mestre com SHOW MASTER LOGS,
encontre o log mais novo entre todos os escravos (se todos os
escravos estiver atualizados, ele será o último log na lista),
faça um backup de todos os logs que você deseja deletar (op-
cional) e limpe até o log alvo.
e motivação para ajustá-lo. Você deve iniciar criando uma camada de biblioteca/modulo
com as seguintes funções:
• safe_writer_connect()
• safe_reader_connect()
• safe_reader_query()
• safe_writer_query()
safe_ significa que a função irá tomar cuidado com o tratamento de todas as condições de
erro.
Então você deve converter seu código cliente para usar a camada de biblioteca. Esse processo
pode ser doloroso e assustador a princípio, mas ele valerá a pena a longo prazo. Todas as
aplicações que seguirem o padrão acima receberão poderão tirar vantagem de uma solução
de um mestre/vários escravos. O código será um pouco mais fácil de manter, e adicionar
opções para localização de defeitos será trivial. Você só precisará modificar uma ou duas
funções, por exemplo, para registrar quanto tempo cada consulta demora para ser executada,
ou qual consulta, entre milhares, está errada. Se você já escreveu muito código, pode
precisar automatizar a tarefa de conversão utilizando o utilitário replace desenvolvido pelo
Monty, que acompanha a distribuição padrão do MySQL, ou escreva seu próprio script Perl.
Esperançosamente, seu código segue algum padrão reconhecido. Se não, provavelmente será
melhor reescrever tudo novamente, ou pelo menos tente começar a seguir algum padrão.
Perceba que, é claro, você pode utilizar nomes diferentes para as funções. O que é importante
é ter uma interface unificada para conexões de leitura e conexões de escrita.
Q: Quando e quanto a replicação do MySQL pode melhorar a performance de meu sistema?
A: A replicação do MySQL é mais eficas para um sistema com leituras frequentes e que não
tenha muitas escritas. Em teoria, utilizando uma conrfiguração de um mestre para vários
escravos você pode escalar adicionando mais escravos até não ter mais banda de rede, ou
até que sua carga de atualizações cresça ao ponto que o mestre não consiga lidar.
Para determinar quantos escravos você pode utilizar antes dos benefícios adicionados
começarem a funcionar e o quanto você pode melhorar a performance de seu site, você
precisará saber seus estilos de query e de maneira empírica (por benchmarking) determinar
a relação entre o rítmo de transferência nas leituras (por segundo ou max_reads) e nas
escritas max_writes) em um mestre e escravo comuns. O exemplo abaixo mostra um
cálculo especialmente simplificado de quanto você pode obter com replicação para seu
sistema imaginário.
Digamos que a carga de seu sistema consista em 10% de escrita e 90% de leitura, e nós
determinamos que max_reads = 1200 - 2 * max_writes, ou em outras palavras, nosso
sistema pode fazer 1200 leituras por segundo com nenhuma escrita, nossa escrita média
é duas vezes mais lenta que a leitura média e a relação é linear. Vamos supor que nosso
mestre e escravo não tenham a mesma capacidade, e possuimos N escravos e 1 mestre.
Então teremos para cada servidor (mestre ou escravo):
leituras = 1200 - 2 * escritas (dos benchmarks)
leituras = 9* escritas / (N + 1) (a leitura é dividida, mas a escrita é enviada a todos
os servidores)
9*escritas/(N+1) + 2 * escritas = 1200
326 Referência técnica para o MySQL versão 3.23.52
Quando você tiver determinado que não há erro de usuário envolvido, e a replicação ainda
não funciona perfeitamente ou está instável, é hora de começar a fazer num relatório de
erros. Nós precisamos do máximo de informações que você puder fornecer para conseguirmos
rastrear o bug. Por favor gaste algum tempo e esforço preparando um bom relato de erro. O
ideal seria nos enviar um realtório no formato encontrato no diretório mysql-test/t/rpl*
da árvore fonte. Se você submeter um relatório como este, você pode esperar um patch em
um dia ou dois na maioria dos casos, embora, é claro, o tempo pode variar dependendo de
um número de fatores.
Outra opção é criar um programa com parâmetros de configuração fáceis para o mestre e o
escravo que irão demonstrar o problema em nossos sistemas. Você pode escreve-lo em Perl
ou em C, dependendo da linguagem que você tenha mais domínio.
Se você pode demonstrar o problema com alguma das formas descritas acima, utilize
mysqlbug para preparar um relatório de erros e envie-o para [email protected]. Se
você tem um fantasma - um problema que só pode ser simulado em seu sistema:
• Verifique se não existem erros de usuário envolvidos. Por exemplo, se você atualiza o
escravo fora da thread escrava, os dados podem ficar fora de sincronia e podem ocorrer
violações de chave única nas atualizações, neste caso a thread escrava irá terminar e
esperar que você limpe as tabelas manualmente para entrar em sincronia.
• Execute o escravo com log-slave-updates e log-bin - isto irá registrar todas as
atualizações no escravo.
• Salve todas as evidências antes de restaurar a replicação. Se não tivermos nenhuma
informação ou apenas algum esboço, será um pouco mais difícil para rastrearmos o
problema. As evidências que você deve coletar são:
− Todos os logs binários no mestre
− Todos os logs binários no escravo
− A saída de SHOW MASTER STATUS no mestre na hora que você descobriu o problema.
− A saída de SHOW SLAVE STATUS no mestre na hora que você descobriu o problema.
− Logs de erro no mestre e no escravo
• Utilize mysqlbinlog para examinar os logs binários. A informação a seguir pode ser
útil para encontrar a consulta problemática, por exemplo:
mysqlbinlog -j pos_from_slave_status /caminho/para/log_do_escravo | head
Uma vez que você coletou as evidências do problema fantasma, tente isolá-lo em um caso
de testes separados inicialmente. Então relate o problema para [email protected]
com a maior quantidade possíveis de informações.
Chapter 5: Otimização do MySQL 329
5 Otimização do MySQL
Otimização é uma tarefa complicada porque necessita um entendimento do sistema como
um todo. Enquanto for possível fazer algumas otimizações com pequeno conhecimento de
seu sistema ou aplicação, quanto mais otimizado você desejar que o seu sistema esteja, mais
terá que saber sobre ele.
Este capítulo tentará explicar e fornecer alguns exemplos de diferentes formas de otimizar
o MySQL. Lembre-se, no entanto, que sempre existirão (cada vez mais difíceis) formas
adicionais de deixar seu sistema mais rápido.
5.1.2 Portabilidade
Como todos os servidores SQL implementam partes diferentes da linguagem SQL, é trabal-
hoso escrever aplicações SQL portáveis. Para inserts e selects muito simples é fácil, mas
quanto mais recurso você precisa, mais difícil se torna a implementação. Se você deseja
uma aplicação que seja rápida com vários bancos de dados a tarefa se tornará mais difícil
ainda!
Para fazer uma aplicação complexa portável você precisará eleger um número fechado de
servidores SQL para funcionar com seu sistema.
Você pode utilizar o MySQL programa/web-page crash-me - http://www.mysql.com/information/crash-
me.php - para encontrar funções, tipos e limites que você pode utilizar com uma seleção de
servidores de bancos de dados. O Crash-me agora testa quase tudo possível, mas continua
compreensível com aproximadamente 450 itens testados.
Por exemplo, você não deve ter nomes de colunas maior do que 18 caracteres se desejar
utilizar o Informix ou DB2.
Os programas de benchmarks e crash-me do MySQL são bastante independentes do bancos
de dados. Dando uma olhada em como nós os tratamos, você pode sentir o que é necessário
para escrever sua aplicação independente do banco de dados. Os benchmarks podem ser
encontrados no diretório ‘sql-bench’ na distribuição fonte do MySQL. Eles são escritos em
Perl com a interface de banco de dados DBI (que resolve a parte do problema de acesso).
Veja http://www.mysql.com/information/benchmarks.html para os resultados deste
benchmark.
Como pode ser visto nestes resultados, todos os bancos de dados tem alguns pontos fra-
cos. Isto é, eles possuem diferentes compromissos de projeto que levam a comportamentos
diferentes.
Se você procura por independencia de banco de dados, precisará ter uma boa idéia dos
gargalos de cada servidor SQL. O MySQL é muito rápido para recuperação e atualização
de dados, mas terá problemas em misturar leituras/escritas lentas na mesma tabela. O
Oracle, por outro lado, possui um grande problema quando você tentar acessar registros
que foram recentemente atualizados (até eles serem atualizados no disco). Bancos de dados
transacionais geralmente não são muito bons gerando tabelas de resumo das tabelas log,
nestes casos o travamento de registros é praticamente inútil.
Para fazer sua aplicação realmente independente de banco de dados, você precisará definir
uma interface que pode ser estendida através da qual você fará a manipulação dos dados.
Como o C++ está disponível na maioria dos sistemas, faz sentido utilizar classes C++ para
fazer a interface ao banco de dados.
Se você utilizar algum recurso específico para algum banco de dados (como o comando
REPLACE no MySQL), você deve codificar um método para os outros serviodores SQL para
implementar o mesmo recurso (mas mais lento). Com o MySQL você pode utilizar a sintaxe
/*! */ para adicionar palavras chave específicas do MySQL para uma query. O código
dentro de /**/ será tratado como um comentário (ignorado) pela maioria dos servidores
SQL.
Se alta performance REAL é mais importante que exatidão, como em algumas aplicações
WEB, uma possibilidade é criar uma camada de aplicação que armazena todos os resultados
para lhe fornecer uma performance ainda mais alta. Deixando resultados antigos ’expirar’
Chapter 5: Otimização do MySQL 331
depois de um tempo, você pode manter o cache razoavelmente atual. Isto é muito bom
no caso de uma carga extremamente pesada, pois neste caso você pode aumentar o cache
dinamicamente e configurar o tempo de expiração maior até que as coisas voltem ao normal.
Neste caso a informação de criação de tabelas devem conter informações do tamanho inicial
do cache e com qual frequência a tabela, normalmente, deve ser renovada.
Nossa sensação inicial é que o Linux irá atuar muito melhor em cargas baixas a médias e o
Solaris irá atuar melhor quando você começar a ter uma carga alta pelo uso extremo de IO
de disco, mas ainda não temos nada conclusivo sobre isto. Depois de algumas discussões com
um desenvolvedor do Kernel do Linux, concluímos que isto pode ser um efeito colateral do
Linux; fornecer tantos recursos para uma tarefa batch que a performance interativa se torna
muito baixa. Isto deixa a máquina muito lenta e sem resposta enquanto grandes batches
estiverem em execução. Esperamos que isto tenha um tratamento melhor em futuras versões
do kernel Linux.
Para executar a suite de benchmarks, você deve fazer download de uma distribuição fonte
do MySQL, instalar o driver DBI do perl, e o driver DBD do perl para o banco de dados
que desejar testar e depois fazer:
cd sql-bench
perl run-all-tests --server=#
onde # é um dos servidores suportados. Você pode obter uma lista de todos parâmetros e
servidores suportados executando run-all-tests --help.
crash-me tenta determinar quais recursos um banco de dados suporta e quais suas capaci-
dades e limitações atuais para a execução de consultas. Por exemplo, ele determina:
• Quais tipos de colunas são suportados
• Quantos índices são suportados
• Quais funções são suportadas
• Qual o tamanho máximo de uma query
• Qual o tamanho máximo de um registro do tipo VARCHAR
Definitivamente você deve fazer benchmarks de sua aplicação e banco de dados para saber
quais são os gargalos. Corrigindo (ou substituindo o gargalho com um ’módulo burro’) você
pode facilmente identificar o próximo gargalo (e continuar). Mesmo se a performance geral
para sua aplicação é suficiente, você deve pelo menos criar um plano para cada gargalo e
decidir como resolvê-lo se algum dia você precisar de performance extra.
Para um exemplo de programas de benchmarks portáveis, consulte o conjunto de bench-
marks do MySQL. See hundefinedi [Benchmarks do MySQL], page hundefinedi. Você pode
pegar qualquer programa deste conjunto e modificá-lo para suas necessidades. Fazendo isto
você pode tentar soluções diferentes para seu problema e testar qual solução é a mais rápida
para você.
É muito comum que alguns problemas somente ocorram quando o sistema estiver muito
carregado. Nós tivemos alguns clientes que nos contactaram quando eles testaram um
sistema em produção e encontraram problemas de carga. Em cada um dos casos, existiam
problemas com projeto básico (busca em tabelas não eram bons com alta carga) ou detalhes
de SO/biblioteca. A maioria destes seriam MUITO mais fáceis de resolver se os sistemas
já não estivessem em uso.
Para evitar problemas deste tipo, você deve colocar algum esforço em testar a performance
de toda sua aplicação sobre a pior carga possível! Você pode utilizar o Super Smack para
isto, e ele está disponível em: http://www.mysql.com/Downloads/super-smack/super-
smack-1.0.tar.gz. Como o nome sugere, ele pode derrubar seu sistema se você solicitar,
portanto, utilize-o somente em sistemas de desenvolvimento.
334 Referência técnica para o MySQL versão 3.23.52
t2.id nunca poderá ser NULL e não ir percorrer até o resto dos reg-
istros em t2 que possuirem o mesmo id. Em outras palavras, para
cada registro em t1 o MySQL só precisa fazer uma única pesquisa
em t2, independente de quantos registros coincidentes existirem em
t2.
range checked for each record (index map: #)
O MySQL não encontrou um bom índice para usar. No lugar, ele
irá fazer uma verificação sobre qual índice usar (se existir) para
cada combinação das tabelas precedentes, e usará este índice para
recuperar os registros da tabela. Isto não é muito rápido mas é
mais rápido que fazer um join sem um índice.
Using filesort
O MySQL precisará fazer uma passada extra para descobrir como
recuperar os registros na ordem de classificação. A classificação é
feita indo através de todos os registros de acordo com join type
e armazenar a chave de ordenação mais o ponteiro para o registro
para todos os registros que combinarem com o WHERE. Então as
chaves são classificadas. Finalmente os registros são recuperados
na ordem de classificação.
Using index
A informação da coluna é recuperada da tabela utilizando somente
informações na árvore de índices sem ter que fazer uma pesquisa
adicional para ler o registro atual. Isto pode ser feito quando todas
as colunas usadas para a tabela fizerem parte do mesmo índice.
Using temporary
Para resolver a consulta, o MySQL precisará criar uma tabela tem-
porária para armazenar o resultado. Isto acontece normalmente se
você fizer um ORDER BY em um conjunto de colunas diferentes das
quais você fez um GROUP BY.
Where used
Uma cláusula WHERE será utilizada para restringir quais registros
serão combinados com a próxima tabela ou enviar para o cliente.
se você não possui esta informação e a tabela é do tipo ALL ou
index, pode existir alguma coisa errada na sua query (Se você não
pretender examinar todos os registros da tabela).
Se você desejar deixar suas consultas o mais rápido possível, você deve dar uma
olhada em Using filesort e Using temporary.
Os diferentes tipos de joins estão listados abaixo, ordenados do melhor para o pior tipo:
system A tabela tem somente um registro (= tabela de sistema). Este é um caso
especial do join do tipo const.
const A tabela possui pelo menos um registro coincidente, que será lido no início da
consulta. Como só há um registro, valores da coluna neste registro podem ser
tratados como contantes pelo otimizador até o final. Tabelas const são muito
rápidas como elas são lidas somente uma vez!
Chapter 5: Otimização do MySQL 337
eq_ref Um registro será lido desta tabela para cada combinação de registros das tabelas
anteriores. Este é o melhor tipo possível de join, depois dos tipos const. Ele é
utilizado quando todas as partes de um índice são usados pelo join e o índice
for UNIQUE ou um PRIMARY KEY.
ref Todos os registros com valores de índices combinando serão lidos desta tabela
para cada combinação de registros das tabelas anteriores. ref é utilizado se
o join usar somente o prefixo mais a esquerda da chave, ou se a chave não
for UNIQUE ou uma PRIMARY KEY (em outras palavras, se a ligação não pode
selecionar um único registro baseado no valor da chave). Se a chave usada
coincidir apenas com poucos registros este tipo de join é de boa qualidade.
range Serão recuperados somentes os registros que estiverem dentro de uma faixa
dada, utilizando um índice para selecionar os registros. A coluna key indica
qual índice é usado. O key_len contem a parte mais longa da chave foi usada.
A coluna ref será NULL para este tipo.
index Isto é o mesmo que ALL, exceto que somente a árvore de índice é lida. Isto
normalmente é mais rápido que ALL já que o arquivo de índice é normalmente
menor que o arquivo de dados.
ALL Uma pesquisa completa será feita na tabela para cada combinação de registros
das tabelas anteriores. Isto normalmente não é bom se a tabela é a primeira
não marcada com const, e normalmente muito ruim em todos os outros casos.
Normalmente você pode evitar ALL adicionando mais índices, assim o registro
pode ser recuperado baseado em valores contantes ou valores de colunas de
tabelas anteriores.
Você pode ter uma boa indicação de quão boa é sua join multiplicando todos os valores
na coluna rows na saída de EXPLAIN. Isto deve dizer a grosso modo quantos registros o
MySQL deve examinar para executar a consulta. Este número é também usado quando
você restringe consultas com a variável max_join_size. See hundefinedi [Parâmetros de
servidor], page hundefinedi.
O exemplo a seguir mostra como um JOIN pode ser otimizado progressivamente utilizando
a informação fornecida por EXPLAIN.
Suponha que você tem a instrução SELECT exibida abaixo, que você está examinando uti-
lizando EXPLAIN:
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn,
tt.ProjectReference, tt.EstimatedShipDate,
tt.ActualShipDate, tt.ClientID,
tt.ServiceCodes, tt.RepetitiveID,
tt.CurrentProcess, tt.CurrentDPPerson,
tt.RecordVolume, tt.DPPrinted, et.COUNTRY,
et_1.COUNTRY, do.CUSTNAME
FROM tt, et, et AS et_1, do
WHERE tt.SubmitTime IS NULL
AND tt.ActualPC = et.EMPLOYID
AND tt.AssignedPC = et_1.EMPLOYID
AND tt.ClientID = do.CUSTNMBR;
Para este exemplo, assuma que:
338 Referência técnica para o MySQL versão 3.23.52
Isto não está perfeito, mas está bem melhor ( o produto dos valores de rows agora menor
por um fator de 74 ). Esta versão é executada em vários segundos.
Uma segunda alteração pode ser feita para eliminar as diferenças de tamanho das colunas
para as comparações tt.AssignedPC = et_1.EMPLOYID e tt.ClientID = do.CUSTNMBR :
mysql> ALTER TABLE tt MODIFY AssignedPC VARCHAR(15),
MODIFY ClientID VARCHAR(15);
Agora EXPLAIN produz a saída mostrada abaixo:
table type possible_keys key key_len ref rows Extra
et ALL PRIMARY NULL NULL NULL 74
tt ref AssignedPC,ClientID,ActualPC ActualPC 15 et.EMPLOYID 52 where used
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Este resultado é quase o melhor que se pode obter.
O problema restante é que, por padrão, o MySQL assume que valores na coluna
tt.ActualPC estão distribuídos igualmente, e este não é o caso para a tabela tt.
Felizmente, é fácil informar ao MySQL sobre isto:
shell> myisamchk --analyze caminho_para_banco_dados_MySQL/tt
shell> mysqladmin refresh
Agora a join está perfeita, e EXPLAIN produz esta saída:
table type possible_keys key key_len ref rows Extra
tt ALL AssignedPC,ClientID,ActualPC NULL NULL NULL 3872 where used
et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1
do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
Perceba que a coluna rows na saída de EXPLAIN é uma boa ajuda para otimizador de joins
do MySQL. Para otimizar uma consulta, você deve conferir se os números estão perto da
realidade. Se não, você pode obter melhor desempenho utilizando STRAIGHT_JOIN em sua
instrução SELECT e tentar listar as tabelas em uma ordem diferente na cláusula FROM.
Entretanto, para escritas, você precisará utilizar 4 requisições para encontrar onde posi-
cionar o novo índice e normalmente 2 buscas para atualizar o índice e escrever o registro.
Perceba que o que foi dito acima não significa que sua aplicação perderá performance por N
log N! Como tudo é armazenado no cache de seu SO ou do servidor SQL as coisas começarão
a ficar um pouco mais lentas quando as tabelas começarem a crescer. Quando os dados se
tornam muito grandes para o cache, as coisas começarão a ficar bem mais lentas até que suas
aplicações estejam limitadas a buscas em disco (o que aumenta em N log N). Para evitar
isto, aumente o cache de índice quando os dados crescerem. See hundefinedi [Parâmetros
do servidor], page hundefinedi.
WHERE key_part_1=constant;
mysql> SELECT ... FROM nome_tabela
ORDER BY key_part1,key_part2,... LIMIT 10;
mysql> SELECT ... FROM nome_tabela
ORDER BY key_part1 DESC,key_part2 DESC,... LIMIT 10;
As seguintes consultas são resolvidas utilizando somente a árvore de índices (assumindo que
as colunas indexadas são numéricas):
mysql> SELECT key_part1,key_part2 FROM nome_tabela WHERE key_part1=val;
mysql> SELECT COUNT(*) FROM nome_tabela
WHERE key_part1=val1 AND key_part2=val2;
mysql> SELECT key_part2 FROM nome_tabela GROUP BY key_part1;
As consultas a seguir utilizam indexação para recuperar os registros na ordem de classi-
ficação sem um passo de ordenação separado:
mysql> SELECT ... FROM nome_tabela ORDER BY key_part1,key_part2,... ;
mysql> SELECT ... FROM nome_tabela ORDER BY key_part1 DESC,key_part2 DESC,... ;
• Se você utiliza LEFT JOIN para encontrar registros que não existem em alguma tabela e
está usando o seguinte teste: nome_coluna IS NULL na parte WHERE, onde nome colun
é um campo que é declarado como NOT NULL, então o MySQL para de pesquisar por
mais registros (para uma combinação particular de chaves) depois de ter encontrado
um registro que combinar com a condição LEFT JOIN.
RIGHT JOIN é implementado de forma análoga à LEFT JOIN.
A ordem de leitura das tabelas forçada por LEFT JOIN e STRAIGHT JOIN irá ajudar o
otimizador de joins (que calcula em qual ordem as tabelas devem ser unidas) a fazer seu
trabalho mais rapidamente, já que haverão poucas permutações de tabelas a serem conferi-
das.
Perceba que o texto acima significa que se você fizer uma consulta do tipo:
SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key
O MySQL irá fazer uma pesquisa completa em b já que o LEFT JOIN irá força-lo a ser lido
antes de d.
A correção neste caso é alterar a consulta para:
SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key
Isto é realmente importante quando você usa bancos de dados como o MySQL que só
tem travamento de tabelas (multiplos leituras/escrita única). Isto também dará melhor
performance com a maioria dos banco de dados, já que o gerenciador de bloqueio de
registro terá menos a fazer neste caso.
• Se você precisar colterar estatisicas de tabelas maiores, utilize tabelas resumo em vez
de buscar em toda a tabela. Manter os resumos deve ser mais rápido que tentar criar
estatitíscas instantaneamente. É muito mais rápido criar novas tabelas através dos logs
quando as coisas mudam (dependendo das descisões de negócio) que ter que alterar a
aplicação em execução.
• Se possível, deve-se classificar relatórios como ’instantâneo’ ou ’estatísticos’ onde os
dados necessários para relatórios estaiísticos são gerados apenas com base nas tabelas
resumo que são geradas a partir dos dados atuais.
• Tire vantagem do fato de que a coluna tem valores padrões. Insira valores explicita-
mente apenas quando os valores a serem inseridos diferem do padrão. Isto reduz a
analise que o MySQL precisa fazer e aumenta a velocidade de inserção.
• Em alguns casos é conveniente empacotar e armazenar os dados em um campo
blob. Neste caso você deve adicionar algum código em sua aplicação para
empacotar/desempacotar as coisas no campo blob, mas isto pode poupar vários
acessos a algum estágio. Isto é prático quando você possui dados que não conformam
com uma estrutura estática de tabela.
• Normalmente, você deve tentar manter todos dados não-redundantes (o que é chamado
de 3a forma normal na teoria de bancos de dados), mas você não deve ter medo de
duplicar alguns itens ou criar tabelas de resumo se você precisar delas para ganhar
mais velocidade.
• Stored Procedures ou UDF (funções definidas pelo usuários) pode ser uma boa forma
para obter mais performance. Neste caso você deve, entretanto, sempre ter uma
maneira de fazer isso de outra maneira (mais lenta) se você utilizar algum banco de
dados que não suporta isto.
• Você pode sempre ganhar velocidade fazendo cache de perguntas/respostas na sua
aplicação e tentando fazer várias inserções/atualizações ao mesmo tempo. Se seu banco
de dados suporta travamento de tabelas (como o MySQL e Oracle), isto deve ajudar
a garantir que o cache de índices é descarregado somente uma vez depois de todas
atualizações.
• Use INSERT /*! DELAYED */ quando não precisar saber quando os dados são gravados.
Isto melhora a velocidade porque vários registros podem ser gravados com uma simples
escrita em disco.
• Use INSERT /*! LOW_PRIORITY */ quando você desejar que suas consultas sejam mais
importantes.
• Use SELECT /*! HIGH_PRIORITY */ para obter consultas que ignoram a fila. Isto é, a
consulta é feita mesmo se alguem estiver esperando para fazer uma escrita.
• Use a instrução INSERT multi-linhas para armazenar vários registros com um comando
SQL (vários servidores SQL suportam isto).
• Use LOAD DATA INFILE para carregar volumes maiores de dados. Isto é mais rápido que
as inserções normais e mais rápido até quando o myisamchk for integrado no mysqld.
348 Referência técnica para o MySQL versão 3.23.52
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.
• 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 hundefinedi [SET OPTION], page hundefinedi.
• Você pode especificar que uma SELECT específica é muito importante com o atributo
HIGH_PRIORITY. See hundefinedi [SELECT], page hundefinedi.
• 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 hundefinedi
[INSERT], page hundefinedi.
• Se você tiver problemas com SELECT e DELETE, a opção LIMIT para DELETE pode ajudar.
See hundefinedi [DELETE], page hundefinedi.
leitura de disco é mais rápida e normalmente menos memória principal será usada. A
indexação também exige menos recursos se for feita em colunas menores.
O MySQL suporta vários diferentes tipos de tabelas e formatos de registros. Você pode
ter um ótimo ganho de performance escolhendo o formato certo de tabela a ser usada. See
hundefinedi [Tipos de tabelas], page hundefinedi.
Pode-se obter melhor performance em uma tabela e minimizar espaço de armazenagem
utilizando as técnicas listadas abaixo:
• Utilize os tipos mais eficientes (menores) sempre que possível. O MySQL tem vários
tipos especializados que economizam espaço em disco e memória.
• Utilize tipos inteiros menores se possível para obter tabelas menores. Por exemplo,
MEDIUMINT normalmente é melhor que INT.
• Declare colunas para serem NOT NULL se possível. Isto deixa tudo mais rápido e você
economiza um bit por coluna. Perceba que se você realmente precisa de NULL nas suas
aplicações, podem ser usados. Tente simplesmente não usá-la em todas as colunas por
padrão.
• Se você não possui nenhuma coluna de tamanho variável (VARCHAR, TEXT ou BLOB),
um formato de registro de tamanho fixo para é utilizado. Isto é mais rápido mas
infelizmente pode ocupar mais espaço. See hundefinedi [Formatos de tabelas MyISAM],
page hundefinedi.
• O índice primário de uma tabela deve ser o mais curto possível. Isto torna a identi-
ficação de um registro fácil e eficiente.
• Para cada tabela, você deve decidir qual metódo de armazenamento/índice utilizar.
See hundefinedi [Tipos de tabelas], page hundefinedi.
• Crie somente os índices necessários. Índices são bons para recuperação mas ruins
quando você precisa armazenar os dados rapidamente. Se na maioria das vezes você
acessa uma tabela pesquisando em uma combinação de colunas, crie um índice para
elas. A primeira parte do índice deve ser a coluna mais utilizada. Se você SEMPRE
utiliza várias colunas, deve usar a coluna com mais duplicações em primeiro lugar para
obter melhor compactação do índice.
• Se for melhor que uma coluna tenha um prefixo único nos primeiros caracteres, é
melhor indexar somente este prefixo. O MySQL suporta um índice em uma parte
de uma coluna de caracteres. Índices menores são mais rápidos não somente porque
eles exigem menos espaço em disco mas também porque eles irão fornecer a você mais
acerto no cache de índice e isto diminui acessos a disco. See hundefinedi [Parâmetros
de servidor], page hundefinedi.
• Em algumas circunstâncias pode ser benéfico dividir uma tabela que é varrida fre-
quentemente em duas. Isto é verdade especificamente se a tabela tiver um formato
dinâmico e for possível utilizar um formato de tabela estático que possa ser usada para
encontrar os registros relevantes quando se fizer uma varredura da tabela.
maior será o custo. Se a tabela possui um índice para as colunas em questão, o MySQL
pode rapidamente obter uma posição para procurar no meio do arquivo de dados sem ter
que varrer todos os registros. Se uma tabela possui 1000 registros, isto é pelo menos 100
vezes mais rápido do que ler todos os registros sequencialmente. Note que se você precisar
acessar quase todos os 1000 registros, seria mais rápido acessá-los sequencialmente porque
evitaria acessos ao disco.
Todos os índices do MySQL (PRIMARY, UNIQUE e INDEX) são armazenados em árvores B.
Strings são automaticamente compactadas nos espaços finais e prefixados. See hundefinedi
[CREATE INDEX], page hundefinedi.
Índices são utilizados para:
• Encontrar rapidamente os registros que coincidam com uma cláusula WHERE.
• Recuperar registros de outras tabelas ao realizar joins.
• Encontrar o valor MAX() ou MIN() para uma coluna indexada espeifica. Isto é otimizado
por um preprocessador que confere se você está utilizando WHERE key part #=constante
em todas as partes da chave < N. Neste caso o MySQL irá fazer uma simples procura
na chave e trocar a expressão MIN() com uma constante. Se todas as expressões forem
trocadas por constantes, a consulta retornará imediatamente:
SELECT MIN(key_part2),MAX(key_part2) FROM nome_tabela where key_part1=10
• Ordenar ou agrupar uma tabela se a ordenação ou agrupamento for feito em um prefixo
mais à esquerda de uma chave util (por exemplo, ORDER BY key_part_1, key_part_2
). A chave é lida na ordem invertida se todas as partes da chave forem seguidas por
DESC.
O índice também pode ser utilizado mesmo se ORDER BY não coincidir exatamente com o
índice, já que todas as partes não utilizadas do índice e todos os extras que são colunas
ORDER BY são constantes na cláusula WHERE A consulta seguinte utilizará o índice para
resolver a parte ORDER BY:
SELECT * FROM foo ORDER BY key_part1,key_part2,key_part3;
SELECT * FROM foo WHERE coluna=constante ORDER BY coluna, key_part1;
SELECT * FROM foo WHERE key_part1=const GROUP BY key_part2;
• Em alguns casos uma consulta pode ser otimizada para recuperar valores sem consultar
o arquivo de dados. Se todas colunas utilizadas para alguma tabela são numéricas e for-
mam um prefixo mais à esquerda para alguma chave, os valores podem ser recuperados
da árvore de índices para aumentar a velocidade:
SELECT key_part3 FROM nome_tabela WHERE key_part1=1
Suponha que você utilize a seguinte instrução SELECT:
mysql> SELECT * FROM nome_tabela WHERE col1=val1 AND col2=val2;
Se um índice de colunas múltiplas existir em col1 e col2, os registros apropriados podem
ser recuperados diretamente. Se índices separados de únicas colunas existirem em col1
e col2, o otimizador tentará encontrar o índice mais restritivo decidindo qual índice irá
encontrar menos registros e usará este índice para recuperar os registros.
Se a tabela possuir um índice de múltiplas colunas, qualquer prefixo mais à esquerda do
índice pode ser usado pelo otimizador para encontrar registros. Por exemplo, se você possui
um índice de três colunas em (col1,col2,col3), você tem capacidades de busca indexada
em (col1), (col1,col2) e (col1,col2,col3).
354 Referência técnica para o MySQL versão 3.23.52
O MySQL não pode utilizar um índice parcial se as colunas não formarem um prefixo mais
à esquerda do índice. Suponha que você tenha as instruções SELECT mostradas abaixo:
mysql> SELECT * FROM nome_tabela WHERE col1=val1;
mysql> SELECT * FROM nome_tabela WHERE col2=val2;
mysql> SELECT * FROM nome_tabela WHERE col2=val2 AND col3=val3;
Se um índice existir em (col1,col2,col3), somente a primeira consulta exibida acima
utiliza o índice. A segunda e terceira consultas involvem colunas indexadas, mas (col2) e
(col2,col3) não são os prefixos mais à esquerda de (col1,col2,col3).
O MySQL também utiliza índices para comparações do tipo LIKE se o argumento para LIKE
for uma string constante que não inicie com um meta caracter Por exemplo as seguintes
instruções SELECT utilizam índices:
mysql> select * from nome_tabela where key_col LIKE "Patrick%";
mysql> select * from nome_tabela where key_col LIKE "Pat%_ck%";
Na primeira instrução, somente os registros com "Patrick" <= key_col < "Patricl" são
considerados. Na segunda instrução, somente registros com "Pat" <= key_col < "Pau" são
considerados.
As seguintes instruções SELECT não usarão índices:
mysql> select * from nome_tabela where key_col LIKE "%Patrick%";
mysql> select * from nome_tabela where key_col LIKE other_col;
Na primeira instrução, o valor LIKE inicia com um meta caracter. Na segunda instrução, o
valor LIKE não é uma constante.
Pesquisas com nome_coluna IS NULL usarão índices se nome coluna for um índice.
O MySQL normalmente utiliza o índice que encontra o menor número de registros. Um
índice é usado para colunas que você compara com os seguintes operadores: =, >, >=, <, <=,
BETWEEN e um LIKE com um prefixo sem meta caracteres como ’algo%’.
Qualquer índice que não cobrem todos os níveis de AND na cláusula WHERE não é utilizado
para otimizar a consulta. Em outras palavras: Para poder usar um índice, um prefixo do
índice deve ser utilizado em todo agrupamento AND.
A seguinte cláusula WHERE utilizará índices:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3
... WHERE index=1 OR A=10 AND index=2 /* index = 1 OR index = 2 */
... WHERE index_part1=’hello’ AND index_part_3=5
/* otimizado como "index_part1=’hello’" */
... WHERE index1=1 and index2=2 or index1=3 and index3=3;
/* pode utilizar índice em index1 mas n~
ao em index2 ou index 3 */
Estas cláusulas WHERE NÃO utilizam índices:
... WHERE index_part2=1 AND index_part3=2 /* index_part_1 n~ ao é usado */
... WHERE index=1 OR A=10 /* O índice n~
ao é usado em ambas as partes AND*/
... WHERE index_part1=1 OR index_part2=10 /* Nenhum indice cobre os registros */
Perceba que em alguns casos o MySQL não utilizará um índice, mesmo se algum estiver
disponível. Alguns dos casos onde isto acontece:
• Se o uso do índice necessita que o MySQL acesse mais de 30% dos registros na tabela.
(Neste caso uma varredura da tabela é provavelmente mais rápido, já que isto necessite
Chapter 5: Otimização do MySQL 355
de menos pesquisas em discos). Perceba que se uma consulta utiliza LIMIT para recu-
perar somente parte dos registros, o MySQL irá utilizar um índice de qualquer forma,
pois assim pode encontrar os poucos registros mais rapidamente e retornar o resultado.
Linux 32-bits temos o limite de tamanho de arquivo de 2G por padrão. Esperamos que
isto seja corrigido logo quando novos sistemas de arquivos forem liberados (XFS/Reiserfs).
Se você precisa desesperadamente de trabalhar com arquivos maiores que 2G em máquinas
intel Linux, você deve obter o patch LFS para o sistema de arquivos ext2.
Como ainda não temos o MySQL em produção em muitas outras plataformas, nós aconsel-
hamos que você teste a plataforma pretendida antes de escolhe-la, se possível.
Outras dicas:
• Se você possui RAM suficiente, você pode remover todos os dispositivos de troca.
Alguns sistemas operacionais irão utilizar um disposotico de troca em alguns contextos,
mesmo se você possuir memória livre.
• Utilize a opção do MySQL --skip-locking para evitar bloqueios externos. Perceba
que isto não irá afetar a funcionalidade do MySQL se você estiver executando um único
servidor. Apenas lembre-se de desligar o servidor (ou travar as partes relevantes) antes
de executar myisamchk. Em alguns sistemas esta troca é obrigatório porque o bloqueio
externo não funciona em nenhum caso.
A opção --skip-locking está ligada por padrão quando compilando com
MIT-pthreads, porque flock() não é totalmente suportado pelas MIT-pthreads em
todas plataformas. É também o padrão para Linux pois o bloqueio de arquivos no
Linux não é muito seguro.
O único caso que você não pode utilizar --skip-locking é se você precisa de vários
servidores MySQL (não clientes) acessando os mesmos dados, ou executar myisamchk
na tabela sem primeiramente descarregar e travar as tabelas no servidor mysqld.
Você pode continuar usando LOCK TABLES/UNLOCK TABLES mesmo se você estiver uti-
lizando --skip-locking.
• Se você utiliza o pgcc e compila tudo com -O6, o servidor mysqld é 1% mais rápido do
que com o gcc 2.95.2.
• Se você liga dinamicamente (sem -static), o resultado é 13% mais lento no Linux.
Note que você ainda pode utilizar uma biblioteca do MySQL dinamicamente ligada. É
só o servidor que é crítico para performance.
• Se você corta seu binário mysqld com strip libexec/mysqld, o binário gerado pode
ficar até 4% mais rápido.
• Se você conecta utilizando TCP/IP em vez de utilizar sockets Unix, o resultado é 7.5%
mais lento no mesmo computador. (Se você fizer conexão à localhost, o MySQL irá,
por padrão, utilizar sockets).
• Se você conectar utilizando TCP/IP de outro computador sobre uma rede Ethernet de
100M as coisas ficarão de 8-11% mais lentas.
• Se você compilar com --with-debug=full, estará perdendo cerca de 20% para a maio-
ria das consultas, mas algumas consultas podem demorar muito mais tempo (os bench-
marks do MySQL demonstram 35% de perda). Se utilizar --with-debug, então irá
perder 15%. Ao iniciar uma versão do mysqld compilada com --with-debug=full
com --skip-safemalloc o resultado final deve ser perto de quando compilado com
--with-debug.
• Em uma Sun SPARCstation 20, SunPro C++ 4.2 é 5 % mais rápido que gcc 2.95.2.
• Compilando com gcc 2.95.2 para o ultrasparc com a opção -mcpu=v8 -Wa,-
xarch=v8plusa melhora a performance em 4%.
• No Solaris 2.5.1, a MIT-pthreads é 8-12% mais lenta do que as threads nativas do
Solaris em um único processador. Com mais carga/CPUs a diferença deve aumentar.
• Executando com --log-bin deixa o MySQL 1 % mais lento.
• Compilando no Linux-x86 com gcc sem frame pointers -fomit-frame-pointer ou -
fomit-frame-pointer -ffixed-ebp deixa o mysqld 1-4% mais rápido.
A distribuição MySQL-Linux fornecida pela MySQL AB é normalmente compilada com
pgcc, mas vamos retornar a usar o gcc pelo fato de um bug no pgcc que gera o código
que não executa no AMD. Continuaremos a usar o gcc até que o bug seja resolvido. Neste
meio tempo, se você possui uma máquina que não seja AMD, você pode ter um binário
mais rápido compilando com o pgcc. O binário padrão do MySQL para Linux é ligado
estaticamente para conseguir mais desempenho e ser mais portável.
uma consulta está sendo executada, uma cópia da string da consulta atual é também
alocada.
• Todas as threads compartilhas a mesma memória base.
• Somente as tabelas ISAM / MyISAM compactadas são mapeadas em memória. Isto é
porque o espaço de memória de 32-bits de 4GB não é grande o bastante para a maioria
das grandes tabelas. Quando sistemas com endereçamento de 64-bits se tornarem
comuns poderemos adicionar um suporte gieral para o mapeamento de memória.
• Cada requisição fazendo uma varredura sequencial em uma tabela aloca um buffer de
leitura (variável record_buffer).
• Ao ler registros na ordem ’randômica’ (por exemplo, depois de uma ordenação) um
buffer de leitura randômico é alocado para evitar pesquisas em disco. (variável record_
rnd_buffer).
• Todas as joins são feitas em um único passo, e a maioria delas podem ser feitas mesmo
sem usar uma tabela temporária. A maioria das tabelas temporárias são tabelas
baseadas em memória (HEAP). Tabelas temporárias com uma grande extensão de
registros (calculada como a soma do tamanho de todas as colunas) ou que contenham
colunas BLOB são armazenadas em disco.
Um problema nas versões do MySQL anteriores a versão 3.23.2 é que se uma tabela
HEAP excede o tamanho de tmp_table_size, você recebe o erro The table nome_
tabela is full. Em versões mais novas isto é tratado alterando automaticamente a
tabela em memória (HEAP) para uma tabela baseada em disco (MyISAM) quando
necessário. Para contornar este problema, você pode aumentar o tamanho da tabela
temporária configurando a opção tmp_table_size do mysqld, ou configurando a opção
do SQL SQL_BIG_TABLES no progrma cliente. See hundefinedi [SET OPTION], page hun-
definedi. Na versão 3.20 do MySQL, o número máximo da tabela temporária era
record_buffer*16, assim, se você estiver utilizando esta versão, você terá que au-
mentar o valor record_buffer. Você também pode iniciar o mysqld com a opção
--big-tables para sempre armazenar as tabelas temporárias em disco. Entretanto
isto afetará a velocidade de várias consultas complicadas.
• A maioria das requisições da ordenação alocam um bufer de ordenação e 0-2 arquivos
temporários dependendo do tamanho do resultado. See hundefinedi [Arquivos tem-
porário], page hundefinedi.
• Quase todas as análises e cálculos são feitos em um armazenamento de memória local.
Nenhuma sobrecarga de memória é necessário para ítens pequenos e a alocação e lib-
eração normal de memória lenta é evitada. A memória é alocada somente para grandes
strings inesperadas (isto é feito com malloc() e free()).
• Cada arquivo de índice é aberto uma vez e o arquivo de dados é aberto uma vez para
cada thread concorrente. Uma estrutura de tabela, estrutura de coluna para cada
coluna e um buffer de tamanho 3 * n é alocado para cada thread concorrente. (onde
n é o maior tamanho do registro, sem levar em consideração colunas BLOB. Um BLOB
utiliza de 5 a 8 bytes mais o tamanho dos dados contidos na mesma. O manipulador
de tabelas ISAM/MyISAM irão usar um registro extra no buffer para uso interno.
• Para cada tabela com colunas BLOB, um buffer é aumentado dinamicamente para ler
grandes valores BLOB. Se você ler uma tabela, um buffer do tamanho do maior registro
BLOB é alocado.
Chapter 5: Otimização do MySQL 363
• Manipuladores de tabelas para todas tabelas em uso são salvos em um cache e geren-
ciado como FIFO. Normalmente o cache possui 64 entradas. Se uma tabela foi usada
por duas threads ao mesmo tempo, o cache terá duas entredas para a tabela. See
hundefinedi [Cache de tabela], page hundefinedi.
• Um comando mysqladmin flush-tables fecha todas tabelas que não estão em uso
e marca todas tabelas em uso para serem fechadas quando a thread atualmente em
execução terminar. Isto irá liberar efetivamente a maioria da memória em uso.
ps e outros programas de informações do sistema podem relatar que o mysqld usa muita
memória. Isto pode ser causado pelas pilhas de threads em diferentes endereços de memória.
Por exemplo, a versão do ps do Solaris conta a memória não usada entre as pilhas como
memória usada. Você pode verificar isto conferindo a memória disponível com swap -s.
Temos testado o mysqld com detectores comerciais de perda de memória, portanto tais
perdas não devem existir.
or
SQL_BUFFER_RESULT = 0 | 1
SQL_BUFFER_RESULT irá forçar que o resultado de SELECT’s seja colocado em
tabelas temporárias. Isto irá ajudar o MySQL a liberar mais cedos bloqueios
de tabela e ajudarão em casos onde elas ocupam muito tempo para enviar o
conjunto de resultados para o cliente.
SQL_LOW_PRIORITY_UPDATES = 0 | 1
Se configurado com 1, todas instruções INSERT, UPDATE, DELETE e LOCK TABLE
WRITE irão esperar até que não existam SELECT ou LOCK TABLE READ pendentes
na tabela afetada.
SQL_MAX_JOIN_SIZE = valor | DEFAULT
Não permita que SELECTs que provavelmente necessitem examinar mais que
valor combinações de registros. Configurando este valor, você pode obter
SELECTs onde chaves não são usadas corretamente e que provavelmente gas-
tarão um bom tempo. Configurando-o para um valor diferente do DEFAULT
irá definir o atributo SQL_BIG_SELECTS com o padrão. Se você configurar o
atributo SQL_BIG_SELECTS novamente, a variável SQL_MAX_JOIN_SIZE será ig-
norada. Você pode configurar um valor padrão para esta variável iniciando o
mysqld com -O max_join_size=#.
SQL_SAFE_UPDATES = 0 | 1
Se configurado com 1, o MySQL irá aborar se tentarmos fazer um UPDATE
ou DELETE sem utilizar uma chave ou LIMIT na cláusula WHERE. Desta forma
é possível capturar atualizações erradas ao criarmos comandos SQL manual-
mente.
SQL_SELECT_LIMIT = valor | DEFAULT
O número máximo de registros para retornar de instruções SELECT. Se uma
SELECT tem uma cláusula LIMIT, o LIMIT tem precedêencia sobre o valor de
SQL_SELECT_LIMIT. O valor padrão para uma nova conexão é “unlimited” (ilim-
itado). Se você alterou o limite, o valor padrão pode ser restaurado atribuindo
o valor DEFAULT a SQL_SELECT_LIMIT.
SQL_LOG_OFF = 0 | 1
Se configurado com 1, nenhum registro será feito no log padrão para este cliente,
se o cliente tiver o privilégio process. Isto não afeta o log de atualizações!
SQL_LOG_UPDATE = 0 | 1
Se configurado com 0, nenhum registro será feito no log de atualizações para o
cliente, se o cliente tiver o privilégio process. Isto não afeta o log padrão!
SQL_QUOTE_SHOW_CREATE = 0 | 1
Se configurado com 1, SHOW CREATE TABLE irá colocar os nomes de tabela e
colunas entre aspas. Está ligado por padrão, para que replicação de tabelas
com nomes de colunas estranhos funcione. hundefinedi [SHOW CREATE TABLE],
page hundefinedi.
TIMESTAMP = valor_timestamp | DEFAULT
Configura a hora/data para este cliente. É usado para obter a hora e data
original se você utiliza o log de atualizações para restaurar registros. valor_
timestamp deve ser um timestamp UNIX Epoch, não um timestamp MySQL.
366 Referência técnica para o MySQL versão 3.23.52
LAST_INSERT_ID = #
Configura o valor a ser retornado de LAST_INSERT_ID(). Ele é armazenado
no log de atualizações quando você utiliza LAST_INSERT_ID() em um comando
que atualiza uma tabela.
INSERT_ID = #
Configura o valor que será usado pelo comando INSERT ou ALTER TABLE seguinte
ao inserir um valor AUTO_INCREMENT. Isto é usado principalmente com o log de
atualizações.
• Uma boa opção é ter ter dados de média importância (aqueles que podem ser regen-
erados) em um armazenamento RAID 0 enquanto os dados realemtente importantes
(como informações de máquinas e logs) em um sistema RAID 0+1 ou RAID de N dis-
cos. RAID N pode ser um problema se você tem várias escritas devido ao tempo para
atualizar os bits de paridade.
• Você pode também configurar os parâmetros para o sistema de arquivos que o banco
de dados usa. Uma alteração simples é montar o sistema de arquivos com a opção
noatime. Isto faz com que ele evite a atualização do último tempo de acesso no inode
e com isto também evita algumas buscas em disco.
• No Linux, você pode obter um desempenho muito melhor (cerca de 100% sobre carga
pode ser comum) utilizando hdparm para configurar sua interface de disco! O exemplo
a seguir deve ser muito útil para o MySQL (e provavelmente várias outras aplicações):
hdparm -m 16 -d 1
Perceba que o desempenho/confiança ao utilizar o exemplo acima depende de seu hard-
ware, portanto nós sugerimos que você teste bem seu sistema depois de utilizar hdparm!
Por favor consulte a página do manual (man) do hdparm para maiores informações! Se
o hdparm não for usado corretamente, poderá resultar em corrupção do sistema de
arquivos. Realize backups de tudo antes de experimentar!
• Em vários sistemas operacionais os discos podem ser montados com a opção ’async’
para configurar o sistema de arquivos a ser atualizado de modo assíncrono. Se o seu
computador é razoavelmente estável, isto deve fornecer mais desempenho sem sacrificar
a segurança. (Esta opção é ligada por padrão no Linux.)
• Se você não precisar saber a última vez que um arquivo foi acessado (o que realmente
não é muito útil em um servidor de banco de dados), você pode montar seus sistema
de arquivos com a opção noatime.
de dados db1 sob o diretório de dados do MySQL, e então criar uma ligação simbólica db2
que aponte para db1.
shell> cd /caminho/para/diretorio/dados
shell> ln -s db1 db2
Agora, para qualquer tabela tbl_a em db1, também aparecerá uma tabela tbl_a em db2.
Se uma thread atualizar db1.tbl_a e outra atualizar db2.tbl_a, ocorrerão porblemas.
Se você realmente precisar disto, você deve alterar o código seguinte em ‘mysys/mf_
format.c’:
if (flag & 32 || (!lstat(to,&stat_buff) && S_ISLNK(stat_buff.st_mode)))
para
if (1)
No Windows você pode utilizar links simbólicos para diretórios compilando o MySQL com
-DUSE_SYMDIR. Isto lhe permite colocar diferentes bancos de dados em discos diferentes.
See hundefinedi [Links simbólicos no Windows], page hundefinedi.
• Se você renomear uma tabela com ALTER TABLE RENAME e não deseja alterar o banco de
dados, o link simbólico para o diretório de banco de dados será renomeada corretamente.
• Se você utiliza ALTER TABLE RENAME para mover uma tabela para outro banco de dados,
então a tabela será movida para outro diretório de banco de dados e os links simbólicos
antigos e os arquivos para os quais eles apontam serão removidos.
• Se você não utiliza links simbólicos, você deve usar a opção --skip-symlink do mysqld
para garantir que ninguém pode apagar ou renomear um arquivo fora do diretório de
dados do mysqld.
O que ainda não é suportado:
• ALTER TABLE ignora todas as opções INDEX/DATA DIRECTORY="caminho".
• CREATE TABLE não relata se a tabela possui links simbólicos.
• O mysqldump não inclui a informação de links simbólicos na saída.
• BACKUP TABLE e RESTORE TABLE não respeitam links simbólicos.
370 Referência técnica para o MySQL versão 3.23.52
6.1.1.1 Strings
Uma string é uma sequência de caracteres, cercada por caracteres de aspas simples (‘’’)
ou duplas (‘"’) (Se você utiliza o modo ANSI deve utilizar somente as aspas simples).
Exemplos:
’uma string’
"outra string"
Em uma string, certas sequências tem um significado especial. Cada uma destas sequências
começam com uma barra invertida (‘\’), conhecida como caracter de escape. O MySQL
reconhece a seguinte sequência de escape:
\_ Um caracter ‘_’. Ele é usado para pesquisar por instâncias literais de ‘_’ em
contextos onde ‘_’ deve, de outra maneira, ser intrerpretado como um meta
caracter. See hundefinedi [Funções de comparações de string], page hundefinedi.
Note que se você utilizar ‘\%’ ou ‘\_’ em alguns contextos de strings, eles retornarão as
strings ‘\%’ e ‘\_’ e não ‘%’ e ‘_’.
Estas são as várias maneiras de incluir aspas com uma string:
• Um ‘’’ dentro de uma string com ‘’’ pode ser escrita como ‘’’’.
• Um ‘"’ dentro de uma string com ‘"’ pode ser escrita como ‘""’.
• Você pode preceder o caracter de aspas com um caracter de escape (‘\’).
• Um ‘’’ dentro de uma string com ‘"’ não precisa de tratamento especial e não precisa
ser duplicada ou utilizada com caracter de escape. Da mesma maneira, ‘"’ dentro de
uma string com ‘’’ não necessita de tratamento especial.
As instruções SELECT exibidas abaixo demonstram como citações e escapes funcionam:
mysql> SELECT ’hello’, ’"hello"’, ’""hello""’, ’hel’’lo’, ’\’hello’;
+-------+---------+-----------+--------+--------+
| hello | "hello" | ""hello"" | hel’lo | ’hello |
+-------+---------+-----------+--------+--------+
6.1.1.2 Números
Inteiros são representados como uma sequência de dígitos. Números de ponto flutuante
utilizam ‘.’ como um separador decimal. Ambos os tipos devem ser precedidos por ‘-’ para
indicar um valor negativo.
Exemplos de inteiros válidos:
1221
0
-32
Exemplo de números de ponto flutuante válidos:
294.42
-32032.6809e+10
148.00
Um inteiro pode ser usado em um contexto de ponto flutuante; ele é interpretado como o
de ponto flutuante equivalente.
É recomendado que você não utilize nomes como 1e, porque uma expressão como 1e+1 é
ambígua. Ela pode ser interpretada como a expressão 1e + 1 ou como o número 1e+1.
No MySQL você pode se referir a uma coluna utilizando uma das formas seguintes:
Coluna de referência Significado
nome_campo Coluna nome_campo de qualquer tabela usada na consulta
contendo uma coluna com aquele nome.
nome_tabela.nome_campo Coluna nome_campo da tabela nome_tabela do banco de
dados atual.
nome_bd.nome_tabela.nome_ Coluna nome_campo da tabela nome_tabela do banco
campo de dados nome_bd. Esta forma é disponível no MySQL
Versão 3.22 ou posterior.
‘nome_coluna‘ Uma coluna que é uma palavra chave ou contem carac-
teres especiais.
Você não precisa especificar um prefixo de nome_tabela ou nome_bd.nome_tabela para
uma referência de coluna em uma instrução, a menos que a referência seja ambígua. Por
exemplo, suponha que cada tabela t1 e t2 contenham uma coluna c, e você deve recuperar
c em uma instrução SELECT que utiliza ambas tabelas t1 e t2. Neste caso, c é ambíguo
porque ele não é único entre as tabelas usadas na instrução, portanto deve ser indicado qual
é a tabela que se deseja escrever, t1.c ou t2.c. De mesma forma, se você for recuperar de
uma tabela t em um banco de dados db1 e uma tabela t em um banco de dados db2, você
deve se refererir às colunas nestas tabelas como db1.t.nome_campo e db2.t.nome_campo.
374 Referência técnica para o MySQL versão 3.23.52
Voce tambm pode configurar uma variável em uma expressão com a sintaxe
@variable:=expr
select @t1:=(@t2:=1)+@t3:=4,@t1,@t2,@t3;
+----------------------+------+------+------+
| @t1:=(@t2:=1)+@t3:=4 | @t1 | @t2 | @t3 |
+----------------------+------+------+------+
| 5 | 5 | 1 | 4 |
+----------------------+------+------+------+
(Devemos utilizar a syntax := aqui porque = esta reservado para comparações).
Variáveis de usuários devem ser utilizadas em expressões onde são permitidas. Isto não
inclui utiliza-las em contextos onde um número é explicitamente necessário, assim como
na cláusula LIMIT de uma instrução SELECT ou a clausula IGNORE number LINE de uma
instrução LOAD DATA.
NOTE: Em uma instrução SELECT , cada expressão só é avaliada quando enviada ao cliente.
Isto significa que nas cláusula HAVING, GROUP BY, ou ORDER BY, você não pode fazer referência
a uma expreesão que envolve variáveis que são configuradas na instrução SELECT. Por
examplo, a seguinte instrução NÃO funcionará como o esperado:
SELECT (@aa:=id) AS a, (@aa+3) AS b FROM nome_tabela HAVING b=5;
A razão é que o @aa não irá conter o valor da linha atual. , mas o valor da id da linha
previamente aceita.
Estas limitações se aplicam tanto a quando se executa mysql interativamente quanto quando
se coloca oos comandos em um arquivo e pede para que mysql leia as entradas deste arquivo
com o comando mysql < some-file.
MySQL não suporta o estilo de comentário ANSI SQL ‘--’. See hundefinedi [Missing
comments], page hundefinedi.
lhe dá uma visão geral dos tipos disponíveis e resume as exigencias de armazenamento em
cada tipo de coluna, também fornece uma descrição mais detalhada da propriedade dos
tipos em cada categoria. A visão dada é propositalmente breve. As descrições mais detal-
hdas devem ser consultadas para informações adicionais sobre tipos de campo particulares
como os formatos permitidos nos quais você pode especificar valores.
Os tipos de campos suportados pelo MySQL estão listados abaixo: As seguintes letras são
usadas como código nas descrições:
M Indica o tamanho máximo do display. O tamanho máximo oficial do display é
255.
D Aplica aos tipos de ponto flutuante e indica o número de digitos após o ponto
decimal. O maior valor possível é 30, mas não pode ser maior que M-2.
Colchetes (‘[’ and ‘]’) indicam partes de tipos específicos que são opicionais
Note que se você especificar ZEROFILL para um campo MySQL automaticamente irá adi-
cionar o atributo UNSIGNED ao campo.
• ‘-’, ‘+’, e ‘*’ serão utilizados em cálculos aritiméticos BIGINT quando ambos
os argumentos forem valores do tipo INTEGER! Isto significa que se você
multilicar dois inteiros grandes (ou obter resultados de funções que retor-
nam inteiros) você pode obter resultados inesperados quando o resultado
for maior que 9223372036854775807.
FLOAT(precis~ao) [ZEROFILL]
Um número de ponto flutuante. Não pode ser sem sinal. precis~ ao pode ser
<=24 para um número de ponto flutuante de precisão simples e entre 25 e 53
para um número de ponto flutuante de dupla-precisão. Estes tipos são como os
tipos FLOAT e DOUBLE descritos logo abaixo. FLOAT(X) tem o mesma faixa que
os tipos correspondentes FLOAT e DOUBLE, mas o tamanho do display e número
de casas decimais é indefinido.
Na versão 3.23 do MySQL, este é um verdadeiro valor de ponto flutuante. Em
versões anteriores , FLOAT(precis~
ao) sempre tem 2 casas decimais.
Note que o uso de FLOAT pode trazer alguns problemas inesperados como nos
cálculos já que em MySQL todos são feitos com dupla-precisão. See hundefinedi
[No matching rows], page hundefinedi.
Esta sintaxe é fornecida para comptibilidade com ODBC.
FLOAT[(M,D)] [ZEROFILL]
Um numero de ponto flutuante pequeno (precisão simples). Não pode ser sem
sinal. Os valores permitidos são de -3.402823466E+38 a -1.175494351E-38, 0
e de 1.175494351E-38 a 3.402823466E+38. O M é a largura do display e o D é
o número de casas decimais. FLOAT sem um argumento ou com um argumento
<=24 tende a um numero de ponto flutuante de precisão simples.
DOUBLE[(M,D)] [ZEROFILL]
Um número de ponto flutuante de tamanho normal (dupla-precisão). Não
pode ser sem sinal. Valores permitidos entre -1.7976931348623157E+308
e -2.2250738585072014E-308, 0 e entre 2.2250738585072014E-308 e
1.7976931348623157E+308. O M é a largura do display e o D é número de
casa decimais. DOUBLE sem argumento ou FLOAT(X) onde 25 <= X <= 53 são
números de ponto flutuante de dupla-precisão.
DOUBLE PRECISION[(M,D)] [ZEROFILL]
REAL[(M,D)] [ZEROFILL]
Estes são sinônimos para DOUBLE.
DECIMAL[(M[,D])] [ZEROFILL]
Um número de ponto flutuante não empacotado. Não pode ser sem sinal. Se
comporta como um campo CHAR: “não empacotado” significa que o número é
armazenado como uma string, usando um caracter para cada digito do valor.
O ponto decimal e, para números negativos, o sinal de menos (‘-’), não são
contados em M (mas é reservado espaço para isto). Se D for 0, os valores não
terão ponto decimal ou parte fracionária. A faixa máxima do valor DECIMAL é
a mesma do DOUBLE, mas a faixa atual para um campo DECIMAL dado pode ser
limitado pela escolha de M e D.
380 Referência técnica para o MySQL versão 3.23.52
Se D não for definido será considerado como 0. Se M não for definido é consid-
erado como 10.
Note que na versão 3.22 do MySQL o argumento M tem que incluir o espaço
necessário para o sinal é o ponto decimal.
NUMERIC(M,D) [ZEROFILL]
Este é um sinônimo para DECIMAL.
DATE
Uma data. A faixa suportada é entre ’1000-01-01’ e ’9999-12-31’. MySQL
mostra valores DATE no formato ’AAAA-MM-DD’, mas permite a você a atribuir
valores a campos DATE utilizando tanto strings quanto números. See hundefinedi
[DATETIME], page hundefinedi.
DATETIME
Um combinação de hora e data. A faixa suportada é entre ’1000-01-01
00:00:00’ e ’9999-12-31 23:59:59’. MySQL mostra valores DATETIME no
formato ’AAAA-MM-DD HH:MM:SS’, mas permite a você que atribuir valores a
campos DATETIME utilizado strings ou números. See hundefinedi [DATETIME],
page hundefinedi.
TIMESTAMP[(M)]
Uma estampa de tempo. A faixa é entre ’1970-01-01 00:00:00’ e algum
momento no ano 2037. MySQL mostra valores TIMESTAMP nos formatos
YYYYMMDDHHMMSS, YYMMDDHHMMSS, YYYYMMDD, ou YYMMDD, dependendo se M é
14 (ou não definido), 12, 8, ou 6, mas permite a você atribuir valores ao
campo TIMESTAMP usando strings ou números. Um cmapo TIMESTAMP é util
para gravar a data e a hora em uma operação de INSERT or UPDATE porque é
automaticamente definido a data e a hora da operação mais recente se você
próprio não especificar um valor. Você também pode definir a data e a hora
atual atribuindo ao campo um valor NULL. See hundefinedi [Date and time
types], page hundefinedi.
Um TIMESTAMP sempre é armazenado em 4 bytes. O argumento M só afeta como
a coluna TIMESTAMP é mostrada.
Note que colunas do tipo TIMESTAMP(X) columns onde X é 8 ou 14 são apre-
sentadas como números enquanto as outras colunas TIMESTAMP(X) são strings.
Isto é apenas para assegurar que podemos eliminar e restaurar com segurança
tabelas com estes tipos! See hundefinedi [DATETIME], page hundefinedi.
TIME
Uma hora. A faixa é entre ’-838:59:59’ e ’838:59:59’. MySQL mostra
valores TIME no formato ’HH:MM:SS’, mas permite a você atribuir valores para
as colunas TIME usando strings ou números. See hundefinedi [TIME], page hun-
definedi.
YEAR[(2|4)]
Um ano no formato de 2 ou 4 digitos (padrão são 4 digitos). Os valores per-
mitidos estão entre 1901 e 2155, 0000 no formato de 4 digitos, e 1970-2069
se você estiver usando o formato de 2 digitos (70-69). MySQL mostra valores
Chapter 6: Referência de Linguagem do MySQL 381
YEAR no formato YYYY, mas permie atribuir valores aos campos do tipo YEAR
usando strings ou números. (O tipo YEAR é novo na versão 3.22 do MySL). See
hundefinedi [YEAR], page hundefinedi.
BIT
BOOL
CHAR Estes três são sinônimos para CHAR(1).
TINYBLOB
TINYTEXT
Um campo BLOB ou TEXT com tamanho máximo de 255 (2^8 - 1) caracteres. See
hundefinedi [Silent column changes], page hundefinedi. See hundefinedi [BLOB],
page hundefinedi.
BLOB
TEXT
Um campo BLOB ou TEXT com tamanho máximo de 65535 (2^16 - 1) caracteres.
See hundefinedi [Silent column changes], page hundefinedi. See hundefinedi
[BLOB], page hundefinedi.
382 Referência técnica para o MySQL versão 3.23.52
MEDIUMBLOB
MEDIUMTEXT
Um campo BLOB ou TEXT com tamanho máximo de 16777215 (2^24 - 1) carac-
teres. See hundefinedi [Silent column changes], page hundefinedi. See hunde-
finedi [BLOB], page hundefinedi.
LONGBLOB
LONGTEXT
Um campo BLOB ou TEXT com tamanho máximo de 4294967295 (2^32 - 1)
caracteres. See hundefinedi [Silent column changes], page hundefinedi. See hun-
definedi [BLOB], page hundefinedi. Note que como o protocolo cliente/servidor
e tabelas MyISAM tem, atualmente, um limite de 16M por pacote de trans-
missão/registro de tabela, você ainda não pode utilizar toda a faixa de valores
deste tipo. See hundefinedi [BLOB], page hundefinedi.
ENUM(’valor1’,’valor2’,...)
Uma enumeração. Um objeto string que só pode ter um valor, selecionado da
lista de valores ’valor1’, ’valor2’, ..., NULL ou valor especial de erro "".
Um ENUM pode ter um máximo de 65535 valores diferentes. See hundefinedi
[ENUM], page hundefinedi.
SET(’valor1’,’valor2’,...)
Um conjunto. Um objeto string que pode ter zero ou mais valores, cada um
deve ser selecionado da lista de valores ’valor1’, ’valor2’, .... Um SET pode
ter até 64 membros. See hundefinedi [SET], page hundefinedi.
O tipo DATETIME é usado quando você precisa de valores que contém informações sobre
data e a a hora. MySQL recupera e mostra valores DATETIME no formato ’YYYY-MM-DD
HH:MM:SS’. A faixa suportada é de ’1000-01-01 00:00:00’ até ’9999-12-31 23:59:59’.
(“Suportada” significa que embora valores anteriores possam funcionar, não há nenhura
garantia de disto.)
O tipo DATA é usado quando se necessita apenas do valor da data, sem a parte da hora.
MySQL recupera e mostra valores do tipo DATA no formato ’YYYY-MM-DD’. A faixa supor-
tada é de ’1000-01-01’ até ’9999-12-31’.
O tipo de campo TIMESTAMP fornece um tipo que pode ser usado para, automaticamente,
marcar operações INSERT or UPDATE com a data e hora atual. Se você tiver multiplas colunas
TIMESTAMP, só a primeira é atualizada automaticamente.
Atualizações automaticas da primeira coluna TIMESTAMP ocorrem sob qualquer uma das
seguintes condições:
• A coluna não é explicitamente especificada em uma instrução INSERT ou LOAD DATA
INFILE.
• A coluna não é explicitamente especificada em uma instrução UPDATE e e alguma outra
coluna muda o valor. (Note que um UPDATE que coloca em uma coluna o mesmo
valor que ele já possui não irá causar a atualização da coluna TIMESTAMP, porque se
você atribui a uma coluna o seu valor atual, MySQL ignora a atualização para maior
eficiência).
• Você define explicitamente a uma coluna TIMESTAMP o valor NULL.
Outras colunas TIMESTAMP, além da primeira podem ser definidas com a data e hora atuais.
Basta defini-las com NULL ou NOW()
Você pode definir colunas TIMESTAMP com um valor diferente da data e hora atuais colocando
explicitamente o valor desejado. Isto é verdade mesmo para a primeira coluna TIMESTAMP.
Você pode usar esta propriedade se, por exemplo, você quiser que um TIMESTAMP tenha seu
valor definido como a data e hora atuais na criação de registros, mas não quer alterá-los
quando o registro for atualizado mais tarde:
• Deixe o MySQL definir a coluna quando o registro é criado. Isto irá inicializa-la com
a data e hora atuais.
• Quando você realizar subsequentes atualizações em outras colunas do registro, defina
explicitamente a coluna TIMESTAMP com o valor atual.
Por outro lado, você pode achar que é mais fácil usar uma coluan DATETIME que você inicial-
iza com NOW() quando o registro for criado e deixa como está em atualizações subsequentes.
Valores TIMESTAMP podem ter valores do incio de 1970 até algum momento do ano 2037,
com a resolução de um segundo. Valores são mostrados como números
O formato no qual o MySQL recupera e mostra valores TIMESTAMP depende do tamanho
do display, como ilustrado pela tabela que se segue: O formato ‘cheio’ TIMESTAMP é de 14
digitos, mas colunas TIMESTAMP podem ser criadas com tamanho de display menores:
Tipo da Coluna Formato do Display
TIMESTAMP(14) YYYYMMDDHHMMSS
TIMESTAMP(12) YYMMDDHHMMSS
TIMESTAMP(10) YYMMDDHHMM
Chapter 6: Referência de Linguagem do MySQL 387
TIMESTAMP(8) YYYYMMDD
TIMESTAMP(6) YYMMDD
TIMESTAMP(4) YYMM
TIMESTAMP(2) YY
Todas as colunas TIMESTAMP tem o mesmo tamanho de armazenamento, independente do
tamanho de display. Os tamanhos de display mais comuns são 6, 8, 12, e 14. Você pode
especificar um tamanho de display arbitrario na hora da criação da tabela, mas valores de
0 ou maiores que 14 são mudados para 14. Valores ímpares de tamanho na faixa de 1 a 13
são mudados para o maior número par mais próximo.
Nota: Na versão 4.1, TIMESTAMP é retornado com uma string com o formato ’YYYY-MM-DD
HH:MM:DD’, e timestamp de diferentes tamamnhos não são mais suportados.
Você pode especificar calores DATETIME, DATE e TIMESTAMP usando qualquer conjunto de
formatos comum:
• Como uma string nos formatos ’YYYY-MM-DD HH:MM:SS’ ou ’YY-MM-DD HH:MM:SS’.
Uma sintaxe “relaxada” é permitida---nenhum caracter de pontuação pode ser usado
como um delimitador entre parte de data ou hora. Por exemplo, ’98-12-31 11:30:45’,
’98.12.31 11+30+45’, ’98/12/31 11*30*45’, e ’98@12@31 11^30^45’ são equiva-
lentes.
• Como uma string nos formatos ’YYYY-MM-DD’ ou ’YY-MM-DD’. Uma sintaxe “relaxada”
é permitida aqui também. Por exemplo, ’98-12-31’, ’98.12.31’, ’98/12/31’, e
’98@12@31’ são equivalentes.
• Como uma string sem delimitadores nos formatos ’YYYYMMDDHHMMSS’ ou
’YYMMDDHHMMSS’, desde que a string faça sentido como data. Por example,
’19970523091528’ e ’970523091528’ são interpretadas com ’1997-05-23
09:15:28’, mas ’971122129015’ é ilegal (tem uma parte de minutos sem sentido) e
se torna ’0000-00-00 00:00:00’.
• Como uma string sem delimitadores nos formatos ’YYYYMMDD’ ou ’YYMMDD’, desde
que a string tenha sentido com data. Por exemplo, ’19970523’ e ’970523’ são in-
terpretedas como ’1997-05-23’, mas ’971332’ é ilegal (tem uma parte de mês sem
sentido) e se torna ’0000-00-00’.
• Como um número nos formatos YYYYMMDDHHMMSS ou YYMMDDHHMMSS, desde que o
número faça sentido como uma data. Por exemplo, 19830905132800 e 830905132800
são interpretedos como ’1983-09-05 13:28:00’.
• Como um número nos formatos YYYYMMDD ou YYMMDD, desde que o número faça sentido
como data. Por exemplo, 19830905 e 830905 são interpretedos como ’1983-09-05’.
• Como o resultado de uma função que retorne uma valor aceitavel em um contexto
DATETIME, DATE ou TIMESTAMP, tal como NOW() ou CURRENT_DATE.
Valores DATETIME, DATE, ou TIMESTAMP ilegais são convertidos para o valor “zero” do tipo
apropriado (’0000-00-00 00:00:00’, ’0000-00-00’, ou 00000000000000).
Para valores especificados com strings que incluem delimitadores de data, não é necessário
especificar dois digitos para valores de mês ou dia qua são menores que 10. ’1979-6-9’
é o mesmo que ’1979-06-09’. Similarmente, para valores especificados como strings que
incluem delimitadores de hora, não é necessário especificar dois digitos para valores de
388 Referência técnica para o MySQL versão 3.23.52
hora, minutos ou segundo que são menores que 10. ’1979-10-30 1:2:3’ Ré o mesmo que
’1979-10-30 01:02:03’.
Valores especificados como números devem ter 6, 8, 12, ou 14 digitos. Se o número é de
8 ou 14 digitos, ele assume estar no formato YYYYMMDD ou YYYYMMDDHHMMSS e que o ano
é dado pelos 4 primeiros dígitos. Se o é de 6 ou 12 dígitos, ele assume estar no formato
YYMMDD or YYMMDDHHMMSS e que o ano é dado pelos 2 primeiros digitos. Números que não
possua estes tamanho são interpretados como calores preenchidos com zero até o tamanho
mais próximo.
Valores especificados como strings não delimitadas são interpretados usando o seu tamanho
como dado. Se a string possui 8 ou 14 caracteres, o ano é assumido como os 4 primeiros
caracteres. De outra forma o assume-se que o ano são os 2 primeiros caracteres. A string
é interpretadada esquerda para direita para encontrar os valores do ano, mês, dia, hora,
minute e segundo, para as partes da string. Isto significa que você não deve utilizar strings
com menos de 6 caracteres. Por exemplo, se você especificar ’9903’, pensando em repre-
sentar Março de 1999, você perceberá que o MySQL insere uma data “zero” em sua tabela.
Isto ocorre porque os valores do ano e mês são 99 e 03, mas a parte contendo o dia não
existe (zero), então o valor não é uma data legal.
Colunas TIMESTAMP armazena valores legais utilizando precisão total com a qual os valores
foram especificados, independente do tamanho do display. Isto tem diversas implicações:
• Sempre especifique o ano, mês e dia, mesmo se seus tipos de coluna são TIMESTAMP(4)
ou TIMESTAMP(2). De outra forma, os valores não serão datas legais date e um 0 será
armazenado.
• Se você usa ALTER TABLE para aumentar uma coluna TIMESTAMP, informações serão
mostradas como se antes estivessem “escondidas”.
• De forma similar, reduzindo o tamanho de uma coluna TIMESTAMP não causa perda de
informação, exceto no sentido de que menos informação aparece quando os valores são
mostrados.
• Embora os valores TIMESTAMP sejam armazenados com precisão total, a única função
que opera diretamente com o valor armazenado é UNIX_TIMESTAMP(). OUtras funções
operam com o formato do valor recuperado Isto significa que não se pode usar funções
como HOUR() or SECOND() a menos que a parte relevante do valor TIMESTAMP esteja
incluído no valor formatado. POr exemplo, a parte HH de uma coluna TIMESTAMP não
é mostrada a menos que o tamanho do display seja de pelo menos 10, logo tentar usar
HOUR() em um valor TIMESTAMP menor produz um resultado sem significado.
Você pode, algumas vezes, atribuir valores de um tipo de data para um objeto de um
diferente tipo de data. No entanto pode haver algumas alterações de valores ou perda de
informação
• Se você atribuir um valor de DATE value a um objeto DATETIME ou TIMESTAMP, a parte
da hora do valor resultante é definido como ’00:00:00’, porque o vlaor DATE não
contém informações de hora.
• Se você atribuir um valor DATETIME ou TIMESTAMP para um objeto DATE, a parte da
hora do valor resultante é deletado, pois o tipo DATE não armazena informações de
hora.
• Lembre-se de que embora todos os valores DATETIME, DATE, e TIMESTAMP possam ser
especificados usando o mesmo conjunto de formatos, os tipos não tem a mesa faixa de
Chapter 6: Referência de Linguagem do MySQL 389
valores. Por exemplo, valores TIMESTAMP não podem ser anteriores a 1970 ou posteriores
a 2037. Isto significia que datas como ’1968-01-01’, são permitidas como valores
DATETIME ou DATE, mas não são válidas para valores TIMESTAMP e serão covertidas para
0 se atribuidas para tais objetos.
Para valores TIME especificados como uma string que incluem delimitadores de hora, não
é necessário especificar dois dígitos para valores de hora, minutos ou segundos que sejam
menores que 10. ’8:3:2’ é o mesmo que ’08:03:02’.
Seja cuidadoso ao atribuir valores TIME “pequenos” para uma coluna TIME. Sem dois pontos,
o MySQL interprete valores assumindo que os digitos mais a direita representam segundos.
(MySQL interpreta valores TIME como tempo decorrido ao invés de hora do dia.) Por
exemplo, você poderia pensar em ’1112’ e 1112 significam ’11:12:00’ (11 horas e 12
minutos), mas o MySQL o intepreta como ’00:11:12’ (onze minutos e 12 segundos). De
forma similar, ’12’ e 12 são interpretados como ’00:00:12’. Valores TIME com dois pontos,
em contrapartida, são tratados como hora do dia. Isto é, ’11:12’ significará ’11:12:00’,
não ’00:11:12’.
Valores que são legais mas que estão fora da faixa permitidas são ajustados para o valor
limita da faixa mais apropriado. Por exemplo, ’-850:00:00’ e ’850:00:00’ são conver-
tidos para ’-838:59:59’ e ’838:59:59’, respectivmente.
Valores TIME ilegais são convertidos para ’00:00:00’. Note que como ’00:00:00’ é um
valor TIME, não temos com dizer, a partir de um valor ’00:00:00’ armazenado na tabela,
se o valor original armazenado foi especificado como ’00:00:00’ ou se foi ilegal.
no tamanho maximo dos valores que eles podem guradar. See hundefinedi [Storage require-
ments], page hundefinedi.
Os quatro tipos TEXT: TINYTEXT, TEXT, MEDIUMTEXT, e LONGTEXT correspondem aos quatro
tipos BLOB e têm o mesmo tamanho máximo e necessidade de tamanho para armazenamento.
A única diferença entre os tipos BLOB e TEXT é que ordenação e comparação são realizadas
no modo caso-sensitivo para valores BLOB e no modo caso-insensitivo para valores TEXT. Em
outras palavras, um TEXT é um BLOB no modo caso-insensitivo.
Se você atribuir um valor a uma coluna BLOB ou TEXT que exceda o tamanho máximo do
tipo da coluna, o valor é truncado para servir ao campo.
Em muitos casos, podemos considerar um campo TEXT como um campo VARCHAR que pode
ser tão grande quando desejamos. Da mesma forma podemos considerar um campo BLOB
como um campo VARCHAR BINARY. As diferenças são:
• Você pode ter indices em um campo BLOB e TEXT no MySQL Versão 3.23.2 e mais
novas. Versões antigas do MySQL não suportam isto.
• Não há remoção de espaços extras para campos BLOB e TEXT quando os valores são
armazenados, como há em campos VARCHAR.
• Colunas BLOB e TEXT não podem ter valores padrões.
MyODBC define valores BLOB como LONGVARBINARY e valores TEXT como LONGVARCHAR.
Como valores BLOB e TEXT podem ser extremamentes longos, você pode deparar com alguns
problemas quando utilizá-los:
• Se você quiser utilizar GROUP BY ou ORDER BY em um campo BLOB ou TEXT, você deve
converte-los em objetos de tamanho fixo. O modo padrão de se fazer isto é com a
função SUBSTRING. Por exemplo:
mysql> SELECT comentario FROM nome_tabela,SUBSTRING(comentario,20) AS substr
-> ORDER BY substr;
Se você não fizer isto, só os primeiros max_sort_length bytes de uma coluna serão
utilizados na ordenação. O valor padrão de max_sort_length é 1024; este calor pode
ser alterado utilizando-se a opção -O quando o servidor é inicializado. Você pode
agrupar uma expressão envolvendo valores BLOB ou TEXT especificando a posição da
coluna ou utilizando apelidos (alias):
mysql> SELECT id,SUBSTRING(col_blob,1,100) FROM nome_tabela GROUP BY 2;
mysql> SELECT id,SUBSTRING(col_blob,1,100) AS b FROM nome_tabela GROUP BY b;
• O tamanho máximo de uma objeto BLOB ou TEXTé determinado pelo seu tipo, mas o
maior valor que você pode, atualmente, transmitir entre o cliente e o servidor é determi-
nado pela quantidade de memória disponível e o tamanho dos buffers de comunicação.
Você pode mudar o tamanho do buffer de mensagem, mas você deve faze-lo no servidor
e no cliente. See hundefinedi [Server parameters], page hundefinedi.
Note que cada valor BLOB ou TEXT é representado internamente por um objeto alocado
searadamente. Está é uma diferença com todos os outros tipos de colunas, para o qual o
armazenamento é alocado um por coluna quando a tabela é aberta.
Chapter 6: Referência de Linguagem do MySQL 393
Valores ENUM são armazenados de acordo com a ordem na qual os membros da enumeração
foram listados na especificação da coluna. (Em outras palavras, valores ENUM são ordena-
dos de acordo com o seus números de índice.) Por exemplo, "a" vem antes de "b" para
ENUM("a", "b"), mas "b" vem antes de "a" para ENUM("b", "a"). A string vazia vem
antes de strings não-vazias, e valores NULL vem antes de todos os outros valores de enu-
meração. Para evitar resultados inesperados, especifique a lista ENUM em ordem alfabética.
Você também pode usar GROUP BY CONCAT(col) para ter certeza de que as colunas estão
ordenadas alfabeticamente e não pelo índice numérico.
Se você quiser obter todos os valores possíveis para uma coluna ENUM, você deve usar:
SHOW COLUMNS FROM nome_tabela LIKE nome_coluna_enum e analizar a definição de ENUM
na segunda coluna.
Para um valor contendo mais que um elemento de SET, não importa em qual ordem os
elementos são listados quando foram inseridos seus valores. Também não importa quan-
tas vezes um dado elemento e listado no valor. Quando o valor é recuperado posterior-
mente, cada elemento aparecerá uma vez, listados de acordo com a ordem em que eles
foram especificados na crição da tabela. Por exemplo, se uma coluna é especificada como
SET("a","b","c","d"), então "a,d", "d,a" e "d,a,a,d,d" irão todos aparecer como
"a,d" quando recuperados.
Se você define um valor que não é suportado pela coluna SET, o valor será ignorado.
Valores SET são ordenados numéricamente. Valores NULL vêm antes de valores SET não
NULL.
Normalmente, você realiza um SELECT em uma coluna SET usando o operador LIKE ou a
função FIND_IN_SET():
mysql> SELECT * FROM nome_tabela WHERE col_set LIKE ’%valor%’;
mysql> SELECT * FROM nome_tabela WHERE FIND_IN_SET(’valor’,col_set)>0;
Mas o seguinte também funciona:
mysql> SELECT * FROM nome_tabela 2 WHERE col_set = ’val1,val2’;
mysql> SELECT * FROM nome_tabela 3 WHERE col_set & 1;
A primeira desta instruções procura por uma correpondencia exata. A segunda por valores
contendo o primeiro membro.
Se você quer obter todos os valores possíveis para uma coluna SET, você deve usar: SHOW
COLUMNS FROM nome_tabela LIKE nome_coluna_set e analizar a definição do SET na se-
gunda coluna.
FLOAT4 FLOAT
FLOAT8 DOUBLE
INT1 TINYINT
INT2 SMALLINT
INT3 MEDIUMINT
INT4 INT
INT8 BIGINT
LONG VARBINARY MEDIUMBLOB
LONG VARCHAR MEDIUMTEXT
MIDDLEINT MEDIUMINT
VARBINARY(NUM) VARCHAR(NUM) BINARY
O mapeamento do tipo de campo ocorre na criação da tabela. Se você cria uma tabela com
tipos usador por outras empresas e então executa uma instrução DESCRIBE nome_tabela,
MySQL relaciona a estrutura de tabela utilizando os tipos equivalentes do MySQL.
As exigências de armazenamento para cada um dos tipos de colunas suportados pelo MySQL
estão listados por categoria.
referências a tabelas ou colunas que possuem o mesmo nome de uma função. Espaços entre
argumentos são permitidos.
Você pode forçar o MySQL a aceitar espaços depois do nome de funções iniciando o mysqld
com a opção --ansi ou usando o CLIENT_IGNORE_SPACE no mysql_connect(), mas neste
caso nome de funções se tornarão palavras reservadas. See hundefinedi [ANSI mode],
page hundefinedi.
Para sermos breve, exemplos mostram a saida do programa mysql na forma abreviada.
Então isto:
mysql> SELECT MOD(29,9);
1 rows in set (0.00 sec)
+-----------+
| mod(29,9) |
+-----------+
| 2 |
+-----------+
é mostrado desta forma:
mysql> SELECT MOD(29,9);
-> 2
6.3.1.1 Parenteses
( ... )
Use parenteses para forçar a ordem em que as expressões serão avaliadas. Por exemplo:
mysql> SELECT 1+2*3;
-> 7
mysql> SELECT (1+2)*3;
-> 9
= Igual:
mysql> SELECT 1 = 0;
-> 0
mysql> SELECT ’0’ = 0;
-> 1
mysql> SELECT ’0.0’ = 0;
-> 1
mysql> SELECT ’0.01’ = 0;
-> 0
mysql> SELECT ’.01’ = 0.01;
-> 1
<>
!= Diferente:
mysql> SELECT ’.01’ <> ’0.01’;
-> 1
mysql> SELECT .01 <> ’0.01’;
-> 0
mysql> SELECT ’zapp’ <> ’zappp’;
-> 1
<= Menor que ou igual:
mysql> SELECT 0.1 <= 2;
-> 1
< Menor que:
mysql> SELECT 2 < 2;
-> 0
>= Maior que ou igual:
400 Referência técnica para o MySQL versão 3.23.52
expr IN (valor,...)
Retorna 1 se expr é qualquer dos valores na lista IN, senão retorna 0. Se todos
os valores são constantes, então os valores são avaliados de acordo com o tipo da
expr e ordenado. A busca do item é então feita usando pesquisa binária. Isto
significa que IN é muito rápido se os valores da lista IN forem todos contantes.
Se expr é uma expressão strig em caso-sensitivo, a comparação é realizadas no
modo caso-sensitvo:
mysql> SELECT 2 IN (0,3,5,’wefwf’);
-> 0
mysql> SELECT ’wefwf’ IN (0,3,5,’wefwf’);
-> 1
O número de valores na lista IN é limitada apenas pelo valor max_allowed_
packet.
Na versão 4.1 (para se adequar ao padrão SQL-99), IN returna NULL não apeans
se a expressão a sua esquerda é NULL, mas também se nenhuma correspondência
é encontrada na lista e uma de suas expressões é NULL.
expr NOT IN (valor,...)
O mesmo que NOT (expr IN (valor,...)).
ISNULL(expr)
Se expr é NULL, ISNULL() retorna 1, senão retorna 0:
mysql> SELECT ISNULL(1+1);
-> 0
mysql> SELECT ISNULL(1/0);
-> 1
Note que a compração de valores NULL usando = sempre será falso!
COALESCE(lista)
Retorna o primeiro elemento não NULL na lista:
mysql> SELECT COALESCE(NULL,1);
-> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
-> NULL
INTERVAL(N,N1,N2,N3,...)
Retorna 0 se N < N1, 1 se N < N2 e assim por diante. Todos os argumentos são
tratados como inteiros. Isto exige que N1 < N2 < N3 < ... < Nn para que esta
função funcione corretamente. Isto ocorre devido a utilização pesquisa binária
(muito rápida):
mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
-> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
-> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
-> 0
Se você está comparando strings em caso-insensitivo com qualquer um dos operadores
padrões (=, <>..., mas não LIKE) espaços em branco extras (espaços, tabulações e novas
linhas) serão ignorados.
402 Referência técnica para o MySQL versão 3.23.52
NOT
! NOT logico. Avalia como 1 se o operador é 0, como 0 se o operador é diferente
de zero, e NOT NULL retorna NULL.
mysql> SELECT NOT 10;
-> 0
mysql> SELECT NOT 0;
-> 1
mysql> SELECT NOT NULL;
-> NULL
mysql> SELECT ! (1+1);
-> 0
mysql> SELECT ! 1+1;
-> 1
O último exemplo produz 1 pois a a expressão é avaliada como (!1)+1.
AND
&& AND lógico. Avalia como 1 se todos os operandos são diferentes de zero e não
é NULL, como 0 se um ou mais operandos são 0, senão retorna NULL.
mysql> SELECT 1 && 1;
-> 1
mysql> SELECT 1 && 0;
-> 0
mysql> SELECT 1 && NULL;
-> NULL
mysql> SELECT 0 && NULL;
-> 0
mysql> SELECT NULL && 0;
-> 0
Por favor note que as versões do MySQL anteriores a versão 4.0.5 param a
avaliação quando um valor NULL é encontrado, e não continua o processo bus-
cando por possíveis 0s. Isto significa que nessa versão, SELECT (NULL AND 0)
retorna NULL ao invés de 0. Na versão 4.0.5 o código tem sido re-elaborado
para que o resultado sempre seja como prescrito pelo padrão SQL utilizando a
otimização sempre que possível.
OR
|| OR lógico. Avalia como 1 se algum operando é diferente de zero e como NULL
se algum operando for NULL, senão 0 é retornado.
Chapter 6: Referência de Linguagem do MySQL 403
mysql> SELECT 1 || 1;
-> 1
mysql> SELECT 1 || 0;
-> 1
mysql> SELECT 0 || 0;
-> 0
mysql> SELECT 0 || NULL;
-> NULL
mysql> SELECT 1 || NULL;
-> 1
XOR XOR lógico. Retorna NULL se o operando também é NULL. Para operandos
não NULL, avalia como 1 se um número ímpar de operandos é diferente de zero,
senão 0 é retornado.
mysql> SELECT 1 XOR 1;
-> 0
mysql> SELECT 1 XOR 0;
-> 1
mysql> SELECT 1 XOR NULL;
-> NULL
mysql> SELECT 1 XOR 1 XOR 1;
-> 1
a XOR b é matematicamente igual a (a AND (NOT b)) OR ((NOT a) and b).
XOR foi adicionado na versão 4.0.2.
NULLIF(expr1,expr2)
Se expr1 = expr2 for verdadeiro, é retornado NULL senão é retornado expr1.
Isto é o mesmo que CASE WHEN x = y THEN NULL ELSE x END:
mysql> SELECT NULLIF(1,1);
-> NULL
mysql> SELECT NULLIF(1,2);
-> 1
Note que expr1 é avaliada duas vezes no MySQL se os argumentos não são
iguais.
IF(expr1,expr2,expr3)
Se expr1 é VERDADEIRA (expr1 <> 0 e expr1 <> NULL) então IF() retorna
expr2, senão ela retorna expr3. IF() returna um valor numérico ou string,
dependendo do contexto no qual é usado.
mysql> SELECT IF(1>2,2,3);
-> 3
mysql> SELECT IF(1<2,’sim’,’n~
ao’);
-> ’sim’
mysql> SELECT IF(STRCMP(’teste’,’teste1’),’n~
ao’,’sim’);
-> ’n~
ao’
Se expr2 ou expr3 é explicitamente NULL então o tipo resultante da função
IF() é o tipo da coluna não NULL. (Este comportamento é novo na versão 4.0.3
do MySQL).
expr1 é avaliada como um valor inteiro, o qual significa que se você está testando
valores de ponto flutuante ou strings, você de fazê-lo usando um operando de
comparação:
mysql> SELECT IF(0.1,1,0);
-> 0
mysql> SELECT IF(0.1<>0,1,0);
-> 1
No primeiro caso acima, IF(0.1) retorna 0 porque 0.1 é convertido para um
valor inteiro, resultando um um teste IF(0). Isto pode não ser o que você
esperava. No segundo caso, a comparação testa se o valor de ponto flutuante
não é zero. O resultado da comparação converte o termo em um interiro.
O tipo de retorno padrão de IF() (o que pode importar quando ele é ar-
mazenado em uma tabela temporária) é calculado na versão 3.23 do MySQL
de seguinte forma:
Expressão Valor de
retorno
expr2 ou expr3 retorna string string
expr2 ou expr3 retorna um valor de ponto ponto flutuante
flutuante
expr2 ou expr3 retorna um inteiro inteiro
Se expr2 e expr3 são strings, então o resultado é caso-insensitivo se ambas
strings são caso insensitivo. (A patir da versão 3.23.51)
Chapter 6: Referência de Linguagem do MySQL 405
CASE valor WHEN [valor comparado] THEN resultado [WHEN [valor comparado] THEN
resultado ...] [ELSE resultado] END
CASE WHEN [condiç~ao] THEN result [WHEN [condiç~ ao] THEN resultado ...] [ELSE
resultado] END
A primeira expressão retorna o resultado onde valor=valor comparado. A
segunda expressão retorna o o resultado da primeira condição, a qual é ver-
dadeira. Se não existe nenhum resultado correspondente, então o resultado
depois do ELSE é retornado. Se não existe parte ELSE então é retornado NULL
is returned:
mysql> SELECT CASE 1 WHEN 1 THEN "um"
WHEN 2 THEN "dois" ELSE "mais" END;
-> "one"
mysql> SELECT CASE WHEN 1>0 THEN "verdadeiro" ELSE "falso" END;
-> "true"
mysql> SELECT CASE BINARY "B" WHEN "a" THEN 1 WHEN "b" THEN 2 END;
-> NULL
O tipo do valor de retorno (INTEGER, DOUBLE ou STRING) é do mesmo tipo do primeiro valor
retornado (a expressão depois do primeiro THEN).
ASCII(str)
Retorna o valor do código ASCII do caracter mais a esquerda da string str.
Retorna 0 se str é uma string vazia. Retorna NULL se str é NULL:
mysql> SELECT ASCII(’2’);
-> 50
mysql> SELECT ASCII(2);
-> 50
mysql> SELECT ASCII(’dx’);
-> 100
Veja também a função ORD().
ORD(str) Se o caracter mais a esquerda da string str é um caracter multi-byte,
é retornado o código para este caracter, calculado a partir dos valores
do código ASCII dos seus caracteres contituintes utizando-se a seguinte
fórmula: ((primeiro byte do código ASCII)*256+(segundo byte do código
ASCII))[*256+terceiro byte do código ASCII...]. Se o caracter mais a
esquerda não é multi-byte, é retornado o mesmo valor que a função ASCII()
retorna:
mysql> SELECT ORD(’2’);
-> 50
406 Referência técnica para o MySQL versão 3.23.52
CONV(N,da_base,para_base)
Converte números entre diferentes bases. Retorna uma representação string do
número N, convertido da base da_base para base para_base. Retorna NULL se
qualquer argumento é NULL. O argumento N é interpretado como um inteiro,
mas pode ser especificado como um inteiro ou uma string. A base mínima é 2
e a máxima é 36. Se para_base é um número negativo, N é considerado como
um número com sinal. Caso contrário, N é tratado como um número sem sinal.
CONV funciona com precisão de 64-bit:
mysql> SELECT CONV("a",16,2);
-> ’1010’
mysql> SELECT CONV("6E",18,8);
-> ’172’
mysql> SELECT CONV(-17,10,-18);
-> ’-H’
mysql> SELECT CONV(10+"10"+’10’+0xa,10,10);
-> ’40’
BIN(N) Retorna um representação string do valor binário de N, onde N é um número
muito grande (BIGINT). Isto é equivalente a CONV(N,10,2). Retorna NULL se N
é NULL:
mysql> SELECT BIN(12);
-> ’1100’
OCT(N)
Retorna uma representação string do valor octal de N, onde N é um número
muito grande. Isto é equivalente a CONV(N,10,8). Retorna NULL se N é NULL:
mysql> SELECT OCT(12);
-> ’14’
HEX(N_ou_S)
Se N OU S é um número, é retornado um representação string do valor hex-
adecimal de N, onde N é um número muito grande (BIGINT). Isto é equivalente
a CONV(N,10,16).
Se N OU S é uma string, é retornado uma string hexadecimal de N OU S onde
cada caracter de N OU S é convertido para 2 dígitos hexadecimais. Isto é o
inverso da string 0xff.
mysql> SELECT HEX(255);
-> ’FF’
mysql> SELECT HEX("abc");
-> 616263
mysql> SELECT 0x616263;
-> "abc"
CHAR(N,...)
CHAR() interpretia os argumentos como inteiros e retorna uma string com car-
acteres dados pelo valor do código ASCII referentes a estes inteiros. Valores
NULL são desconsiderados:
mysql> SELECT CHAR(77,121,83,81,’76’);
-> ’MySQL’
Chapter 6: Referência de Linguagem do MySQL 407
-> ’QuOndetico’
Esta função é multi-byte.
ELT(N,str1,str2,str3,...)
Retorna str1 se N = 1, str2 se N = 2, e assim por diante. Retorna NULL se N
é menor que 1 ou maior que o número de argumentos. ELT() é o complemento
de FIELD():
mysql> SELECT ELT(1, ’ej’, ’Heja’, ’hej’, ’foo’);
-> ’ej’
mysql> SELECT ELT(4, ’ej’, ’Heja’, ’hej’, ’foo’);
-> ’foo’
FIELD(str,str1,str2,str3,...)
Retorna o índice de str na lista str1, str2, str3, .... Retorns 0 se str não
for encontrada. FIELD() é o complemento de ELT():
mysql> SELECT FIELD(’ej’, ’Hej’, ’ej’, ’Heja’, ’hej’, ’foo’);
-> 2
mysql> SELECT FIELD(’fo’, ’Hej’, ’ej’, ’Heja’, ’hej’, ’foo’);
-> 0
FIND_IN_SET(str,strlista)
Retorna um valor 1 para N se a string str está na lista strlist contendo N
substrings. A lista de string é composta de substrings separadas pelo caracter
‘,’. Se o primeiro argumento é uma string constante e o segundo é uma col-
una do tipo SET, a função FIND_IN_SET() é otimizada para usar aritmética
binária! Retorna 0 se str não está na strlista ou se strlista é uma string
vazia. Retorna NULL se os argumentos são NULL. Esta função não irá funcionar
adequadamente se o primeiro argumento contém uma ‘,’:
mysql> SELECT FIND_IN_SET(’b’,’a,b,c,d’);
-> 2
MAKE_SET(bits,str1,str2,...)
Retorna um conjunto (uma string contendo substrings separadas por ‘,’) con-
tendo as strings que tem o bit correspondente em bits definido . str1 corre-
sponde ao bit 1, str2 ao bit 2, etc. Strings NULL em str1, str2, ... não são
adicionadas ao resultado:
mysql> SELECT MAKE_SET(1,’a’,’b’,’c’);
-> ’a’
mysql> SELECT MAKE_SET(1 | 4,’Oi’,’meu’,’mundo’);
-> ’Oi,mundo’
mysql> SELECT MAKE_SET(0,’a’,’b’,’c’);
-> ’’
EXPORT_SET(bits,on,off,[separador,[numero_de_bits]])
Retorna uma string onde para todo bit 1 em ’bit’, você obtém uma string ’on’
e para cada bit 0 você obtem uma string ’off’, Cada string é separada com
’separador’ (padrão,’,’) e só ’número de bits’ (padrão 64) de ’bits’ é usado:
mysql> SELECT EXPORT_SET(5,’S’,’N’,’,’,4)
-> S,N,S,N
412 Referência técnica para o MySQL versão 3.23.52
LCASE(str)
LOWER(str)
Retorna a string str com todos caracteres alterados para letra minúsculas de
acordo com o conjunto de caracteres atual (o padrão é ISO-8859-1 Latin1):
mysql> SELECT LCASE(’MYSQL’);
-> ’mysql’
Esta é uma função multi-byte.
UCASE(str)
UPPER(str)
Retorna a string str com todos caracteres alterados para letra maiúsculas de
acordo com o conjunto de caracteres atual (o padrão é ISO-8859-1 Latin1):
mysql> SELECT UCASE(’Hej’);
-> ’HEJ’
Esta é uma função multi-byte.
LOAD_FILE(nome_arquivo)
Lêb o arquivo e retona o conteudo do arquivo como uma string. O arquivo beve
estar no servidor, você deve especificar o caminho completo para o arquivo, e
você deve ter o privilégio FILE. O arquivo deve ser legível para todos e ser
menor que o especificado em max_allowed_packet.
Se o arquivo não existe ou não pode ser lido devido a alguma das razões acima,
a função retornará NULL:
mysql> UPDATE nome_tabela
SET coluna_blob=LOAD_FILE("/tmp/picture")
WHERE id=1;
Se você não está usando a versão 3.23 MySQL, você tem que fazer a leitura
do arquivo dentro do seu aplicativo e criar uma instrução INSERT para atu-
alizar o banco de dados com a informação do arquivo. Um modo de se fazer
isto, se você estiver usando a biblioteca MySQL++, pode ser encontrada em
http://www.mysql.com/documentation/mysql++/mysql++-examples.html.
QUOTE(str)
Coloca uma string entre aspas para produzir um resultado que possa ser usada
em uma intrução SQL como um valor de dados com o caracter de escape correto.
A string é retornada entre aspas simples e cada instâqncia de aspas simples
(‘’’), barra invertida (‘\’), ASCII NUL, e Control-Z é precedida por uma barra
invertida. Se o argumento é NULL, o valor retornado é a palavra “NULL” sem
aspas simples.
A função QUOTE foi adicionada na versão 4.0.3 do MySQL.
mysql> SELECT QUOTE("Don’t");
-> ’Don\’t!’
mysql> SELECT QUOTE(NULL);
-> NULL
-> 1
Nota: Como MySQL usa sintaxe de escape do C em strings (por exemplo,
‘\n’), você deve dobrar qualquer ‘\’ que você usar em sua string LIKE. Por
exemplo, para pesquisar por ‘\n’, especifique-o como ‘\\n’. Para buscar por
‘\’, especifique-o como ‘\\\\’ (as barras invertidas são eliminadas uma vez pelo
analizador e outra vez quando a correspondência de padrões é feita, deixando
uma únicas barra invertida para ser verificada).
Note: O LIKE atual não é um caracter multi-byte. Comparaçãoes são feitas
caracter por caracter.
expr NOT LIKE pad [ESCAPE ’car-escape’]
O mesmo que NOT (expr LIKE pad [ESCAPE ’car-escape’]).
expr SOUNDS LIKE expr
O mesmo que SOUNDEX(expr)=SOUNDEX(expr) (disponível apenas na versão 4.1
ou posterior).
expr REGEXP pad
expr RLIKE pad
Realiza a busca de padrões em uma expressã string com base no padrão pad.
O padrão pode ser uma expressão regular extendida. See hundefinedi [Regexp],
page hundefinedi. Retorna 1 se expr conincide com pad, senão retorna 0. RLIKE
é um sinônimo para REGEXP, fornecido para compatibilidade com mSQL. Nota:
Como MySQL usa a sintaxe de escape do C em strings (por exemplo, ‘\n’),
você deve dobrar qualquer ‘\’ que você use em sua string REGEXP. Como na
versão 3.23.4 do MySQL, REGEXP é caso- insensitivo para strings normais (não
binárias).
mysql> SELECT ’Monty!’ REGEXP ’m%y%%’;
-> 0
mysql> SELECT ’Monty!’ REGEXP ’.*’;
-> 1
mysql> SELECT ’new*\n*line’ REGEXP ’new\\*.\\*line’;
-> 1
mysql> SELECT "a" REGEXP "A", "a" REGEXP BINARY "A";
-> 1 0
mysql> SELECT "a" REGEXP "^[a-d]";
-> 1
REGEXP e RLIKE usam o conjunto de caracteres atual (ISO-8859-1 Latin1 por
padrão) para decidir o tipo de caracter.
expr NOT REGEXP pad
expr NOT RLIKE pad
O mesmo que NOT (expr REGEXP pad).
STRCMP(expr1,expr2)
STRCMP() retorna 0 se as string são a mesma, -1 se o primeiro argumento é
menor que o segundo de acordo com a ordenação atual e 1 em caso contrário:
mysql> SELECT STRCMP(’texto’, ’texto2’);
-> -1
Chapter 6: Referência de Linguagem do MySQL 415
6.3.2.2 Caso-Sensitivo
BINARY O operador BINARY transforma uma string em uma string binária. Este é um
modo fácil de forçar a comparação para se caso-sensitivo mesmo se a coluna
não seja definida como BINARY ou BLOB:
mysql> SELECT "a" = "A";
-> 1
mysql> SELECT BINARY "a" = "A";
-> 0
BINARY string é um atalho para CAST(string AS BINARY). See hundefinedi
[Cast Functions], page hundefinedi. BINARY foi introduzida na versão 3.23.0 do
MySQL.
Note que em alguns contextos MySQL não estará apto a usar o índice de forma
eficiente quando se transformar uma coluna índice em BINARY.
Se você quiser compara um blob caso-insensitivo você pode sempre convertê-lo para letras
maiúsculas antes de faer a comparação:
SELECT ’A’ LIKE UPPER(col_blobl) FROM nome_tabela;
Não planejamos introduzir em breve coerção (casting) entre diferentes conjuntos de carac-
teres para tornar comparções de strings mais flexível.
+ Adição:
mysql> SELECT 3+5;
-> 8
416 Referência técnica para o MySQL versão 3.23.52
- Subtração:
mysql> SELECT 3-5;
-> -2
* Multiplicação:
mysql> SELECT 3*5;
-> 15
mysql> SELECT 18014398509481984*18014398509481984.0;
-> 324518553658426726783156020576256.0
mysql> SELECT 18014398509481984*18014398509481984;
-> 0
O resultado da última expressão é incorreta porque o resultado da multiplicação
de inteiros excede a faixa de 64-bits dos cálculos BIGINT.
/ Divisão:
mysql> SELECT 3/5;
-> 0.60
Divisões por zero produz um resultado NULL:
mysql> SELECT 102/(1-1);
-> NULL
Uma divisão será calculada com aritimética BIGINT somente se executada em
um contexto no qual o resultado é convertido para um interiro!
MOD(N,M)
% Modulo (como o operador % em C). Retorna o resto de N dividido por M:
mysql> SELECT MOD(234, 10);
-> 4
mysql> SELECT 253 % 7;
-> 1
mysql> SELECT MOD(29,9);
-> 2
mysql> SELECT 29 MOD 9;
-> 2
O uso desta função é seguro com valores BIGINT. O último exemplo só funciona
no MySQL 4.1
FLOOR(X) Retorna o maior valor inteiro não maior que X:
mysql> SELECT FLOOR(1.23);
-> 1
mysql> SELECT FLOOR(-1.23);
-> -2
Note que o valor retornado é convertido para um BIGINT!
CEILING(X)
Retorna o menor valor inteiro não menor que X:
mysql> SELECT CEILING(1.23);
-> 2
mysql> SELECT CEILING(-1.23);
-> -1
Note que o valor retornado é convertido para um BIGINT!
ROUND(X)
ROUND(X,D)
Retorna o argumeto X, arredondado para o inteiro mais próximo. Com dois
argumentos o arredandamento é feito para um número com D decimais.
mysql> SELECT ROUND(-1.23);
-> -1
mysql> SELECT ROUND(-1.58);
-> -2
mysql> SELECT ROUND(1.58);
-> 2
mysql> SELECT ROUND(1.298, 1);
-> 1.3
mysql> SELECT ROUND(1.298, 0);
-> 1
Note que o comportamento de ROUND() quando o argumento está no meio do
caminho entre dois inteiros depende da implementação da biblioteca C. Alguns
arredondamentos para o número mais próximo, são sempre para baixo, para
cima ou são zero. Se você precisa de um tipo de arredondamento, você deve
usar uma função bem definida como TRUNCATE() ou FLOOR().
DIV Divisão de inteiros. Similar ao FLOOR() mas seguro com valores BIGINT.
418 Referência técnica para o MySQL versão 3.23.52
POW(X,Y)
POWER(X,Y)
Retorna o valor de X elevado a potência de Y:
mysql> SELECT POW(2,2);
-> 4.000000
mysql> SELECT POW(2,-2);
-> 0.250000
SQRT(X) Retorna o a raiz quadrada não negativa de X:
mysql> SELECT SQRT(4);
-> 2.000000
mysql> SELECT SQRT(20);
-> 4.472136
PI() Retorna o valor de PI. A quantidade de números decimais padrão é 5, mas o
MySQL usa internamente a precisão dupla completa para PI.
mysql> SELECT PI();
-> 3.141593
mysql> SELECT PI()+0.000000000000000000;
-> 3.141592653589793116
COS(X) Retorna o cosseno de X, onde X é dado em radianos:
mysql> SELECT COS(PI());
-> -1.000000
SIN(X) Retorna o seno de X, onde X é dado em radianos:
mysql> SELECT SIN(PI());
-> 0.000000
TAN(X) Retorna a tangente de X, onde X é dado em radianos:
mysql> SELECT TAN(PI()+1);
-> 1.557408
ACOS(X) Retorna o arco cosseno X, isto é, o valor cujo cosseno é X. Retorna NULL se X
não está na faixa de -1 a 1:
mysql> SELECT ACOS(1);
-> 0.000000
mysql> SELECT ACOS(1.0001);
-> NULL
mysql> SELECT ACOS(0);
-> 1.570796
ASIN(X) Retorna o arco seno X, isto é, o valor cujo seno é X. Retorna NULL se X não está
na faixa de -1 a 1:
mysql> SELECT ASIN(0.2);
-> 0.201358
mysql> SELECT ASIN(’foo’);
-> 0.000000
ATAN(X) Retorna o arco tangente X, isto é, o valor cuja tangente é X. X:
420 Referência técnica para o MySQL versão 3.23.52
DAYOFWEEK(data)
Retorna o índice do dia da semana para data (1 = Domingo, 2 = Segunda, ...
7 = Sábado). Estes valores de índices correspondem ao padrão ODBC.
mysql> SELECT DAYOFWEEK(’1998-02-03’);
-> 3
WEEKDAY(data)
Retorna o índice do dia das semana para data (0 = Segunda, 1 = Terça, ... 6
= Domingo):
mysql> SELECT WEEKDAY(’1998-02-03 22:23:00’);
-> 1
mysql> SELECT WEEKDAY(’1997-11-05’);
-> 2
DAYOFMONTH(data)
Retorna o dia do mês para data, na faixa de 1 até 31:
mysql> SELECT DAYOFMONTH(’1998-02-03’);
-> 3
DAYOFYEAR(data)
Retorna o dia do ano para data, na faixa de 1 até 366:
mysql> SELECT DAYOFYEAR(’1998-02-03’);
-> 34
Chapter 6: Referência de Linguagem do MySQL 423
MONTH(data)
Retorna o mês para data, na faixa de 1 até 12:
mysql> SELECT MONTH(’1998-02-03’);
-> 2
DAYNAME(data)
Retorna o nome do dia da semana para data:
mysql> SELECT DAYNAME("1998-02-05");
-> ’Thurday’
MONTHNAME(data)
Retorna o nome do mês para data:
mysql> SELECT MONTHNAME("1998-02-05");
-> ’February’
QUARTER(data)
Retorna o trimestre para data, na faixa de 1 até 4:
mysql> SELECT QUARTER(’98-04-01’);
-> 2
WEEK(data)
WEEK(data,primeiro)
Com um único argumento, retorna a semana para date, na faixa de 0 a 53 (sim,
pode ter o inicio de uma semana 53), para locais onde Domingo é o primeiro
dia da semana. A forma de WEEK com dois argumentos permite especificar se a
semana começa no Domingo ou na Segunda e se o valor de retorno de estar na
faixa 0-53 ou 1-52.
Aqui está uma tabela para como o segundo argumento funciona:
Value Meaning
0 Semana começa no Domingo e retorna
valor na faixa 0-53
1 Semana começa na Segunda e retorna
valor na faixa 0-53
2 Semana começa no Domingo e retorna
valor na faixa 1-53
3 Semana começa na Segunda e retorna
valor na faixa 1-53 (ISO 8601)
mysql> SELECT WEEK(’1998-02-20’);
-> 7
mysql> SELECT WEEK(’1998-02-20’,0);
-> 7
mysql> SELECT WEEK(’1998-02-20’,1);
-> 8
mysql> SELECT WEEK(’1998-12-31’,1);
-> 53
Você pode definir o valor padrão do segundo argumento através de uma variável
default week format. A sintaxe de default week format é:
SET [SESSION | GLOBAL] default week format = [0|1|2|3];
Nota: Na versão 4.0, WEEK(#,0) foi alterado para corresponder ao calendário
americano.
424 Referência técnica para o MySQL versão 3.23.52
Note que se a semana for a última semana do ano anterior, MySQL retornará
0 se você não usar 2 ou 3 como argumento opcional:
mysql> SELECT YEAR(’2000-01-01’), WEEK(’2000-01-01’,0);
-> 2000, 0
mysql> SELECT WEEK(’2000-01-01’,2);
-> 52
Algúem pode dizer que o MySQL deveria retornar 52 para a função WEEK() ja
que a data dada é, na verdade, a 52 semana de 1999. Nós decidimos retornar
0 já que queremos que função retorne ’o número da semana do ano dado’. Isto
faz com que o uso da função WEEK() seja seguro quando combinado com outras
funções que extraiam um parte de uma data.
Se você prefere saber a semana correta do ano, então você deve usar o 2 ou 3
como argumento opcional ou usar a função YEARWEEK():
mysql> SELECT YEARWEEK(’2000-01-01’);
-> 199952
mysql> SELECT MID(YEARWEEK(’2000-01-01’),5,2);
-> 52
YEAR(data)
Retorna o ano para data na faixa de 1000 a 9999:
mysql> SELECT YEAR(’98-02-03’);
-> 1998
YEARWEEK(data)
YEARWEEK(data,primeiro)
Retorna o ano e a semana para a data. O segundo argumento funciona exata-
mente como o segundo argumento de WEEK(). Note que o ano pode ser diferente
do ano no argumento data para a primeira e a última semana do ano:
mysql> SELECT YEARWEEK(’1987-01-01’);
-> 198653
Note que o número da semana é diferente do que seria retornado pela função
WEEK() (0) para os argumentos opcionais 0 ou 1, já que WEEK() retorna a semana
no centexto de um ano dado.
HOUR(hora)
Retorna a hora para hora, na faixa de 0 a 23:
mysql> SELECT HOUR(’10:05:03’);
-> 10
MINUTE(hora)
Retorna o minuto para hora, na faixa de 0 a 59:
mysql> SELECT MINUTE(’98-02-03 10:05:03’);
-> 5
SECOND(hora)
Retorna o segundo para hora, na faixa de 0 a 59:
mysql> SELECT SECOND(’10:05:03’);
-> 3
Chapter 6: Referência de Linguagem do MySQL 425
PERIOD_ADD(P,N)
Adiciona N meses ao período P (no formato AAMM ou AAAAMM). Retorna um valor
no formato AAAAMM.
Note que o argumento de período P não é um valor de data:
mysql> SELECT PERIOD_ADD(9801,2);
-> 199803
PERIOD_DIFF(P1,P2)
Retorna o número de meses entre os períodos P1 e P2. P1 e P2 devem estar no
formato AAMM ou AAAAMM.
Note que os argumentos de período P1 e P2 não são valores de data:
mysql> SELECT PERIOD_DIFF(9802,199703);
-> 11
DATE_ADD(data,INTERVAL tipo expr)
DATE_SUB(data,INTERVAL tipo expr)
ADDDATE(data,INTERVAL tipo expr)
SUBDATE(data,INTERVAL tipo expr)
Estas funções realizam operações aritméticas em datas. ADDDATE() e SUBDATE()
são sinônimos para DATE_ADD() e DATE_SUB().
Na versão 3.23 do MySQL, você pode usar + e - ao invés de DATE_ADD() e
DATE_SUB() se a expressão do lado direito é um coluna date ou datetime. (Veja
exemplo abaixo.)
data é um valor DATETIME ou DATE especificando a data de início. expr is
an expressão especificando o intervala a ser adicionado ou subtraido da data de
início. expr é uma string; ela pode iniciar com um ‘-’ para intervalos negativos.
type é uma palavra chave indicando como a expressão deve ser interpretada.
A seguinte tabela mostra como os argumentos tipo e expr se relacionam:
tipo do valor Formarto esperado da expr
SECOND SEGUNDOS
MINUTE MINUTOS
HOUR HORAS
DAY DIAS
MONTH MESES
YEAR ANOS
MINUTE_SECOND "MINUTOS:SEGUNDOS"
HOUR_MINUTE "HORAS:MINUTOS"
DAY_HOUR "DIAS HORAS"
YEAR_MONTH "ANOS-MESES"
HOUR_SECOND "HORAS:MINUTOS:SEGUNDOS"
DAY_MINUTE "DIAS HORAS:MINUTOS"
DAY_SECOND "DIAS HORAS:MINUTOS:SEGUNDOS"
O MySQL permite qualquer delimitador de pontuação no formato de expr. Os
delimitadores mostrados na tabela são apenas sugeridos. Se o argumento date
é um valor de DATA e seus cálculos envolvem apenas as partes ANO, MS, e DIA
(into é, nenhuma parte de hora), o resultado é um valor do tipo DATE. Senão,
o resultado é um valor do tipo DATETIME:
426 Referência técnica para o MySQL versão 3.23.52
TIME_FORMAT(hora,formato)
É usado como a função DATE_FORMAT() acima, mas a string de formato pode
conter apenas os especificadores de formato que tratam de horas, minutos e
segundos. Outros especificadores produzem um valor NULL ou 0.
Chapter 6: Referência de Linguagem do MySQL 429
CURDATE()
CURRENT_DATE
Retorna a data de hoje como um valor no formato ’YYYY-MM-DD’ ou YYYYMMDD,
dependendo se a função é usada num contexto numérico ou de string.
mysql> SELECT CURDATE();
-> ’1997-12-15’
mysql> SELECT CURDATE() + 0;
-> 19971215
CURTIME()
CURRENT_TIME
Retorna a hora atual como um valor no formato ’HH:MM:SS’ ou HHMMSS,
mysql> SELECT CURTIME();
-> ’23:50:26’
mysql> SELECT CURTIME() + 0;
-> 235026
NOW()
SYSDATE()
CURRENT_TIMESTAMP
Retorna a data e hora atual como um valor no formato ’YYYY-MM-DD HH:MM:SS’
ou YYYYMMDDHHMMSS, dependendo se a função é utilizada num contexto numérico
ou de string.
mysql> SELECT NOW();
-> ’1997-12-15 23:50:26’
mysql> SELECT NOW() + 0;
-> 19971215235026
Note que NOW() só é avaliado uma vez por consulta, definido no inicio da ex-
ecução. Isto significa que múltiplas referências a NOW() em uma única consulta
irá sempre retornar o mesmo valor.
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(data)
Se chamado sem argumento, retorna um tipo timestamp do Unix (segundos
desde ’1970-01-01 00:00:00’ GMT) como um inteiro sem sinal. Se UNIX_
TIMESTAMP() é chamada com um argumento data, é retornado o valor do argu-
mento como segundo desde ’1970-01-01 00:00:00’ GMT. data pode ser um
string DATE, uma string DATETIME, um TIMESTAMP, ou um número no formato
YYMMDD ou YYYYMMDD na hora local:
mysql> SELECT UNIX_TIMESTAMP();
-> 882226357
mysql> SELECT UNIX_TIMESTAMP(’1997-10-04 22:23:00’);
-> 875996580
Qaundo UNIX_TIMESTAMP é usado em uma coluna TIMESTAMP, a função re-
tornará o valor timestamp interno diretamente, sem nenhuma conversão “string-
para-unix-timestamp” implicita. Se você passar uma data fora da faixa para
UNIX_TIMESTAMP(), a função irá retornar 0, mas por favor note que só veri-
ficações básicas são realizadas. (ano 1970-2037, mês 01-12, dia 01-31).
430 Referência técnica para o MySQL versão 3.23.52
ou
CONVERT(express~ao,tipo)
Onde tipo é um dos:
• BINARY
• CHAR (Novo na versão 4.0.6)
• DATE
• DATETIME
Chapter 6: Referência de Linguagem do MySQL 431
• SIGNED {INTEGER}
• TIME
• UNSIGNED {INTEGER}
CAST() é da sintaxe SQL-99 syntax e CONVERT() é da sintaxe ODBC.
A função de conversão é principalmente útil quando você deseja criar uma coluna com um
tipo específico em uma CREATE ... SELECT:
CREATE TABLE nova_tabela SELECT CAST(’2000-01-01’ AS DATE);
CAST(string AS BINARY é a mesma coisa que BINARY string. CAST(expr AS CHAR trata a
expressão como sendo uma string com o conjunto de caracteres padrão.
Para converter uma string para um valor numérico, normalmente não é necessário se fazer
nada; apenas use a string como se fosse um número:
mysql> SELECT 1+’1’;
-> 2
Se você usar um número em um contexto string, o número será convertido automaticamente
para uma string BINARY.
mysql> SELECT CONCAT("hello you ",2);
-> "hello you 2"
O MySQL suporta aritimético com valores de 64 bits com sinal e sem sinal. Se você está
usando um operação numérica (como +) e um dos operandos é unsigned integer (inteiro
sem sinal), o resultado também será sem sinal (unsigned). Você pode forçar o tipo usando
os operadores de conversão SIGNED e UNSIGNED, os quais irão converter a operação para um
inteiro de 65 bits com sinal e sem sinal, respectivamente.
mysql> SELECT CAST(1-2 AS UNSIGNED)
-> 18446744073709551615
mysql> SELECT CAST(CAST(1-2 AS UNSIGNED) AS SIGNED);
-> -1
Note que se um dos operdores for um valor de ponto flutuante (neste contexto DECIMAL()
é considerado um valor de ponto flutuante) o resultado será um valor de ponto flutuante e
não é afetado pela regra acima.
mysql> SELECT CAST(1 AS UNSIGNED) -2.0
-> -1.0
Se você estiver utilizando uma string em uma operação aritimética, ela é convertida para
um número de ponto flutuante.
As funções CAST() e CONVERT() foram adicionadas no MySQL 4.0.2.
O tratamento de valores sem sinais foi mudado no MySQL 4.0 para suportar valores BIGINT
apropriadamente. Se você tiver algum código que deseja executar no MySQL 4.0 e 3.23
(casos em que você provavelmente não poderá usar a função CAST), você pode utilizar o
seguinte truque para conseguir um resultado com sinal quando subtraindo duas colunas do
tipo unsigned integer (inteiro sem sinal):
SELECT (coluna_sem_sinal_1+0.0)-(coluna_sem_sinal_2+0.0);
A idéia é que as colunas sejam convertidas para ponto flutuante antes de se fazer a subtração.
Se você tiver algum problema com colunas UNSIGNED no seu aplicação MySQL antiga ao
portar para o MySQL 4.0, você pode usar a opção --sql-mode=NO_UNSIGNED_SUBTRACTION
432 Referência técnica para o MySQL versão 3.23.52
ao iniciar mysqld. Note, no entanto, que enquanto você utilizar esta opção, não será possível
conseguir um uso efetivo do tipo de coluna UNSIGNED BIGINT.
| Operador binário OR
mysql> SELECT 29 | 15;
-> 31
O resultado é um inteiro sem sinal de 64 bits.
& Operado binário AND
mysql> SELECT 29 & 15;
-> 13
O resultado é um inteiro sem sinal de 64 bits.
^ Operado binário XOR
mysql> SELECT 1 ^ 1;
-> 0
mysql> SELECT 1 ^ 0;
-> 1
mysql> SELECT 11 ^ 3;
-> 8
O resultado é um inteiro sem sinal de 64 bits.
XOR foi adicionado na versão 4.0.2.
<<
Desloca um numero BIGINT (muito grande) a esquerda:
mysql> SELECT 1 << 2;
-> 4
O resultado é um inteiro sem sinal de 64 bits.
>> Desloca um numero BIGINT (muito grande) a direita:
mysql> SELECT 4 >> 2;
-> 1
O resultado é um inteiro sem sinal de 64 bits.
~ Inverte todos os bits:
mysql> SELECT 5 & ~1;
-> 4
O resultado é um inteiro sem sinal de 64 bits.
BIT_COUNT(N)
Retorna o número de bits que são passados no argumento N:
mysql> SELECT BIT_COUNT(29);
-> 4
Chapter 6: Referência de Linguagem do MySQL 433
Você pode dizer ao MySQL para ler novos valores de arquivos de chave com o
comando FLUSH DES_KEY_FILE. Isto exige o privilégio Reload_priv.
Um benefício de ter um conjunto de chaves padrões é que ele dá a aplicação um
modo de verificar a existência de valores criptografados em colunas, sem dar ao
usuário final o direito de descriptografar estes valores.
mysql> SELECT endereco_clientes FROM tabela_clientes WHERE
cartao_credito_criptografado = DES_ENCRYPT("numero_cartao_
credito");
DES_DECRYPT(string_para_descriptografar [, chave_string])
Derscritogra uma string criptografada com DES_ENCRYPT().
Note que esta função sé funciona se você tiver configurado o MySQL com su-
porte SSL. See hundefinedi [Conexões seguras], page hundefinedi.
Se nenhum argumento chave_string for dado, DES_DECRYPT() examina o
primeiro byte da string criptografada para determinar o número de chave DES
que foi usado para criptografar a string original, e então lê a chave de des-key-
file para descriptografar a mensagem. Para isto funcionar o usuário deve ter
o privilégio SUPER.
Se você passar para esta função um argumento chave_string, aquela string é
usada como a chave para descriptografar a mensagem.
Se a string_para_descriptografar não se paracer com uma string crip-
tografada, o MySQL retornará a string_para_descriptografar dada.
Havendo erro, esta função retorna NULL.
LAST_INSERT_ID([expr])
Retorna o último valor gerado automaticamente que tenha sido inserido em um
coluna AUTO_INCREMENT. See hundefinedi [mysql_insert_id()], page hunde-
finedi.
mysql> SELECT LAST_INSERT_ID();
-> 195
O último ID que foi gerado e mantido no servidor em uma base por conexão.
Ele não será alterado por outro cliente. Ele nem mesmo será atualizado se você
atuializar outra coluna AUTO_INCREMENT com um valor não-mágico (Isto é, um
valro que não seja NULL e nem 0).
Se você inserir muitos registros ao mesmo tempo com uma instrução insert,
LAST_INSERT_ID() retorna o valor da primeira linha inserida. A razão para
isto é tornar possível reproduzir facilmente a mesma intrução INSERT em algum
outro servidor.
Se expr é dado com um argumento para LAST_INSERT_ID(), então o valor
do argumento é retornado pela função e é configurado como o próximo valor
para ser retornado pela LAST_INSERT_ID(). Isto pode ser útil para simular
sequências:
Primeiro crie a tabela:
mysql> CREATE TABLE sequencia (id INT NOT NULL);
mysql> INSERT INTO sequencia VALUES (0);
Então a tabela pode ser usada para gerar sequência de números como estes:
Chapter 6: Referência de Linguagem do MySQL 437
-> 1
mysql> SELECT IS_FREE_LOCK("lock2");
-> 1
mysql> SELECT GET_LOCK("lock2",10);
-> 1
mysql> SELECT RELEASE_LOCK("lock2");
-> 1
mysql> SELECT RELEASE_LOCK("lock1");
-> NULL
Note que a segunda chamada de RELEASE_LOCK() retorna NULL porque a trava
"lock1" foi liberada automaticamente pela segunda. GET_LOCK() call.
RELEASE_LOCK(str)
Libera a trava nomeada pela string str que foi obtida com GET_LOCK(). Re-
torna 1 se a trava foi liberada, 0 se a trava não foi bloquada pela thread (caso
onde a trava não é liberada), e NULL se o nome da trava não existe. A trava
nunca exitirá se ela nunca for obtida pela chamada de GET_LOCK() ou se ela ja
tiver sido liberada.
A instrução DO é conveniente para ser utilizada com RELEASE_LOCK(). See
hundefinedi [DO], page hundefinedi.
IS_FREE_LOCK(str)
Verifica se a trava chamada str está livre para ser utilizada (ex. não está
bloqueada). Retorna 1 se a trava está liver (ninguém a esta usando), 0 se a
trava está em uso, e NULL caso ocorra erro (como argumentos incorretos).
BENCHMARK(cont,expr)
A função BENCHMARK() executa a expressão expr repetidamente cont vezes. Ela
pode ser usada para medir a velocidade em que o MySQL processa a expressão.
O valor resultante é sempre 0. A intenção é usá-la no clientei mysql, relatando
o tempo de execução da consulta:
mysql> SELECT BENCHMARK(1000000,ENCODE("hello","goodbye"));
+----------------------------------------------+
| BENCHMARK(1000000,ENCODE("hello","goodbye")) |
+----------------------------------------------+
| 0 |
+----------------------------------------------+
1 row in set (4.74 sec)
O tempo relatado é o tempo decorrido no cliente, não o tempo de CPU no servi-
dor. Pode ser aconselhável executar BENCHMARK() diversas vezes e interpretar
o resultado cosiderado o peso da carga da maquina servidora.
INET_NTOA(expr)
Dado um endereço numérico de rede (4 ou 8 bytes), retorna a representacão no
formato com pontos do endereço como uma string:
mysql> SELECT INET_NTOA(3520061480);
-> "209.207.224.40"
Chapter 6: Referência de Linguagem do MySQL 439
INET_ATON(expr)
Dada a represenação com pontos de um endereço de rede como uma string,
retorna um inteiro que representa o valor numérico deste endereço. Endereços
podem ter 4 ou 8 bytes de endereçamento:
mysql> SELECT INET_ATON("209.207.224.40");
-> 3520061480
O número gerado é sempre na ordem de bytes da rede; por exemplo o número
acima é calculado como 209*256^3 + 207*256^2 + 224*256 +40.
MASTER_POS_WAIT(nome_log, log_pos [, tempo_limite])
Envia blocos o escravo alcançar (ex.: ter lido e aplicado todas as atualizações) a
posição específica no log mestre. Se a informação mestre não está inicializada,
ou se os argumentos estão incorretos, retorna NULL. Se o escravo não está
em execução, enviará blocos e irá esperar até que ele seja iniciado e vá para
(ou passe por) a posição especificada. Se o escravo já passou pela posição
especificada, retorna imediatamente.
Se tempo_limite (novo na versão 4.0.10) é especificado, irá esperar até que
tempo_limite segundos tenham se passado. tempo_limite deve ser maior que
0; zero ou um tempo_limite negativo significa sem tempo limite. O valor de
retorno é o número de eventos de log que ele tem que esperar para obter a
posição especificada, NULL no caso de erro, ou -1 se o tempo limite tiver sido
excedido.
O comando é útil para controle de sincronização mo mestre-escravo.
FOUND_ROWS()
Retorna o número de linhas qeu o comando SELECT SQL_CALC_FOUND_ROWS ...
anterior teria retornado, se ele não tiver sido restrigido com LIMIT.
mysql> SELECT SQL_CALC_FOUND_ROWS * FROM nome_tabela
WHERE id > 100 LIMIT 10;
mysql> SELECT FOUND_ROWS();
O segundo SELECT irá retornar um número indicando quantas linhas o primeiro
SELECT teria retornado se ele fosse escrito sem a cláusula LIMIT.
Note que se você estiver usando SELECT SQL_CALC_FOUND_ROWS ..., o MySQL
tem que calcular todos os registros no conjunto de resultados. No entanto, isto
é mais rápido que se você não utilizar LIMIT, já que o resultado precisa ser
enviado ao cliente.
O valor de FOUND_ROWS() só é relevante logo após um comando SELECT SQL_
CALC_FOUND_ROWS.
SQL_CALC_FOUND_ROWS está disponível a partir da versão 4.0.0 do MySQL.
O MySQL tem extendido o uso de GROUP BY. Você pode utilizar colunas ou cálculos na
expressão SELECT que não aparecem na parte GROUP BY. Ele espera por qalquer valor possível
para este grupo. Você pode utilizar isto para conseguir um melhor desempenho evitando
ordenação e agrupamento em itens desnecessários. Por exemplo, você não precisa fazer um
agrupamento em cliente.nome na consulta seguinte:
mysql> SELECT pedido.idcliente,cliente.nome,MAX(pagamento)
-> FROM pedido, cliente
-> WHERE pedido.idcliente = cliente.idcliente
-> GROUP BY pedido.idcliente;
No padrão SQL, você teria que adicionar cliente.nome a cláusula GROUP BY. No MySQL,
o nomê é redundante se você não o executa em modo ANSI.
Não utilize este recurso se as colunas omitidas na parte GROUP BY não são únicas no grupo!
Você obterá resultados inexperados.
Em alguns casos, você pode utilizar MIN e MAX para obter o valor de uma coluna específica,
mesmo que ele não seja único. O exemplo seguinte fornece o valor de coluna do registro
contendo o menor valor na coluna ordem:
SUBSTR(MIN(CONCAT(RPAD(ordem,6,’ ’),coluna)),7)
See Maximum-column-group-row-snt [example-Maximum-column-group-row],
page Maximum-column-group-row-pg.
NOte que se você estiver usando a versão 3.22 do MySQL (ou anterior) ou se estiver tentando
seguir o SQL-99, você não pode utilizar expressões nas cláusulas GROUP BY or ORDER BY. Você
pode contornar esta limitação utilizando um alias para a expressão:
mysql> SELECT id,FLOOR(value/100) AS val FROM nome_tabela
-> GROUP BY id,val ORDER BY val;
Na versão 3.23 do MySQL você pode fazer:
mysql> SELECT id,FLOOR(value/100) FROM nome_tabela ORDER BY RAND();
SELECT é utilizado para retornar registros selecionados de uma ou mais tabelas. express~
ao_
select indica as colunas que você deseja recuperar. SELECT tanbém pode ser utilizado para
retornar registros calculados sem referência a nenhuma tabela. Por exemplo:
mysql> SELECT 1 + 1;
-> 2
Todas as palavras chaves devem ser fornecidas exatamente na ordem mostrada acima. Por
exemplo, uma cláusula HAVING deve vir depois de qualquer cláusula GROUP BY e antes de
qualquer cláusula ORDER BY.
• Uma expressão SELECT pode utilizar um alias usando AS. O alias é usaado como o
nome da coluna da expressão e pode ser usado com cláusulas ORDER BY ou HAVING. Por
exemplo:
mysql> SELECT CONCAT(primeiro_nome,’ ’,ultimo_nome) AS nome_completo
FROM minha_tabela ORDER BY nome_completo;
• Não é permitido utilizar um alias de coluna em uma cláusula WHERE, pois o valor da
coluna pode ainda não ter sido determinado quando a cláusula WHERE for executada.
See hundefinedi [Problemas com alias], page hundefinedi.
• A cláusula FROM table_references indica a tabela de onde os registros serão retor-
nados. Se você indicar mais de uma tabela, você estará realizando uma join. Para
informações sobre a sintaxe de join, veja hundefinedi [JOIN], page hundefinedi. Para
cada tabela especificada, você pode, opcionalmente, especificar um alias.
nome_tabela [[AS] alias] [[USE INDEX (lista_indice)] | [IGNORE INDEX (lista_
indice)] | FORCE INDEX (lista_indice)]]
Como na versão 3.23.12 do MySQL, você pode dar sugestões sobre qual índice o MySQL
deve usar ao recuperar informações de uma tabela. Isto é útil se EXPLAIN mostrar que o
MySQL esta utilizando o índice errado da lista de índices possíveis. Especificando USE
INDEX (lista_indice) você pode dizer ao MySQL para usar somente um dos índices
possíveis para encontrar registros em uma tabela. A sintaxe alternativa IGNORE INDEX
(lista_indice) pode ser usada para dizer ao MySQL para não utilizar alguns índices
particulares.
Na versão 4.0.9 do MySQL você também pode usar FORCE INDEX. Ele funciona como
USE INDEX (lista_indice) mas ele assume que uma varredura em uma tabelas é
MUITO cara. Em outras palavras, uma varredura só será usada se não houver nenhum
modo de utilizar um dos índices dados para encontrar registros nas tabelas.
USE/IGNORE/FORCE KEY é sinônimo de USE/IGNORE/FORCE INDEX.
• Você pode se referir a uma tabela como nome_tabela (dentro do banco de dados
atual) ou como nomebd.nome_tabela para especificar um banco de dados. Você
pode se referir a um coluna como nome_coluna, nome_tabela.nome_coluna ou
nomebd.nome_tabela.nome_coluna. Você não precisa especificar um prefixo
nome_tabla ou nomebd.nome_tabela para referência a uma coluna em uma
instrução SELECT a menos a referência seja ambígua. Veja hundefinedi [Legal names],
page hundefinedi, para exemplos de ambiguidade que exigem a forma mais explicita
de referência a coluna.
• Pode se definir um alias fazendo referência a uma tabela utilizando nome_tabela [AS]
nome_alias:
444 Referência técnica para o MySQL versão 3.23.52
preferir ordenar fazendo uma tabela temporária com um cahve nos elementos GROUP
BY.
• SQL_BUFFER_RESULT forçará que o resultado seja colocado em uma tabela temporária.
Isto ajudará o MySQL a liberar as travas de tabelas mais cedo e ajudará nos casos
onde ele levá muito tempo para enviar o conjunto de resultado ao cliente.
• SQL_SMALL_RESULT, uma opção especifica do MySQL, pode ser usada com GROUP BY ou
DISTINCT para dizer ao otimizador que o conjunto de resultados será pequeno. Neste
caso, o MySQL usará tabelas temporárias rápidas para armazenar a tabela resultante
em vez de usar ordenação. Na versão 3.23 do MySQL isto não é necessário normalmente.
• SQL_CALC_FOUND_ROWS (versão 4.0.0 e acima) diz ao MySQL para calcular quantas
linhas haveriam nop conjunto de resultados, desconsiderando qualquer cláusula LIMIT.
O número de linhas pode ser recuperado com SELECT FOUND_ROWS(). See hundefinedi
[Funções diversas], page hundefinedi.
Por favor, note que em nversões anteriores a 4.1.0 isto não funciona com LIMIT 0,
o qual é otimizado para retornar instantaneamente (resultando em 0 registros). See
hundefinedi [Otimização LIMIT], page hundefinedi.
• SQL_CACHE diz ao MySQL para armazenar o resultado da consulta em um cache de
consultas se você estiver utilizando QUERY_CACHE_TYPE=2 (DEMAND). See hundefinedi
[Cache de consultas], page hundefinedi.
• SQL_NO_CACHE diz ao MySQL para não permitir que o resulado da consulta deja asr-
mazenado nesta cahe de consultas. See hundefinedi [Cache de consultas], page hunde-
finedi.
• Se você utiliza GROUP BY, os registros de saída serão ordenados de acordo com o GROUP
BY como se você tivesse tido um ORDER BY sobre todos os campos no GROUP BY. O
MySQL tem estendido o GROUP BY para que você também possa especificar ASC e DESC
ao GROUP BY:
SELECT a,COUNT(b) FROM tabela_teste GROUP BY a DESC
• O MySQL tem extendido o uso do GROUP BY para lhe permitir selecionar campos que não
estão mencionados na cláusula GROUP BY. Se você não está conseguindo os resultados
esperados ara a sua consulta, leia a descrição de GROUP BY. See hundefinedi [Funções
Group By], page hundefinedi.
• STRAIGHT_JOIN força o otimizador a unir as tabelas en ordem em que elas são listads
na cláusula FROM. Você pode usá-lo para aumentar a velocidade de uma consultase o
otimizador de unir as tabelas em uma ordem não otimizada. See hundefinedi [EXPLAIN],
page hundefinedi.
• A cláusula LIMIT pode ser usada para restringir o número de linhas retornadas pela
instrução SELECT. LIMIT utiliza um ou dois agumebntos numéricos. Os argumentos
devem ser constants inteiras.
Se forem fornecidos dois argumentos, o primeiro especifica a posição do primeiro registro
a ser retornado e o segundo especifica o número máximo de linhas a retornar. A posição
do registro inicial é 0 (não 1):
Para ser compatível com o PostgreeSQL, o MySQL suporta a sintaxe: LIMIT # OFFSET
#.
mysql> SELECT * FROM tabela LIMIT 5,10; # Recupera linhas 6-15
446 Referência técnica para o MySQL versão 3.23.52
To retrieve all rows from a certain offset up to the end of the result set, you can use -1
for the second parameter:
mysql> SELECT * FROM tabela LIMIT 95,-1; # Recupera linhas 96-ultima.
Se um dos argumentos é dado, ele indica o número máximo de linhas a retornar:
mysql> SELECT * FROM tabela LIMIT 5; # Recupera as primeiras 5 linhas
Em outras palavras, LIMIT n é equivalente a LIMIT 0,n.
• iA forma SELECT ... INTO OUTFILE ’nome_arquivo’ do SELECT grava os registros se-
lecionados em um arquivo. O arquivo é criado na máquina servidora e não pode já
existir (entre outras coisas, isto previne tabelas de banco de dados e arquivos tais
como ‘/etc/passwd’ de serem destruídos). Você deve ter o privilégio FILE na máquina
servidora para utilizar esta forma de SELECT.
SELECT ... INTO OUTFILE tem como intenção principal deixar que você descarregue
rapidamente um tabela de uma máquina servidora. Se você quiser criar o arquivo
resultante em outra máquina, diferente do servidor, você não deve usar SELECT ...
INTO OUTFILE. Neste caso você deve usar algum programa cliente como mysqldump
--tab ou mysql -e "SELECT..." > outfile para gerar o arquivo.
SELECT ... INTO OUTFILE é o complemento de LOAD DATA INFILE; a sintaxe para a
parte opç~oes_exportaç~ao de uma instrução consiste das mesmas cláusulas CAMPOS
e LINHAS que são usadas com a instrução LOAD DATA INFILE. See hundefinedi [LOAD
DATA], page hundefinedi.
No arquivo texto resultante, somente os seguintes coracteres são escritos com o caracter
ESCAPE BY:
• O caracter ESCAPE BY
• O primeiro caracter em FIELDS TERMINATED BY
• O primeiro caracter em LINES TERMINATED BY
Adicionalmente, ASCII 0 é convertido para ESCAPE BY seguido por 0 (ASCII 48).
A razão para o mostrado acima é que você deve escapar qualquer caracter FIELDS
TERMINATED BY, ESCAPE BY, or LINES TERMINATED BY para termos a segurança que o
arquivo poderá ser lido de volta. É feito escape de ASCII 0 para facilitar a visuzlização
com alguns paginadores.
Como o arquivo resultante não tem que estar em conformidade com a sintaxe SQL,
nada mais precisa ser seguido de caraceres de escape.
Aqui segue um exemplo de como se obter um arquivo no formato usado por muitos
programas antigos.
SELECT a,b,a+b INTO OUTFILE "/tmp/result.text"
FIELDS TERMINATED BY ’,’ OPTIONALLY ENCLOSED BY ’"’
LINES TERMINATED BY "\n"
FROM tabela_teste;
• Se você utilizar INTO DUMPFILE em vez de INTO OUTFILE, o MySQL só irá escrever um
linha no arquivo, sem nenhum terminador de linha ou colunas e sem nenhum escape.
Ele é útil se você quiser armazenar um blob em um arquivo.
• Note que qualuqer arquivo criado por INTO OUTFILE e INTO DUMPFILE poderão ser
escritos por todos os usuários! A razão é que o servidor MySQL não pode criar um
Chapter 6: Referência de Linguagem do MySQL 447
arquivo que pertence a qualquer um além do usuário que o está executando (você nunca
deve executar mysqld como root) o arquivo tem que ser gravável para todos para que
você possa manipulá-lo.
• Se você estiver utilizando FOR UPDATE em um mecanismo de armazenamento com trava-
mento de páginas/registros, as linas examinadas serão travadas para escrita.
Este exemplo encontra todas as linhas em tabela1 com um valor id que não está
presente em tabela2 (isto é, toda as linhas em tabela1 sem linha correspondente
em tabela2). Assume-se que tabela2.id é declarada NOT NULL. See hundefinedi
[Otimização LEFT JOIN], page hundefinedi.
• A cláusula USING (lista_colunas) nomeia uma lista de colunas que devem existir en
ambas as tabelas. Uma cláusula USING como:
A LEFT JOIN B USING (C1,C2,C3,...)
é definida para ser semanticamente identica a uma exprssão ON como esta:
A.C1=B.C1 AND A.C2=B.C2 AND A.C3=B.C3,...
• Um NATURAL [LEFT] JOIN de duas tabelas é definido para ser semanticamente equiva-
lente a um INNER JOIN ou um LEFT JOIN com uma cláusula USING que nomeia todas
as colunas que exitem em ambas as tabelas.
• INNER JOIN e , (vírgula) são semanticamente equivalentes. Ambos fazem um join
completo entre as tabelas usadas. Normalmente você especifica como as tabelas devem
ser ligadas em uma condição WHERE.
• RIGHT JOIN funciona de forma análoga a um LEFT JOIN. Para manter o código portável
entre banco de dados, é recomendado usar LEFT JOIN em vez de RIGHT JOIN.
• STRAIGHT_JOIN é identico a JOIN, exceto pelo fato de que a tabela de esquerda sempre
é lida antes da tabela da direita. Ele pode ser usado para aqueles casos (poucos) onde
o otimizador join coloca as tabelas na ordem errada.
• Como na versão 3.23.12, você pode dar sugestões sobre qual índice o MySQL deve
us quando retornar informações de uma tabela. Isto é útil se EXPLAIN mostar que
o MySQL está utilizando o índice errado da lista de índices possíveis. Especificando
USE INDEX (lista_indice), você pode dizer ao MySQL para usar somente um dos
índices possíveis para encontrar registros em uma tabela. A sintaxe alternativa IGNORE
INDEX (lista_indice) pode ser usado para dizer ao MySQL para não utilizar índices
particulares.
Na versão 4.0.9 do MySQL você também pode utilizar FORCE INDEX. Ele funciona
como USE INDEX (key_list) mas com assume que uma varredura na tabela é MUITO
cara. Em outras palavras, uma varredura na tabela só será feita se não houver modo
de uitlizar um dos índices fornecidos para se enecontrar registros no tabela.
USE/IGNORE KEY são sinônimos de USE/IGNORE INDEX.
Alguns exemplos:
mysql> SELECT *
FROM tabela1,tabela2 WHERE tabela1.id=tabela2.id;
mysql> SELECT *
FROM tabela1 LEFT JOIN tabela2 ON tabela1.id=tabela2.id;
mysql> SELECT *
FROM tabela1 LEFT JOIN tabela2 USING (id);
mysql> SELECT *
FROM tabela1 LEFT JOIN tabela2 ON tabela1.id=tabela2.id
-> LEFT JOIN tabela3 ON tabela2.id=tabela3.id;
mysql> SELECT * FROM tabela1 USE INDEX (chave1,chave2)
-> WHERE chave1=1 AND chave2=2 AND chave3=3;
mysql> SELECT * FROM tabela1 IGNORE INDEX (chave3)
-> WHERE chave1=1 AND chave2=2 AND chave3=3;
See hundefinedi [Otimização LEFT JOIN], page hundefinedi.
Chapter 6: Referência de Linguagem do MySQL 449
A terceira forma busca uma linha (ou mais, especificado pela cláusula LIMIT) da tabela na
ordem do índice, correspondendo a condição WHERE.
A quarta forma (sem especificação de índice) busca um registro (ou mais, especificado pela
cláusula LIMIT) da tabela na ordem natural da linhas (como armazenado no arquivo de
dados) de acordo com a condição WHERE é mais rápido que HANDLER nome_tabela READ
nome_indice quando é necessária uma varredura completa da tabela.
HANDLER ... CLOSE fecha uma tabela que foi aberta com HANDLER ... OPEN.
Nota: Se você estiver utilizando a interface HANDLER para PRIMARY KEY você deve se lembrar
de colocar o nome entre aspas: HANDLER tbl READ ‘PRIMARY‘ > (...)
HANDLER é uma instrução de baixo nível. Por exemplo, ela não fornece consitência. Isto é,
HANDLER ... OPEN NÃO pega uma imagem instântanea da tabela, e NÃO trava a tabela.
Isto significa que depois que um HANDLER ... OPEN é feito, os dados da tabela podem
ser modificados (por esta ou outra thread) e estas modificações podem aparecer apenas
parcialmente nas buscas HANDLER ... NEXT ou HANDLER ... PREV.
As razões para se utilizar esta interface em vez do SQL normal são:
• Ela é mais rápida que SELECT porque:
• Um mecanismo de armazenamento designado é alocado pela thread em HANDLER
OPEN.
• Existe menos análise envolvida.
• Nào existe sobrecaga de otimização e verificação de consultas.
• A tabela utilizada não precisa estar travada em pedidos de dois handlers.
• A interface handler não precisa fornecer uma aprência consistente dos dados (por
exemplo, dirty-reads são permitidas), assim o mecanismo de armazenamento pode
fazer otimizações que o SQL normalmente não permite.
• É muito mais fácil portar aplicações que usam interface como ISAM para o MySQL.
• Ele permite se fazer uma travessia em um banco de dados de uma maneira que não é
facil (em alguns casos impossível) de fazer com SQL. A interface handler é um modo
mais natural de mostrar dados ao trabalhar com aplicações que fornecem uma interface
interativa com o usuário para o banco de dados.
INSERT insere novos registros em uma tabela existente. A forma INSERT ... VALUES da
instrução insere registros baseado em valores especificados explicitamente. A forma INSERT
... SELECT insere linhas selecionadas de outra(s) tabela(s). A forma INSERT ... VALUES
com listas de múltiplos valores é suportado a partir da versão 3.22.5. A sintaxe nome_
coluna=express~ ao é suportada a partir da verão 3.22.10 do MySQL.
nome_tabela é a tabela na qual as linhas serão inseridas. A lista de nome das colunas ou
a cláusula SET indica para quais colunas a instrução especifica valor:
• Se você não especificar a lista de colunas para INSERT ... VALUES ou INSERT ...
SELECT, deverão ser fornecidos valores para todas as colunas na lista VALUES() ou pelo
SELECT. Se você não souber a ordem das colunas nas tabelas, use DESCRIBE nome_
tabela para descobrir.
• Qualquer coluna que não tiver o valor fornecido explicitamente assumirá o seu valor
padrão. Por exemplo, se você especificar uma lista de colunas que não definem todas
as coolunas na tabela, às colunas não definidas serão atribuídos o seu valor padrão.
Atribuição de valor padrão é definido em hundefinedi [CREATE TABLE], page hundefinedi.
Você também pode utilizar a palavra-chave DEFAULT para atribuir o valor padrão a uma
coluna (Novo na versão 4.0.3. do MySQL). Fica mais fácil de se escrever instruções
INSERT que atribuem valor a apenas algumas colunas porque ele permite que você evite
escrever uma lista VALUES() incompleta (uma lista que não inclu um valor para cada
coluna da tabela). De outa forma, você teria que escrever a lista de nomes de colunas
correspondentes a cada valor na lista VALUES().
MySQL sempre tem uma valor padrão para todos os campos. Isto é algo imposto pelo
MySQL para estar apto a funcionar com tabelas transacionais e não transcaionais.
Nossa visão é que a verificação do conteúdo dos campos deve ser feita pela application
and not in the database server.
• Uma express~ ao pode se referir a qualquer coluna que tenha sida definaida anterior-
mente na lista de valores. Por exemplo, você pode dizer:
mysql> INSERT INTO nome_tabela (col1,col2) VALUES(15,col1*2);
Mas não:
mysql> INSERT INTO nome_tabela (col1,col2) VALUES(col2*2,15);
• Se você especificar a palavra-chave LOW_PRIORITY, a execução do INSERT é atrasada até
que nenhum outro cliente esteja lendo a tabela. Neste caso o cliente tem que esperar
até que a instrução insert esteja completa, a qual pode levar bastante tempo se a tabela
estiver em uso constante. É diferente de INSERT DELAYED, que deixa o cliente continuar
de uma vez. See hundefinedi [INSERT DELAYED], page hundefinedi. Note que LOW_
PRIORITY não deve normalmente ser usado com tabelas MyISAM ja que elas disabilitam
inserções concorrentes. See hundefinedi [MyISAM], page hundefinedi.
• If you specify the keyword IGNORE in an INSERT with many value rows, any rows
that duplicate an existing PRIMARY or UNIQUE key in the table are ignored and are
not inserted. If you do not specify IGNORE, the insert is aborted if there is any row
that duplicates an existing key value. You can determine with the C API function
mysql_info() how many rows were inserted into the table.
• If you specify ON DUPLICATE KEY UPDATE clause (new in MySQL 4.1.0), and a row is
inserted that would cause a duplicate value in a PRIMARY or UNIQUE key, an UPDATE of
the old row is performed. For example, the command:
452 Referência técnica para o MySQL versão 3.23.52
• Inserting a string into a CHAR, VARCHAR, TEXT, or BLOB column that exceeds the column’s
maximum length. The value is truncated to the column’s maximum length.
• Inserting a value into a date or time column that is illegal for the column type. The
column is set to the appropriate zero value for the type.
The following describes in detail what happens when you use the DELAYED option to INSERT
or REPLACE. In this description, the “thread” is the thread that received an INSERT DELAYED
command and “handler” is the thread that handles all INSERT DELAYED statements for a
particular table.
• When a thread executes a DELAYED statement for a table, a handler thread is created
to process all DELAYED statements for the table, if no such handler already exists.
• The thread checks whether the handler has acquired a DELAYED lock already; if not,
it tells the handler thread to do so. The DELAYED lock can be obtained even if other
threads have a READ or WRITE lock on the table. However, the handler will wait for all
ALTER TABLE locks or FLUSH TABLES to ensure that the table structure is up to date.
• The thread executes the INSERT statement, but instead of writing the row to the table,
it puts a copy of the final row into a queue that is managed by the handler thread.
Any syntax errors are noticed by the thread and reported to the client program.
• The client can’t report the number of duplicates or the AUTO_INCREMENT value for the
resulting row; it can’t obtain them from the server, because the INSERT returns before
the insert operation has been completed. If you use the C API, the mysql_info()
function doesn’t return anything meaningful, for the same reason.
• The binary log is updated by the handler thread when the row is inserted into the
table. In case of multiple-row inserts, the binary log is updated when the first row is
inserted.
• After every delayed_insert_limit rows are written, the handler checks whether any
SELECT statements are still pending. If so, it allows these to execute before continuing.
• When the handler has no more rows in its queue, the table is unlocked. If no new INSERT
DELAYED commands are received within delayed_insert_timeout seconds, the handler
terminates.
• If more than delayed_queue_size rows are pending already in a specific handler queue,
the thread requesting INSERT DELAYED waits until there is room in the queue. This is
done to ensure that the mysqld server doesn’t use all memory for the delayed memory
queue.
• The handler thread will show up in the MySQL process list with delayed_insert in
the Command column. It will be killed if you execute a FLUSH TABLES command or kill it
with KILL thread_id. However, it will first store all queued rows into the table before
exiting. During this time it will not accept any new INSERT commands from another
thread. If you execute an INSERT DELAYED command after this, a new handler thread
will be created.
Note that the above means that INSERT DELAYED commands have higher priority than
normal INSERT commands if there is an INSERT DELAYED handler already running!
Other update commands will have to wait until the INSERT DELAYED queue is empty,
someone kills the handler thread (with KILL thread_id), or someone executes FLUSH
TABLES.
• The following status variables provide information about INSERT DELAYED commands:
Variable Meaning
Delayed_insert_threads Number of handler threads
Delayed_writes Number of rows written with INSERT DELAYED
Chapter 6: Referência de Linguagem do MySQL 455
or
If an ORDER BY clause is used (available from MySQL 4.0.0), the rows will be updated in
that order. This is really only useful in conjunction with LIMIT.
Starting with MySQL Version 4.0.4, you can also perform UPDATE operations that cover
multiple tables:
UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;
Note: you can not use ORDER BY or LIMIT with multi-table UPDATE.
or
or
The first multi-table delete format is supported starting from MySQL 4.0.0. The second
multi-table delete format is supported starting from MySQL 4.0.2.
The idea is that only matching rows from the tables listed before the FROM or before the
USING clause are deleted. The effect is that you can delete rows from many tables at the
same time and also have additional tables that are used for searching.
The .* after the table names is there just to be compatible with Access:
DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id
or
In MySQL 3.23.49 and MySQL 4.0.2 LOCAL will only work if you have not started mysqld
with --local-infile=0 or if you have not enabled your client to support LOCAL. See
hundefinedi [LOAD DATA LOCAL], page hundefinedi.
If you specify the keyword LOW_PRIORITY, execution of the LOAD DATA statement is delayed
until no other clients are reading from the table.
If you specify the keyword CONCURRENT with a MyISAM table, then other threads can retrieve
data from the table while LOAD DATA is executing. Using this option will of course affect the
performance of LOAD DATA a bit even if no other thread is using the table at the same time.
Using LOCAL will be a bit slower than letting the server access the files directly, because the
contents of the file must travel from the client host to the server host. On the other hand,
you do not need the FILE privilege to load local files.
If you are using MySQL before Version 3.23.24 you can’t read from a FIFO with LOAD DATA
INFILE. If you need to read from a FIFO (for example the output from gunzip), use LOAD
DATA LOCAL INFILE instead.
You can also load datafiles by using the mysqlimport utility; it operates by sending a
LOAD DATA INFILE command to the server. The --local option causes mysqlimport to
read datafiles from the client host. You can specify the --compress option to get better
performance over slow networks if the client and server support the compressed protocol.
When locating files on the server host, the server uses the following rules:
• If an absolute pathname is given, the server uses the pathname as is.
• If a relative pathname with one or more leading components is given, the server searches
for the file relative to the server’s data directory.
• If a filename with no leading components is given, the server looks for the file in the
database directory of the current database.
Note that these rules mean a file given as ‘./myfile.txt’ is read from the server’s data
directory, whereas a file given as ‘myfile.txt’ is read from the database directory of the
current database. For example, the following LOAD DATA statement reads the file ‘data.txt’
from the database directory for db1 because db1 is the current database, even though the
statement explicitly loads the file into a table in the db2 database:
mysql> USE db1;
mysql> LOAD DATA INFILE "data.txt" INTO TABLE db2.my_table;
The REPLACE and IGNORE keywords control handling of input records that duplicate existing
records on unique key values. If you specify REPLACE, new rows replace existing rows that
have the same unique key value. If you specify IGNORE, input rows that duplicate an existing
row on a unique key value are skipped. If you don’t specify either option, an error occurs
when a duplicate key value is found, and the rest of the text file is ignored.
If you load data from a local file using the LOCAL keyword, the server has no way to stop
transmission of the file in the middle of the operation, so the default behaviour is the same
as if IGNORE is specified.
If you use LOAD DATA INFILE on an empty MyISAM table, all non-unique indexes are created
in a separate batch (like in REPAIR). This normally makes LOAD DATA INFILE much faster
when you have many indexes.
LOAD DATA INFILE is the complement of SELECT ... INTO OUTFILE. See hundefinedi
[SELECT], page hundefinedi. To write data from a database to a file, use SELECT ... INTO
460 Referência técnica para o MySQL versão 3.23.52
OUTFILE. To read the file back into the database, use LOAD DATA INFILE. The syntax of
the FIELDS and LINES clauses is the same for both commands. Both clauses are optional,
but FIELDS must precede LINES if both are specified.
If you specify a FIELDS clause, each of its subclauses (TERMINATED BY, [OPTIONALLY]
ENCLOSED BY, and ESCAPED BY) is also optional, except that you must specify at least one
of them.
If you don’t specify a FIELDS clause, the defaults are the same as if you had written this:
FIELDS TERMINATED BY ’\t’ ENCLOSED BY ’’ ESCAPED BY ’\\’
If you don’t specify a LINES clause, the default is the same as if you had written this:
LINES TERMINATED BY ’\n’
In other words, the defaults cause LOAD DATA INFILE to act as follows when reading input:
• Look for line boundaries at newlines.
• Break lines into fields at tabs.
• Do not expect fields to be enclosed within any quoting characters.
• Interpret occurrences of tab, newline, or ‘\’ preceded by ‘\’ as literal characters that
are part of field values.
Conversely, the defaults cause SELECT ... INTO OUTFILE to act as follows when writing
output:
• Write tabs between fields.
• Do not enclose fields within any quoting characters.
• Use ‘\’ to escape instances of tab, newline or ‘\’ that occur within field values.
• Write newlines at the ends of lines.
Note that to write FIELDS ESCAPED BY ’\\’, you must specify two backslashes for the value
to be read as a single backslash.
The IGNORE number LINES option can be used to ignore a header of column names at the
start of the file:
mysql> LOAD DATA INFILE "/tmp/file_name" INTO TABLE test IGNORE 1 LINES;
When you use SELECT ... INTO OUTFILE in tandem with LOAD DATA INFILE to write data
from a database into a file and then read the file back into the database later, the field and
line handling options for both commands must match. Otherwise, LOAD DATA INFILE will
not interpret the contents of the file properly. Suppose you use SELECT ... INTO OUTFILE
to write a file with fields delimited by commas:
mysql> SELECT * INTO OUTFILE ’data.txt’
-> FIELDS TERMINATED BY ’,’
-> FROM ...;
To read the comma-delimited file back in, the correct statement would be:
mysql> LOAD DATA INFILE ’data.txt’ INTO TABLE table2
-> FIELDS TERMINATED BY ’,’;
If instead you tried to read in the file with the statement shown here, it wouldn’t work
because it instructs LOAD DATA INFILE to look for tabs between fields:
Chapter 6: Referência de Linguagem do MySQL 461
For input, the ENCLOSED BY character, if present, is stripped from the ends of field values.
(This is true whether OPTIONALLY is specified; OPTIONALLY has no effect on input interpre-
tation.) Occurrences of the ENCLOSED BY character preceded by the ESCAPED BY character
are interpreted as part of the current field value. In addition, duplicated ENCLOSED BY char-
acters occurring within fields are interpreted as single ENCLOSED BY characters if the field
itself starts with that character. For example, if ENCLOSED BY ’"’ is specified, quotes are
handled as shown here:
"The ""BIG"" boss" -> The "BIG" boss
The "BIG" boss -> The "BIG" boss
The ""BIG"" boss -> The ""BIG"" boss
FIELDS ESCAPED BY controls how to write or read special characters. If the FIELDS ESCAPED
BY character is not empty, it is used to prefix the following characters on output:
• The FIELDS ESCAPED BY character
• The FIELDS [OPTIONALLY] ENCLOSED BY character
• The first character of the FIELDS TERMINATED BY and LINES TERMINATED BY values
• ASCII 0 (what is actually written following the escape character is ASCII ’0’, not a
zero-valued byte)
If the FIELDS ESCAPED BY character is empty, no characters are escaped. It is probably not
a good idea to specify an empty escape character, particularly if field values in your data
contain any of the characters in the list just given.
For input, if the FIELDS ESCAPED BY character is not empty, occurrences of that character
are stripped and the following character is taken literally as part of a field value. The
exceptions are an escaped ‘0’ or ‘N’ (for example, \0 or \N if the escape character is ‘\’).
These sequences are interpreted as ASCII 0 (a zero-valued byte) and NULL. See below for
the rules on NULL handling.
For more information about ‘\’-escape syntax, see hundefinedi [Literals], page hundefinedi.
In certain cases, field and line handling options interact:
• If LINES TERMINATED BY is an empty string and FIELDS TERMINATED BY is non-empty,
lines are also terminated with FIELDS TERMINATED BY.
• If the FIELDS TERMINATED BY and FIELDS ENCLOSED BY values are both empty (’’), a
fixed-row (non-delimited) format is used. With fixed-row format, no delimiters are used
between fields. Instead, column values are written and read using the “display” widths
of the columns. For example, if a column is declared as INT(7), values for the column
are written using 7-character fields. On input, values for the column are obtained by
reading 7 characters. Fixed-row format also affects handling of NULL values; see below.
Note that fixed-size format will not work if you are using a multi-byte character set.
Handling of NULL values varies, depending on the FIELDS and LINES options you use:
• For the default FIELDS and LINES values, NULL is written as \N for output and \N is
read as NULL for input (assuming the ESCAPED BY character is ‘\’).
• If FIELDS ENCLOSED BY is not empty, a field containing the literal word NULL as its
value is read as a NULL value (this differs from the word NULL enclosed within FIELDS
ENCLOSED BY characters, which is read as the string ’NULL’).
• If FIELDS ESCAPED BY is empty, NULL is written as the word NULL.
Chapter 6: Referência de Linguagem do MySQL 463
• With fixed-row format (which happens when FIELDS TERMINATED BY and FIELDS
ENCLOSED BY are both empty), NULL is written as an empty string. Note that this
causes both NULL values and empty strings in the table to be indistinguishable when
written to the file because they are both written as empty strings. If you need to be
able to tell the two apart when reading the file back in, you should not use fixed-row
format.
Some cases are not supported by LOAD DATA INFILE:
• Fixed-size rows (FIELDS TERMINATED BY and FIELDS ENCLOSED BY both empty) and
BLOB or TEXT columns.
• If you specify one separator that is the same as or a prefix of another, LOAD DATA INFILE
won’t be able to interpret the input properly. For example, the following FIELDS clause
would cause problems:
FIELDS TERMINATED BY ’"’ ENCLOSED BY ’"’
• If FIELDS ESCAPED BY is empty, a field value that contains an occurrence of FIELDS
ENCLOSED BY or LINES TERMINATED BY followed by the FIELDS TERMINATED BY value
will cause LOAD DATA INFILE to stop reading a field or line too early. This happens
because LOAD DATA INFILE cannot properly determine where the field or line value
ends.
The following example loads all columns of the persondata table:
mysql> LOAD DATA INFILE ’persondata.txt’ INTO TABLE persondata;
No field list is specified, so LOAD DATA INFILE expects input rows to contain a field for each
table column. The default FIELDS and LINES values are used.
If you wish to load only some of a table’s columns, specify a field list:
mysql> LOAD DATA INFILE ’persondata.txt’
-> INTO TABLE persondata (col1,col2,...);
You must also specify a field list if the order of the fields in the input file differs from the
order of the columns in the table. Otherwise, MySQL cannot tell how to match up input
fields with table columns.
If a row has too few fields, the columns for which no input field is present are set to default
values. Default value assignment is described in hundefinedi [CREATE TABLE], page hunde-
finedi.
An empty field value is interpreted differently than if the field value is missing:
• For string types, the column is set to the empty string.
• For numeric types, the column is set to 0.
• For date and time types, the column is set to the appropriate “zero” value for the type.
See hundefinedi [Date and time types], page hundefinedi.
Note that these are the same values that result if you assign an empty string explicitly to
a string, numeric, or date or time type explicitly in an INSERT or UPDATE statement.
TIMESTAMP columns are only set to the current date and time if there is a NULL value for
the column, or (for the first TIMESTAMP column only) if the TIMESTAMP column is left out
from the field list when a field list is specified.
If an input row has too many fields, the extra fields are ignored and the number of warnings
is incremented.
464 Referência técnica para o MySQL versão 3.23.52
LOAD DATA INFILE regards all input as strings, so you can’t use numeric values for ENUM or
SET columns the way you can with INSERT statements. All ENUM and SET values must be
specified as strings!
If you are using the C API, you can get information about the query by calling the API
function mysql_info() when the LOAD DATA INFILE query finishes. The format of the
information string is shown here:
Records: 1 Deleted: 0 Skipped: 0 Warnings: 0
Warnings occur under the same circumstances as when values are inserted via the INSERT
statement (see hundefinedi [INSERT], page hundefinedi), except that LOAD DATA INFILE also
generates warnings when there are too few or too many fields in the input row. The warnings
are not stored anywhere; the number of warnings can only be used as an indication if
everything went well. If you get warnings and want to know exactly why you got them,
one way to do this is to use SELECT ... INTO OUTFILE into another file and compare this
to your original input file.
If you need LOAD DATA to read from a pipe, you can use the following trick:
mkfifo /mysql/db/x/x
chmod 666 /mysql/db/x/x
cat < /dev/tcp/10.1.1.12/4711 > /nt/mysql/db/x/x
mysql -e "LOAD DATA INFILE ’x’ INTO TABLE x" x
If you are using a version of MySQL older than 3.23.25 you can only do the above with
LOAD DATA LOCAL INFILE.
For more information about the efficiency of INSERT versus LOAD DATA INFILE and speeding
up LOAD DATA INFILE, See hundefinedi [Insert speed], page hundefinedi.
6.4.10 DO Syntax
DO expression, [expression, ...]
Execute the expression but don’t return any results. This is a shorthand of SELECT
expression, expression, but has the advantage that it’s slightly faster when you don’t
care about the result.
This is mainly useful with functions that has side effects, like RELEASE_LOCK.
or
create_definition:
nome_coluna type [NOT NULL | NULL] [DEFAULT default_value] [AUTO_INCREMENT]
[PRIMARY KEY] [reference_definition]
or PRIMARY KEY (index_nome_coluna,...)
or KEY [index_name] (index_nome_coluna,...)
or INDEX [index_name] (index_nome_coluna,...)
or UNIQUE [INDEX] [index_name] (index_nome_coluna,...)
or FULLTEXT [INDEX] [index_name] (index_nome_coluna,...)
or [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_nome_coluna,...)
[reference_definition]
or CHECK (expr)
type:
TINYINT[(length)] [UNSIGNED] [ZEROFILL]
or SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
or MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
or INT[(length)] [UNSIGNED] [ZEROFILL]
or INTEGER[(length)] [UNSIGNED] [ZEROFILL]
466 Referência técnica para o MySQL versão 3.23.52
index_nome_coluna:
nome_coluna [(length)]
reference_definition:
REFERENCES nome_tabela [(index_nome_coluna,...)]
[MATCH FULL | MATCH PARTIAL]
[ON DELETE reference_option]
[ON UPDATE reference_option]
reference_option:
RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT
table_options:
TYPE = {BDB | HEAP | ISAM | InnoDB | MERGE | MRG_MYISAM | MYISAM }
or AUTO_INCREMENT = #
or AVG_ROW_LENGTH = #
or CHECKSUM = {0 | 1}
or COMMENT = "string"
or MAX_ROWS = #
or MIN_ROWS = #
or PACK_KEYS = {0 | 1 | DEFAULT}
or PASSWORD = "string"
or DELAY_KEY_WRITE = {0 | 1}
or ROW_FORMAT= { default | dynamic | fixed | compressed }
or RAID_TYPE= {1 | STRIPED | RAID0 } RAID_CHUNKS=# RAID_CHUNKSIZE=#
or UNION = (table_name,[table_name...])
Chapter 6: Referência de Linguagem do MySQL 467
select_statement:
[IGNORE | REPLACE] SELECT ... (Some legal select statement)
CREATE TABLE creates a table with the given name in the current database. Rules for
allowable table names are given in hundefinedi [Legal names], page hundefinedi. An error
occurs if there is no current database or if the table already exists.
In MySQL Version 3.22 or later, the table name can be specified as db_name.nome_tabela.
This works regardless of whether there is a current database.
From MySQL Version 3.23, you can use the TEMPORARY keyword when you create a table.
The name is restricted to the current connection, and the temporary table will automatically
be deleted when the connection is closed. This means that two different connections can
both use the same temporary table name without conflicting with each other or with an
existing table of the same name. (The existing table is hidden until the temporary table is
deleted.). From MySQL 4.0.2 one must have the CREATE TEMPORARY TABLES privilege to be
able to create temporary tables.
In MySQL Version 3.23 or later, you can use the keywords IF NOT EXISTS so that an error
does not occur if the table already exists. Note that there is no verification that the table
structures are identical.
In MySQL 4.1 you can use LIKE to create a table based on a table definition in another
table. In MySQL 4.1 you can also specify the type for a generated column:
CREATE TABLE foo (a tinyint not null) SELECT b+1 AS ’a’ FROM bar;
Each table nome_tabela is represented by some files in the database directory. In the case
of MyISAM-type tables you will get:
File Purpose
nome_tabela.frm Table definition (form)
file
nome_tabela.MYD Datafile
nome_tabela.MYI Index file
For more information on the properties of the various column types, see hundefinedi [Column
types], page hundefinedi:
• If neither NULL nor NOT NULL is specified, the column is treated as though NULL had
been specified.
• An integer column may have the additional attribute AUTO_INCREMENT. When you
insert a value of NULL (recommended) or 0 into an AUTO_INCREMENT column, the column
is set to value+1, where value is the largest value for the column currently in the
table. AUTO_INCREMENT sequences begin with 1. See hundefinedi [mysql_insert_id()],
page hundefinedi.
If you delete the row containing the maximum value for an AUTO_INCREMENT column,
the value will be reused with an ISAM, or BDB table but not with a MyISAM or InnoDB
table. If you delete all rows in the table with DELETE FROM table_name (without a
WHERE) in AUTOCOMMIT mode, the sequence starts over for all table types.
468 Referência técnica para o MySQL versão 3.23.52
Note: there can be only one AUTO_INCREMENT column per table, and it must be indexed.
MySQL Version 3.23 will also only work properly if the AUTO_INCREMENT column only
has positive values. Inserting a negative number is regarded as inserting a very large
positive number. This is done to avoid precision problems when numbers ’wrap’ over
from positive to negative and also to ensure that one doesn’t accidentally get an AUTO_
INCREMENT column that contains 0.
In MyISAM and BDB tables you can specify AUTO_INCREMENT secondary column in
a multi-column key. See AUTO˙INCREMENT-snt [example-AUTO INCREMENT],
page AUTO˙INCREMENT-pg.
To make MySQL compatible with some ODBC applications, you can find the last
inserted row with the following query:
SELECT * FROM nome_tabela WHERE auto_col IS NULL
• CREATE TABLE automatically commits the current InnoDB transaction if MySQL binary
logging is used.
• NULL values are handled differently for TIMESTAMP columns than for other column types.
You cannot store a literal NULL in a TIMESTAMP column; setting the column to NULL
sets it to the current date and time. Because TIMESTAMP columns behave this way, the
NULL and NOT NULL attributes do not apply in the normal way and are ignored if you
specify them.
On the other hand, to make it easier for MySQL clients to use TIMESTAMP columns,
the server reports that such columns may be assigned NULL values (which is true), even
though TIMESTAMP never actually will contain a NULL value. You can see this when you
use DESCRIBE nome_tabela to get a description of your table.
Note that setting a TIMESTAMP column to 0 is not the same as setting it to NULL,
because 0 is a valid TIMESTAMP value.
• A DEFAULT value has to be a constant, it cannot be a function or an expression.
If no DEFAULT value is specified for a column, MySQL automatically assigns one, as
follows.
If the column may take NULL as a value, the default value is NULL.
If the column is declared as NOT NULL, the default value depends on the column type:
− For numeric types other than those declared with the AUTO_INCREMENT attribute,
the default is 0. For an AUTO_INCREMENT column, the default value is the next
value in the sequence.
− For date and time types other than TIMESTAMP, the default is the appropriate zero
value for the type. For the first TIMESTAMP column in a table, the default value
is the current date and time. See hundefinedi [Date and time types], page hunde-
finedi.
− For string types other than ENUM, the default value is the empty string. For ENUM,
the default is the first enumeration value.
Default values must be constants. This means, for example, that you cannot set the
default for a date column to be the value of a function such as NOW() or CURRENT_DATE.
• KEY is a synonym for INDEX.
• In MySQL, a UNIQUE key can have only distinct values. An error occurs if you try to
add a new row with a key that matches an existing row.
Chapter 6: Referência de Linguagem do MySQL 469
• A PRIMARY KEY is a unique KEY with the extra constraint that all key columns must
be defined as NOT NULL. In MySQL the key is named PRIMARY. A table can have only
one PRIMARY KEY. If you don’t have a PRIMARY KEY and some applications ask for the
PRIMARY KEY in your tables, MySQL will return the first UNIQUE key, which doesn’t
have any NULL columns, as the PRIMARY KEY.
• A PRIMARY KEY can be a multiple-column index. However, you cannot create a multiple-
column index using the PRIMARY KEY key attibute in a column specification. Doing so
will mark only that single column as primary. You must use the PRIMARY KEY(index_
nome_coluna, ...) syntax.
• If the PRIMARY or UNIQUE key consists of only one column and this is of type integer,
you can also refer to it as _rowid (new in Version 3.23.11).
• If you don’t assign a name to an index, the index will be assigned the same name as the
first index_nome_coluna, with an optional suffix (_2, _3, ...) to make it unique. You
can see index names for a table using SHOW INDEX FROM nome_tabela. See hundefinedi
[SHOW DATABASE INFO], page hundefinedi.
• Only the MyISAM, InnoDB, and BDB table types support indexes on columns that can
have NULL values. In other cases you must declare such columns NOT NULL or an error
results.
• With nome_coluna(length) syntax, you can specify an index that uses only a part of
a CHAR or VARCHAR column. This can make the index file much smaller. See hundefinedi
[Indexes], page hundefinedi.
• Only the MyISAM table type supports indexing on BLOB and TEXT columns. When
putting an index on a BLOB or TEXT column you MUST always specify the length of
the index:
CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));
• When you use ORDER BY or GROUP BY with a TEXT or BLOB column, only the first max_
sort_length bytes are used. See hundefinedi [BLOB], page hundefinedi.
• In MySQL Version 3.23.23 or later, you can also create special FULLTEXT indexes. They
are used for full-text search. Only the MyISAM table type supports FULLTEXT indexes.
They can be created only from CHAR, VARCHAR, and TEXT columns. Indexing always
happens over the entire column; partial indexing is not supported. See hundefinedi
[Fulltext Search], page hundefinedi for details of operation.
• In MySQL Version 3.23.44 or later, InnoDB tables support checking of foreign key
constraints. See hundefinedi [InnoDB], page hundefinedi. Note that the FOREIGN KEY
syntax in InnoDB is more restricted than the syntax presented above. InnoDB does
not allow index_name to be specified, and the columns of the referenced table always
have to be explicitly named. Starting from 4.0.8 InnoDB supports both ON DELETE
and ON UPDATE actions on foreign keys. See the InnoDB manual section for the precise
syntax. See hundefinedi [InnoDB], page hundefinedi. For other table types, MySQL
Server does parse the FOREIGN KEY, CHECK, and REFERENCES syntax in CREATE TABLE
commands, but without further action being taken. See hundefinedi [ANSI diff Foreign
Keys], page hundefinedi.
• Each NULL column takes one bit extra, rounded up to the nearest byte.
• The maximum record length in bytes can be calculated as follows:
470 Referência técnica para o MySQL versão 3.23.52
row length = 1
+ (sum of column lengths)
+ (number of NULL columns + 7)/8
+ (number of variable-length columns)
• The table_options and SELECT options are only implemented in MySQL Version 3.23
and above.
The different table types are:
Table type Description
BDB or BerkeleyDB Transaction-safe tables with page locking. See hundefinedi
[BDB], page hundefinedi.
HEAP The data for this table is only stored in memory. See hunde-
finedi [HEAP], page hundefinedi.
ISAM The original storage engine. See hundefinedi [ISAM],
page hundefinedi.
InnoDB Transaction-safe tables with row locking. See hundefinedi
[InnoDB], page hundefinedi.
MERGE A collection of MyISAM tables used as one table. See hunde-
finedi [MERGE], page hundefinedi.
MRG MyISAM An alias for MERGE tables
MyISAM The new binary portable storage engine that is replacing
ISAM. See hundefinedi [MyISAM], page hundefinedi.
See hundefinedi [Table types], page hundefinedi.
If a table type is specified, and that particular type is not available, MySQL will choose
the closest table type to the one that you have specified. For example, if TYPE=BDB is
specified, and that distribution of MySQL does not support BDB tables, the table will
be created as MyISAM instead.
The other table options are used to optimise the behaviour of the table. In most cases,
you don’t have to specify any of them. The options work for all table types, if not
otherwise indicated:
Option Description
AUTO_INCREMENT The next AUTO_INCREMENT value you want to set for your table
(MyISAM).
AVG_ROW_LENGTH An approximation of the average row length for your table.
You only need to set this for large tables with variable size
records.
CHECKSUM Set this to 1 if you want MySQL to maintain a checksum for
all rows (makes the table a little slower to update but makes
it easier to find corrupted tables) (MyISAM).
COMMENT A 60-character comment for your table.
MAX_ROWS Max number of rows you plan to store in the table.
MIN_ROWS Minimum number of rows you plan to store in the table.
PACK_KEYS Set this to 1 if you want to have a smaller index. This usu-
ally makes updates slower and reads faster (MyISAM, ISAM).
Setting this to 0 will disable all packing of keys. Setting this
to DEFAULT (MySQL 4.0) will tell the storage engine to only
pack long CHAR/VARCHAR columns.
Chapter 6: Referência de Linguagem do MySQL 471
PASSWORD Encrypt the ‘.frm’ file with a password. This option doesn’t
do anything in the standard MySQL version.
DELAY_KEY_WRITE Set this to 1 if want to delay key table updates until the table
is closed (MyISAM).
ROW_FORMAT Defines how the rows should be stored. Currently this option
only works with MyISAM tables, which supports the DYNAMIC
and FIXED row formats. See hundefinedi [MyISAM table for-
mats], page hundefinedi.
When you use a MyISAM table, MySQL uses the product of max_rows * avg_row_
length to decide how big the resulting table will be. If you don’t specify any of
the above options, the maximum size for a table will be 4G (or 2G if your operating
systems only supports 2G tables). The reason for this is just to keep down the pointer
sizes to make the index smaller and faster if you don’t really need big files.
If you don’t use PACK_KEYS, the default is to only pack strings, not numbers. If you
use PACK_KEYS=1, numbers will be packed as well.
When packing binary number keys, MySQL will use prefix compression. This means
that you will only get a big benefit of this if you have many numbers that are the same.
Prefix compression means that every key needs one extra byte to indicate how many
bytes of the previous key are the same for the next key (note that the pointer to the
row is stored in high-byte-first-order directly after the key, to improve compression).
This means that if you have many equal keys on two rows in a row, all following ’same’
keys will usually only take 2 bytes (including the pointer to the row). Compare this to
the ordinary case where the following keys will take storage size for key + pointer size
(usually 4). On the other hand, if all keys are totally different, you will lose 1 byte
per key, if the key isn’t a key that can have NULL values. (In this case the packed key
length will be stored in the same byte that is used to mark if a key is NULL.)
• If you specify a SELECT after the CREATE statement, MySQL will create new fields for
all elements in the SELECT. For example:
mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
-> PRIMARY KEY (a), KEY(b))
-> TYPE=MyISAM SELECT b,c FROM test2;
This will create a MyISAM table with three columns, a, b, and c. Notice that the columns
from the SELECT statement are appended to the right side of the table, not overlapped
onto it. Take the following example:
mysql> SELECT * FROM foo;
+---+
| n |
+---+
| 1 |
+---+
| m | n |
+------+---+
| NULL | 1 |
+------+---+
1 row in set (0.00 sec)
For each row in table foo, a row is inserted in bar with the values from foo and default
values for the new columns.
CREATE TABLE ... SELECT will not automatically create any indexes for you. This is
done intentionally to make the command as flexible as possible. If you want to have
indexes in the created table, you should specify these before the SELECT statement:
mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;
If any errors occur while copying the data to the table, it will automatically be deleted.
To ensure that the update log/binary log can be used to re-create the original tables,
MySQL will not allow concurrent inserts during CREATE TABLE ... SELECT.
• The RAID_TYPE option will help you to break the 2G/4G limit for the MyISAM datafile
(not the index file) on operating systems that don’t support big files. Note that this
option is not recommended for filesystem that supports big files!
You can get more speed from the I/O bottleneck by putting RAID directories on different
physical disks. RAID_TYPE will work on any OS, as long as you have configured MySQL
with --with-raid. For now the only allowed RAID_TYPE is STRIPED (1 and RAID0 are
aliases for this).
If you specify RAID_TYPE=STRIPED for a MyISAM table, MyISAM will create RAID_CHUNKS
subdirectories named 00, 01, 02 in the database directory. In each of these directories
MyISAM will create a table_name.MYD. When writing data to the datafile, the RAID
handler will map the first RAID_CHUNKSIZE *1024 bytes to the first file, the next RAID_
CHUNKSIZE *1024 bytes to the next file and so on.
• UNION is used when you want to use a collection of identical tables as one. This only
works with MERGE tables. See hundefinedi [MERGE], page hundefinedi.
For the moment you need to have SELECT, UPDATE, and DELETE privileges on the tables
you map to a MERGE table. All mapped tables must be in the same database as the
MERGE table.
• If you want to insert data in a MERGE table, you have to specify with INSERT_METHOD into
with table the row should be inserted. See hundefinedi [MERGE], page hundefinedi.
This option was introduced in MySQL 4.0.0.
• In the created table the PRIMARY key will be placed first, followed by all UNIQUE keys
and then the normal keys. This helps the MySQL optimiser to prioritise which key to
use and also more quickly detect duplicated UNIQUE keys.
• By using DATA DIRECTORY="directory" or INDEX DIRECTORY="directory" you can
specify where the storage engine should put it’s table and index files. Note that the
directory should be a full path to the directory (not relative path).
This only works for MyISAM tables in MySQL 4.0, when you are not using the --skip-
symlink option. See hundefinedi [Symbolic links to tables], page hundefinedi.
Chapter 6: Referência de Linguagem do MySQL 473
alter_specification:
ADD [COLUMN] create_definition [FIRST | AFTER column_name ]
or ADD [COLUMN] (create_definition, create_definition,...)
or ADD INDEX [index_name] (index_nome_coluna,...)
or ADD PRIMARY KEY (index_nome_coluna,...)
or ADD UNIQUE [index_name] (index_nome_coluna,...)
or ADD FULLTEXT [index_name] (index_nome_coluna,...)
or ADD [CONSTRAINT symbol] FOREIGN KEY [index_name] (index_nome_coluna,...)
[reference_definition]
or ALTER [COLUMN] nome_coluna {SET DEFAULT literal | DROP DEFAULT}
or CHANGE [COLUMN] old_nome_coluna create_definition
[FIRST | AFTER column_name]
or MODIFY [COLUMN] create_definition [FIRST | AFTER column_name]
or DROP [COLUMN] nome_coluna
or DROP PRIMARY KEY
474 Referência técnica para o MySQL versão 3.23.52
• If you use ALTER TABLE on a MyISAM table, all non-unique indexes are created in a
separate batch (like in REPAIR). This should make ALTER TABLE much faster when you
have many indexes.
• Since MySQL 4.0 the above feature can be activated explicitly. ALTER TABLE ...
DISABLE KEYS makes MySQL to stop updating non-unique indexes for MyISAM table.
ALTER TABLE ... ENABLE KEYS then should be used to recreate missing indexes. As
MySQL does it with special algorithm which is much faster then inserting keys one by
one, disabling keys could give a considerable speedup on bulk inserts.
• With the C API function mysql_info(), you can find out how many records were
copied, and (when IGNORE is used) how many records were deleted due to duplication
of unique key values.
• The FOREIGN KEY, CHECK, and REFERENCES clauses don’t actually do anything,
except for InnoDB type tables which support ADD CONSTRAINT FOREIGN KEY (...)
REFERENCES ... (...). Note that InnoDB does not allow an index_name to be
specified. See hundefinedi [InnoDB], page hundefinedi. The syntax for other table
types is provided only for compatibility, to make it easier to port code from other SQL
servers and to run applications that create tables with references. See hundefinedi
[Differences from ANSI], page hundefinedi.
Here is an example that shows some of the uses of ALTER TABLE. We begin with a table t1
that is created as shown here:
mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));
To rename the table from t1 to t2:
mysql> ALTER TABLE t1 RENAME t2;
To change column a from INTEGER to TINYINT NOT NULL (leaving the name the same), and
to change column b from CHAR(10) to CHAR(20) as well as renaming it from b to c:
mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);
To add a new TIMESTAMP column named d:
mysql> ALTER TABLE t2 ADD d TIMESTAMP;
To add an index on column d, and make column a the primary key:
mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);
To remove column c:
mysql> ALTER TABLE t2 DROP COLUMN c;
To add a new AUTO_INCREMENT integer column named c:
mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
ADD INDEX (c);
Note that we indexed c, because AUTO_INCREMENT columns must be indexed, and also that
we declare c as NOT NULL, because indexed columns cannot be NULL.
When you add an AUTO_INCREMENT column, column values are filled in with sequence num-
bers for you automatically. You can set the first sequence number by executing SET INSERT_
ID=# before ALTER TABLE or using the AUTO_INCREMENT = # table option. See hundefinedi
[SET OPTION], page hundefinedi.
Chapter 6: Referência de Linguagem do MySQL 477
With MyISAM tables, if you don’t change the AUTO_INCREMENT column, the sequence num-
ber will not be affected. If you drop an AUTO_INCREMENT column and then add another
AUTO_INCREMENT column, the numbers will start from 1 again.
See hundefinedi [ALTER TABLE problems], page hundefinedi.
Note that if you are using non-transaction-safe tables, the changes will be stored at once,
independent of the status of the autocommit mode.
If you do a ROLLBACK when you have updated a non-transactional table you will get an
error (ER_WARNING_NOT_COMPLETE_ROLLBACK) as a warning. All transaction-safe tables will
be restored but any non-transaction-safe table will not change.
If you are using START TRANSACTION or SET AUTOCOMMIT=0, you should use the MySQL
binary log for backups instead of the older update log. Transactions are stored in the
binary log in one chunk, upon COMMIT, to ensure that transactions which are rolled back
are not stored. See hundefinedi [Binary log], page hundefinedi.
The following commands automatically end a transaction (as if you had done a COMMIT
before executing the command):
Command Command Command
ALTER TABLE BEGIN CREATE INDEX
DROP DATABASE DROP TABLE RENAME TABLE
TRUNCATE
You can change the isolation level for transactions with SET TRANSACTION ISOLATION LEVEL
.... See hundefinedi [SET TRANSACTION], page hundefinedi.
WRITE thread has gotten the lock and released it. You can use LOW_PRIORITY WRITE locks
to allow other threads to obtain READ locks while the thread is waiting for the WRITE lock.
You should only use LOW_PRIORITY WRITE locks if you are sure that there will eventually
be a time when no threads will have a READ lock.
LOCK TABLES works as follows:
1. Sort all tables to be locked in a internally defined order (from the user standpoint the
order is undefined).
2. If a table is locked with a read and a write lock, put the write lock before the read lock.
3. Lock one table at a time until the thread gets all locks.
This policy ensures that table locking is deadlock free. There is however other things one
needs to be aware of with this schema:
If you are using a LOW_PRIORITY WRITE lock for a table, this means only that MySQL will
wait for this particlar lock until there is no threads that wants a READ lock. When the
thread has got the WRITE lock and is waiting to get the lock for the next table in the lock
table list, all other threads will wait for the WRITE lock to be released. If this becomes a
serious problem with your application, you should consider converting some of your tables
to transactions safe tables.
You can safely kill a thread that is waiting for a table lock with KILL. See hundefinedi
[KILL], page hundefinedi.
Note that you should not lock any tables that you are using with INSERT DELAYED. This is
because that in this case the INSERT is done by a separate thread.
Normally, you don’t have to lock tables, as all single UPDATE statements are atomic; no
other thread can interfere with any other currently executing SQL statement. There are a
few cases when you would like to lock tables anyway:
• If you are going to run many operations on a bunch of tables, it’s much faster to lock
the tables you are going to use. The downside is, of course, that no other thread can
update a READ-locked table and no other thread can read a WRITE-locked table.
The reason some things are faster under LOCK TABLES is that MySQL will not flush the
key cache for the locked tables until UNLOCK TABLES is called (normally the key cache
is flushed after each SQL statement). This speeds up inserting/updateing/deletes on
MyISAM tables.
• If you are using a storage engine in MySQL that doesn’t support transactions, you
must use LOCK TABLES if you want to ensure that no other thread comes between a
SELECT and an UPDATE. The example shown here requires LOCK TABLES in order to
execute safely:
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;
Without LOCK TABLES, there is a chance that another thread might insert a new row
in the trans table between execution of the SELECT and UPDATE statements.
By using incremental updates (UPDATE customer SET value=value+new_value) or the
LAST_INSERT_ID() function, you can avoid using LOCK TABLES in many cases.
482 Referência técnica para o MySQL versão 3.23.52
You can also solve some cases by using the user-level lock functions GET_LOCK() and
RELEASE_LOCK(). These locks are saved in a hash table in the server and implemented
with pthread_mutex_lock() and pthread_mutex_unlock() for high speed. See hunde-
finedi [Miscellaneous functions], page hundefinedi.
See hundefinedi [Internal locking], page hundefinedi, for more information on locking policy.
You can lock all tables in all databases with read locks with the FLUSH TABLES WITH READ
LOCK command. See hundefinedi [FLUSH], page hundefinedi. This is very convenient way
to get backups if you have a filesystem, like Veritas, that can take snapshots in time.
NOTE: LOCK TABLES is not transaction-safe and will automatically commit any active trans-
actions before attempting to lock the tables.
query_cache_limit Don’t cache results that are bigger than this. (Default 1M).
query_cache_min_res_unit
This variable is present from version 4.1.
The result of a query (the data that is also sent to the client) is stored in the query
cache during result retrieval. Therefore the data is usually not handled in one big
chunk. The query cache allocates blocks for storing this data on demand, so when
one block is filled, a new block is allocated. Because memory allocation operation is
costly (time wise), the query cache allocates blocks with a minimum size of query_
cache_min_res_unit. When a query is executed, the last result block is trimmed to
the actual data size, so that unused memory is freed.
• The default value of query_cache_min_res_unit is 4 KB which should be ade-
quate for most cases.
• If you have a lot of queries with small results, the default block size may lead
to memory fragmentation (indicated by a large number of free blocks (Qcache_
free_blocks), which can cause the query cache to have to delete queries from the
cache due to lack of memory (Qcache_lowmem_prunes)). In this case you should
decrease query_cache_min_res_unit.
• If you mostly have queres with big results (see Qcache_total_blocks and Qcache_
queries_in_cache), you can increase performance by increasing query_cache_
min_res_unit. However, be careful to not make it to large (see the previous
point).
query_cache_size The amount of memory (specified in bytes) allocated to store results
from old queries. If this is 0, the query cache is disabled (default).
query_cache_type This may be set (only numeric) to
Option Description
0 (OFF, don’t cache or retrieve results)
1 (ON, cache all results except SELECT SQL_NO_CACHE ... queries)
2 (DEMAND, cache only SELECT SQL_CACHE ... queries)
Inside a thread (connection), the behaviour of the query cache can be changed from the
default. The syntax is as follows:
QUERY_CACHE_TYPE = OFF | ON | DEMAND QUERY_CACHE_TYPE = 0 | 1 | 2
Option Description
0 or OFF Don’t cache or retrieve results.
1 or ON Cache all results except SELECT SQL_NO_CACHE ... queries.
2 or DEMAND Cache only SELECT SQL_CACHE ... queries.
SQL_NO_CACHE Make this query non-cachable, don’t allow this query to be stored in
the cache.
As of MySQL Version 3.23.6, you can choose between three basic table formats (ISAM, HEAP
and MyISAM). Newer versions of MySQL support additional table types (InnoDB, or BDB),
depending on how you compile it.
When you create a new table, you can tell MySQL what type of table to create. The default
table type is usually MyISAM.
MySQL will always create a ‘.frm’ file to hold the table and column definitions. The table’s
index and data will be stored in one or more other files, depending on the table type.
If you try to use a table type that is not compiled-in or activated, MySQL will instead
create a table of type MyISAM. This behaviour is convenient when you want to copy tables
between MySQL servers that support different table types. (Perhaps your master server
supports transactional storage engines for increased safety, while the slave servers use only
non-transactional storage engines for greater speed.)
This automatic change of table types can be confusing for new MySQL users. We plan to fix
this by introducing warnings in the new client-server protocol in version 4.1 and generating
a warning when a table type is automatically changed.
You can convert tables between different types with the ALTER TABLE statement. See hun-
definedi [ALTER TABLE], page hundefinedi.
Note that MySQL supports two different kinds of tables: transaction-safe tables (InnoDB
and BDB) and not transaction-safe tables (HEAP, ISAM, MERGE, and MyISAM).
Advantages of transaction-safe tables (TST):
• Safer. Even if MySQL crashes or you get hardware problems, you can get your data
back, either by automatic recovery or from a backup + the transaction log.
• You can combine many statements and accept these all in one go with the COMMIT
command.
• You can execute ROLLBACK to ignore your changes (if you are not running in auto-
commit mode).
• If an update fails, all your changes will be restored. (With NTST tables all changes
that have taken place are permanent)
• Can provide better concurrency if the table gets many updates concurrently with reads.
Note that to use InnoDB tables you have to use at least the innodb_data_file_path startup
option. See hundefinedi [InnoDB start], page hundefinedi.
Advantages of not transaction-safe tables (NTST):
• Much faster as there is no transaction overhead.
• Will use less disk space as there is no overhead of transactions.
• Will use less memory to do updates.
You can combine TST and NTST tables in the same statements to get the best of both
worlds.
492 Referência técnica para o MySQL versão 3.23.52
• myisamchk will mark tables as checked if one runs it with --update-state. myisamchk
--fast will only check those tables that don’t have this mark.
• myisamchk -a stores statistics for key parts (and not only for whole keys as in ISAM).
• Dynamic size rows will now be much less fragmented when mixing deletes with updates
and inserts. This is done by automatically combining adjacent deleted blocks and by
extending blocks if the next block is deleted.
• myisampack can pack BLOB and VARCHAR columns.
• You can use put the datafile and index file on different directories to get more speed
(with the DATA/INDEX DIRECTORY="path" option to CREATE TABLE). See hundefinedi
[CREATE TABLE], page hundefinedi.
MyISAM also supports the following things, which MySQL will be able to use in the near
future:
• Support for a true VARCHAR type; a VARCHAR column starts with a length stored in 2
bytes.
• Tables with VARCHAR may have fixed or dynamic record length.
• VARCHAR and CHAR may be up to 64K. All key segments have their own language
definition. This will enable MySQL to have different language definitions per column.
• A hashed computed index can be used for UNIQUE. This will allow you to have UNIQUE
on any combination of columns in a table. (You can’t search on a UNIQUE computed
index, however.)
Note that index files are usually much smaller with MyISAM than with ISAM. This means
that MyISAM will normally use less system resources than ISAM, but will need more CPU
time when inserting data into a compressed index.
The following options to mysqld can be used to change the behaviour of MyISAM tables. See
hundefinedi [SHOW VARIABLES], page hundefinedi.
Option Description
--myisam-recover=# Automatic recovery of crashed tables.
-O myisam_sort_buffer_size=# Buffer used when recovering tables.
--delay-key-write=ALL Don’t flush key buffers between writes for any My-
ISAM table
-O myisam_max_extra_sort_file_ Used to help MySQL to decide when to use the slow
size=# but safe key cache index create method. Note that
this parameter is given in megabytes before 4.0.3 and
in bytes beginning with this version.
-O myisam_max_sort_file_size=# Don’t use the fast sort index method to created in-
dex if the temporary file would get bigger than this.
Note that this parameter is given in megabytes be-
fore 4.0.3 and in bytes beginning with this version.
-O bulk_insert_buffer_size=# Size of tree cache used in bulk insert optimisation.
Note that this is a limit per thread!
The automatic recovery is activated if you start mysqld with --myisam-recover=#. See line
options-snt [Command-line options], page line options-pg. On open, the table is checked if
it’s marked as crashed or if the open count variable for the table is not 0 and you are running
with --skip-external-locking. If either of the above is true the following happens.
494 Referência técnica para o MySQL versão 3.23.52
• Not as easy to reconstruct after a crash, because a record may be fragmented into many
pieces and a link (fragment) may be missing.
• The expected row length for dynamic sized records is:
3
+ (number of columns + 7) / 8
+ (number of char columns)
+ packed size of numeric columns
+ length of strings
+ (number of NULL columns + 7) / 8
There is a penalty of 6 bytes for each link. A dynamic record is linked whenever an
update causes an enlargement of the record. Each new link will be at least 20 bytes, so
the next enlargement will probably go in the same link. If not, there will be another
link. You may check how many links there are with myisamchk -ed. All links may be
removed with myisamchk -r.
• To avoid problems with interaction with other processes that may do a check on the
table, the counter is not decremented on close if it was 0.
In other words, the only ways this can go out of sync are:
• The MyISAM tables are copied without a LOCK and FLUSH TABLES.
• MySQL has crashed between an update and the final close. (Note that the table may
still be okay, as MySQL always issues writes for everything between each statement.)
• Someone has done a myisamchk --recover or myisamchk --update-stateon a table
that was in use by mysqld.
• Many mysqld servers are using the table and one has done a REPAIR or CHECK of the
table while it was in use by another server. In this setup the CHECK is safe to do
(even if you will get the warning from other servers), but REPAIR should be avoided
as it currently replaces the datafile with a new one, which is not signaled to the other
servers.
• More efficient repairs. It’s easier to repair the individual files that are mapped to a
MERGE file than trying to repair a really big file.
• Instant mapping of many files as one. A MERGE table uses the index of the individual
tables. It doesn’t need to maintain an index of its one. This makes MERGE table
collections VERY fast to make or remap. Note that you must specify the key definitions
when you create a MERGE table!.
• If you have a set of tables that you join to a big table on demand or batch, you should
instead create a MERGE table on them on demand. This is much faster and will save a
lot of disk space.
• Go around the file-size limit for the operating system.
• You can create an alias/synonym for a table by just using MERGE over one table. There
shouldn’t be any really notable performance impacts of doing this (only a couple of
indirect calls and memcpy() calls for each read).
The disadvantages with MERGE tables are:
• You can only use identical MyISAM tables for a MERGE table.
• REPLACE doesn’t work.
• MERGE tables uses more file descriptors. If you are using a MERGE table that maps over
10 tables and 10 users are using this, you are using 10*10 + 10 file descriptors. (10
datafiles for 10 users and 10 shared index files.)
• Key reads are slower. When you do a read on a key, the MERGE storage engine will
need to issue a read on all underlying tables to check which one most closely matches
the given key. If you then do a "read-next" then the MERGE storage engine will need
to search the read buffers to find the next key. Only when one key buffer is used
up, the storage engine will need to read the next key block. This makes MERGE keys
much slower on eq_ref searches, but not much slower on ref searches. See hundefinedi
[EXPLAIN], page hundefinedi.
• You can’t do DROP TABLE, ALTER TABLE, DELETE FROM table_name without a WHERE
clause, REPAIR TABLE, TRUNCATE TABLE, OPTIMIZE TABLE, or ANALYZE TABLE on any of
the table that is mapped by a MERGE table that is "open". If you do this, the MERGE table
may still refer to the original table and you will get unexpected results. The easiest
way to get around this deficiency is to issue the FLUSH TABLES command, ensuring no
MERGE tables remain "open".
When you create a MERGE table you have to specify with UNION(list-of-tables) which
tables you want to use as one. Optionally you can specify with INSERT_METHOD if you want
insert for the MERGE table to happen in the first or last table in the UNION list. If you don’t
specify INSERT_METHOD or specify NO, then all INSERT commands on the MERGE table will
return an error.
The following example shows you how to use MERGE tables:
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
CREATE TABLE t2 (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20));
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("t1");
INSERT INTO t2 (message) VALUES ("Testing"),("table"),("t2");
CREATE TABLE total (a INT AUTO_INCREMENT PRIMARY KEY, message CHAR(20))
TYPE=MERGE UNION=(t1,t2) INSERT_METHOD=LAST;
500 Referência técnica para o MySQL versão 3.23.52
Note that you can also manipulate the ‘.MRG’ file directly from the outside of the MySQL
server:
shell> cd /mysql-data-directory/current-database
shell> ls -1 t1.MYI t2.MYI > total.MRG
shell> mysqladmin flush-tables
Now you can do things like:
mysql> SELECT * FROM total;
+---+---------+
| a | message |
+---+---------+
| 1 | Testing |
| 2 | table |
| 3 | t1 |
| 1 | Testing |
| 2 | table |
| 3 | t2 |
+---+---------+
Note that the a column, though declared as PRIMARY KEY, is not really unique, as MERGE
table cannot enforce uniqueness over a set of underlying MyISAM tables.
To remap a MERGE table you can do one of the following:
• DROP the table and re-create it
• Use ALTER TABLE table_name UNION(...)
• Change the ‘.MRG’ file and issue a FLUSH TABLE on the MERGE table and all underlying
tables to force the storage engine to read the new definition file.
• The range optimiser can’t yet use MERGE table efficiently and may sometimes produce
non-optimal joins. This will be fixed in MySQL 4.0.x.
• DROP TABLE on a table that is in use by a MERGE table will not work on Windows
because the MERGE storage engine does the table mapping hidden from the upper layer of
MySQL. Because Windows doesn’t allow you to drop files that are open, you first must
flush all MERGE tables (with FLUSH TABLES) or drop the MERGE table before dropping
the table. We will fix this at the same time we introduce VIEWs.
multiuser concurrency and performance. There is no need for lock escalation in InnoDB,
because row level locks in InnoDB fit in very small space. InnoDB tables support FOREIGN
KEY constraints as the first table type in MySQL.
InnoDB has been designed for maximum performance when processing large data volumes.
Its CPU efficiency is probably not matched by any other disk-based relational database
engine.
InnoDB is used in production at númerous large database sites requiring high performance.
The famous Internet news site Slashdot.org runs on InnoDB. Mytrix, Inc. stores over 1 TB
of data in InnoDB, and another site handles an average load of 800 inserts/updates per
second in InnoDB.
Technically, InnoDB is a complete database backend placed under MySQL. InnoDB has its
own buffer pool for caching data and indexes in main memory. InnoDB stores its tables
and indexes in a tablespace, which may consist of several files (or raw disk partitions). This
is different from, for example, MyISAM tables where each table is stored as a separate file.
InnoDB tables can be of any size also on those operating systems where file-size is limited
to 2 GB.
You can find the latest information about InnoDB at http://www.innodb.com/. The most
up-to-date version of the InnoDB manual is always placed there, and you can also order
commercial licenses and support for InnoDB.
In the source distribution of MySQL, InnoDB appears as a subdirectory. InnoDB is dis-
tributed under the GNU GPL License Version 2 (of June 1991).
the default is to create these files to the datadir of MySQL. If you specify innodb_data_
home_dir as an empty string, then you can give absolute paths to your data files in innodb_
data_file_path.
The minimal way to modify it is to add to the [mysqld] section the line
innodb_data_file_path=ibdata:30M
but to get good performance it is best that you specify options as recommended. See
hundefinedi [InnoDB start], page hundefinedi.
innodb_flush_log_at_trx_commit=1
set-variable = innodb_lock_wait_timeout=50
#innodb_flush_method=fdatasync
#set-variable = innodb_thread_concurrency=5
Note that we have placed the two datafiles on different disks. InnoDB will fill the tablespace
formed by the datafiles from bottom up. In some cases it will improve the performance of
the database if all data is not placed on the same physical disk. Putting log files on a
different disk from data is very often beneficial for performance. You can also use raw disk
partitions (raw devices) as datafiles. In some Unixes they speed up I/O. See the manual
section on InnoDB file space management about how to specify them in ‘my.cnf’.
Warning: on Linux x86 you must be careful you do not set memory usage too high. glibc
will allow the process heap to grow over thread stacks, which will crash your server. It is a
risk if the value of
innodb_buffer_pool_size + key_buffer +
max_connections * (sort_buffer + read_buffer_size) + max_connections * 2 MB
is close to 2 GB or exceeds 2 GB. Each thread will use a stack (often 2 MB, but in MySQL
AB binaries only 256 KB) and in the worst case also sort_buffer + read_buffer_size
additional memory.
How to tune other ‘mysqld’ server parameters? Typical values which suit most users are:
skip-locking
set-variable = max_connections=200
set-variable = read_buffer_size=1M
set-variable = sort_buffer=1M
# Set key_buffer to 5 - 50%
# of your RAM depending on how
# much you use MyISAM tables, but
# keep key_buffer + InnoDB
# buffer pool size < 80% of
# your RAM
set-variable = key_buffer=...
Note that some parameters are given using the numeric ‘my.cnf’ parameter format: set-
variable = innodb... = 123, others (string and boolean parameters) with another format:
innodb_... = ... .
Option Description
innodb_data_home_dir The common part of the directory path for all InnoDB
datafiles. If you do not mentioned this option in ‘my.cnf’
the default is the datadir of MySQL. You can specify
this also as an empty string, in which case you can use
absolute file paths in innodb_data_file_path.
508 Referência técnica para o MySQL versão 3.23.52
innodb_data_file_path Paths to individual datafiles and their sizes. The full di-
rectory path to each datafile is acquired by concatenating
innodb data home dir to the paths specified here. The
file sizes are specified in megabytes, hence the ’M’ after
the size specification above. InnoDB also understands
the abbreviation ’G’, 1 G meaning 1024 MB. Starting
from 3.23.44 you can set the file-size bigger than 4 GB
on those operating systems which support big files. On
some operating systems files must be < 2 GB. The sum
of the sizes of the files must be at least 10 MB.
innodb_mirrored_log_groups Number of identical copies of log groups we keep for the
database. Currently this should be set to 1.
innodb_log_group_home_dir Directory path to InnoDB log files.
innodb_log_files_in_group Number of log files in the log group. InnoDB writes to
the files in a circular fashion. Value 3 is recommended
here.
innodb_log_file_size Size of each log file in a log group in megabytes. Sensible
values range from 1M to 1/nth of the size of the buffer
pool specified below, where n is the number of log files in
the group. The bigger the value, the less checkpoint flush
activity is needed in the buffer pool, saving disk I/O. But
bigger log files also mean that recovery will be slower in
case of a crash. The combined size of log files must be <
4 GB on 32-bit computers.
innodb_log_buffer_size The size of the buffer which InnoDB uses to write log to
the log files on disk. Sensible values range from 1M to 8M.
A big log buffer allows large transactions to run without a
need to write the log to disk until the transaction commit.
Thus, if you have big transactions, making the log buffer
big will save disk I/O.
innodb_flush_log_at_trx_ Normally you set this to 1, meaning that at a transaction
commit commit the log is flushed to disk, and the modifications
made by the transaction become permanent, and survive
a database crash. If you are willing to compromise this
safety, and you are running small transactions, you may
set this to 0 or 2 to reduce disk I/O to the logs. Value 0
means that the log is only written to the log file and the
log file flushed to disk approximately once per second.
Value 2 means the log is written to the log file at each
commit, but the log file is only flushed to disk approxi-
mately once per second. The default value is 1 starting
from MySQL-4.0.13, previously it was 0.
innodb_log_arch_dir The directory where fully written log files would be
archived if we used log archiving. The value of this pa-
rameter should currently be set the same as innodb_log_
group_home_dir.
Chapter 7: MySQL Table Types 509
new to be created
InnoDB: Setting file /home/heikki/data/ibdata2 size to 262144000
InnoDB: Database physically writes the file full: wait...
InnoDB: Log file /home/heikki/data/logs/ib_logfile0 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile0 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile1 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile1 size to 5242880
InnoDB: Log file /home/heikki/data/logs/ib_logfile2 did not exist:
new to be created
InnoDB: Setting log file /home/heikki/data/logs/ib_logfile2 size to 5242880
InnoDB: Started
mysqld: ready for connections
A new InnoDB database has now been created. You can connect to the MySQL server with
the usual MySQL client programs like mysql. When you shut down the MySQL server with
‘mysqladmin shutdown’, InnoDB output will be like the following:
010321 18:33:34 mysqld: Normal shutdown
010321 18:33:34 mysqld: Shutdown Complete
InnoDB: Starting shutdown...
InnoDB: Shutdown completed
You can now look at the datafiles and logs directories and you will see the files created.
The log directory will also contain a small file named ‘ib_arch_log_0000000000’. That file
resulted from the database creation, after which InnoDB switched off log archiving. When
MySQL is again started, the output will be like the following:
~/mysqlm/sql > mysqld
InnoDB: Started
mysqld: ready for connections
‘my.cnf’, and start MySQL again. InnoDB will tell you at the startup that it is creating
new log files.
7.5.7.1 Checkpoints
InnoDB implements a checkpoint mechanism called a fuzzy checkpoint. InnoDB will flush
modified database pages from the buffer pool in small batches, there is no need to flush
the buffer pool in one single batch, which would in practice stop processing of user SQL
statements for a while.
In crash recovery InnoDB looks for a checkpoint label written to the log files. It knows that
all modifications to the database before the label are already present on the disk image of
the database. Then InnoDB scans the log files forward from the place of the checkpoint
applying the logged modifications to the database.
InnoDB writes to the log files in a circular fashion. All committed modifications which make
the database pages in the buffer pool different from the images on disk must be available
in the log files in case InnoDB has to do a recovery. This means that when InnoDB starts
to reuse a log file in the circular fashion, it has to make sure that the database page images
on disk already contain the modifications logged in the log file InnoDB is going to reuse. In
other words, InnoDB has to make a checkpoint and often this involves flushing of modified
database pages to disk.
The above explains why making your log files very big may save disk I/O in checkpointing.
It can make sense to set the total size of the log files as big as the buffer pool or even bigger.
The drawback in big log files is that crash recovery can last longer because there will be
more log to apply to the database.
copying all the relevant files, which we already listed in the previous section on backing up
a database. If the floating-point formats on the machines are different but you have not
used FLOAT or DOUBLE data types in your tables then the procedure is the same: just copy
the relevant files. If the formats are different and your tables contain floating-point data,
you have to use ‘mysqldump’ and ‘mysqlimport’ to move those tables.
A performance tip is to switch off auto-commit mode when you import data into your
database, assuming your tablespace has enough space for the big rollback segment the big
import transaction will generate. Do the commit only after importing a whole table or a
segment of a table.
A user can change the isolation level of a single session or all new incoming connections
with the
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED
| REPEATABLE READ | SERIALIZABLE}
SQL statement. Note that there are no hyphens in level names in the SQL syntax. If you
specify the keyword GLOBAL in the above statement, it will determine the initial isolation
level of new incoming connections, but will not change the isolation level of old connections.
Chapter 7: MySQL Table Types 517
Any user is free to change the isolation level of his session, even in the middle of a transac-
tion. In versions < 3.23.50 SET TRANSACTION had no effect on InnoDB tables. In versions <
4.0.5 only REPEATABLE READ and SERIALIZABLE were available.
You can query the global and session transaction isolation levels with:
SELECT @@global.tx_isolation;
SELECT @@tx_isolation;
In row level locking InnoDB uses so-called next-key locking. That means that besides index
records, InnoDB can also lock the ’gap’ before an index record to block insertions by other
users immediately before the index record. A next-key lock means a lock which locks an
index record and the gap before it. A gap lock means a lock which only locks a gap before
some index record.
A detailed description of each isolation level in InnoDB:
• READ UNCOMMITTED This is also called ’dirty read’: non-locking SELECTs are performed
so that we do not look at a possible earlier version of a record; thus they are not ’con-
sistent’ reads under this isolation level; otherwise this level works like READ COMMITTED.
• READ COMMITTED Somewhat Oracle-like isolation level. All SELECT ... FOR UPDATE and
SELECT ... LOCK IN SHARE MODE statements only lock the index records, NOT the gaps
before them, and thus allow free inserting of new records next to locked records. UPDATE
and DELETE which use a unique index with a unique search condition, only lock the
index record found, not the gap before it. But still in range type UPDATE and DELETE
InnoDB must set next-key or gap locks and block insertions by other users to the
gaps covered by the range. This is necessary since ’phantom rows’ have to be blocked
for MySQL replication and recovery to work. Consistent reads behave like in Oracle:
each consistent read, even within the same transaction, sets and reads its own fresh
snapshot.
• REPEATABLE READ This is the default isolation level of InnoDB. SELECT ... FOR UPDATE,
SELECT ... LOCK IN SHARE MODE, UPDATE, and DELETE which use a unique index with
a unique search condition, only lock the index record found, not the gap before it.
Otherwise these operations employ next-key locking, locking the index range scanned
with next-key or gap locks, and block new insertions by other users. In consistent
reads there is an important difference from the previous isolation level: in this level
all consistent reads within the same transaction read the same snapshot established by
the first read. This convention means that if you issue several plain SELECTs within
the same transaction, these SELECTs are consistent also with respect to each other.
• SERIALIZABLE This level is like the previous one, but all plain SELECTs are implicitly
converted to SELECT ... LOCK IN SHARE MODE.
that transaction. You can get a fresher snapshot for your queries by committing the current
transaction and after that issuing new queries.
Consistent read is the default mode in which InnoDB processes SELECT statements in READ
COMMITTED and REPEATABLE READ isolation levels. A consistent read does not set any locks
on the tables it accesses, and therefore other users are free to modify those tables at the
same time a consistent read is being performed on the table.
The locks InnoDB sets on index records also affect the ’gap’ before that index record. If a
user has a shared or exclusive lock on record R in an index, then another user cannot insert
a new index record immediately before R in the index order. This locking of gaps is done to
prevent the so-called phantom problem. Suppose I want to read and lock all children with
identifier bigger than 100 from table CHILD, and update some field in the selected rows.
SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;
Suppose there is an index on table CHILD on column ID. Our query will scan that index
starting from the first record where ID is bigger than 100. Now, if the locks set on the
index records would not lock out inserts made in the gaps, a new child might meanwhile be
inserted to the table. If now I in my transaction execute
SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;
again, I will see a new child in the result set the query returns. This is against the isolation
principle of transactions: a transaction should be able to run so that the data it has read
does not change during the transaction. If we regard a set of rows as a data item, then the
new ’phantom’ child would break this isolation principle.
When InnoDB scans an index it can also lock the gap after the last record in the index.
Just that happens in the previous example: the locks set by InnoDB will prevent any insert
to the table where ID would be bigger than 100.
You can use next-key locking to implement a uniqueness check in your application: if you
read your data in share mode and do not see a duplicate for a row you are going to insert,
then you can safely insert your row and know that the next-key lock set on the successor
of your row during the read will prevent anyone meanwhile inserting a duplicate for your
row. Thus the next-key locking allows you to ’lock’ the non-existence of something in your
table.
User A User B
SELECT * FROM t;
empty set;
COMMIT;
SELECT * FROM t;
---------------------
| 1 | 2 |
---------------------
Thus user A sees the row inserted by B only when B has committed the insert, and A has
committed his own transaction so that the timepoint is advanced past the commit of B.
If you want to see the “freshest” state of the database, you should use a locking read:
SELECT * FROM t LOCK IN SHARE MODE;
• Access your tables and rows in a fixed order. Then transactions will form nice queues,
and do not deadlock.
• Add good indexes to your tables. Then your queries need to scan less index records
and consequently set less locks. Use EXPLAIN SELECT to determine that MySQL picks
appropriate indexes for your queries.
• Use less locking: if you can afford a SELECT to return data from an old snapshot, do
not add the clause FOR UPDATE or LOCK IN SHARE MODE to it. Using READ COMMITTED
isolation level is good here, because each consistent read within the same transaction
reads from its own fresh snapshot.
• If nothing helps, serialize your transactions with table level locks: LOCK TABLES
t1 WRITE, t2 READ, ... ; [do something with tables t1 and t2 here]; UNLOCK
TABLES. Table level locks make you transactions to queue nicely, and deadlocks are
avoided. Note that LOCK TABLES implicitly starts a transaction, just like the command
BEGIN, and UNLOCK TABLES implicitly ends the transaction in a COMMIT.
• Another solution to serialize transactions is to create an auxiliary ’semaphore’ table
where there is just a single row. Each transaction updates that row before accessing
other tables. In that way all transactions happen in a serial fashion. Note that then
also the InnoDB instant deadlock detection algorithm works, because the serializing
lock is a row level lock. In MySQL table level locks we have to resort to the timeout
method to resolve a deadlock.
7. In importing data to InnoDB, make sure that MySQL does not have autocommit=1 on.
Then every insert requires a log flush to disk. Put before your plain SQL import file line
SET AUTOCOMMIT=0;
and after it
COMMIT;
If you use the ‘mysqldump’ option --opt, you will get dump files which are fast to import
also to an InnoDB table, even without wrapping them to the above SET AUTOCOMMIT=0;
... COMMIT; wrappers.
8. Beware of big rollbacks of mass inserts: InnoDB uses the insert buffer to save disk I/O in
inserts, but in a corresponding rollback no such mechanism is used. A disk-bound rollback
can take 30 times the time of the corresponding insert. Killing the database process will
not help because the rollback will start again at the database startup. The only way to
get rid of a runaway rollback is to increase the buffer pool so that the rollback becomes
CPU-bound and runs fast, or delete the whole InnoDB database.
9. Beware also of other big disk-bound operations. Use DROP TABLE or TRUNCATE (from
MySQL-4.0 up) to empty a table, not DELETE FROM yourtable.
10. Use the multi-line INSERT to reduce communication overhead between the client and
the server if you need to insert many rows:
INSERT INTO yourtable VALUES (1, 2), (5, 5);
This tip is of course valid for inserts into any table type, not just InnoDB.
shut down the database when the monitor is running, and you want to start the monitor
again, you have to drop the table before you can issue a new CREATE TABLE to start the
monitor. This syntax may change in a future release.
A sample output of the InnoDB Monitor:
================================
010809 18:45:06 INNODB MONITOR OUTPUT
================================
--------------------------
LOCKS HELD BY TRANSACTIONS
--------------------------
LOCK INFO:
Number of locks in the record hash table 1294
LOCKS FOR TRANSACTION ID 0 579342744
TABLE LOCK table test/mytable trx id 0 582333343 lock_mode IX
RECORD LOCKS space id 0 page no 12758 n bits 104 table test/mytable index
PRIMARY trx id 0 582333343 lock_mode X
Record lock, heap no 2 PHYSICAL RECORD: n_fields 74; 1-byte offs FALSE;
info bits 0
0: len 4; hex 0001a801; asc ;; 1: len 6; hex 000022b5b39f; asc ";;
2: len 7; hex 000002001e03ec; asc ;; 3: len 4; hex 00000001;
...
-----------------------------------------------
CURRENT SEMAPHORES RESERVED AND SEMAPHORE WAITS
-----------------------------------------------
SYNC INFO:
Sorry, cannot give mutex list info in non-debug version!
Sorry, cannot give rw-lock list info in non-debug version!
-----------------------------------------------------
SYNC ARRAY INFO: reservation count 6041054, signal count 2913432
4a239430 waited for by thread 49627477 op. S-LOCK file NOT KNOWN line 0
Mut ex 0 sp 5530989 r 62038708 sys 2155035;
rws 0 8257574 8025336; rwx 0 1121090 1848344
-----------------------------------------------------
CURRENT PENDING FILE I/O’S
--------------------------
Pending normal aio reads:
Reserved slot, messages 40157658 4a4a40b8
Reserved slot, messages 40157658 4a477e28
...
Reserved slot, messages 40157658 4a4424a8
Reserved slot, messages 40157658 4a39ea38
Total of 36 reserved aio slots
Pending aio writes:
Total of 0 reserved aio slots
Pending insert buffer aio reads:
Total of 0 reserved aio slots
Pending log writes or reads:
Reserved slot, messages 40158c98 40157f98
Chapter 7: MySQL Table Types 525
InnoDB uses the information in the rollback segment to perform the undo operations needed
in a transaction rollback. It also uses the information to build earlier versions of a row for
a consistent read.
Undo logs in the rollback segment are divided into insert and update undo logs. Insert undo
logs are only needed in transaction rollback and can be discarded as soon as the transaction
commits. Update undo logs are used also in consistent reads, and they can be discarded
only after there is no transaction present for which InnoDB has assigned a snapshot that
in a consistent read could need the information in the update undo log to build an earlier
version of a database row.
You must remember to commit your transactions regularly, also those transactions which
only issue consistent reads. Otherwise InnoDB cannot discard data from the update undo
logs, and the rollback segment may grow too big, filling up your tablespace.
The physical size of an undo log record in the rollback segment is typically smaller than
the corresponding inserted or updated row. You can use this information to calculate the
space need for your rollback segment.
In our multi-versioning scheme a row is not physically removed from the database immedi-
ately when you delete it with an SQL statement. Only when InnoDB can discard the update
undo log record written for the deletion, it can also physically remove the corresponding
row and its index records from the database. This removal operation is called a purge, and
it is quite fast, usually taking the same order of time as the SQL statement which did the
deletion.
All indexes in InnoDB are B-trees where the index records are stored in the leaf pages of the
tree. The default size of an index page is 16 KB. When new records are inserted, InnoDB
tries to leave 1 / 16 of the page free for future insertions and updates of the index records.
If index records are inserted in a sequential (ascending or descending) order, the resulting
index pages will be about 15/16 full. If records are inserted in a random order, then the
pages will be 1/2 - 15/16 full. If the fillfactor of an index page drops below 1/2, InnoDB
will try to contract the index tree to free the page.
It is a common situation in a database application that the primary key is a unique identifier
and new rows are inserted in the ascending order of the primary key. Thus the insertions
to the clustered index do not require random reads from a disk.
On the other hand, secondary indexes are usually non-unique and insertions happen in a
relatively random order into secondary indexes. This would cause a lot of random disk I/Os
without a special mechanism used in InnoDB.
If an index record should be inserted to a non-unique secondary index, InnoDB checks if
the secondary index page is already in the buffer pool. If that is the case, InnoDB will do
the insertion directly to the index page. But, if the index page is not found from the buffer
pool, InnoDB inserts the record to a special insert buffer structure. The insert buffer is
kept so small that it entirely fits in the buffer pool, and insertions can be made to it very
fast.
The insert buffer is periodically merged to the secondary index trees in the database. Often
we can merge several insertions on the same page in of the index tree, and hence save disk
I/Os. It has been measured that the insert buffer can speed up insertions to a table up to
15 times.
If a database fits almost entirely in main memory, then the fastest way to perform queries
on it is to use hash indexes. InnoDB has an automatic mechanism which monitors index
searches made to the indexes defined for a table, and if InnoDB notices that queries could
benefit from building of a hash index, such an index is automatically built.
But note that the hash index is always built based on an existing B-tree index on the table.
InnoDB can build a hash index on a prefix of any length of the key defined for the B-tree,
depending on what search pattern InnoDB observes on the B-tree index. A hash index
can be partial: it is not required that the whole B-tree index is cached in the buffer pool.
InnoDB will build hash indexes on demand to those pages of the index which are often
accessed.
In a sense, through the adaptive hash index mechanism InnoDB adapts itself to ample main
memory, coming closer to the architecture of main memory databases.
528 Referência técnica para o MySQL versão 3.23.52
On Windows NT InnoDB uses non-buffered I/O. That means that the disk pages InnoDB
reads or writes are not buffered in the operating system file cache. This saves some memory
bandwidth.
Starting from 3.23.41 InnoDB uses a novel file flush technique called doublewrite. It adds
safety to crash recovery after an operating system crash or a power outage, and improves
performance on most Unix flavors by reducing the need for fsync operations.
Doublewrite means that InnoDB before writing pages to a datafile first writes them to a
contiguous tablespace area called the doublewrite buffer. Only after the write and the flush
to the doublewrite buffer has completed, InnoDB writes the pages to their proper positions
in the datafile. If the operating system crashes in the middle of a page write, InnoDB will
in recovery find a good copy of the page from the doublewrite buffer.
Starting from 3.23.41 you can also use a raw disk partition as a datafile, though this has
not been tested yet. When you create a new datafile you have to put the keyword newraw
immediately after the data file-size in innodb_data_file_path. The partition must be >=
than you specify as the size. Note that 1M in InnoDB is 1024 x 1024 bytes, while in disk
specifications 1 MB usually means 1000 000 bytes.
innodb_data_file_path=hdd1:5Gnewraw;hdd2:2Gnewraw
When you start the database again you must change the keyword to raw. Otherwise,
InnoDB will write over your partition!
innodb_data_file_path=hdd1:5Graw;hdd2:2Graw
By using a raw disk you can on some Unixes perform unbuffered I/O.
There are two read-ahead heuristics in InnoDB: sequential read-ahead and random read-
ahead. In sequential read-ahead InnoDB notices that the access pattern to a segment in the
tablespace is sequential. Then InnoDB will post in advance a batch of reads of database
pages to the I/O system. In random read-ahead InnoDB notices that some area in a
tablespace seems to be in the process of being fully read into the buffer pool. Then InnoDB
posts the remaining reads to the I/O system.
Some pages in the tablespace contain bitmaps of other pages, and therefore a few extents in
an InnoDB tablespace cannot be allocated to segments as a whole, but only as individual
pages.
When you issue a query SHOW TABLE STATUS FROM ... LIKE ... to ask for available free
space in the tablespace, InnoDB will report the extents which are definitely free in the
tablespace. InnoDB always reserves some extents for clean-up and other internal purposes;
these reserved extents are not included in the free space.
When you delete data from a table, InnoDB will contract the corresponding B-tree indexes.
It depends on the pattern of deletes if that frees individual pages or extents to the tablespace,
so that the freed space is available for other users. Dropping a table or deleting all rows
from it is guaranteed to release the space to other users, but remember that deleted rows
can be physically removed only in a purge operation after they are no longer needed in
transaction rollback or consistent read.
• Fixed a bug: REPLACE INTO t1 SELECT ... did not work if t1 has an auto-inc
column.
• An outstanding bug: SET FOREIGN KEY CHECKS=0 is not replicated properly in
the MySQL replication.
• Tables and indexes now reserve 4 % less space in the tablespace. Also existing tables
reserve less space. By upgrading to 4.0.8 you will see more free space in "InnoDB free"
in SHOW TABLE STATUS.
• Fixed bugs: updating the PRIMARY KEY of a row would generate a foreign key error
on all FOREIGN KEYs which referenced secondary keys of the row to be updated.
Also, if a referencing FOREIGN KEY constraint only referenced the first columns in
an index, and there were more columns in that index, updating the additional columns
generated a foreign key error.
• Fixed a bug: if an index contains some column twice, and that column is updated, the
table will become corrupt. From now on InnoDB prevents creation of such indexes.
• Fixed a bug: removed superfluous error 149 and 150 printouts from the .err log when
a locking SELECT caused a deadlock or a lock wait timeout.
• Fixed a bug: an assertion in btr0sea.c, in function btr search info update slow could
theoretically fail in a race of 3 threads.
• Fixed a bug: one could not switch a session transaction isolation level back to RE-
PEATABLE READ after setting it to something else.
• Fixed a bug: ORDER BY could fail if you had not created a primary key to a table,
but had defined several indexes of which at least one was a UNIQUE index with all its
columns declared as NOT NULL.
• Fixed a bug: a lock wait timeout in connection with ON DELETE CASCADE could
cause corruption in indexes.
• Fixed a bug: if a SELECT was done with a unique key from a primary index, and
the search matched to a delete-marked record, InnoDB could erroneously return the
NEXT record.
• Fixed a bug introduced in 3.23.53: LOCK TABLES ... READ LOCAL should not
set row locks on the rows read. This caused deadlocks and lock wait timeouts in
mysqldump.
• Fixed a bug: if an index contains some column twice, and that column is updated, the
table will become corrupt. From now on InnoDB prevents creation of such indexes.
• Fixed a potential bug in 4.0.4: InnoDB now does ORDER BY ... DESC like MyISAM.
• Fixed a bug: DROP TABLE could cause crash or a hang if there was a rollback
concurrently running on the table. The fix will only be backported to 3.23 if this
appears a real problem for users.
• Fixed a bug: ORDER BY could fail if you had not created a primary key to a table,
but had defined several indexes of which at least one was a UNIQUE index with all its
columns declared as NOT NULL.
• Fixed a bug: a lock wait timeout in connection with ON DELETE CASCADE could
cause corruption in indexes.
• Fixed a bug: if a SELECT was done with a unique key from a primary index, and the
search matched to a delete-marked record, InnoDB could return the NEXT record.
• Outstanding bugs: in 4.0.4 two bugs were introduced to AUTO INCREMENT. RE-
PLACE can cause the counter to be left 1 too low. A deadlock or a lock wait timeout
can cause the same problem. These will be fixed in 4.0.6.
• Increased the max key length of InnoDB tables from 500 to 1024 bytes.
• Increased the table comment field in SHOW TABLE STATUS so that up to 16000
characters of foreign key definitions can be printed there.
• The auto-increment counter is no longer incremented if an insert of a row immediately
fails in an error.
• Allow dropping and creating a table even if innodb force recovery is set. One can use
this to drop a table which would cause a crash in rollback or purge, or if a failed table
import causes a runaway rollback in recovery.
• Fixed a bug: Using ORDER BY primarykey DESC in 4.0.3 causes an assertion failure
in btr0pcur.c, line 203.
• Fixed a bug: fast shutdown (which is the default) sometimes was slowed down by purge
and insert buffer merge.
• Fixed a bug: doing a big SELECT from a table where no rows were visible in a
consistent read could cause a very long (> 600 seconds) semaphore wait in btr0cur.c
line 310.
• Fixed a bug: if the MySQL query cache was used, it did not get invalidated by a
modification done by ON DELETE CASCADE or ...SET NULL.
• Fixed a bug: if you created a temporary table inside LOCK TABLES, and used that
temporary table, that caused an assertion failure in ha innodb.cc.
• Fixed a bug: if you set innodb flush log at trx commit to 1, SHOW VARIABLES
would show its value as 16 million.
• A new SQL command SHOW INNODB STATUS returns the output of the InnoDB
Monitor to the client. The InnoDB Monitor now prints detailed info on the latest
detected deadlock.
• InnoDB made the SQL query optimiser to avoid too much index-only range scans and
choose full table scans instead. This is now fixed.
• "BEGIN" and "COMMIT" are now added in the binlog around transactions. The
MySQL replication now respects transaction borders: a user will no longer see half
transactions in replication slaves.
• A replication slave now prints in crash recovery the last master binlog position it was
able to recover to.
• A new setting innodb flush log at trx commit=2 makes InnoDB to write the log to
the operating system file cache at each commit. This is almost as fast as the setting
innodb flush log at trx commit=0, and the setting 2 also has the nice feature that in a
crash where the operating system does not crash, no committed transaction is lost. If
the operating system crashes or there is a power outage, then the setting 2 is no safer
than the setting 0.
• Added checksum fields to log blocks.
• SET FOREIGN KEY CHECKS=0 helps in importing tables in an arbitrary order
which does not respect the foreign key rules.
• SET UNIQUE CHECKS=0 speeds up table imports into InnoDB if you have UNIQUE
constraints on secondary indexes.
• SHOW TABLE STATUS now lists also possible ON DELETE CASCADE or ON
DELETE SET NULL in the comment field of the table.
• When CHECK TABLE is run on any InnoDB type table, it now checks also the adaptive
hash index for all tables.
• If you defined ON DELETE CASCADE or SET NULL and updated the referenced key
in the parent row, InnoDB deleted or updated the child row. This is now changed to
conform to SQL-92: you get the error ’Cannot delete parent row’.
• Improved the auto-increment algorithm: now the first insert or SHOW TABLE STA-
TUS initializes the auto-inc counter for the table. This removes almost all surprising
deadlocks caused by SHOW TABLE STATUS.
• Aligned some buffers used in reading and writing to data files. This allows using
unbuffered raw devices as data files in Linux.
• Fixed a bug: If you updated the primary key of a table so that only the case of
characters changed, that could cause assertion failures, mostly in page0page.ic line
515.
• Fixed a bug: If you delete or update a row referenced in a foreign key constraint and
the foreign key check has to wait for a lock, then the check may report an erroneous
result. This affects also the ON DELETE... operation.
• Fixed a bug: A deadlock or a lock wait timeout error in InnoDB causes InnoDB to roll
back the whole transaction, but MySQL could still write the earlier SQL statements
to the binlog, even though InnoDB rolled them back. This could, for example, cause
replicated databases to get out-of-sync.
Chapter 7: MySQL Table Types 539
• Fixed a bug: If the database happened to crash in the middle of a commit, then the
recovery might leak tablespace pages.
• Fixed a bug: If you specified a non-latin1 character set in my.cnf, then, in contrary to
what is stated in the manual, in a foreign key constraint a string type column had to
have the same length specification in the referencing table and the referenced table.
• Fixed a bug: DROP TABLE or DROP DATABASE could fail if there simultaneously
was a CREATE TABLE running.
• Fixed a bug: If you configured the buffer pool bigger than 2 GB in a 32-bit computer,
InnoDB would assert in buf0buf.ic line 214.
• Fixed a bug: on 64-bit computers updating rows which contained the SQL NULL in
some column could cause the undo log and the ordinary log to become corrupt.
• Fixed a bug: innodb log monitor caused a hang if it suppressed lock prints for a page.
• Fixed a bug: in the HP-UX-10.20 version mutexes would leak and cause race conditions
and crashes in any part of InnoDB code.
• Fixed a bug: if you ran in the AUTOCOMMIT mode, executed a SELECT, and
immediately after that a RENAME TABLE, then RENAME would fail and MySQL
would complain about error 1192.
• Fixed a bug: if compiled on 64-bit Solaris, InnoDB produced a bus error at startup.
• The log scan phase in crash recovery will now run much faster.
• Starting from this server version, the hot backup tool truncates unused ends in the
backup InnoDB data files.
• To allow the hot backup tool to work, on Windows we no longer use unbuffered i/o or
native async i/o; instead we use the same simulated async i/o as on Unix.
• You can now define the ON DELETE CASCADE or ON DELETE SET NULL clause
on foreign keys.
• FOREIGN KEY constraints now survive ALTER TABLE and CREATE INDEX.
• We suppress the FOREIGN KEY check if any of the column values in the foreign key
or referenced key to be checked is the SQL NULL. This is compatible with Oracle, for
example.
• SHOW CREATE TABLE now lists also foreign key constraints. Also mysqldump no
longer forgets about foreign keys in table definitions.
• You can now add a new foreign key constraint with ALTER TABLE ... ADD CON-
STRAINT FOREIGN KEY (...) REFERENCES ... (...).
• FOREIGN KEY definitions now allow backquotes around table and column names.
• MySQL command SET TRANSACTION ISOLATION LEVEL ... has now the fol-
lowing effect on InnoDB tables: if a transaction is defined as SERIALIZABLE then
InnoDB conceptually adds LOCK IN SHARE MODE to all consistent reads. If a
transaction is defined to have any other isolation level, then InnoDB obeys its default
locking strategy which is REPEATABLE READ.
• SHOW TABLE STATUS no longer sets an x-lock at the end of an auto-increment index
if the auto-increment counter has already been initialized. This removes in almost all
cases the surprising deadlocks caused by SHOW TABLE STATUS.
• Fixed a bug: in a CREATE TABLE statement the string ’foreign’ followed by a non-
space character confused the FOREIGN KEY parser and caused table creation to fail
with errno 150.
• If MySQL binlogging is used, InnoDB now prints after crash recovery the latest MySQL
binlog file name and the position in that file (= byte offset) InnoDB was able to recover
to. This is useful, for example, when resynchronizing a master and a slave database in
replication.
• Added better error messages to help in installation problems.
• One can now recover also MySQL temporary tables which have become orphaned inside
the InnoDB tablespace.
• InnoDB now prevents a FOREIGN KEY declaration where the signedness is not the
same in the referencing and referenced integer columns.
• Fixed a bug: calling SHOW CREATE TABLE or SHOW TABLE STATUS could cause
memory corruption and make mysqld to crash. Especially at risk was mysqldump,
because it calls frequently SHOW CREATE TABLE.
• Fixed a bug: if on Unix you did an ALTER TABLE to an InnoDB table and simul-
taneously did queries to it, mysqld could crash with an assertion failure in row0row.c,
line 474.
• Fixed a bug: if inserts to several tables containing an auto-inc column were wrapped
inside one LOCK TABLES, InnoDB asserted in lock0lock.c.
• In 3.23.47 we allowed several NULLS in a UNIQUE secondary index. But CHECK
TABLE was not relaxed: it reports the table as corrupt. CHECK TABLE no longer
complains in this situation.
• Fixed a bug: on Sparc and other high-endian processors SHOW VARIABLES showed
innodb flush log at trx commit and other boolean-valued startup parameters always
OFF even if they were switched on.
• Fixed a bug: if you ran mysqld-max-nt as a service on Windows NT/2000, the service
shutdown did not always wait long enough for the InnoDB shutdown to finish.
• MySQL now knows that the table scan of an InnoDB table is done through the primary
key. This will save a sort in some ORDER BY queries.
• The maximum key length of InnoDB tables is again restricted to 500 bytes. The
MySQL interpreter is not able to handle longer keys.
• The default value of innodb lock wait timeout was changed from infinite to 50 seconds,
the default value of innodb file io threads from 9 to 4.
BDB distribution that has a couple of small patches to make it work more smoothly with
MySQL. You can’t use a non-patched BDB version with MySQL.
We at MySQL AB are working in close cooperation with Sleepycat to keep the quality of
the MySQL/BDB interface high.
When it comes to supporting BDB tables, we are committed to help our users to locate the
problem and help creating a reproducible test case for any problems involving BDB tables.
Any such test case will be forwarded to Sleepycat who in turn will help us find and fix the
problem. As this is a two-stage operation, any problems with BDB tables may take a little
longer for us to fix than for other storage engines. However, as the BerkeleyDB code itself
has been used by many other applications than MySQL, we don’t envision any big problems
with this. See hundefinedi [Support], page hundefinedi.
Note: The above list is not complete; we will update it as we receive more information.
If you build MySQL with support for BDB tables and get the following error in the log file
when you start mysqld:
bdb: architecture lacks fast mutexes: applications cannot be threaded
Can’t init dtabases
This means that BDB tables are not supported for your architecture. In this case you must
rebuild MySQL without BDB table support.
8 MySQL APIs
Este capítulo descreve as APIs disponíveis para o MySQL, onde consegui-las e como utilizá-
las. A API C é a coberta mais estensamente, já que ela foi desenvolvida pela equipe do
MySQL e é a base para a maioria das outras APIs.
MYSQL_RES
Esta estrutura representa o resultado de uma consulta que retorna linhas
(SELECT, SHOW, DESCRIBE, EXPLAIN). A informação retornada de uma consulta
é chamada conjunto de resultado no resto desta seção.
MYSQL_ROW
Esta é uma representação segura de tipo de uma linha de dados. Ela é imple-
mentada atualmente como um vetor de strings de tamanho fixo (Você não pode
tratá-los como strings terminadas com null se os valores do campo podem conter
dados binários, porque tais valores podem conter um byte null internamente.).
Linhas são obtidas pela chamada de mysql_fetch_row().
MYSQL_FIELD
Esta estrutura contém informação sobre um campo, tais como nome, tipo e
tamanho do campo. Seus membros são descritos em mais detalhes aqui. Você
pode obter a estrutura MYSQL_FIELD para cada campo chamando mysql_fetch_
field() repetidamente. Valores de campos não são parte desta estrutura; eles
estão contidos na estrutura MYSQL_ROW.
MYSQL_FIELD_OFFSET
Esta é uma representação segura de um offset em uma lista de campos MySQL.
(Usado por mysql_field_seek().) Offsets são números de campos em um
registro, começando com zero.
my_ulonglong
O tipo usado pelo número de linhas e para mysql_affected_rows(),
mysql_num_rows(), e mysql_insert_id(). Este tipo fornece uma faixa de 0
a 1.84e19.
Em alguns sistemas, tentar imprimir um valor do tipo my_ulonglong não fun-
cionará. Para imprimir tais valores, converta-os para unsigned long e use o
formato de impressão %lu. Exemplo:
printf ("Número de linhas: %lu\n", (unsigned long) mysql_num_
rows(resultado));
A estrutura MYSQL_FIELD contem os membros listados aqui:
char * name
O nome do campo, como um string terminada com null.
char * table
O nome da tabela contendo este campo, se não for um campo calculado. Para
campos calculador, o valor table é uma string vazia.
char * def
O valor padrão para este campo, como um string terminada em null. Ele é
atribuido apenas se você utilizar mysql_list_fields().
enum enum_field_types tipo
O tipo do campo. O valor tipo pode ser um dos seguintes:
Valou tipo Descrição do tipo
FIELD_TYPE_TINY campo TINYINT
Chapter 8: MySQL APIs 551
mysql drop db() Apaga um banco de dados; Esta função esta obsoleta; utiliza
o comando SQL DROP DATABASE.
mysql dump debug info() Faz o servidor escrever informações de depouração no log.
mysql eof() Determina quando a ulitma linha de um conjunto de re-
sultados foi lida. Esta função foi obsoleta; Utilize mysql_
errno() ou mysql_error()
mysql errno() Retorna o número de erro para a função MySQL chamada
mais recentemente.
mysql error() Retorna a mensagem de erro para função MySQL chamada
mais recentemente.
mysql escape string() Escapa caracteres especiais em uma string para ser usada
em uma instrução SQL.
mysql fetch field() Retorna o tipo do próximo campo na tabela.
mysql fetch field direct() Retorna o tipo de um campo da tabela, dado um número
do campo.
mysql fetch fields() Retorna um vetor de todas as estruturas do campo.
mysql fetch lengths() Retorna o tamanho de todas as colunas na linha atual.
mysql fetch row() Busca o próximo registro no conjunto de resultados.
mysql insert id() Retorna o ID gerado para uma coluna AUTO_INCREMENT pela
consulta anterior.
mysql kill() Mata uma thread dada.
mysql list dbs() Retorna o nome do banco de dados correspondente a uma
expressão regular.
mysql list fields() retorna nome de campos coincidindo com uma expressão
regular.
mysql list processes() Retorna uma lista das threads atuais do servidor.
mysql list tables() Retorna os nomes de tabelas correspondente a uma ex-
pressão regular.
mysql num fields() Retorna o número de coluans em um conjunto de resultados.
mysql num rows() Retorna o número de linhas em um conjunto de resultados.
mysql options() Define opções de conexão para mysql_connect().
mysql ping() Verifica se a conexão ao servidor está funcionando, re-
conectando se necessário.
mysql query() Executa uma consulta SQL especificada com uma string ter-
minada com null.
mysql real connect() Conecta ao servidor MySQL.
mysql real escape string() Escapa caracteres especiais em uma string para ser utilizada
em uma instrução SQL, olhando na conta o conjunto de
caracteres atual da conexão
mysql real query() Executa uma consulta SQL especificada como uma string
fixa.
mysql reload() Diz ao servidor pra recarregar a tabela de permissões
mysql row seek() Busca por uma linha no resultado, usando o valor retornado
de mysql_row_tell().
mysql row tell() Retorna a posição dio cursor de linhas.
mysql select db() Seleciona um banco de dados.
mysql shutdown() Desliga o servidor de banco de dados.
mysql stat() Retorna o status do servidor como uma string.
mysql store result() Recupera um resultado completo para o cliente.
mysql thread id() Retorna a identificação da thread atual.
mysql thread safe() Retorna 1 se o cliente foi compilado como thread-safe.
Chapter 8: MySQL APIs 555
mysql use result() Inicia uma resultado recuperado registro por registro.
mysql commit() Faz um commits na transação (novo na versão 4.1).
mysql rollback() Faz um roll back na transação (novo na versão 4.1).
mysql autocommit() Muda o modo autocommit em ligado/desligado (novo na
versão 4.1).
mysql more results() Verifica se não existem mais resultados (novo na versão 4.1).
mysql next result() Retorna/Inicia o próximo resultado em execuções consultas
múltiplas (inovo na versão 4.1).
Para se conectar ao servidor, chame mysql_init() para iniciar um manipulador de conexão,
então chame mysql_real_connect() com este manipulador (com informações de nome
de máquina, usuários e senha). Conectado, mysql_real_connect() define o parâmetro
reconnect (parte da estrutura MYSQL) para um valor de 1. Este parâmetro indica, no
evento que uma consulta não pode ser realizada por perda de conexão, para tentar reconectar
ao servidor ao antes de desistir. Quando não precisar mais da conexão, chame mysql_
close() para terminá-la.
Enquanto a conexão estiver ativa, o cliente pode enviar consultas SQL para o servidor
usando mysql_query() ou mysql_real_query(). A diferença entre os dois é que mysql_
query() espera que a consulta seja especificada como uma string terminada em null, en-
quanto mysql_real_query() espera um string de tamanho fixa. Se a string conter dados
binários (a qual pode incluir bytes null), vocêdeve usar mysql_real_query().
Para cada consulta não-SELECT (por exemplo, INSERT, UPDATE, DELETE), você pode desco-
brir quantas linhas foram alteradas (afetadas) chamando mysql_affected_rows().
Para consultas SELECT, você retorna os registros selecionados como um resultado. (Note que
algumas intruções são como a SELECT ao retornar registros. Elas incluem SHOW, DESCRIBE
e EXPLAIN. elas devem ser tratadas da mesma maneira que instruções SELECT.)
Existem dois modos para um cliente processae o resultado. Um mode é recuperar todo o
resultado de uma vez chamando mysql_store_result(). Esta função busca no servidor
todas as linhas retornadas pela consulta e as armazena no cliente. O segundo modo é o
cliente iniciar um retorno do resultado registro por registro chamando mysql_use_result().
Esta função inicia o retorno, mas não busca realmente nenhuma linha do servidor.
Em ambos os casos, acesse registros chamando mysql_fetch_row(). Com mysql_store_
result(), mysql_fetch_row() acessa registros que já tenham sido buscado do servidor.
Com mysql_use_result(), mysql_fetch_row() recupera, na verdade, o registro do servi-
dor. Informações sobre o tamanho dos dados em cada registro é disponível pela chamada
mysql_fetch_lengths().
Depois de finalizar o uso do resultado, chame mysql_free_result() para liberar a memória
usada por ele.
Os dois mecanismos de recuperação são complementares. Programas clientes devem escolher
a abordagem mais apropriada para suas necessidades. Na prática, clientes tendem a utilizar
mysql_store_result().
Uma vantagem de mysql_store_result() é que pelo fato de todos os registros serem
trazidos para o cliente, você não só pode acessar registros sequencialmente, mas também
556 Referência técnica para o MySQL versão 3.23.52
pode mover para tarz e para frente no resultado utilizando mysql_data_seek() ou mysql_
row_seek() para altera a posição atual do registro no resultado. Você também pode saber
quantas linhas existem chamando mysql_num_rows(). Por outro lado, a necessidade de
memória para mysql_store_result() pode ser muito alta para resultados grandes e você
encontrará como mais facilidade condições de estouro de memória.
Uma vantagem de mysql_use_result() é que o clientes exige menos memória para o re-
sultado porque ele mantem apenas um registro por vez (por haver menor sobrecarga de
alocação, mysql_use_result() pode ser mais rápido). As desvantagens são que você deve
processar cada registro rapidamente para evitar prender o servidor, você não tem acesso
aleatório aos registros no resultado (você só pode acessá-los sequencialmente) e você não
sabe quantos registros existem no resultado até que você recupere todos eles. Além disso,
você deve recuperar todos os registros mesmo que você já tenham encontrado a informação
que procura antes do finalizar o conjunto de resultados.
A API torna possível para os clientes responder apropriadamente as consultas (recuperando
somente os regiostros necessários) sem saber se a consulta é uma instrução SELECT ou não.
Você pode fazer isto chamando mysql_store_result() depois de cada mysql_query() (ou
mysql_real_query()). Se o resultado for obtido com sucesso, a consulta foi um SELECT e
você pode ler os registros. Se a obtenção do resultado falhar, chame mysql_field_count()
para determinar se o resultado era o esperado. Se mysql_field_count() retornar zero, a
consulta não retornou nenhum dado (indicando que ela era um INSERT, UPDATE, DELETE,
etc.), e não era esperado que retornasse registros. Se mysql_field_count() é diferente de
zero, a consulta deveria retornar registros, mas não o fez. Isto indica que a consulta foi um
SELECT que falhou. Veja a descrição de mysql_field_count() para um exemplo de como
deve ser feito.
mysql_store_result() e mysql_use_result() permitem que você obtenha informação
sobre os campos que montam o resultado (o número de campos, os seus nome e tipos, etc.)
Você pode acessar informações de campo sequencialmente dentro dos registros chamando
mysql_fetch_field() repetidamente, ou pelo número do campo dentro do registro
chamando mysql_fetch_field_direct(). A posição atual do cursor de campos pode ser
alterada cahamando mysql_field_seek(). Definir o cursor de campo afeta chamadas
subsequentes de mysql_fetch_field(). Você também pode conseguir informações de
todos os campos de uma só vez chamando mysql_fetch_fields().
Para detectar e relatar problemas, o MySQL fornace acesso a informações de erro através das
funções mysql_errno() e mysql_error(). Elas retornam o código de erro ou a mensagem
de erro para a função chamada mais recentemente que tenha tido sucesso ou que tenha
falhado, permitindo a você determinar quando um erro ocorreu e qual foi ele.
um erro. A menos que a descrição da função diga algo diferente, não faça teste com outro
valor além do zero.
if (result) /* correct */
... error ...
8.1.3.1 mysql_affected_rows()
my_ulonglong mysql_affected_rows(MYSQL *mysql)
Descrição
Retorna o número de registros alterados pelo último UPDATE, deletados elo último DELETE ou
inseridos pelo último INSERT. Pode ser chamado imediatamente após mysql_query() para
instruções UPDATE, DELETE, ou INSERT. Para instruções SELECT, mysql_affected_rows()
funciona como mysql_num_rows().
Valor Retornado
Um inteiro maior que zero indica o número de registros afetados ou recuperados. Zero indica
que nenhum registro foi atualizado por uma instrução UPDATE, nenhuma linha foi encontrada
pela cláusula WHERE na consulta ou a consulta ainda não foi executada. -1 indica que a
consulta retornou um erro ou que, para uma consulta SELECT, mysql_affected_rows() foi
chamado antes da chamada mysql_store_result().
Erros
Nenhum.
Exemplo
mysql_query(&mysql,"UPDATE products SET cost=cost*1.25 WHERE group=10");
printf("%ld products updated",(long) mysql_affected_rows(&mysql));
Se se for especificado o parâmetro CLIENT_FOUND_ROWS ao conectar no mysqld, mysql_
affected_rows() retornará o número de linhas encontardos pela cláusula WHERE para a
instrução UPDATE.
Note que quando for utilizado um comando REPLACE, mysql_affected_rows() retornará
2 se o novo registro substituir um mais antigo. Isto é porque neste caso um registro foi
inserido e depois os registros duplicados foram deletados.
558 Referência técnica para o MySQL versão 3.23.52
8.1.3.2 mysql_change_user()
my_bool mysql_change_user(MYSQL *mysql, const char *user, const char
*password, const char *db)
Descrição
Altera o usuário é faz com que o banco de dados especificado por db se torne o banco de
dados padrão (atual) na conexão especificada por mysql. Em consultas subsequentes este
banco de dados é o padrão para referências a tabelas que não especificam o banco de dados
explicitamente.
Esta função foi introduzida na versão do MySQL.
mysql_change_user() falha a menos que o usuário conectado possa ser autenticado ou se
ele não tiver permissão para utilizar o banco de dodos. Neste caso o usuário e o banco de
dados não são alterados.
O parâmetro db pode ser definido como NULL se você não dseseja ter um banco de dados
padrão.
A partir da versão 4.0.6 do MySQL este comando sempre fará ROLLBACK de qualquer
transação ativa, fecha todas as tabelas temporárias, destrava todas as tabelas bloqueadas e
volta a um estado como se tivesse feito uma inova conexão. Isto irá acontecer mesmo se o
usuário não foi alterado.
Valor Retornado
Zero se obteve successo. Diferente de zero se ocorreu um erro.
Erros
O mesmo que pode ser obtido com mysql_real_connect().
CR_COMMANDS_OUT_OF_SYNC
Comandos forma executados em ordem inapropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL finalizou.
CR_SERVER_LOST
A conexão ao servidor foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
ER_UNKNOWN_COM_ERROR
O servidor MySQL não possui este comando (provavelmente um versão mais
antiga)
ER_ACCESS_DENIED_ERROR
O usuário ou a senha estavam errados.
ER_BAD_DB_ERROR
O banco de dados não existe.
Chapter 8: MySQL APIs 559
ER_DBACCESS_DENIED_ERROR
O usuário não tem direitos de acessoa este banco de dados.
ER_WRONG_DB_NAME
O nome de banco de dados é muito grande.
Exemplo
if (mysql_change_user(&mysql, "user", "password", "new_database"))
{
fprintf(stderr, "Failed to change user. Error: %s\n",
mysql_error(&mysql));
}
8.1.3.3 mysql_character_set_name()
const char *mysql_character_set_name(MYSQL *mysql)
Descrição
Retorna o conjunto de caracteres padrão para a conexão atual.
Valor Retornado
O conjunto de carcteres padrão
Erros
Nenhum.
8.1.3.4 mysql_close()
void mysql_close(MYSQL *mysql)
Descrição
feca uma conexão aberta anteriormente. mysql_close() também desaloca o ponteiro do
manipulador da conexão para o mysql se ele tiver sido alocado automaticamente por mysql_
init() ou mysql_connect().
Valor Retornado
Nenhum.
Erros
Nenhum.
8.1.3.5 mysql_connect()
MYSQL *mysql_connect(MYSQL *mysql, const char *host, const char *user, const
char *passwd)
560 Referência técnica para o MySQL versão 3.23.52
Descrição
A função está obsoleta. É melhor utilizar mysql_real_connect().
mysql_connect() tenta estabelecer uma conexão a um banco de dados MySQL executando
em host. mysql_connect() deve completar com suceso antes que você podssa executar
qualquer uma das função da API, com a exceção de mysql_get_client_info().
O significado dos parâmetros são os mesmos que os parâmetros correspondentes para mysql_
real_connect() com a diferença que o parâmetro de conexão pode ser NULL. Neste caso a
API C aloca memória para a estrutura de conexão automaticamente e a libera quando você
chamar mysql_close(). A disvantagem desta abordagem é que você não pode retornar uma
mensagem de erro se a conexão falhar. (Para obter informações de erro de mysql_errno()
ou mysql_error(), você deve fornecer um ponteiro MYSQL válido.)
Valor Retornado
O mesmo de mysql_real_connect().
Erros
O mesmo de mysql_real_connect().
8.1.3.6 mysql_create_db()
int mysql_create_db(MYSQL *mysql, const char *db)
Descrição
Cria o banco de dados nomeado pelo parâmetro db.
Esta função está obsoleta. É melhor utilizar mysql_query() para comandar uma instrução
SQL CREATE DATABASE.
Valor Retornado
Zero se o banco de dados foi criado com successo. Diferente de zero se ocorreu um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
Chapter 8: MySQL APIs 561
Exemplo
if(mysql_create_db(&mysql, "my_database"))
{
fprintf(stderr, "Failed to create new database. Error: %s\n",
mysql_error(&mysql));
}
8.1.3.7 mysql_data_seek()
void mysql_data_seek(MYSQL_RES *result, my_ulonglong offset)
Descrição
Busca um registro arbitrário em um resultado de uma consulta. Ela exige que a estrutura
do resultado contenha todo o resultado da consulta, assim mysql_data_seek() só pode ser
usado em conjunto com mysql_store_result(), não com mysql_use_result().
O offset deve der um valor na faixa de 0 a mysql_num_rows(result)-1.
Valor Retornado
Nenhum.
Erros
Nenhum.
8.1.3.8 mysql_debug()
void mysql_debug(const char *debug)
Descrição
Faz um DBUG_PUSH com a string dada. mysql_debug() usa a biblioteca de depuração
Fred Fish. Para utilizar esta função você deve compilar a biblioteca cliente para suportar
depuração. See hundefinedi [Depurando o servidor], page hundefinedi. See hundefinedi
[Depurando o cliente], page hundefinedi.
Valor Retornado
Nenhum.
Erros
Nenhum.
Exemplo
A chamada mostrada aqui faz com que a biblioteca cliente gere um arquivo de rastreamento
‘/tmp/client.trace’ na máquina cliente:
mysql_debug("d:t:O,/tmp/client.trace");
562 Referência técnica para o MySQL versão 3.23.52
8.1.3.9 mysql_drop_db()
int mysql_drop_db(MYSQL *mysql, const char *db)
Descrição
Apaga o banco de dados nomeado pelo parâmetro db.
Esta função está obsoleta. É melhor utilizar mysql_query() para realizar uma instrução
SQL DROP DATABASE.
Valor Retornado
Zero se o banco de dados foi apagdo com sucesso. Diferente de zero ocorreu um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
Exemplo
if(mysql_drop_db(&mysql, "my_database"))
fprintf(stderr, "Failed to drop the database: Error: %s\n",
mysql_error(&mysql));
8.1.3.10 mysql_dump_debug_info()
int mysql_dump_debug_info(MYSQL *mysql)
Descrição
Instrui o servidor a gravar algumas informações de depuração no log. Para funcionar, o
usuário conectado deve ter pivilégio SUPER.
Valor Retornado
Zero se o comando obteve sucesso. Diferete de zero se ocorreu um erro.
Chapter 8: MySQL APIs 563
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.11 mysql_eof()
my_bool mysql_eof(MYSQL_RES *result)
Descrição
Esta função está obsoleta. mysql_errno() ou mysql_error() podem ser usados em seu
lugar.
mysql_eof() determina se o último registro de um resultado foi lido.
Se você buscar um resultado com um chamada mysql_store_result() bem sucedida, o
cliente recebe todo o resultado em uma operação. Neste caso, é um valor NULL retornado de
mysql_fetch_row() sempre significa que o fim do resultado foi atingido e não é necessário
chamar mysql_eof(). Quando usado com mysql_store_result(), mysql_eof() sempre
retornará verdadeiro.
Por outro lado, se você utilizar mysql_use_result() para iniciar um resultado recuperado,
as linhas do conjunto são obtido do servidor uma a uma, chamando mysql_fetch_row()
repetidamente. Como pode ocorrer um erro na conexão durante este processo, um valor NULL
retornado de mysql_fetch_row() não significa, necessáriaemente, que o fim do resultado
fo atingido normalmente. Neste caso, você pode utilizar mysql_eof() para determinar o
que aconteceu. mysql_eof() retorna um valor diferente de zero se o fim do resultaod foi
atingido e zero se ocorreu um erro.
Historicamente, mysql_eof() é preterido pelas funções de erro padrão do MySQL mysql_
errno() e mysql_error(). Como estas funções de erro fornecem a mesma informação,
o uso das duas últimas é preferido sobre mysql_eof(), a qual está obsoleta. (De fato,
elas fornecem mais informações, porque mysql_eof() retorna apenas um valor booleano
enquanto as funções de erro indicam uma razão para a ocorrência do erro quando ele ocorre).
Valor Retornado
Zero se nenhum erro ocorreu. Diferente de zero o fim do resultado foi atingido.
Erros
Nenhum.
564 Referência técnica para o MySQL versão 3.23.52
Exemplo
Os exemplos seguintes mostram como você deve usar mysql_eof():
mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
// faz algo com os dados
}
if(!mysql_eof(result)) // mysql_fetch_row() falha devido a um erro
{
fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}
No entanto, você pode conseguir o mesmo efeito com as funções de erro padrões do MySQL:
mysql_query(&mysql,"SELECT * FROM some_table");
result = mysql_use_result(&mysql);
while((row = mysql_fetch_row(result)))
{
// faz algo com os dados
}
if(mysql_errno(&mysql)) // mysql_fetch_row() falha devido a um erro
{
fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}
8.1.3.12 mysql_errno()
unsigned int mysql_errno(MYSQL *mysql)
Descrição
Para a conexão especificada pelo mysql, mysql_errno() retorna o código de erro para a
função API chamada mais recentemente que tenha obtido sucesso ou falhado. Um valor
de retorno de zero significa que um erro ocorreu. Númeroos de mensagens de erro de
clientes são listados no arquivo de cabeçalho ‘errmsg.h’ do MySQL. Números de mensagem
de erros do servidor são listados no arquivo ‘mysqld_error.h’. Na distribuição fonte do
MySQL você pode encontrar uma lista completa de núeros de mensagens de erro no arquivo
‘Docs/mysqld_error.txt’.
Valor Retornado
Um valor com código de erro. Zero se nenhum erro ocorrer.
Erros
Nenhum.
8.1.3.13 mysql_error()
char *mysql_error(MYSQL *mysql)
Chapter 8: MySQL APIs 565
Descrição
Para a conexão especificada por mysql, mysql_error() retorna a mensagem de erro para
a função de API chamda mais recentemented API que tenha falhado ou não. Uma string
vazia ("") é retornada se nenhum erro ocorrer. OIsto significa que os dois testes seguintes
são equivalentes:
if(mysql_errno(&mysql))
{
// ocorreu um erro
}
if(mysql_error(&mysql)[0] != ’\0’)
{
// ocorreu um erro
}
A língua da mensagem de erro do cliente pode ser alterada recompilando a biblioteca do
cliente MySQL. Atualmente você pode escolher mensagens de erro em várias línguas difer-
entes. See hundefinedi [Languages], page hundefinedi.
Valor Retornado
Uma string que descreve um erro. Uma string vazia se nenhum erro ocorrer.
Erros
Nenhum.
8.1.3.14 mysql_escape_string()
Você deve usar mysql_real_escape_string() em seu lugar!
Esta função é identica a mysql_real_escape_string() exceto que mysql_real_escape_
string() pega um manipulador de cnexão como seu primeiro argumento e escapa a string
de acordo com a conjunto de caracteres padrão. mysql_escape_string() não utiliza um
argumento de conexão e não respeita o conjunto de caracteres atual.
8.1.3.15 mysql_fetch_field()
MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)
Descrição
Retorna a definição de uma coluna de um resultado como uma estrutura MYSQL_FIELD.
Chame esta função repetidamente para retornar informações sobre todas as colunas no
resultado. mysql_fetch_field() retorna NULL quando não existirem mais campos.
mysql_fetch_field() é definido para retornar a informação do primeiro campo cada vez
que você executar uma nova consulta SELECT. O campo retornado por mysql_fetch_
field() também é afetado pela chamadas mysql_field_seek().
566 Referência técnica para o MySQL versão 3.23.52
Se vovê tiver chamado mysql_query() para realizar um SELECT em uma tabela mas não
tiver chamado mysql_store_result(), MySQL retorna o tamanho padrão do blob (8K
bytes) quando chamar mysql_fetch_field() para saber o tamanho de um campo BLOB.
(O tamanho de 8 k é escolhido porque o MySQL não sabe o tamanho máximo do BLOB. Ele
pode ser configurado algumas vezes.) Uma vez retornado o resultado, campo->tamanho_max
contém o tamanho da maior valor para esta coluna em uma consulta específica.
Valor Retornado
A estrutura MYSQL_FIELD para a coluna atual. NULL não houver mais colunas.
Erros
Nenhum.
Exemplo
MYSQL_FIELD *field;
while((field = mysql_fetch_field(result)))
{
printf("field name %s\n", field->name);
}
8.1.3.16 mysql_fetch_fields()
MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)
Descrição
Retorna um vetor de todas as estruturas MYSQL_FIELD no resultado. Cada estrutura fornece
a definição do campo para uma coluna do resultado.
Valor Retornado
Um vetor da estrutura MYSQL_FIELD para todas as colunas no resultado.
Erros
Nenhum.
Exemplo
unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *fields;
num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
for(i = 0; i < num_fields; i++)
Chapter 8: MySQL APIs 567
{
printf("Field %u is %s\n", i, fields[i].name);
}
8.1.3.17 mysql_fetch_field_direct()
MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *result, unsigned int
fieldnr)
Descrição
Dado um número de campo fieldnr para uma colua em resultado, retorna a informação
de campo daquela coluna como uma estrutura MYSQL_FIELD Você pode utilizar esta função
para retornar a definição para uma coluna arbitrária. O valor de fieldnr deve estar na
faixa de 0 a mysql_num_fields(result)-1.
Valor Retornado
A estrutura MYSQL_FIELD para uma coluna específica.
Erros
Nenhum.
Exemplo
unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *field;
num_fields = mysql_num_fields(result);
for(i = 0; i < num_fields; i++)
{
field = mysql_fetch_field_direct(result, i);
printf("Field %u is %s\n", i, field->name);
}
8.1.3.18 mysql_fetch_lengths()
unsigned long *mysql_fetch_lengths(MYSQL_RES *result)
Descrição
Retorna o tamanho da coluna do registro atual em um resultado. Se você planeja copiar
calores dos compos, esta informação de tamanho é útil também para a otimização,
porque você pode evitar a chamada strlen(). Se o resultado contém dados biários, você
deveutilizar esta função para determinar o tamanho dos dados, pois strlen() retorna um
valor incorreto para quaquer campo contendo caracteres nulos.
O tamanho para colunas vazias e para colunas contendo valores NULL é zero. Para ver como
distnguir este dois casos, veja a descrição de mysql_fetch_row().
568 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
Um vetor de unsigned long integers (inteiros longos sem sinal) representando o tamanho de
cada coluna (não incluindo nenhuma caracter nulo). NULL se ocorrer um erro.
Erros
mysql_fetch_lengths() só é válido para o registro atual no resultado. Ele retorna NULL
se você chamá-lo antes de mysql_fetch_row() ou depois de retornar todos os registros em
um resultado.
Exemplo
MYSQL_ROW row;
unsigned long *lengths;
unsigned int num_fields;
unsigned int i;
row = mysql_fetch_row(result);
if (row)
{
num_fields = mysql_num_fields(result);
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("Column %u is %lu bytes in length.\n", i, lengths[i]);
}
}
8.1.3.19 mysql_fetch_row()
MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)
Descrição
Recuera o próximo registro do resultado. Quando usado depois de mysql_store_result(),
mysql_fetch_row() retorna NULL quando não houver mais registros para retornar. Quando
usado depois de mysql_use_result(), mysql_fetch_row() retorna NULL quando não hou-
ver mais registros para retornar ou ocorrer um erro.
O número de valores no registro é dado por mysql_num_fields(result). Se row guarda
o valor retornado de uma chamada mysql_fetch_row(), apontadores para os valores são
acessados como row[0] a row[mysql_num_fields(result)-1]. Valores NULL no registro
são indicados por apontadores NULL.
Os tamanhos dos valores do campo no registro poden ser obtidos chamando mysql_fetch_
lengths(). Campos vazios e campos contendo NULL tem tamanho 0; você pode distingui-los
verificando o apontador para o valor do campo. Se o apontador é NULL, o campo é NULL;
senão o campo está vazio.
Chapter 8: MySQL APIs 569
Valor Retornado
Uma estrutura MYSQL_ROW para o próximo registro. NULL se não houver mais linhas para
retornar ou ocorrer um erro.
Erros
CR_SERVER_LOST
A conexão com o servidor foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
Exemplo
MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
unsigned long *lengths;
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
}
printf("\n");
}
8.1.3.20 mysql_field_count()
unsigned int mysql_field_count(MYSQL *mysql)
Se você estiver utilizando uma versão anterior a versão 3.22.24 do MySQL, você deve utilizar
unsigned int mysql_num_fields(MYSQL *mysql).
Descrição
Retorna o número de colunas para a consulta mais recente na conexão.
Normalmente esta função é utilizada quando mysql_store_result() retorna NULL (então
você não possui um apontador para o resultado). Neste caso, você pode chamar mysql_
field_count() para determinar se mysql_store_result() não produziu um resultado
vazio. Isto permite que o programa cliente tome a ação aprpriada sem saber se a consulta
foi uma instrução SELECT (ou do mesmo tipo). O exemplo mostrado aqui ilustra como isto
pode ser feito.
See hundefinedi [NULL mysql_store_result()], page hundefinedi.
570 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
Um unsigned integer (inteiro sem sinal) representando o número de campo em um resultado.
Erros
Nenhum.
Exemplo
MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;
if (mysql_query(&mysql,query_string))
{
// error
}
else // query succeeded, process any data returned by it
{
result = mysql_store_result(&mysql);
if (result) // there are rows
{
num_fields = mysql_num_fields(result);
// retrieve rows, then call mysql_free_result(result)
}
else // mysql_store_result() returned nothing; should it have?
{
if(mysql_field_count(&mysql) == 0)
{
// query does not return data
// (it was not a SELECT)
num_rows = mysql_affected_rows(&mysql);
}
else // mysql_store_result() should have returned data
{
fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}
}
}
Uma alternativa é substituir a chamada mysql_field_count(&mysql) com
mysql_errno(&mysql). Neste caso, você está verificando diretamente um erro de
mysql_store_result() em vez de conferir o valor de mysql_field_count() se a instrução
foi uma SELECT.
8.1.3.21 mysql_field_seek()
MYSQL_FIELD_OFFSET mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET
offset)
Chapter 8: MySQL APIs 571
Descrição
Define o cursor campo com o offset dado. A próxima chamada para mysql_fetch_field()
irá recuperar a definição de campo da coluna associada com o offset.
Para buscar o inicio de um registro, passe zero como valor do offset.
Valor Retornado
O valor anterior do cursor de campo.
Erros
Nenhum.
8.1.3.22 mysql_field_tell()
MYSQL_FIELD_OFFSET mysql_field_tell(MYSQL_RES *result)
Descrição
Retorna a posição do cursos do campo usado pelo último mysql_fetch_field(). Este valor
pode ser usado como um argumento para mysql_field_seek().
Valor Retornado
O offset atual do cursor de campo.
Erros
Nenhum.
8.1.3.23 mysql_free_result()
void mysql_free_result(MYSQL_RES *result)
Descrição
Libera a memória alocada para o resultado por mysql_store_result(), mysql_use_
result(), mysql_list_dbs(), etc. Quando você finalizar o uso do resultado, você deve
liberar a memória utilizada chamando mysql_free_result().
Valor Retornado
Nenhum.
Erros
Nenhum.
572 Referência técnica para o MySQL versão 3.23.52
8.1.3.24 mysql_get_client_info()
char *mysql_get_client_info(void)
Descrição
Retorna uam string que representa a versão da biblioteca cliente.
Valor Retornado
Uma string representando a versão da biblioteca cliente do MySQL.
Erros
Nenhum.
8.1.3.25 mysql_get_server_version()
unsigned long mysql_get_server_version(MYSQL *mysql)
Descrição
Retorna o número de versão do servidor como um inteiro (novo na versão 4.1)
Valor Retornado
Um número que representa a versão do servidor MySQL no formato:
versão principal*10000 + versão menor*100 + sub versão
Por exemplo, 4.1.0 é retornado como 40100.
Ela é útil para determinar a versão do servidor rapidamente em um programa cliente para
saber se algumas capacidades existem.
Erros
Nenhum.
8.1.3.26 mysql_get_host_info()
char *mysql_get_host_info(MYSQL *mysql)
Descrição
Retorna uma string descrevendo o tipo da conexão em uso, incluindo o nome da maquina
servidora.
Valor Retornado
Uma string respresntando o nome da máquina servidora e o tipo de conexão.
Chapter 8: MySQL APIs 573
Erros
Nenhum.
8.1.3.27 mysql_get_proto_info()
unsigned int mysql_get_proto_info(MYSQL *mysql)
Descrição
Retorna a versão do protocolo usado pela conexão atual.
Valor Retornado
Um unsigned integer (inteiro sem sinal) representando a versão do protocolo usado pela
conexão atual.
Erros
Nenhum.
8.1.3.28 mysql_get_server_info()
char *mysql_get_server_info(MYSQL *mysql)
Descrição
Retorna um string que representa o número da versão do servidor.
Valor Retornado
Um string representando o número da versão do servidor.
Erros
Nenhum.
8.1.3.29 mysql_info()
char *mysql_info(MYSQL *mysql)
Descrição
Retorna um string fornecendo informação sobre a consulta executada mais recentemente,
mas apenas para as instruções listadas aqui. Para outras inastruções, mysql_info() retorna
NULL. O formato da string varia dependendo do tipo de consulta, como descrito aqui. Os
números são apenas ilustrativos; a string irá conter valores apropriados para a consulta.
INSERT INTO ... SELECT ...
Formato da string: Records: 100 Duplicates: 0 Warnings: 0
574 Referência técnica para o MySQL versão 3.23.52
Note que mysql_info() retorna um valor não-NULL para a instrução INSERT ... VALUES
somente se um lista de míltiplos valores é especificada na instrução.
Valor Retornado
Uma string represntando informação adicional sobre a consulta executada mais recente-
mente. NULL se não houver nenhuma informação disponível para a consulta.
Erros
Nenhum.
8.1.3.30 mysql_init()
MYSQL *mysql_init(MYSQL *mysql)
Descrição
Aloca ou inicializa um objeto MYSQL apropriado para mysql_real_connect(). Se mysql é
um ponteiro NULL, a função aloca, inicializa e retorna um novo objeto. Senão o objeto é
inicializado e o endereço do objeto é retornado. Se mysql_init() aloca um novo objeto,
ele será liberado quando mysql_close() for chamado para fechar a conexão.
Valor Retornado
Um handle MYSQL* inicializado. NULL se não houver memória suficiente para alocar o novo
objeto.
Erros
Em caso de memória insuficiente, NULL é retornado.
8.1.3.31 mysql_insert_id()
my_ulonglong mysql_insert_id(MYSQL *mysql)
Chapter 8: MySQL APIs 575
Descrição
Retorna o ID gerado para uma coluna AUTO_INCREMENT pela consulta anterior. Use esta
função depois de ter realizado um consulta INSERT em uma tabela que contenha um campo
AUTO_INCREMENT.
Note que mysql_insert_id() retorna 0 se a consulta anterior não gerar um valor AUTO_
INCREMENT. Se você desejar salvar o valor para uso posterior, chame mysql_insert_id()
imediatamente depois da consulta que gerou o valor.
mysql_insert_id() é atualizado depois de instruções INSERT e UPDATE que geram um
valor AUTO_INCREMENT ou que definem um valor de coluna com LAST_INSERT_ID(expr).
See hundefinedi [Funções diversas], page hundefinedi.
Note também que o valor da função SQL LAST_INSERT_ID() sempre contém o o valor AUTO_
INCREMENT gerado mais recentemente e não é zerado entre as consultas porque o valor desta
função é mantido no servidor.
Valor Retornado
O valor do campo AUTO_INCREMENT que foi atualizado pela consulta anterior. Retorna
zero se não houve consultas anteriores na conexão ou se a consulta não atualizou o valor
AUTO_INCREMENT.
Erros
Nenhum.
8.1.3.32 mysql_kill()
int mysql_kill(MYSQL *mysql, unsigned long pid)
Descrição
Diz para o servidor matar um thread especificada pelo pid.
Valor Retornado
Zero em caso de sucesso. Diferente de zero se ocorrer um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
576 Referência técnica para o MySQL versão 3.23.52
8.1.3.33 mysql_list_dbs()
MYSQL_RES *mysql_list_dbs(MYSQL *mysql, const char *wild)
Descrição
Retorna um resultado com nome de banco de dados no servidor que correspondem a uma
expressão regular especificada pelo parâmetro wild. wild pode conter o meta caracteres ‘%’
ou ‘_’, ou pode ser um ponteiro NULL para coreesponder a todos os banco de dados. Chamar
mysql_list_dbs() é o mesmo que executar a consulta SHOW databases [LIKE wild].
Você deve liberar o resultado com mysql_free_result().
Valor Retornado
Um conjunto de resultados MYSQL_RES no caso de sucesso. NULL se ocorrer um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.34 mysql_list_fields()
MYSQL_RES *mysql_list_fields(MYSQL *mysql, const char *table, const char
*wild)
Descrição
Retorna um resultado contendo nomes de campos de uma tabela dada que correspondam a
expressão regular especificada pelo parâmetro wild. wild pode conter os metacaracteres ‘%’
ou ‘_’, ou pode ser um ponteiro NULL para corresponder a todos os campos. Chamar mysql_
list_fields() é o mesmo que executar a consulta SHOW COLUMNS FROM nome_tabela [LIKE
wild].
Note que é recomendado que você use SHOW COLUMNS FROM nome_tabela em vez de mysql_
list_fields().
Você deve liberar o resultado com mysql_free_result().
Valor Retornado
Um conjunto de resultados MYSQL_RES em caso de sucesso. NULL se ocorrer um erro.
Chapter 8: MySQL APIs 577
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.35 mysql_list_processes()
MYSQL_RES *mysql_list_processes(MYSQL *mysql)
Descrição
Retorna um resultado descrevendo a thread atual do servidor. É o mesmo tipo de informação
relatado por mysqladmin processlist ou uma consulta SHOW PROCESSLIST.
Você deve liberar o resultado com mysql_free_result().
Valor Retornado
Um conjunto de resultados MYSQL_RES em caso de sucesso. NULL se ocorrer um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.36 mysql_list_tables()
MYSQL_RES *mysql_list_tables(MYSQL *mysql, const char *wild)
Descrição
Retorna um resultado contendo nomes de tabelas no banco de dados atual que correspondam
a expressão regular especificada pelo parâmetro wild. wild pode conter os mets caracteres
‘%’ or ‘_’, ou pode ser uma ponteiro NULL para corresponde a todas as tabelas. Chamar
mysql_list_tables() é o mesmo que executar a consulta SHOW tables [LIKE wild].
Você deve liberar o resultado com mysql_free_result().
578 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
Um conjunto de resultados MYSQL_RES em caso de sucesso. NULL se ocorrer um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.37 mysql_num_fields()
unsigned int mysql_num_fields(MYSQL_RES *result)
ou
unsigned int mysql_num_fields(MYSQL *mysql)
A segunda forma não funciona na versão 3.22.24 ou mais novas do MySQL. Para passar um
argumento MYSQL* você de utilizar unsigned int mysql_field_count(MYSQL *mysql) em
seu lugar.
Descrição
Retorna o número de colunas em um resultado.
Note que você pode obter o número de colunas com um ponteiro para o conjunto de resul-
tados ou para um manipulador (handle) de conexão. Você usaria o manipular de conexão
se mysql_store_result() ou mysql_use_result() retorna NULL (então você não tem um
ponteiro para o resultado). Neste caso, você pode chamar mysql_field_count() para de-
terminar se mysql_store_result() não produziu um resultado vazio. Isto permite que o
programa cliente tome a ação apropriada sem saber se a consulta foi uma instrução SELECT
(ou do tipo SELECT). O exemplo mostrado abaixo ilustra como isto pode ser feito.
See hundefinedi [NULL mysql_store_result()], page hundefinedi.
Valor Retornado
Um unsigned integer (inteiro sem sinal) representando o número de campos no conjunto de
resultasdos.
Erros
Nenhum.
Chapter 8: MySQL APIs 579
Exemplo
MYSQL_RES *result;
unsigned int num_fields;
unsigned int num_rows;
if (mysql_query(&mysql,query_string))
{
// erro
}
else // query succeeded, process any data returned by it
{
result = mysql_store_result(&mysql);
if (result) // existem resgitros
{
num_fields = mysql_num_fields(result);
// retorna registros e chama mysql_free_result(result)
}
else // mysql_store_result() retorna vazio; era esperado?
{
if (mysql_errno(&mysql))
{
fprintf(stderr, "Error: %s\n", mysql_error(&mysql));
}
else if (mysql_field_count(&mysql) == 0)
{
// consulta n~
ao retora dados
// (ela n~
ao era um SELECT)
num_rows = mysql_affected_rows(&mysql);
}
}
}
Uma alternativa (se você souber qyue a sua consulta retornou um resultado) é substituir
a chamada mysql_errno(&mysql) pela verificação de se mysql_field_count(&mysql) é =
0. Isto só acontece se alguma coisa der errado.
8.1.3.38 mysql_num_rows()
my_ulonglong mysql_num_rows(MYSQL_RES *result)
Descrição
Retorna o número de linhas em um resultado.
O uso de mysql_num_rows() depende de se você utiliza mysql_store_result() ou mysql_
use_result() para retornar o resultado. Se você usa mysql_store_result(), mysql_num_
rows() pode ser chamado imediatamente. Se você usa mysql_use_result(), mysql_num_
rows() não retornará o valor correto até que todas as linhas no resultado tenham sido
recuperadas.
580 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
O numero de linhas no resultado.
Erros
Nenhum.
8.1.3.39 mysql_options()
int mysql_options(MYSQL *mysql, enum mysql_option option, const char *arg)
Descrição
Pode ser usado para definir opções extras de conexão e afetar o comportamento de uma
conexão. Esta função pode ser chamada várias vezes para definir diversas opções.
mysql_options() deve ser chamado depois de mysql_init() e antes de mysql_connect()
ou mysql_real_connect().
O argumento option é a opção que você que definir; o argumento arg é o valor para a
opção. Se a opção é um inteiro, então arg deve apontar para o valor do inteiro.
Valores possíveis para as opções:
Opção Tipo de Função
argumento
MYSQL_OPT_CONNECT_TIMEOUT unsigned int Tempo limite de conexão em
* segundos.
MYSQL_OPT_COMPRESS Não usado Usa o protocolo cliente/servidor
compactado.
MYSQL_OPT_LOCAL_INFILE ponteiro para Se nenhum ponteiro for dado ou
unsigned se apontar para um unsigned
integer int != 0 o comando LOAD LOCAL
opcional INFILE está habilitado.
MYSQL_OPT_NAMED_PIPE Não usado Usa named pipes para conectar
ao servidor MySQL no NT.
MYSQL_INIT_COMMAND char * Comando para executar ao
conectar ao servidor MySQL.
Será automaticamente execu-
tado ao se reconectar.
MYSQL_READ_DEFAULT_FILE char * Lê opções do arquivo de opções
definido no lugar de ‘my.cnf’.
MYSQL_READ_DEFAULT_GROUP char * Lê opções do grupo indicado no
arquivo ‘my.cnf’ ou no arquivo
especificado com MYSQL_READ_
DEFAULT_FILE.
Note que o grupo client é sempre lido se você utiliza MYSQL_READ_DEFAULT_FILE ou MYSQL_
READ_DEFAULT_GROUP.
O grupo especificado no arquivo de opçõs pode conter as seguintes opções:
Opção Descrição
Chapter 8: MySQL APIs 581
Valor Retornado
Zero em caso de sucesso. Diferente de zero se você utilizar uma opção desconhecida.
Exemplo
MYSQL mysql;
mysql_init(&mysql);
mysql_options(&mysql,MYSQL_OPT_COMPRESS,0);
582 Referência técnica para o MySQL versão 3.23.52
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"odbc");
if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&mysql));
}
O exemplo acima diz ao cliente para usar o protocolo cliente/servidor compactado e ler a
opção adicional da seção odbc no arquivo de opções ‘my.cnf’.
8.1.3.40 mysql_ping()
int mysql_ping(MYSQL *mysql)
Descrição
Verifica se a conexão ao servidor está funcionando. Se ela tiver caído é feita uma tentativa
de conexão automaticamente.
Esta função pode ser usada pelos clientes que se ficam inativo por um longo tempo para
verificar se o servidor fechou a conexão e reconectar se necessário.
Valor Retornado
Zero se o servidor estiver funcionando. Diferente de zero se ocorrer um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.41 mysql_query()
int mysql_query(MYSQL *mysql, const char *query)
Descrição
Executa uma consulta SQL apontada pela string terminada em null query. A consulta deve
deve consistir de uma única instrução SQL. Você não deve adicionar ponto e vírgula (‘;’)
ou \g ao fim da instrução.
mysql_query() não pode ser usadas por consultas que contenham dados binários; você deve
utilizar mysql_real_query() em seu lugar. (Dados binários podem conter o caracter ‘\0’,
que mysql_query() interpreta como o fim a string de consulta.)
Se você quiser saber se a consulta deve retornar um resultado ou não, você pode uti-
lizar mysql_field_count() para verificar isto. See hundefinedi [mysql_field_count()],
page hundefinedi.
Chapter 8: MySQL APIs 583
Valor Retornado
Zero se a consulta obteve sucesso. Diferente de zero se ocorreu um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.42 mysql_real_connect()
MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user,
const char *passwd, const char *db, unsigned int port, const char *unix_socket,
unsigned int client_flag)
Descrição
mysql_real_connect() tenta estabelecer uma conexão mecanismo MySQL de banco de
dados executando em host. mysql_real_connect() deve completar com suceeso antes que
você possa executar qualquer um das outars funçãoes da API, com a excessão de mysql_
get_client_info().
Os parâmetros são especificados da seguinte forma:
• O primeiro parâmetro deve ser o endereço de uma estrutura MYSQL existente. Antes
de chamar mysql_real_connect() você deve chamar mysql_init() para inicializar a
estrutura MYSQL. Você pode alterar vária opções de conexão com a chamada mysql_
options(). See hundefinedi [mysql options], page hundefinedi.
• O valor de host pode ser tanto um nome de máquivo quanto um endereço IP. Se host
é NULL ou a string "localhost", a conexão é feita na máquina local. Se o SO suporta
sockets (Unix) ou named pipes (Windows), eles são utilizados em vez de TCP/IP para
a conexão ao servidor.
• O parâmetro user contém a indetificação do usuário MySQL. Se user é NULL, considera-
se o usuário padrão. Sob Unix, ele é o login atual. Sob ODBC no Windows, o usuário
atual deve ser especificado explicitamente. See hundefinedi [Administrador ODBC],
page hundefinedi.
• O parâmetro passwd contém a senha para user. Se passwd é NULL, somente entradas
na tabela user para usuários que tenham campo de senha em branco (vazia) serão
verificados ipor um padrão coincidenete. Isto permite que o admistrador do banco
de dados configure o sistema de privilégios do MySQL de tal maneira que usuários
os usuários conseguirão privileios diferentes, dependendo se ele espcificou ou não uma
senha.
584 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
Um handle de conexão MYSQL* se a conexão foi obtida com sucesso, NULL se a conexão
falhou. Para um conexão estabelecida o valor de retorn é o mesmo que o valor do primeiro
parâmetro.
Erros
CR_CONN_HOST_ERROR
Falhou ao conectar ao servidor MySQL.
CR_CONNECTION_ERROR
Falhou ao conectar ao servidor MySQL local.
CR_IPSOCK_ERROR
Falhou au criar um socket IP.
CR_OUT_OF_MEMORY
Sem memória.
CR_SOCKET_CREATE_ERROR
Falhou ao criar um socket Unix.
Chapter 8: MySQL APIs 585
CR_UNKNOWN_HOST
Falhou ao procurar o endereço IP para o nome de maquina.
CR_VERSION_ERROR
Um erro de protocolo resultou da tentativa de conexao a um servidor com
uma biblioteca cliente que utiliza uma versão de protocolo diferente. Isto pode
acontecer se você utiliza uma biblioteca cliente muito antiga para se conectar a
um novo servidor qua não foi iniciado com a opção --old-protocol.
CR_NAMEDPIPEOPEN_ERROR
Falhou ao criar um named pipe no Windows.
CR_NAMEDPIPEWAIT_ERROR
Falhou ao esperar por um named pipe no Windows.
CR_NAMEDPIPESETSTATE_ERROR
Falhou ao conseguir mainpulador do pipe no Windows.
CR_SERVER_LOST
Se connect_timeout > 0 e leva mais que connect_timeout segundos para
conectar ao servidor ou se o servidro foi finalizado ao executar o init-command.
Exemplo
MYSQL mysql;
mysql_init(&mysql);
mysql_options(&mysql,MYSQL_READ_DEFAULT_GROUP,"seu_programa");
if (!mysql_real_connect(&mysql,"host","user","passwd","database",0,NULL,0))
{
fprintf(stderr, "Failed to connect to database: Error: %s\n",
mysql_error(&mysql));
}
Usando mysql_options() a biblioteca MySQL irá ler as seções [client] e [seu_programa]
no arquivo ‘my.cnf’ o qual irá assegurar que seu programa irá funcionar, mesmo se alguem
tiver configurado o MySQL de um modo fora do padrão.
Note que sob a conexão, mysql_real_connect() define o parâmetro reconnect (parte da
estrutura MYSQL) para um valor de 1. Este parâmetro indica, no evento em que uma consulta
não pode ser realizada devido a perda de conexão, para tentar se reconectar ao servidor
antes de esgotar as tentativas.
8.1.3.43 mysql_real_escape_string()
unsigned long mysql_real_escape_string(MYSQL *mysql, char *to, const char
*from, unsigned long length)
Descrição
A função é usada para criar um string SQL válida que você pode usar em uma instrução
SQL. See hundefinedi [Sintaxe de string], page hundefinedi.
586 Referência técnica para o MySQL versão 3.23.52
A string em from é codificada para uma string SQL com escape, levando em conta o conjunto
de caracteres atual da conexãon. O resultado é colocada em to e uma byte nulo de terminção
é adcionado. Caracteres codificados são NUL (ASCII 0), ‘\n’, ‘\r’, ‘\’, ‘’’, ‘"’, e Control-
Z (See hundefinedi [Literais], page hundefinedi). (O MySQL precisa que apenas a barra
invertida e as aspas utilizadas para citar a consulta sejam escapadas. Esta função coloca os
outros caracteres entre aspas para torná-lo mais fácil de ser lido em arquivos log.)
A string apontada por from deve ter o tamanho de length bytes. Você deve alocar o buffer
to para o tamanho de pelo menos length*2+1 bytes. (No pior caso, cada caracter pode
precisar de ser codificado como se utilizasse dois bytes, e você preciria de espaço para o
byte null de terminação.) Quando mysql_real_escape_string() retornar, o conteúdo de
to será uma string terminada em null. O valor é o tamanho da string codificada. não
incluindo o caracter nulo usado para terminar a string.
Exemplo
char query[1000],*end;
Valor Retornado
O tamanho do valor colocado em to, não incluindo o caracter null de terminação.
Erros
Nenhum.
8.1.3.44 mysql_real_query()
int mysql_real_query(MYSQL *mysql, const char *query, unsigned long length)
Chapter 8: MySQL APIs 587
Descrição
Executa a consulta SQL apontada por query, que deve ser uma string de length bytes. A
consulta deve consistir de uma instrução SQL simples. Você não deve adicionar um ponto
e virgula (‘;’) ou \g no fim da instrução.
Você deve utilizar mysql_real_query() em lugar de mysql_query() para consultas que
contenham dados binários, pois eles podem conter o caracter ‘\0’. Além disso, mysql_real_
query() é mais rápido que mysql_query() pois ele não faz chamadas strlen() na string
de consulta.
Se você quiser saber se a consulta retornou um resultado ou não, você pode usar mysql_
field_count(). See hundefinedi [mysql field count], page hundefinedi.
Valor Retornado
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.45 mysql_reload()
Descrição
Diz ao servidor MySQL para recarregar a tabela de ables. The connected user must have
the RELOAD privilege.
This function is deprecated. It is preferable to use mysql_query() to issue a SQL FLUSH
PRIVILEGES statement instead.
Valor Retornado
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.46 mysql_row_seek()
MYSQL_ROW_OFFSET mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET offset)
Descrição
Atribui ao cursor de linha um registro arbitrário em resultado de uma consulta. Isto exige
que a estrutura do resultado contenha todo o resultado da consulta, assim mysql_row_
seek() pode ser um usado em conjunto apenas com mysql_store_result(), e não com
mysql_use_result().
O offset deve ser um valor retornado de uma chamada a mysql_row_tell() ou a mysql_
row_seek(). Este valor não simplesmente um número de linha; se você quiser buscasr um
registro em um resultado usando o número de linha utilize mysql_data_seek().
Valor Retornado
O valor anterior do cursor de linha. Este valor pode ser passado a uma chamada subsequente
mysql_row_seek().
Erros
Nenhum.
8.1.3.47 mysql_row_tell()
MYSQL_ROW_OFFSET mysql_row_tell(MYSQL_RES *result)
Descrição
Retorna a posição atual do cursor de linha para a última mysql_fetch_row(). Este valor
pode ser utilizado como argumento para mysql_row_seek().
Você deve utilizar mysql_row_tell() somente depois de mysql_store_result(), e não
depois de mysql_use_result().
Valor Retornado
O offset atual do cursos de linha.
Chapter 8: MySQL APIs 589
Erros
Nenhum.
8.1.3.48 mysql_select_db()
int mysql_select_db(MYSQL *mysql, const char *db)
Descrição
Faz com que o banco de dados espexcificado por db se torne o padrão (atual) na conexão
especificada por mysql. Nas consultas seguintes este banco de dados é o padrão para tabelas
que não incluem uma especificação explicita para o banco de dados.
mysql_select_db() falha a menos que o usuário conectado possa ser autenticado com
permissão para utilizar o banco de dados.
Valor Retornado
Zero em caso de sucesso. Deiferente de zero se ocorrer um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.49 mysql_shutdown()
int mysql_shutdown(MYSQL *mysql)
Descrição
Diz ao servidor de banco de dados para finalizar. O usuário conectado deve ter privilégio
SHUTDOWN.
Valor Retornado
Zero em caso de sucesso. Deiferente de zero se ocorrer um erro.
590 Referência técnica para o MySQL versão 3.23.52
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.50 mysql_stat()
char *mysql_stat(MYSQL *mysql)
Descrição
Retorna uma string contendo informações sinmilares a aquelas fornecidas pelo comando
mysqladmin status. Isto inclui o tempo de conexão em segundos e o número de threads
em execução, recargas e tabelas abertas.
Valor Retornado
Uma string descrevendo o status do servidor. NULL se um erro ocorrer.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.51 mysql_store_result()
MYSQL_RES *mysql_store_result(MYSQL *mysql)
Descrição
Você deve chamar mysql_store_result() ou mysql_use_result() para cada consulta que
retorne dados com sucesso (SELECT, SHOW, DESCRIBE, EXPLAIN).
Você não precisa chamar mysql_store_result() ou mysql_use_result() para outras con-
sultas, mas ele não causará nenhum dano ou nenhuma queda notel de desempenho se você
Chapter 8: MySQL APIs 591
Valor Retornado
Uma estrutura de resultado MYSQL_RES com o resultado. NULL se um erro ocorreu.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_OUT_OF_MEMORY
Sem memoria.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.52 mysql_thread_id()
unsigned long mysql_thread_id(MYSQL *mysql)
592 Referência técnica para o MySQL versão 3.23.52
Descrição
Retorna a ID da thread da conexão atual. Este valor pode ser usado como um argumento
para mysql_kill() para finalizar a thread.
Se a conexão for perdida e você reconectar com mysql_ping(), a ID da thread irá alterar.
Isto significa que você deve obter a ID da thread e guardá-la para uso posterior. Você deve
obtê-la quando precisar dela.
Valor Retornado
A ID da thread da conexão atual.
Erros
Nenhum.
8.1.3.53 mysql_use_result()
MYSQL_RES *mysql_use_result(MYSQL *mysql)
Descrição
Você deve chamar mysql_store_result() ou mysql_use_result() para cada consulta que
retornar data com sucesso (SELECT, SHOW, DESCRIBE, EXPLAIN).
mysql_use_result() inicicia a recuperação de um resultado mas não lê realmente o re-
sultado no cliente como mysql_store_result() faz. Cada regiostro deve ser recuperado
individualmente fazendo chamadas a mysql_fetch_row(). Ele lê o resultado de uma con-
sulta diretamente do servidor sem armazenar em uma tabela temporária ou em um buffer
local, o o que é mais rápido e utiliza menos memória que mysql_store_result(). O cliente
sío irá alocar memória para o registro atual para o buffer de comunicação que pode crescer
para max_allowed_packet bytes.
Por outro lado , você não deve utilizar mysql_use_result() se você estiver fazendo vários
processamentos para cada registros no lado do cliente, ou se a saída é enviada para a tela,
na qual o usuário de digitar um ^S (parada de tela). Isto irá prender o servidor e impedir
outras threads de atualizar qualquer tabela na qual o dados esteja sendo buascado.
Ao usar mysql_use_result(), você deve executar mysql_fetch_row() até um valor NULL
ser retornado, senão, os registros não buscados retornarão como part do resultado de sua
próxima consulta. A API C fornecerá o erro Commands out of sync; you can’t run this
command now se você esquecer de fazê-lo.
Você não pode utilizar mysql_data_seek(), mysql_row_seek(), mysql_row_tell(),
mysql_num_rows(), ou mysql_affected_rows() com m resultado retornado de
mysql_use_result(), nem pode executar outras consultas até que mysql_use_result()
tenha finalizado. (No entanto, depois de buscar todos os regitros, mysql_num_rows()
retornará corretamente o número de regiostros buscados).
Você deve chamar mysql_free_result() após terminar de utilizar o resultado.
Chapter 8: MySQL APIs 593
Valor Retornado
Uma estrutura de resultado MYSQL_RES. NULL se ocorrer um erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_OUT_OF_MEMORY
Sem memória.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.3.54 mysql_commit()
my_bool mysql_commit(MYSQL *mysql)
Descrição
Faz um commits na transação atual. Disponível no MySQL 4.1
Valor Retornado
Zero em caso de sucesso. Deiferente de zero se ocorrer um erro.
Erros
Nenhum.
8.1.3.55 mysql_rollback()
my_bool mysql_rollback(MYSQL *mysql)
Descrição
Faz um rollback na transação atual. Disponível no MySQL 4.1
Valor Retornado
Zero em caso de sucesso. Deiferente de zero se ocorrer um erro.
Erros
Nenhum.
594 Referência técnica para o MySQL versão 3.23.52
8.1.3.56 mysql_autocommit()
my_bool mysql_autocommit(MYSQL *mysql, my_bool mode)
Descrição
Define o modo autocommit como ligado/desligado. Se o mode for 1, defien o modo auto-
commit como ligado; Se for 0, como desligado. Disponível no MySQL 4.1
Valor Retornado
Zero em caso de sucesso. Deiferente de zero se ocorrer um erro.
Erros
Nenhum.
8.1.3.57 mysql_more_results()
my_bool mysql_more_results(MYSQL *mysql)
Descrição
Retorna verdade se mais resultados da consulta atualmente em execução existem, e a
aplicação deve chamar mysql_next_result() para buscar os resultados. Disponível no
MySQL 4.1
Valor Retornado
TRUE se existem mais resultados. FALSE se não existem mais resultados.
Erros
Nenhum.
8.1.3.58 mysql_next_result()
int mysql_next_result(MYSQL *mysql)
Descrição
Se existem mais resultados da consulta, mysql_next_result() lê o próximo resultado da
consulta e retorna o status a aplicação. Disponível no MySQL 4.1
Valor Retornado
Zero em caso de sucesso. Deiferente de zero se ocorrer um erro.
Erros
Nenhum.
Chapter 8: MySQL APIs 595
MYSQL_STMT
Esta estrutura representa um manipuladaor de instrução para instruçãoes
preparadas. Ele é usada por todas as funções relacionadas a instruções.
A instrução é inicializada quando a consulta é preparada utilizando mysql_
prepare().
Uma conexão pode ter ’n’ maniouladores de instruções, e o limite depende dos
recursos do sistema.
MYSQL_BIND
Esta estrutura é utilizada para ligar buffer de parâmetros (mysql_bind_
param()) utlizando os dados dos parâmetros para chamar mysql_execute();
assim como ligar buffer de registros (mysql_bind_result()) para buscar o
resultado com os dados utilizando mysql_fetch().
A estrutura MYSQL_BIND contém os membros listados aqui:
enum enum_field_types buffer_type [input]
O tipo do buffer. O valor type deve ser um dos seguintes:
• MYSQL_TYPE_TINY
• MYSQL_TYPE_SHORT
• MYSQL_TYPE_LONG
• MYSQL_TYPE_LONGLONG
• MYSQL_TYPE_FLOAT
• MYSQL_TYPE_DOUBLE
• MYSQL_TYPE_TIME
• MYSQL_TYPE_DATE
596 Referência técnica para o MySQL versão 3.23.52
• MYSQL_TYPE_DATETIME
• MYSQL_TYPE_TIMESTAMP
• MYSQL_TYPE_STRING
• MYSQL_TYPE_VAR_STRING
• MYSQL_TYPE_TINY_BLOB
• MYSQL_TYPE_MEDIUM_BLOB
• MYSQL_TYPE_LONG_BLOB
• MYSQL_TYPE_BLOB
void *buffer [input/output]
Um ponteiro para um buffer de dados de parâmetros no caso dele
ser utilizado para fornecer dados de parâmetros ou ponteiro para
um buffer no qual se deve retornar os dados quando a estrutura
para ligação do resultado.
unsigned long buffer_length [input]
Tamanho do *buffer em bytes. Para caracteres e dados C binários,
buffer length especifica o tamanho do *buffer a ser utilizado como
um dado de parâmetro no caso dele ser usado com mysql_bind_
param() ou para retornar vários bytes ao buscar o resultado quando
ele é usado com mysql_bind_result().
long *length [input/output]
Ponteiro para o buffer para o tamanho do parâmetro. Quando
a estrutura é usada como uma entrada para a ligação dos da-
dos dos parâmetros, este argumento aponta para um buffer que,
quando mysql_execute() é chamado, contem o tamanho do valor
do parâmetro aramzenado em *buffer. Isto é ignorado exceto para
caracteres ou dados C binários.
Se o tamanho é um ponteiro nulo, o protocolo assume que todos os
caracteres e dados binários são terminaodos com null.
When this structure is used in output binding, then mysql_fetch()
return the the length of the data that is returned.
bool *is_null [input/output]
Indica se o dado do parâmetro é NULL ou o dado buscado é NULL.
MYSQL_TIME
Esta estrutura é utilizada para enviar e receber dados DATE, TIME e TIMES-
TAMP diretamente de/para o servidor.
A estrutura MYSQL_TIME contém os membros listados abaixo:
Membro Tipo Descrição
year unsigned int Ano.
month unsigned int Mês.
day unsigned int Dia do mês.
hour unsigned int Hora do dia(TIME).
minute unsigned int Minutos.
Chapter 8: MySQL APIs 597
mysql send long data() Envia dados longos em blocos para o servidor.
Chama mysql_prepare() para preparar e iniciar o manipulador de instruções, chama
mysql_bind_param() para fornecer os dados do parâmetro e chama mysql_execute() para
executar a consulta. Você pode repetir o mysql_execute() alterando o valor do parâmetro
do buffer respectivo fornecido por mysql_bind_param().
No caso do consulta ser uma instrução SELECT ou qualquer outra consulta que retorne um
resultado, mysql prepare() também retornará a informação dos meta dados do resultado na
forma de um resultado MYSQL_RES através de mysql_prepare_result().
Você pode forncer o buffer de resultado usando mysql_bind_result(), assim mysql_
fetch() retornará automaticamente os dados para este buffer. Esta busca é feita registro
a registro.
Você também pode enviar o texto ou dado binário em blocos para o servidor
utilizando mysql_send_long_data(), especficando a opção is long data=1 ou
length=MYSQL LONG DATA ou -2 na estrutura MYSQL BIND fornecida com
mysql_bind_param().
Assim que a instrução executada acabar, ela deve ser liberada usando mysql_stmt_close
para liberar todos os recursos alocados para o manipulador de instrução.
Execution Steps:
Para prepara e executar uma instrução, a aplicação:
• Chama mysql prepare() e passa uma string contendo uma instrução SQL. Em um
preparo com sucesso, mysql prepare retorna o manipulador de instrução válido para a
aplicação.
• Se a consulta retorna um resultado, mysql prepare result retorna a informação de meta
dados do resultado.
• Define o valor de qualquer parâmetro usando mysql bind param. Todos os parâmetros
devem ser definidos. Senão será retornado um erro ou produzido um resultado inesper-
ado.
• Chama mysql execute() para executar a instrução.
• Repete os passos 2 e 3 se necessário, alterando o valor do parâmetro e re-executando a
instrução.
• Liga o buffer de dados pata retornar o valor do registro, se for um resultado de uma
consulta; usando mysql bind result().
• Busca os dados para o buffer registro a registro chamando mysql fetch() repetidas vezes
até não haver mais registros.
• Quando mysql prepare() é chamado, no protocolo cliente/servidor do MySQL:
− O servidor analiza a consulta e envia o status de ok de volta para o cliente
atribuindo uma identificação a instrução. Ele também envia um número total
de parâmetros, contagem de colunas e sua meta informação se for um resultado
orientado a consulta. Toda a sintaxe e semântica da consulta é verificada esta
chamada pelo servidor.
− O clinte utiliza esta identificação da instrução para as demais execuções, assim o
servidor identifica a instrução dentre outras existentes. Agora o cliente aloca um
manipulador de instruções com esta identificação e a retorna para a aplicação.
Chapter 8: MySQL APIs 599
8.1.7.1 mysql_prepare()
MYSQL_STMT * mysql_prepare(MYSQL *mysql, const char *query, unsigned long
length)
Descrição
Prepara a consulta SQL apontada pela string com terminação em nulo ’query’. A consul-
tadeve consistir de uma única instrução SQL. Você não deve adicionar ponto e virgula (‘;‘)
ou \g a instrução.
A aplicação pode incluir um ou mais marcadores de parâmetro na instrução SQL. Para
incluir um marcador de parâmetro, a aplicação embute uma exclamação (?) na string SQL
na posição aprpriada.
Os marcadores só são válidos em certos lugares na instrução SQL. Por exemplo, eles não
são permitidos em lista select (a lista de colunas retornadas por uma instrução SELECT),
nem são permitidas como ambos operadores de operção binária assim como o sinal de igual
(=), porque seria impossível determinar o tipo do parâmetro. Em geral, parâmetros são
válidos somente em instrução de Linguagem de Manipulação de Dados (Data Manipula-
tion Languange-DML), e não em instruções de Linguagem de Definição de Dados (Data
Defination Language-DDL).
Os marcadores de parâmetro limitam variáveis de aplicações utilizando mysql_bind_
param().
Valor Retornado
MYSQL_STMT se o preparo obteve sucesso. NULL se ocorreu um erro.
600 Referência técnica para o MySQL versão 3.23.52
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_OUT_OF_MEMORY
Falta de memória
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
Se o preparo não obteve sucesso, ex. quando mysql_prepare() retorna uma instrução
NULL, os erros podem ser obtidos chamando mysql_error().
Exemplo
Para o uso de mysql_prepare() consulte o exemplo de hundefinedi [mysql execute],
page hundefinedi.
8.1.7.2 mysql_param_count()
unsigned int mysql_param_count(MYSQL_STMT *stmt)
Descrição
Retorna o número de marcadores de parâmetros presentes na consulta preparada.
Valor Retornado
Um unsigned integer (inteiro sem sinal) representando o número de parâmetros em uma
instrução.
Erros
Nenhum.
Exemplo
Para utilizar mysql_param_count() consulte o exemplo de hundefinedi [mysql execute],
page hundefinedi.
8.1.7.3 mysql_prepare_result()
MYSQL_RES *mysql_prepare_result(MYSQL_STMT *stmt)
Chapter 8: MySQL APIs 601
Descrição
Se mysql_prepare() retornou um resultado de uma consulta, mysql_prepare_result() re-
torna o resultado dos meta dados na forma de uma estrutura MYSQL_RES; que também pode
ser usada para processar a meta informação como o número total de campos e informação
de campos indivíduais. O resultado retornado pode ser passado como um argumento para
qualquer um dos campos com base na API para processar informação do resultado dos meta
dados com:
− mysql num fields()
− mysql fetch field()
− mysql fetch field direct()
− mysql fetch fields()
− mysql field count()
− mysql field seek()
− mysql field tell() and
− mysql free result()
Valor Retornado
Uma estrutura de resultado MYSQL_RES. NULL se nenhuma meta informação existe na
consulta preparada.
Erros
CR_OUT_OF_MEMORY
Falta de memória
CR_UNKNOWN_ERROR
Ocorreu um erro desconhecido
Exemplo
Para utilizar mysql_prepare_result() consulte o exemplo de hundefinedi [mysql fetch],
page hundefinedi
8.1.7.4 mysql_bind_param()
int mysql_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
Descrição
mysql_bind_param é utilizado para ligar dados para os marcadores de parâmetros na in-
strução SQL com mysql_prepare. Ele utiliza a estrutura MYSQL BIND para fornecer os
dados.
Os tipos de buffers suportados são:
• MYSQL TYPE TINY
602 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
Zeros se a ligação foi obtida com sucesso. Diferente de zero se ocorrer um erro.
Erros
CR_NO_PREPARE_STMT
Não existem instruções preparadas
CR_NO_PARAMETERS_EXISTS
Não existem parâmetros para ligar
CR_INVALID_BUFFER_USE
Indica se a ligação forncerá dados longos em bolcos e se o tipo de buffer é binário
ou não é uma string.
CR_UNSUPPORTED_PARAM_TYPE
A conversão não é suportada, possivelmente o buffer type é inválido ou não é
um dos tipos suportados listados acima.
CR_OUT_OF_MEMOR
Falta de memória
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
Exemplo
Para utilizar mysql_bind_param() consulte o exemplo de hundefinedi [mysql execute],
page hundefinedi.
8.1.7.5 mysql_execute()
int mysql_execute(MYSQL_STMT *stmt.
Chapter 8: MySQL APIs 603
Descrição
mysql_execute() executa a consulta preparada associada ao manipulador de instruções.
O valor do marcador de parâmetros será enviado para o servidor durante esta chamada,
assimque o servidor substituir marcadores com os novos dados fornecidos.
Se a instrução é um UPDATE,DELETE,ou INSERT, o número total de changed/
deletd/inserted pode ser encontrado chamando mysql_stmt_affected_rows. Se este é um
resultado de uma consulta, deve se chamar mysql_fetch() para buscar dados previamente
para fazer qualquer outra chamada que resulte em um processamento de consulta. Para
mais informações sobre como buscar dados ibinários, consulte hundefinedi [mysql fetch],
page hundefinedi.
Valor Retornado
mysql_execute() retorna os seguintes valores:
Valor de Retorno Descrição
0 Sucesso
1 Erro ocorrido. Código e mensagem de erro podem ser
obtidos chamando mysql_stmt_errno() e mysql_stmt_
error().
Erros
CR_NO_PREPARE_QUERY
Nenhuma consulta preprada previamente para execução
CR_ALL_PARAMS_NOT_BOUND
Não forma fornecidos todos os dados de parâmetros.
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_OUT_OF_MEMORY
Falta de memória
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
Exemplo
O seguinte exemplo explica o uso de mysql_prepare, mysql_param_count, mysql_bind_
param, mysql_execute e mysql_stmt_affected_rows().
MYSQL_BIND bind[3];
MYSQL_STMT *stmt;
604 Referência técnica para o MySQL versão 3.23.52
ulonglong affected_rows;
long length;
unsigned int param_count;
int int_data;
short small_data;
char str_data[50], query[255];
my_bool is_null;
/* PARTE INTEGER */
Chapter 8: MySQL APIs 605
bind[0].buffer_type= MYSQL_TYPE_LONG;
bind[0].buffer= (char *)&int_data;
bind[0].is_null= 0;
bind[0].length= 0;
/* PARTE STRING */
bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
bind[1].buffer= (char *)str_data;
bind[1].buffer_length= sizeof(str_data);
bind[1].is_null= 0;
bind[1].length= 0;
/* PARTE SMALLINT */
bind[2].buffer_type= MYSQL_TYPE_SHORT;
bind[2].buffer= (char *)&small_data;
bind[2].is_null= &is_null;
bind[2].length= 0;
is_null= 0;
/* Liga os buffers */
if (mysql_bind_param(stmt, bind))
{
fprintf(stderr, "\n param bind failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
/* Especifica os dados */
int_data= 10; /* integer */
strcpy(str_data,"MySQL"); /* string */
/* Executa a instruç~
ao insert - 1*/
if (mysql_execute(stmt))
{
fprintf(stderr, "\n execute 1 failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
fprintf(stderr, "\n send a bug report to [email protected], by asking why thi
exit(0);
}
{
fprintf(stderr, "\n invalid affected rows by MySQL");
exit(0);
}
/* Executa a instruç~
ao insert - 2*/
if (mysql_execute(stmt))
{
fprintf(stderr, "\n execute 2 failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
/* Fecha a instruç~
ao */
if (mysql_stmt_close(stmt))
{
fprintf(stderr, "\n failed while closing the statement");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
/* APAGA A TABELA */
if (mysql_query(mysql,"DROP TABLE test_table"))
{
fprintf(stderr, "\n drop table failed");
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(0);
}
fprintf(stdout, "Success, MySQL prepared statements are working!!!");
8.1.7.6 mysql_stmt_affected_rows()
ulonglong mysql_stmt_affected_rows(MYSQL_STMT *stmt)
Chapter 8: MySQL APIs 607
Descrição
Retorna o número total de registros alterados pela última instruçãoexecutada. Pode
ser chamada imediatamente depois de mysql execute() para UPDATE,DELETE,ou
instruções INSERT. Para instruções SELECT, mysql stmt affected rows funciona como
mysql num rows().
Valor Retornado
Um integer (inteiro) maior que zero indica o número de registros afetados ou retornados.
Zero indica que nenhum registro foi atualizado em uma instrução UPDATE, nenhum re-
gitro coincidiu com a cláusula WHERE na consulta ou que nenhuma consulta foi exeutada
ainda. -1 indica que a consulta retornou um erro ou que, para uma consulta SELECT,
mysql stmt affected rows() foi chamado antes de chamra mysql fetch().
Erros
Nenhum.
Exemplo
Para utilizar mysql_stmt_affected_rows() consulte o exemplo de hundefinedi
[mysql execute], page hundefinedi.
8.1.7.7 mysql_bind_result()
my_bool mysql_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
Descrição
mysql_bind_result() é usado para associar, ou ligar, colunas no resultados ao buffer de
dados e buffer de tamanho. Quando mysql_fetch() é chamado para buscar dados, o
protocolo clinete MySQL retorna os para as colunas limitiadas no buffer especificado.
Note que todas as colunas devem ser limitadas antes de chamar mysql_fetch() no caso
de buscar os dados para o buffers; senão mysql_fetch() simplesmente ignorado os dados
trazidos; os buffers devem se suficientes para guardar os dados já que o protocolo não retorna
dados em blocos.
Uma coluna pode ser limitada a qualquer hora, mesmo depois do dados ter sido buscado
do resultado. A nova ligação tem efeito ba próxima vez em que mysql_fetch() é chamado.
Por exemplo, suponha que uma aplicação liga a coluna em um resultado e chama mysql_
fetch(). O protocolo MySQL retorna dados em buffers limitados. Agora suponha que a
aplicação ligue a coluna a um diferente cojunto de buffers, então o protocolo não coloca os
dados do registro recem buscados em um novo buffer limitado. Ele o faz que o próximo
mysql_fetch() for chamado.
Para ligar uma coluna, uma aplicação chama mysql_bind_result() e passa o tipo, o en-
dereço e o endereço do buffer do tamanho.
Os tipos de buffers suportados são:
608 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
Zero se a ligação obteve sucesso. Diferente de zero se ocorreu um erro.
Erros
CR_NO_PREPARE_STMT
Não existe instruções preparadas
CR_UNSUPPORTED_PARAM_TYPE
A conversão não é suportada, possivelmente o buffer type é inválido ou não
nanlista dos tipos de buffers suportados
CR_OUT_OF_MEMOR
Falta de memória
CR_UNKNOWN_ERROR
Ocorreu um erro desconhecido
Exemplo
Para utilizar mysql_bind_result() consulta o exemplo de hundefinedi [mysql fetch],
page hundefinedi
8.1.7.8 mysql_stmt_store_result()
int mysql_stmt_store_result(MYSQL_STMT *stmt)
Chapter 8: MySQL APIs 609
Descrição
Você deve chamar mysql_stmt_store_result() para cada query que retornar dados com
sucesso(SELECT,SHOW,DESCRIBE, EXPLAIN), e só se você quiser armazenar todo o resultado
no buffer no cliente, assim que a chamada mysql_fetch() subsequente retornar os dados
em buffers.
Você não precisa chamar mysql_stmt_store_result() para outras consultas, mas não
causará nenhum dano ou queda de performance em todo caso. Você pode detectar se a
consulta não gera um resultado verificado se mysql_prepare_result() retorna 0. Para
mais informações consulte hundefinedi [mysql prepare result], page hundefinedi.
Valor Retornado
Zero se o resultado foi armazenado em buffer com sucesso ou Diferente de zero em caso
de erro.
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_OUT_OF_MEMORY
Falta de memoria.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
8.1.7.9 mysql_stmt_data_seek()
void mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong offset)
Descrição
Busca um registro arbitrário no resultado de uma instrução. Isto exige que a estrutura
do resultado da instrução contenha todo o resultado da última consulta executada, assim
mysql_stmt_data_seek() pode ser usada em conjunto apenas com mysql_stmt_store_
result().
O offset deve ser um valor na faixa de 0 a mysql_stmt_num_rows(stmt)-1.
Valor Retornado
Nenhum.
610 Referência técnica para o MySQL versão 3.23.52
Erros
Nenhum.
8.1.7.10 mysql_stmt_row_seek()
MYSQL_ROW_OFFSET mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET
offset)
Descrição
Define o cursor de linha com um registro arbitrário em um resultado de instrução. Isto
exige que a estrutura do resultado contenha todo o resultado da consulta, assim mysql_
stmt_row_seek() pode ser usado em conjunto apenas com mysql_stmt_store_result().
O offset deve ser um valor retornado de uma chamada a mysql_stmt_row_tell() ou a
mysql_stmt_row_seek(). Este valor não é simplesmente um númerod de linha; se você
quiser buscar um registro em um resultado usando um número de linha utilize mysql_
stmt_data_seek().
Valor Retornado
O valor anterior do cursor de linha. Este valor pode ser passado a uma chamada subsequente
de mysql_stmt_row_seek().
Erros
Nenhum.
8.1.7.11 mysql_stmt_row_tell()
MYSQL_ROW_OFFSET mysql_stmt_row_tell(MYSQL_STMT *stmt)
Descrição
Retorna a posição corrente do cursor de linha para o último mysql_fetch(). Este valor
pode ser usado como um argumento para mysql_stmt_row_seek().
Você deve usar mysql_stmt_row_tell() somente depois de mysql_stmt_store_result().
Valor Retornado
O offset atual do cursor de linha.
Erros
Nenhum.
8.1.7.12 mysql_stmt_num_rows()
my_ulonglong mysql_stmt_num_rows(MYSQL_STMT *stmt)
Chapter 8: MySQL APIs 611
Descrição
Rertorna o número de registros no resultado.
O uso de mysql_stmt_num_rows() depende de se você utilizou mysql_stmt_store_
result() para armazenar todo o resultado no manipulador de instruções ou
não.
Se você utilizou mysql_stmt_store_result(), mysql_stmt_num_rows() pode ser chamado
imediatamente.
Valor Retornado
O número de linhas no resultado.
Erros
Nenhum.
8.1.7.13 mysql_fetch()
int mysql_fetch(MYSQL_STMT *stmt)
Descrição
mysql_fetch() retorna o próximo conjunto de registros no resultado. Ele pode ser chamado
apenas enquanto existir o conjunto de resultados. Per exemplo, depois de uma chamada de
mysql_execute() que cria o resultado ou depois de mysql_stmt_store_result(), que é
chamado depois de mysql_execute() para armazenar todo o resultado.
Se buffers de linhas são limitados usando mysql_bind_result(), ele retorna os dados neste
buffer para todas as colunas no registro atual e os tamanhos são retornados para o apontador
do tamanho.
Note que, todas as colunas devem ser limitadas pela aplicação.
Se o dado buscado é um dado NULL, então o valor is_null de MYSQL_BIND contém TRUE
(VERDASDEIRO), 1, senão o dado e seu tamanho é retornado para as variáveis *buffer
e *length baseada no tipo de buffer especificado pela aplicação, Todos os tipos numéricos,
float e double tem o tamanho fixo (em bytes) como mostrado abaixo:
Tipo Tamanho
MYSQL TYPE TINY 1
MYSQL TYPE SHORT 2
MYSQL TYPE LONG 4
MYSQL TYPE FLOAT 4
MYSQL TYPE LONGLONG 8
MYSQL TYPE DOUBLE 8
MYSQL TYPE TIME sizeof(MYSQL TIME)
MYSQL TYPE DATE sizeof(MYSQL TIME)
MYSQL TYPE DATETIME sizeof(MYSQL TIME)
MYSQL TYPE TIMESTAMP sizeof(MYSQL TIME)
MYSQL TYPE STRING tam dados
612 Referência técnica para o MySQL versão 3.23.52
Valor Retornado
Valor retornado Descrição
0 Sucesso, o dado foi buscado para o buffers de dados da
aplicação.
1 Ocorreu um erro. O código e a mensagem de erro podem
ser obtidos chamando mysql_stmt_errno() e mysql_
stmt_error().
100, MYSQL NO DATA Não existem mais registros/dados
Erros
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_OUT_OF_MEMORY
Falta de memoria.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_SERVER_LOST
A conexão ao servidor MySQL foi perdida durante a consulta.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
CR_UNSUPPORTED_PARAM_TYPE
Se o tipo de buffer é MYSQL TYPE DATE,DATETIME,TIME,ou TIMES-
TAMP; e se o tipo de dado não é DATE, TIME, DATETIME ou TIMESTAMP.
Todos os outros erros de conversão não suportada são retornados de mysql_
bind_result().
Exemplo
O seguinte exemplo explica o uso de mysql_prepare_result, mysql_bind_result(), e
mysql_fetch()
MYSQL_STMT *stmt;
MYSQL_BIND bind[2];
MYSQL_RES *result;
int int_data;
Chapter 8: MySQL APIs 613
if (mysql_num_fields(result) != 2)
{
fprintf(stderr, "\n prepare returned invalid field count");
exit(0);
}
bind[1].buffer_type= MYSQL_TYPE_VAR_STRING;
bind[1].buffer= (void *)str_data;
bind[1].buffer_length= 20;
bind[1].is_null= &is_null[1];
bind[1].length= &str_length;
if (mysql_bind_result(stmt, bind))
614 Referência técnica para o MySQL versão 3.23.52
{
fprintf(stderr, "\n bind_result failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
if (is_null[0])
fprintf(stdout, "\n Col1 data is NULL");
else
fprintf(stdout, "\n Col1: %d, length: %ld", int_data, int_length);
if (is_null[1])
fprintf(stdout, "\n Col2 data is NULL");
else
fprintf(stdout, "\n Col2: %s, length: %ld", str_data, str_length);
8.1.7.14 mysql_send_long_data()
Descrição
Permite que um aplicação envie os dados em blocos para o servidor. Esta função pode ser
usada para enviar valores de dados binários e caracteres em partes para uma coluna (deve
ser text ou blob) com um tipo de dado binário ou de caracter.
data é um ponterio para o buffer contendo os dados atauis para o parâmetro represntado
por parameter_number. length indica a quantidade de dados a ser enviado em bytes.
Valor Retornado
Zero se os dados são enviados com sucesso para o servidir. Diferente de zero se ocorrer um
erro.
Erros
CR_INVALID_PARAMETER_NO
Número de parâmetro inválido
CR_COMMANDS_OUT_OF_SYNC
Os comando foram executados em uma ordem inpropriada.
CR_OUT_OF_MEMORY
Falta de memoria.
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_UNKNOWN_ERROR
Um erro desconhecido ocorreu.
Example
O exemplo seguinte explica como enviar os dados em blocos para um coluna do tipo text:
MYSQL_BIND bind[1];
long length;
/* Liga os buffers */
616 Referência técnica para o MySQL versão 3.23.52
if (mysql_bind_param(stmt, bind))
{
fprintf(stderr, "\n param bind failed");
fprintf(stderr, "\n %s", mysql_stmt_error(stmt));
exit(0);
}
This inserts the data, "MySQL - The most popular open source database"
to the field ’text_column’.
8.1.7.15 mysql_stmt_close()
my_bool mysql_stmt_close(MYSQL_STMT *)
Descrição
Fecha a instrução preparada. mysql_stmt_close() também desaloca o manipulador de
instruções apontado por stmt.
Se os resultados do consulta atual estão pendentes ou não foram lidos; o resultado da
consulta é cancelado para que a próxima chamada possa ser executada.
Valor Retornado
Zero se a instrução for libera com sucesso. Diferente de zero se ocorrer um erro.
Chapter 8: MySQL APIs 617
Erros
CR_SERVER_GONE_ERROR
O servidor MySQL foi finalizado.
CR_UNKNOWN_ERROR
Ocorreu um erro desconhecido.
Exemplo
Para utilizar mysql_stmt_close() consulte o exemplo de hundefinedi [mysql execute],
page hundefinedi.
8.1.7.16 mysql_stmt_errno()
unsigned int mysql_stmt_errno(MYSQL_STMT *stmt)
Descrição
Para a instrução especificada por stmt, mysql_stmt_errno() retorna o código de erro para
a função de instruções da API chamada mais recentemente. Um valor de retorno de zero
significa que não ocorreu nenhum erro. Números de mensagens de erro do cliente estão
listadas no arquivo cabeçlho errmsg.h do MySQL. lient error message numbers are listed in
the MySQL errmsg.h header file. Números de mensagens de erro do servidor estão listado
no arquivo mysqld error.h. Na distribuição fonte do MySQL você pode encontra uma lista
completa com mensagem de erros e números de erros no arquivo Docs/mysqld error.txt
Valor Retornado
Um valor de código de erro. Zero se não ocorreu erro.
Erros
Nenhum
8.1.7.17 mysql_stmt_error()
char *mysql_stmt_error(MYSQL_STMT *stmt)
Descrição
Para a instrução especificada por stmt, mysql_stmt_error() retorna a mensagem de erro
para a função de instrução da API chamada mais recentemente. Um string vazia ("")
é retornado se não ocorreu nenhum erro. Isto significa que os seguintes comandos são
equivalentes:
if (mysql_stmt_errno(stmt))
{
// an error occured
618 Referência técnica para o MySQL versão 3.23.52
if (mysql_stmt_error(stmt))
{
// an error occured
}
A linguagem da mensagem de erro do cliente pode ser alterada recompilando a biblioteca
cliente do MySQL. Atualmente você pode escolher mensagem de erros em diversas lingua-
gens.
Valor Retornado
Um string contendo a descrição do erro. Uma string vazia se não ocorrer erros.
Erros
Nenhum
MYSQL_TIME ts;
MYSQL_BIND bind[3];
MYSQL_STMT *stmt;
mysql_bind_param(stmt, bind);
ts.hour= 10;
ts.minute= 45;
ts.second= 20;
mysql_execute(stmt);
..
8.1.10.1 my_init()
void my_init(void)
Descrição
Esta função precisa ser chamada uma vez pelo programa antes de se chamar qualquer
função do MySQL. Ela inicializa algumas varáveis globais que o MySQL precisa. se você
está usando uma biblioteca cliente de thread segura, também será feita uma chamada a
mysql_thread_init() para esta thread.
Ela é chamada automaticamente por mysql_init(), mysql_server_init() e
mysql_connect().
Valor Retornado
Nenhum
8.1.10.2 mysql_thread_init()
my_bool mysql_thread_init(void)
Descrição
Esta função preisa aser chamada para cada thread criada para inicializar variáveis específicas
de threads.
Ela é automaticamente chamada por my_init() e mysql_connect().
Valor Retornado
Nenhum.
8.1.10.3 mysql_thread_end()
void mysql_thread_end(void)
Chapter 8: MySQL APIs 621
Descrição
Esta função precisa ser chamada antes da chamada de pthread_exit() para liberar a
memória alocada por mysql_thread_init().
Note que a função não é chamada automaticamente pela biblioteca cliente. Deve ser
chamada explicitamente para evitar perda de memória.
Valor Retornado
Nenhum.
8.1.10.4 mysql_thread_safe()
unsigned int mysql_thread_safe(void)
Descrição
Esta função indica se o cliente é compilado como uma thread segura.
Valor Retornado
1 se o cliente possui thread segura, 0 em outro caso.
8.1.11.1 mysql_server_init()
int mysql_server_init(int argc, char **argv, char **groups)
Descrição
Esta função deve ser chamada uma vez no program usando o servidor embutido aantes
de se chamar qualquer iutra função do MySQL. Ela inicia o servidor e inicializa qualquer
subsistema (mysys, InnoDB, etc.) que o servidor utilize. Se esta função não for chamada, o
programa irá falhar. Se você estiver usando o pacote DBUG que vem com o MySQL, você
deve chamar esta função depois de ter chamado MY_INIT().
Os argumentos argc e argv são análogos ao argumentos para o main(). O primeiro elemento
de argv é ignorado (ele contém normalmente, o nome do programa). por conveniência, argc
pode ser 0 (zero) se não houver argumentos de linha de comando para o servidor. mysql_
server_init() faz uma copia dos argumentos, assim é seguro destruir argv ou groups
depois da chamada.
A lista de strings terminadas em NULL em groups seleciona qual grupo no arquivo de opções
será ativado. See hundefinedi [Arquivos de opções], page hundefinedi. Por conveniência,
groups deve ser NULL, caso no qual os grupos [server] d [emedded] estarão ativos.
622 Referência técnica para o MySQL versão 3.23.52
Exemplo
#include <mysql.h>
#include <stdlib.h>
int main(void) {
mysql_server_init(sizeof(server_args) / sizeof(char *),
server_args, server_groups);
mysql_server_end();
return EXIT_SUCCESS;
}
Valor Retornado
0 se okay, 1 se ocorrer um erro.
8.1.11.2 mysql_server_end()
void mysql_server_end(void)
Descrição
Esta função deve ser chamada no programa depois de todas outra funções MySQL. Ela
finaliza o srvidor embutido.
Valor Retornado
Nenhum.
if (mysql_error(&mysql)[0] == 0 &&
mysql_num_fields(result) == 0 &&
mysql_insert_id(&mysql) != 0)
{
used_id = mysql_insert_id(&mysql);
}
O ID gerado mais recentemente é mantido no servidor em uma base por conexão. Ele não
será alterado por outro cliente. Ele não será alterado mesmo se você atualizar outra coluna
AUTO_INCREMENT com um valor não mágico (isto é, um valor que não é NULL e nem 0).
Se você quiser utilizar o ID que foi gerado por uma tabela e inserido em uma segunda tabela,
você ode utilizar instruções SQL como esta:
INSERT INTO foo (auto,text)
VALUES(NULL,’text’); # gera ID inserindo NULL
INSERT INTO foo2 (id,text)
VALUES(LAST_INSERT_ID(),’text’); # usa ID na segunda tabela
vez que mysql_store_result() esteja pronto, a trva pode ser liberada e outras threads
podem utilizar a mesma conexão.
• Se você programa com threads POSIX, você pode utilizar pthread_mutex_lock() e
pthread_mutex_unlock() para estabelecer e liberar uma trava mutex.
Você precisa saber o seguinte se você tiver uma thread que estiver chamando funções MySQL
que não criaram a conexão ao banco de dados MySQL:
Quando você chamar mysql_init() ou mysql_connect(), MySQL irá criar um variável
especica da thread para a thread que é utilizada pela bibklioteca de depuração (entre outra
coisas).
Se você chamar uma função MySQL, antes da thread chamar mysql_init() ou mysql_
connect(), a thread não terá as variáveis específicas de thread necessárias alocadas e você
acabará finalizando com uma descarga de memória mais cedo ou mais tarde.
Para fazer que as coisas funcionem suavemente você tem que fazer o seguinte:
1. Chama my_init() no início do seu programa se for chamar qualquer outra função
MySQL antes de chamar mysql_real_connect().
2. Chame mysql_thread_init() no manipulador de thread antes de chamar qualquer
outra função MySQL.
3. Na thread, chame mysql_thread_end() antes de chamar pthread_exit(). Isto irá
liberar a memória usada pelas variáveis específicas da thread do MySQL.
Você pode obter alguns erros devido a símbolos indefinidos ao ligar seu cliente com
libmysqlclient_r. Na maioria dos casos isto ocorre por não estar incluída a biblioteca
de threads na linha de ligação/compilação.
#include <mysql.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
MYSQL *one, *two;
[test_libmysqld_SERVER]
language = /path/to/source/of/mysql/sql/share/english
one = db_connect("test");
two = db_connect(NULL);
mysql_close(two);
mysql_close(one);
exit(EXIT_SUCCESS);
}
static void
die(MYSQL *db, char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
(void)putc(’\n’, stderr);
if (db)
db_disconnect(db);
exit(EXIT_FAILURE);
}
MYSQL *
db_connect(const char *dbname)
{
MYSQL *db = mysql_init(NULL);
if (!db)
die(db, "mysql_init failed: no memory");
/*
* Certifique-se que o cliente e o servidor utilizam grupos diferentes.
* Isto é critico pois o servidor n~
ao aceitará as opç~
oes do
* cliente e vice versa.
*/
mysql_options(db, MYSQL_READ_DEFAULT_GROUP, "test_libmysqld_CLIENT");
if (!mysql_real_connect(db, NULL, NULL, NULL, dbname, 0, NULL, 0))
die(db, "mysql_real_connect failed: %s", mysql_error(db));
630 Referência técnica para o MySQL versão 3.23.52
return db;
}
void
db_disconnect(MYSQL *db)
{
mysql_close(db);
}
void
db_do_query(MYSQL *db, const char *query)
{
if (mysql_query(db, query) != 0)
goto err;
if (mysql_field_count(db) > 0)
{
MYSQL_RES *res;
MYSQL_ROW row, end_row;
int num_fields;
if (!(res = mysql_store_result(db)))
goto err;
num_fields = mysql_num_fields(res);
while ((row = mysql_fetch_row(res)))
{
(void)fputs(">> ", stdout);
for (end_row = row + num_fields; row < end_row; ++row)
(void)printf("%s\t", row ? (char*)*row : "NULL");
(void)fputc(’\n’, stdout);
}
(void)fputc(’\n’, stdout);
}
else
(void)printf("Affected rows: %lld\n", mysql_affected_rows(db));
mysql_free_result(res);
return;
err:
die(db, "db_do_query failed: %s [%s]", mysql_error(db), query);
}
‘GNUmakefile’
# This assumes the MySQL software is installed in /usr/local/mysql
inc := /usr/local/mysql/include/mysql
lib := /usr/local/mysql/lib
Chapter 8: MySQL APIs 631
# If you have not installed the MySQL software yet, try this instead
#inc := $(HOME)/mysql-4.0/include
#lib := $(HOME)/mysql-4.0/libmysqld
CC := gcc
CPPFLAGS := -I$(inc) -D_THREAD_SAFE -D_REENTRANT
CFLAGS := -g -W -Wall
LDFLAGS := -static
# You can change -lmysqld to -lmysqlclient to use the
# client/server library
LDLIBS = -L$(lib) -lmysqld -lz -lm -lcrypt
all: $(targets)
clean:
rm -f $(targets) $(objects) *.core
O código fonte do MySQL é coberto pela licenção GNU GPL (see hundefinedi [Licença GPL],
page hundefinedi). Um resultado disto é que qualquer programa que incluam, na ligação
com libmysqld, o código fonte do MySQL deve ser distribuído como software livre. (sob
uma licença compatível com a GPL).
Nós encorajamos a todos a promover o software livre distribuindo o código sob a GPL ou
uma licença compatível. Para aqueles que não puderem fazê-lo, outra opção é comprar um
licença comercial para o código MySQL da MySQL AB. Para maiores detalhes, consulte
hundefinedi [MySQL licenses], page hundefinedi.
• Agora inicie a sua aplicação e selcione o driver ODBC com o DSN que voc6e especificou
no adminitrador ODBC.
Verifique se há outra opção de configuração na tela do MySQL (trace, não pergunta ao
conectar, etc) que você possa tentar se ocorrerem problemas.
• If you are linking a table through MyODBC, which has BIGINT as one
of the column, then the results will be displayed as #DELETED. The work
around solution is:
• Have one more dummy column with TIMESTAMP as the data type,
preferably TIMESTAMP(14).
• Check the ’Change BIGINT columns to INT’ in connection options di-
alog in ODBC DSN Administrator
• Delete the table link from access and re-create it.
It still displays the previous records as #DELETED#, but newly
added/updated records will be displayed properly.
• If you still get the error Another user has changed your data after adding
a TIMESTAMP column, the following trick may help you:
Don’t use table data sheet view. Create instead a form with the fields you
want, and use that form data sheet view. You should set the DefaultValue
property for the TIMESTAMP column to NOW(). It may be a good idea to
hide the TIMESTAMP column from view so your users are not confused.
• In some cases, Access may generate illegal SQL queries that MySQL can’t
understand. You can fix this by selecting "Query|SQLSpecific|Pass-
Through" from the Access menu.
• Access on NT will report BLOB columns as OLE OBJECTS. If you want to
have MEMO columns instead, you should change the column to TEXT with
ALTER TABLE.
• Access can’t always handle DATE columns properly. If you have a problem
with these, change the columns to DATETIME.
• If you have in Access a column defined as BYTE, Access will try to export
this as TINYINT instead of TINYINT UNSIGNED. This will give you problems
if you have values > 127 in the column!
ADO When you are coding with the ADO API and MyODBC you need to put attention
in some default properties that aren’t supported by the MySQL server. For
example, using the CursorLocation Property as adUseServer will return for
the RecordCount Property a result of -1. To have the right value, you need to
set this property to adUseClient, like is showing in the VB code here:
Dim myconn As New ADODB.Connection
Dim myrs As New Recordset
Dim mySQL As String
Dim myrows As Long
myconn.Open "DSN=MyODBCsample"
mySQL = "SELECT * from user"
myrs.Source = mySQL
Set myrs.ActiveConnection = myconn
myrs.CursorLocation = adUseClient
myrs.Open
myrows = myrs.RecordCount
Chapter 8: MySQL APIs 637
myrs.Close
myconn.Close
Another workaround is to use a SELECT COUNT(*) statement for a similar query
to get the correct row count.
Active server pages (ASP)
You should use the option flag Return matching rows.
BDE applications
To get these to work, you should set the option flags Don’t optimize column
widths and Return matching rows.
Borland Builder 4
When you start a query you can use the property Active or use the method
Open. Note that Active will start by automatically issuing a SELECT * FROM
... query that may not be a good thing if your tables are big!
ColdFusion (On Unix)
The following information is taken from the ColdFusion documentation:
Use the following information to configure ColdFusion Server for Linux to use
the unixODBC driver with MyODBC for MySQL data sources. Allaire has verified
that MyODBC Version 2.50.26 works with MySQL Version 3.22.27 and ColdFusion
for Linux. (Any newer version should also work.) You can download MyODBC at
http://www.mysql.com/downloads/api-myodbc.html
ColdFusion Version 4.5.1 allows you to us the ColdFusion Administrator to
add the MySQL data source. However, the driver is not included with Cold-
Fusion Version 4.5.1. Before the MySQL driver will appear in the ODBC
datasources drop-down list, you must build and copy the MyODBC driver to
‘/opt/coldfusion/lib/libmyodbc.so’.
The Contrib directory contains the program ‘mydsn-xxx.zip’ which allows you
to build and remove the DSN registry file for the MyODBC driver on Coldfusion
applications.
DataJunction
You have to change it to output VARCHAR rather than ENUM, as it exports the
latter in a manner that causes MySQL grief.
Excel Works. A few tips:
• If you have problems with dates, try to select them as strings using the
CONCAT() function. For example:
select CONCAT(rise_time), CONCAT(set_time)
from sunrise_sunset;
Values retrieved as strings this way should be correctly recognised as time
values by Excel97.
The purpose of CONCAT() in this example is to fool ODBC into thinking
the column is of “string type”. Without the CONCAT(), ODBC knows the
column is of time type, and Excel does not understand that.
638 Referência técnica para o MySQL versão 3.23.52
Word
To retrieve data from MySQL to Word/Excel documents, you need to use the
MyODBC driver and the Add-in Microsoft Query help.
For example, create a db with a table containing 2 columns of text:
• Insert rows using the mysql client command-line tool.
• Create a DSN file using the ODBC manager, for example, ‘my’ for the db
above.
• Open the Word application.
• Create a blank new documentation.
• Using the tool bar called Database, press the button insert database.
• Press the button Get Data.
• At the right hand of the screen Get Data, press the button Ms Query.
• In the Ms Query create a New Data Source using the DSN file my.
• Select the new query.
• Select the columns that you want.
• Make a filter if you want.
• Make a Sort if you want.
• Select Return Data to Microsoft Word.
• Click Finish.
• Click Insert data and select the records.
• Click OK and you see the rows in your Word document.
odbcadmin
Test program for ODBC.
Delphi You must use BDE Version 3.2 or newer. Set the Don’t optimize column
width option field when connecting to MySQL.
Also, here is some potentially useful Delphi code that sets up both an ODBC
entry and a BDE entry for MyODBC (the BDE entry requires a BDE Alias Editor
that is free at a Delphi Super Page near you. (Thanks to Bryan Brunton
[email protected] for this):
fReg:= TRegistry.Create;
fReg.OpenKey(’\Software\ODBC\ODBC.INI\DocumentsFab’, True);
fReg.WriteString(’Database’, ’Documents’);
fReg.WriteString(’Description’, ’ ’);
fReg.WriteString(’Driver’, ’C:\WINNT\System32\myodbc.dll’);
fReg.WriteString(’Flag’, ’1’);
fReg.WriteString(’Password’, ’’);
fReg.WriteString(’Port’, ’ ’);
Chapter 8: MySQL APIs 639
fReg.WriteString(’Server’, ’xmark’);
fReg.WriteString(’User’, ’winuser’);
fReg.OpenKey(’\Software\ODBC\ODBC.INI\ODBC Data Sources’, True);
fReg.WriteString(’DocumentsFab’, ’MySQL’);
fReg.CloseKey;
fReg.Free;
Memo1.Lines.Add(’DATABASE NAME=’);
Memo1.Lines.Add(’USER NAME=’);
Memo1.Lines.Add(’ODBC DSN=DocumentsFab’);
Memo1.Lines.Add(’OPEN MODE=READ/WRITE’);
Memo1.Lines.Add(’BATCH COUNT=200’);
Memo1.Lines.Add(’LANGDRIVER=’);
Memo1.Lines.Add(’MAX ROWS=-1’);
Memo1.Lines.Add(’SCHEMA CACHE DIR=’);
Memo1.Lines.Add(’SCHEMA CACHE SIZE=8’);
Memo1.Lines.Add(’SCHEMA CACHE TIME=-1’);
Memo1.Lines.Add(’SQLPASSTHRU MODE=SHARED AUTOCOMMIT’);
Memo1.Lines.Add(’SQLQRYMODE=’);
Memo1.Lines.Add(’ENABLE SCHEMA CACHE=FALSE’);
Memo1.Lines.Add(’ENABLE BCD=FALSE’);
Memo1.Lines.Add(’ROWSET SIZE=20’);
Memo1.Lines.Add(’BLOBS TO CACHE=64’);
Memo1.Lines.Add(’BLOB SIZE=32’);
AliasEditor.Add(’DocumentsFab’,’MySQL’,Memo1.Lines);
C++ Builder
Tested with BDE Version 3.0. The only known problem is that when the table
schema changes, query fields are not updated. BDE, however, does not seem to
recognise primary keys, only the index PRIMARY, though this has not been a
problem.
Vision You should use the option flag Return matching rows.
Visual Basic
To be able to update a table, you must define a primary key for the table.
Visual Basic with ADO can’t handle big integers. This means that some
queries like SHOW PROCESSLIST will not work properly. The fix is to set the
option OPTION=16384 in the ODBC connect string or to set the Change BIGINT
columns to INT option in the MyODBC connect screen. You may also want to
set the Return matching rows option.
VisualInterDev
If you get the error [Microsoft][ODBC Driver Manager] Driver does not
support this parameter the reason may be that you have a BIGINT in
your result. Try setting the Change BIGINT columns to INT option in the
MyODBC connect screen.
Visual Objects
You should use the option flag Don’t optimize column widths.
640 Referência técnica para o MySQL versão 3.23.52
If you can create a program that also shows this problem, please upload this too!
If the program works with some other SQL server, you should make an ODBC log file where
you do exactly the same thing in the other SQL server.
Remember that the more information you can supply to us, the more likely it is that we
can fix the problem!
mysql_socket=/path/to/socket
Specify the pathname of the Unix socket that is used to connect to
the server (MySQL Version 3.21.15 or later).
Multiple modifiers may be given; each must be preceded by a semicolon.
For example, if you want to avoid hardcoding the user name and password into
a DBI script, you can take them from the user’s ‘~/.my.cnf’ option file instead
by writing your connect call like this:
$dbh = DBI->connect("DBI:mysql:$database"
. ";mysql_read_default_file=$ENV{HOME}/.my.cnf",
$user, $password);
This call will read options defined for the [client] group in the option file. If
you wanted to do the same thing but use options specified for the [perl] group
as well, you could use this:
$dbh = DBI->connect("DBI:mysql:$database"
. ";mysql_read_default_file=$ENV{HOME}/.my.cnf"
. ";mysql_read_default_group=perl",
$user, $password);
disconnect
The disconnect method disconnects the database handle from the database.
This is typically called right before you exit from the program. Example:
$rc = $dbh->disconnect;
prepare($statement)
Prepares a SQL statement for execution by the database engine and returns a
statement handle ($sth), which you can use to invoke the execute method.
Typically you handle SELECT statements (and SELECT-like statements such as
SHOW, DESCRIBE, and EXPLAIN) by means of prepare and execute. Example:
$sth = $dbh->prepare($statement)
or die "Can’t prepare $statement: $dbh->errstr\n";
If you want to read big results to your client you can tell Perl to use mysql_
use_result() with:
my $sth = $dbh->prepare($statement { "mysql_use_result" => 1});
execute The execute method executes a prepared statement. For non-SELECT state-
ments, execute returns the number of rows affected. If no rows are affected,
execute returns "0E0", which Perl treats as zero but regards as true. If an error
occurs, execute returns undef. For SELECT statements, execute only starts
the SQL query in the database; you need to use one of the fetch_* methods
described here to retrieve the data. Example:
$rv = $sth->execute
or die "can’t execute the query: $sth->errstr;
do($statement)
The do method prepares and executes a SQL statement and returns the number
of rows affected. If no rows are affected, do returns "0E0", which Perl treats as
Chapter 8: MySQL APIs 645
zero but regards as true. This method is generally used for non-SELECT state-
ments that cannot be prepared in advance (due to driver limitations) or that
do not need to be executed more than once (inserts, deletes, etc.). Example:
$rv = $dbh->do($statement)
or die "Can’t execute $statement: $dbh- >errstr\n";
Generally the ’do’ statement is much faster (and is preferable) than
prepare/execute for statements that don’t contain parameters.
quote($string)
The quote method is used to "escape" any special characters contained in the
string and to add the required outer quotation marks. Example:
$sql = $dbh->quote($string)
fetchrow_array
This method fetches the next row of data and returns it as an array of field
values. Example:
while(@row = $sth->fetchrow_array) {
print qw($row[0]\t$row[1]\t$row[2]\n);
}
fetchrow_arrayref
This method fetches the next row of data and returns it as a reference to an
array of field values. Example:
while($row_ref = $sth->fetchrow_arrayref) {
print qw($row_ref->[0]\t$row_ref->[1]\t$row_ref->[2]\n);
}
fetchrow_hashref
This method fetches a row of data and returns a reference to a hash table
containing field name/value pairs. This method is not nearly as efficient as
using array references as demonstrated above. Example:
while($hash_ref = $sth->fetchrow_hashref) {
print qw($hash_ref->{firstname}\t$hash_ref->{lastname}\t\
$hash_ref->{title}\n);
}
fetchall_arrayref
This method is used to get all the data (rows) to be returned from the SQL
statement. It returns a reference to an array of references to arrays for each
row. You access or print the data by using a nested loop. Example:
my $table = $sth->fetchall_arrayref
or die "$sth->errstr\n";
my($i, $j);
for $i ( 0 .. $#{$table} ) {
for $j ( 0 .. $#{$table->[$i]} ) {
print "$table->[$i][$j]\t";
}
print "\n";
}
646 Referência técnica para o MySQL versão 3.23.52
finish Indicates that no more data will be fetched from this statement handle. You
call this method to free up the statement handle and any system resources
associated with it. Example:
$rc = $sth->finish;
rows Returns the number of rows changed (updated, deleted, etc.) by the last com-
mand. This is usually used after a non-SELECT execute statement. Example:
$rv = $sth->rows;
NULLABLE Returns a reference to an array of values that indicate whether columns may
contain NULL values. The possible values for each array element are 0 or the
empty string if the column cannot be NULL, 1 if it can, and 2 if the column’s
NULL status is unknown. Example:
$null_possible = $sth->{NULLABLE};
NUM_OF_FIELDS
This attribute indicates the number of fields returned by a SELECT or SHOW
FIELDS statement. You may use this for checking whether a statement returned
a result: A zero value indicates a non-SELECT statement like INSERT, DELETE,
or UPDATE. Example:
$nr_of_fields = $sth->{NUM_OF_FIELDS};
data_sources($driver_name)
This method returns an array containing names of databases available to the
MySQL server on the host ’localhost’. Example:
@dbs = DBI->data_sources("mysql");
ChopBlanks
This attribute determines whether the fetchrow_* methods will chop leading
and trailing blanks from the returned values. Example:
$sth->{’ChopBlanks’} =1;
trace($trace_level)
trace($trace_level, $trace_filename)
The trace method enables or disables tracing. When invoked as a DBI class
method, it affects tracing for all handles. When invoked as a database or
statement handle method, it affects tracing for the given handle (and any future
children of the handle). Setting $trace_level to 2 provides detailed trace
information. Setting $trace_level to 0 disables tracing. Trace output goes to
the standard error output by default. If $trace_filename is specified, the file
is opened in append mode and output for all traced handles is written to that
file. Example:
DBI->trace(2); # trace everything
DBI->trace(2,"/tmp/dbi.out"); # trace everything to
# /tmp/dbi.out
$dth->trace(2); # trace this database handle
$sth->trace(2); # trace this statement handle
You can also enable DBI tracing by setting the DBI_TRACE environment variable.
Setting it to a numeric value is equivalent to calling DBI->(value). Setting it
to a pathname is equivalent to calling DBI->(2,value).
Chapter 8: MySQL APIs 647
MySQL-specific Methods
The methods shown here are MySQL-specific and not part of the DBI standard. Several of
them are now deprecated: is_blob, is_key, is_num, is_pri_key, is_not_null, length,
max_length, and table. Where DBI-standard alternatives exist, they are noted here:
insertid If you use the AUTO_INCREMENT feature of MySQL, the new auto-incremented
values will be stored here. Example:
$new_id = $sth->{insertid};
As an alternative, you can use $dbh->{’mysql_insertid’}.
is_blob Returns a reference to an array of boolean values; for each element of the array,
a value of TRUE indicates that the respective column is a BLOB. Example:
$keys = $sth->{is_blob};
is_key Returns a reference to an array of boolean values; for each element of the array,
a value of TRUE indicates that the respective column is a key. Example:
$keys = $sth->{is_key};
is_num Returns a reference to an array of boolean values; for each element of the array,
a value of TRUE indicates that the respective column contains numeric values.
Example:
$nums = $sth->{is_num};
is_pri_key
Returns a reference to an array of boolean values; for each element of the array, a
value of TRUE indicates that the respective column is a primary key. Example:
$pri_keys = $sth->{is_pri_key};
is_not_null
Returns a reference to an array of boolean values; for each element of the array,
a value of FALSE indicates that this column may contain NULL values. Example:
$not_nulls = $sth->{is_not_null};
is_not_null is deprecated; it is preferable to use the NULLABLE attribute (de-
scribed above), because that is a DBI standard.
length
max_length
Each of these methods returns a reference to an array of column sizes. The
length array indicates the maximum possible sizes that each column may be
(as declared in the table description). The max_length array indicates the
maximum sizes actually present in the result table. Example:
$lengths = $sth->{length};
$max_lengths = $sth->{max_length};
NAME Returns a reference to an array of column names. Example:
$names = $sth->{NAME};
table Returns a reference to an array of table names. Example:
$tables = $sth->{table};
type Returns a reference to an array of column types. Example:
$types = $sth->{type};
648 Referência técnica para o MySQL versão 3.23.52
9.1 Introduction
In release 4.1 MySQL introduces spatial extensions, which allow generating, storing and
analysing of geographic features.
You can also find documents which use term geospatial feature to refer to geographic
features.
Geometry is another word that denotes a geographic feature. The original meaning of
the word geometry denotes a branch of mathematics. Another meaning that comes from
cartography, referring to the geometric features that cartographers use to map the world.
We will mean the same thing using all these terms, a geographic feature, or a geospatial
feature, or a feature, or a geometry, with geometry as the most used in this documen-
tation.
Let’s define a geometry as a point or an aggregate of points representing anything in the
world that has a location.
9.1.2 Approach
MySQL implements spatial extensions following OpenGIS specifications.
The OpenGIS Consortium (OGC), is an international consortium of more than 250 compa-
nies, agencies, universities participating in the development of publicly available conceptual
solutions that can be useful with all kinds of applications that manage spatial data. See
http://www.opengis.org/.
In 1997, the OpenGIS Consortium published the OpenGIS (r) Simple Features
Specifications For SQL, which proposes several conceptual ways for extending an SQL
RDBMS to support spatial data. MySQL implements a subset of the SQL with Geometry
Types environment proposed by OGC. This term refers to an SQL environment that
has been extended with a set of geometry types. A geometry-valued SQL column is
implemented as a column of a geometry type. The specifications describe a set of SQL
geometry types, as well as functions on those types to create and analyse geometry values.
650 Referência técnica para o MySQL versão 3.23.52
Point examples
Imagine a large-scale map of the world with a lot of cities. A point could represent
each city.
On a city map, a Point could represent a bus stop.
Point properties
X-coordinate value.
Y-coordinate value.
The Boundary of a Point is an empty set.
A Point is defined as zero-dimensional geometry.
Curve properties
Coordinates of its points.
Curve is defined as one-dimensional geometry.
A Curve is simple if it does not pass through the same point twice.
A Curve is closed if its start point is equal to its end point.
The boundary of a closed Curve is empty.
The boundary of a non-closed Curve consists of its two end points.
A Curve that is simple and closed is Ring.
LineString examples
On a world map a LineStrings could represent rivers.
In a city map a LineStrings could represent streets.
LineString properties
Coordinates of LineString segments, defined by each consecutive pair of points.
A LineString is a Line, if it consists of exactly two points.
A LineString is a LinearRing, of it’s both closed and simple.
Chapter 9: Spatial Extensions in MySQL 653
Surface properties
A Surface is defined as a two-dimensional geometry.
The OpenGIS specification defines a simple Surface as consisting of a single ’patch’
that is associated with one ’exterior boundary’ and zero or more ’interior’ boundaries.
The boundary of a simple Surface is the set of closed curves corresponding to its exterior
and interior boundaries.
The only instantiable subclass of Surface defined in OpenGIS specification, is Polygon.
Polygon examples
On a region map: forests, districts, etc.
The assertions for polygons (the rules that define valid polygons) are:
1. The boundary of a Polygon consists of a set of LinearRings (i.e. LineStrings that are
both simple and closed) that make up its exterior and interior boundaries.
2. No two rings in the boundary cross, the rings in the boundary of a Polygon may
intersect at a Point but only as a tangent.
3. A Polygon may not have cut lines, spikes or punctures.
4. The Interior of every Polygon is a connected point set.
5. The Exterior of a Polygon with one or more holes is not connected. Each hole defines
a connected component of the Exterior.
In the above assertions, polygons are simple geometries.
MultiPoint examples
One a world map, a Multipoint could represent a chain of small islands.
MultiPoint properties
MultiPoint is defined as a zero-dimensional geometry.
A MultiPoint is simple if no two Points in the MultiPoint are equal (have identical
coordinate values).
The boundary of a MultiPoint is empty set.
MultiCurve properties
A MultiCurve is simple if and only if all of its elements are simple, the only intersections
between any two elements occur at points that are on the boundaries of both elements.
The boundary of a MultiCurve is obtained by applying the "mod 2 union rule": A
point is in the boundary of a MultiCurve if it is in the boundaries of an odd number
of elements of the MultiCurve.
A MultiCurve is defined as a one-dimensional geometry.
A MultiCurve is closed if all of its elements are closed.
The boundary of a closed MultiCurve is always empty.
MultiLineString examples
On a region map, a MultiLineString could represent a river system or a highway system.
MultiSurface assertions
1. The interiors of any two surfaces in a MultiSurface may not intersect.
2. The boundaries of any two elements in a MultiSurface may intersect at most at a finite
number of points.
The only instantiable subclass of MultiSurface is MultiPolygon.
MultiPolygon examples
On a region map, a MultiPolygon could represent a system of lakes.
MultiPolygon properties
MultiPolygon is defined as two-dimensional geometry.
The boundary of a MultiPolygon is a set of closed curves (LineStrings) corresponding
to the boundaries of its element Polygons.
Each Curve in the boundary of the MultiPolygon is in the boundary of exactly one
element Polygon, and every Curve in the boundary of an element Polygon is in the
boundary of the MultiPolygon.
<Polygon Text> := EMPTY | ( <LineString Text > {, < LineString Text > }*
<Multipoint Text> := EMPTY | ( <Point Text > {, <Point Text > }* )
<MultiLineString Text> := EMPTY | ( <LineString Text > {, < LineString Text > }*
<MultiPolygon Text> := EMPTY | ( < Polygon Text > {, < Polygon Text > }* )
<GeometryCollection Text> := EMPTY | ( <Geometry Tagged Text> {, <Geometry Tagged Te
WKBGeometryCollection collection;
WKBMultiPoint mpoint;
WKBMultiLineString mlinestring;
WKBMultiPolygon mpolygon;
}
}
WKBGeometryCollection
{
byte byte_order;
uint32 wkbType; // 7
uint32 num_wkbGeometries;
WKBGeometry wkbGeometries[num_wkbGeometries];
}
Boundary(g:Geometry):Geometry
Returns the closure of the combinatorial boundary of this Geometry.
IsEmpty(geometry g):Integer
Returns 1 (TRUE) if this Geometry is the empty geometry. If true, then this
Geometry represents the empty point set.
IsSimple(geometry g):Integer
Returns 1 (TRUE) if this Geometry has no anomalous geometric points, such as
self intersection or self tangency. The description of each instantiable geometric
class includes the specific conditions that cause an instance of that class to be
classified as not simple.
+------------------------------------------------------------
----------------------------+
|
+------------------------------------------------------------
----------------------------+
1 row in set (0.00 sec)
ExteriorRing(Polygon p):LineString
Returns the exterior ring of this Polygon as a LineString.
mysql> SELECT AsText(ExteriorRing(GeomFromText(’Polygon((0 0,0 3,3 3,3 0,0
+------------------------------------------------------------
--------------------------------+
| AsText(ExteriorRing(GeomFromText(’Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1 2
+------------------------------------------------------------
--------------------------------+
| LINESTRING(0 0,0 3,3 3,3 0,0 0)
+------------------------------------------------------------
--------------------------------+
InteriorRingN(Polygon p, Integer N):LineString
Returns the N-th interior ring for this Polygon as a LineString.
mysql> SELECT AsText(InteriorRingN(GeomFromText(’Polygon((0 0,0 3,3 3,3 0,
+------------------------------------------------------------
-----------------------------------+
| AsText(InteriorRingN(GeomFromText(’Polygon((0 0,0 3,3 3,3 0,0 0),(1 1,1
+------------------------------------------------------------
-----------------------------------+
| LINESTRING(1 1,1 2,2 2,2 1,1 1)
+------------------------------------------------------------
-----------------------------------+
Note: MySQL does not yet implement the following functions:
Centroid(Polygon p):Point
The mathematical centroid for this Polygon as a Point. The result is not guar-
anteed to be on this Polygon.
PointOnSurface(p:Polygon):Point
A point guaranteed to be on this Polygon.
|
+------------------------------------------------------------
-----------------------+
Note: MySQL does not yet implement the following functions:
Centroid(MultyPolygon p):Point
The mathematical centroid for this MultiPolygon as a Point. The result is not
guaranteed to be on this MultiPolygon.
PointOnSurface(MultiPolygon m):Point
A Point guaranteed to be on this MultiPolygon.
Envelope(geometry g):geometry
StartPoint(LineString l):Point
EndPoint(LineString l):Point
PointN(LineString l,integer n):Point
ExteriorRing(Polygon p):LineString
InteriorRingN(Polygon p, Integer N):LineString
GeometryN(GeometryCollection g,integer N):Geometry
Crosses(geom1,geom2)
Returns 1 if geom1 spatially crosses geom2. If geom1 is a polygon or a multipoly-
gon, NULL is returned. If geom2 is a point or a multipoint, NULL is returned.
Otherwise 0 is returned.
The term spatially crosses denotes a spatial relation when two given geome-
tries intersect, and their intersection results in a geometry that has a dimension
that is one less than the maximum dimension of the two given geometries, and
the intersection is not equal to any of the two given geometries.
Disjoint(geom1,geom2)
Returns 1 if geom1 is spatially disjoint from geom2, i.e. if given geometries do
not intersect. Otherwise, 0 is returned.
Equal(geom1,geom2)
Returns 1 if geom1 is spatially equal to geom2, otherwise 0 is returned.
Intersects(geom1,geom2)
Returns 1 if geom1 spatially intersects geom2, otherwise 0 is returned.
Overlaps(geom1,geom2)
Returns 1 if geom1 spatially overlaps geom2, otherwise, 0 is returned. Term
spatially overlaps is used if two geometries intersect and their intersection
results in a geometry of the same dimension but not equal to either of the given
geometries.
Touches(geom1,geom2)
Returns 1 if geom1 spatially touches geom2, otherwise, 0 is returned. Two
geometries spatially touch if the interior of both geometries do not intersect,
but the boundary of one of the geometries intersects either the boundary or the
interioir of the geometries.
Within(geom1,geom2)
Returns 1 if geom1 is spatially within geom2, otherwise, 0 is returned.
Distance(geom1:Geometry,geom2:Geometry):Double
The shortest distance between any two points in the two geometries.
| fid | AsText(g)
+-----+----------------------------------------------------------------
-------------+
| 21 | LINESTRING(30350.4 15828.8,30350.6 15845,30333.8 15845,30333.8 15828.8)
| 22 | LINESTRING(30350.6 15871.4,30350.6 15887.8,30334 15887.8,30334 15871.4)
| 23 | LINESTRING(30350.6 15914.2,30350.6 15930.4,30334 15930.4,30334 15914.2)
| 24 | LINESTRING(30290.2 15823,30290.2 15839.4,30273.4 15839.4,30273.4 15823)
| 25 | LINESTRING(30291.4 15866.2,30291.6 15882.4,30274.8 15882.4,30274.8 15866.2)
| 26 | LINESTRING(30291.6 15918.2,30291.6 15934.4,30275 15934.4,30275 15918.2)
| 249 | LINESTRING(30337.8 15938.6,30337.8 15946.8,30320.4 15946.8,30320.4 15938.4)
| 1 | LINESTRING(30250.4 15129.2,30248.8 15138.4,30238.2 15136.4,30240 15127.2)
| 2 | LINESTRING(30220.2 15122.8,30217.2 15137.8,30207.6 15136,30210.4 15121)
| 3 | LINESTRING(30179 15114.4,30176.6 15129.4,30167 15128,30169 15113)
| 4 | LINESTRING(30155.2 15121.4,30140.4 15118.6,30142 15109,30157 15111.6)
| 5 | LINESTRING(30192.4 15085,30177.6 15082.2,30179.2 15072.4,30194.2 15075.2)
| 6 | LINESTRING(30244 15087,30229 15086.2,30229.4 15076.4,30244.6 15077)
| 7 | LINESTRING(30200.6 15059.4,30185.6 15058.6,30186 15048.8,30201.2 15049.4)
| 10 | LINESTRING(30179.6 15017.8,30181 15002.8,30190.8 15003.6,30189.6 15019)
| 11 | LINESTRING(30154.2 15000.4,30168.6 15004.8,30166 15014.2,30151.2 15009.8)
| 13 | LINESTRING(30105 15065.8,30108.4 15050.8,30118 15053,30114.6 15067.8)
| 154 | LINESTRING(30276.2 15143.8,30261.4 15141,30263 15131.4,30278 15134)
| 155 | LINESTRING(30269.8 15084,30269.4 15093.4,30258.6 15093,30259 15083.4)
| 157 | LINESTRING(30128.2 15011,30113.2 15010.2,30113.6 15000.4,30128.8 15001)
+-----+----------------------------------------------------------------
-------------+
20 rows in set (0.00 sec)
Now let’s check the way this query is executed, using EXPLAIN:
mysql> EXPLAIN SELECT fid,AsText(g) FROM g WHERE
mysql> MBRContains(GeomFromText(’Polygon((30000 15000,31000 15000,31000 16000,30000
+----+-------------+-------+-------+---------------+------+---------+--
----+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows |
+----+-------------+-------+-------+---------------+------+---------+--
----+------+-------------+
| 1 | SIMPLE | g | range | g | g | 32 | NULL | 50 |
+----+-------------+-------+-------+---------------+------+---------+--
----+------+-------------+
1 row in set (0.00 sec)
Now let’s check what would happen if we didn’t have a spatial index:
mysql> EXPLAIN SELECT fid,AsText(g) FROM g IGNORE INDEX (g) WHERE
mysql> MBRContains(GeomFromText(’Polygon((30000 15000,31000 15000,31000 16000,30000
+----+-------------+-------+------+---------------+------+---------+---
---+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows |
+----+-------------+-------+------+---------------+------+---------+---
---+-------+-------------+
| 1 | SIMPLE | g | ALL | NULL | NULL | NULL | NULL | 32376 |
676 Referência técnica para o MySQL versão 3.23.52
+----+-------------+-------+------+---------------+------+---------+---
---+-------+-------------+
1 row in set (0.00 sec)
Lets execute the above query, ignoring the spatial key we have:
The execution time for this query rises from 0.00 seconds to 0.46 seconds, when the index
is not used.
In the future releases, spatial indexes will also be used for optimising other functions. See
hundefinedi [GIS functions for testing spatial relations between geometric objects], page hun-
definedi.
10 Extending MySQL
developers, to do regression tests on the MySQL code. To address this problem, we have
created a new test system that is included in the source and binary distributions starting
in Version 3.23.29.
The current set of test cases doesn’t test everything in MySQL, but it should catch most
obvious bugs in the SQL processing code, OS/library issues, and is quite thorough in testing
replication. Our eventual goal is to have the tests cover 100% of the code. We welcome
contributions to our test suite. You may especially want to contribute tests that examine
the functionality critical to your system, as this will ensure that all future MySQL releases
will work well with your applications.
• To be consistent with our setup, you should put your result files in mysql-test/r
directory and name them test_name.result. If the test produces more than one
result, you should use test_name.a.result, test_name.b.result, etc.
• If a statement returns an error, you should on the line before the statement specify with
the --error error-number. The error number can be a list of possible error numbers
separated with ’,’.
• If you are writing a replication test case, you should on the first line of the test file,
put source include/master-slave.inc;. To switch between master and slave, use
connection master; and connection slave;. If you need to do something on an al-
ternate connection, you can do connection master1; for the master, and connection
slave1; for the slave.
• If you need to do something in a loop, you can use something like this:
let $1=1000;
while ($1)
{
# do your queries here
dec $1;
}
• To sleep between queries, use the sleep command. It supports fractions of a second,
so you can do sleep 1.3;, for example, to sleep 1.3 seconds.
• To run the slave with additional options for your test case, put them in the command-
line format in mysql-test/t/test_name-slave.opt. For the master, put them in
mysql-test/t/test_name-master.opt.
• If you have a question about the test suite, or have a test case to contribute, e-mail
to [email protected]. As the list does not accept attachments, you should
ftp all the relevant files to: ftp://support.mysql.com/pub/mysql/Incoming/
• If you have compiled MySQL yourself, check our manual for how to compile MySQL
on your platform or, preferable, use one of the binaries we have compiled for you at
http://www.mysql.com/downloads/. All our standard binaries should pass the test
suite !
• If you get an error, like Result length mismatch or Result content mismatch it
means that the output of the test didn’t match exactly the expected output. This
could be a bug in MySQL or that your mysqld version produces slight different results
under some circumstances.
Failed test results are put in a file with the same base name as the result file with the
.reject extension. If your test case is failing, you should do a diff on the two files. If
you cannot see how they are different, examine both with od -c and also check their
lengths.
• If a test fails totally, you should check the logs file in the mysql-test/var/log directory
for hints of what went wrong.
• If you have compiled MySQL with debugging you can try to debug this by running
mysql-test-run with the --gdb and/or --debug options. See hundefinedi [Making
trace files], page hundefinedi.
If you have not compiled MySQL for debugging you should probably do that. Just
specify the --with-debug options to configure! See hundefinedi [Installing source],
page hundefinedi.
STRING char *
INTEGER long long
REAL double
xxx_init() (optional)
The initialisation function for xxx(). It can be used to:
• Check the number of arguments to XXX().
• Check that the arguments are of a required type or, alternatively, tell
MySQL to coerce arguments to the types you want when the main function
is called.
• Allocate any memory required by the main function.
• Specify the maximum length of the result.
• Specify (for REAL functions) the maximum number of decimals.
• Specify whether the result can be NULL.
xxx_deinit() (optional)
The deinitialisation function for xxx(). It should deallocate any memory allo-
cated by the initialisation function.
When a SQL statement invokes XXX(), MySQL calls the initialisation function xxx_init()
to let it perform any required setup, such as argument checking or memory allocation. If
xxx_init() returns an error, the SQL statement is aborted with an error message and the
main and deinitialisation functions are not called. Otherwise, the main function xxx() is
called once for each row. After all rows have been processed, the deinitialisation function
xxx_deinit() is called so it can perform any required cleanup.
For aggregate functions (like SUM()), you must also provide the following functions:
xxx_reset() (required)
Reset sum and insert the argument as the initial value for a new group.
xxx_add() (required)
Add the argument to the old sum.
When using aggregate UDF functions MySQL works the following way:
1. Call xxx_init() to let the aggregate function allocate the memory it will need to store
results.
2. Sort the table according to the GROUP BY expression.
3. For the first row in a new group, call the xxx_reset() function.
4. For each new row that belongs in the same group, call the xxx_add() function.
5. When the group changes or after the last row has been processed, call xxx() to get the
result for the aggregate.
6. Repeat 3-5 until all rows has been processed
7. Call xxx_deinit() to let the UDF free any memory it has allocated.
All functions must be thread-safe (not just the main function, but the initialisation and
deinitialisation functions as well). This means that you are not allowed to allocate any
global or static variables that change! If you need memory, you should allocate it in xxx_
init() and free it in xxx_deinit().
684 Referência técnica para o MySQL versão 3.23.52
initid->ptr = allocated_memory;
In xxx() and xxx_deinit(), refer to initid->ptr to use or deallocate the
memory.
if (args->arg_count != 2)
{
strcpy(message,"XXX() requires two arguments");
return 1;
}
enum Item_result *arg_type
The types for each argument. The possible type values are STRING_RESULT,
INT_RESULT, and REAL_RESULT.
To make sure that arguments are of a given type and return an error if they
are not, check the arg_type array in the initialisation function. For example:
if (args->arg_type[0] != STRING_RESULT ||
args->arg_type[1] != INT_RESULT)
{
strcpy(message,"XXX() requires a string and an integer");
return 1;
}
As an alternative to requiring your function’s arguments to be of particular
types, you can use the initialisation function to set the arg_type elements to
the types you want. This causes MySQL to coerce arguments to those types for
each call to xxx(). For example, to specify coercion of the first two arguments
to string and integer, do this in xxx_init():
args->arg_type[0] = STRING_RESULT;
args->arg_type[1] = INT_RESULT;
char **args
args->args communicates information to the initialisation function about the
general nature of the arguments your function was called with. For a constant
argument i, args->args[i] points to the argument value. (See below for
instructions on how to access the value properly.) For a non-constant argument,
args->args[i] is 0. A constant argument is an expression that uses only
constants, such as 3 or 4*7-2 or SIN(3.14). A non-constant argument is an
expression that refers to values that may change from row to row, such as
column names or functions that are called with non-constant arguments.
For each invocation of the main function, args->args contains the actual ar-
guments that are passed for the row currently being processed.
Functions can refer to an argument i as follows:
• An argument of type STRING_RESULT is given as a string pointer plus
a length, to allow handling of binary data or data of arbitrary length.
The string contents are available as args->args[i] and the string
length is args->lengths[i]. You should not assume that strings are
null-terminated.
• For an argument of type INT_RESULT, you must cast args->args[i] to a
long long value:
long long int_val;
int_val = *((long long*) args->args[i]);
Chapter 10: Extending MySQL 687
If you inherit your object from any of the standard items (like Item_num_func), you
probably only have to define one of the above functions and let the parent object take
care of the other functions. For example, the Item_str_func class defines a val()
function that executes atof() on the value returned by ::str().
5. You should probably also define the following object function:
void Item_func_newname::fix_length_and_dec()
This function should at least calculate max_length based on the given arguments. max_
length is the maximum number of characters the function may return. This function
should also set maybe_null = 0 if the main function can’t return a NULL value. The
function can check if any of the function arguments can return NULL by checking the
arguments maybe_null variable. You can take a look at Item_func_mod::fix_length_
and_dec for a typical example of how to do this.
All functions must be thread-safe (in other words, don’t use any global or static variables
in the functions without protecting them with mutexes).
If you want to return NULL, from ::val(), ::val_int() or ::str() you should set null_
value to 1 and return 0.
For ::str() object functions, there are some additional considerations to be aware of:
• The String *str argument provides a string buffer that may be used to hold the result.
(For more information about the String type, take a look at the ‘sql_string.h’ file.)
• The ::str() function should return the string that holds the result or (char*) 0 if
the result is NULL.
• All current string functions try to avoid allocating any memory unless absolutely nec-
essary!
description of how the system is behaving and what you think is happening. You should
also state why you think it’s MySQL that is causing the problems. Take into consideration
all the situations in this chapter. State any problems exactly how they appear when you
examine your system. Use the ’cut and paste’ method for any output and/or error messages
from programs and/or log files!
Try to describe in detail which program is not working and all symptoms you see! We have
in the past received many bug reports that just state "the system doesn’t work". This
doesn’t provide us with any information about what could be the problem.
If a program fails, it’s always useful to know:
• Has the program in question made a segmentation fault (core dumped)?
• Is the program taking up the whole CPU? Check with top. Let the program run for a
while, it may be evaluating something heavy.
• If it’s the mysqld server that is causing problems, can you do mysqladmin -u root
ping or mysqladmin -u root processlist?
• What does a client program say (try with mysql, for example) when you try to connect
to the MySQL server? Does the client jam? Do you get any output from the program?
When sending a bug report, you should of follow the outlines described in this manual. See
hundefinedi [Asking questions], page hundefinedi.
The error (2002) Can’t connect to ... normally means that there isn’t a MySQL server
running on the system or that you are using a wrong socket file or TCP/IP port when
trying to connect to the mysqld server.
Start by checking (using ps or the task manager on Windows) that there is a process running
named mysqld on your server! If there isn’t any mysqld process, you should start one. See
hundefinedi [Starting server], page hundefinedi.
If a mysqld process is running, you can check the server by trying these different connections
(the port number and socket pathname might be different in your setup, of course):
shell> mysqladmin version
shell> mysqladmin variables
shell> mysqladmin -h ‘hostname‘ version variables
shell> mysqladmin -h ‘hostname‘ --port=3306 version
shell> mysqladmin -h ’ip for your host’ version
shell> mysqladmin --protocol=socket --socket=/tmp/mysql.sock version
Note the use of backquotes rather than forward quotes with the hostname command; these
cause the output of hostname (that is, the current hostname) to be substituted into the
mysqladmin command.
Here are some reasons the Can’t connect to local MySQL server error might occur:
• mysqld is not running.
• You are running on a system that uses MIT-pthreads. If you are running on a system
that doesn’t have native threads, mysqld uses the MIT-pthreads package. See hunde-
finedi [Which OS], page hundefinedi. However, not all MIT-pthreads versions support
Unix sockets. On a system without sockets support you must always specify the host-
name explicitly when connecting to the server. Try using this command to check the
connection to the server:
shell> mysqladmin -h ‘hostname‘ version
• Someone has removed the Unix socket that mysqld uses (default ‘/tmp/mysqld.sock’).
You might have a cron job that removes the MySQL socket (for example, a job that
removes old files from the ‘/tmp’ directory). You can always run mysqladmin version
and check that the socket mysqladmin is trying to use really exists. The fix in this
case is to change the cron job to not remove ‘mysqld.sock’ or to place the socket
somewhere else. See hundefinedi [Problems with mysql.sock], page hundefinedi.
• You have started the mysqld server with the --socket=/path/to/socket option. If
you change the socket pathname for the server, you must also notify the MySQL clients
about the new path. You can do this by providing the socket path as an argument to
the client. See hundefinedi [Problems with mysql.sock], page hundefinedi.
• You are using Linux and one thread has died (core dumped). In this case you must
kill the other mysqld threads (for example, with the mysql_zap script before you can
start a new MySQL server. See hundefinedi [Crashing], page hundefinedi.
• You may not have read and write privilege to either the directory that holds the socket
file or privilege to the socket file itself. In this case you have to either change the
privilege for the directory / file or restart mysqld so that it uses a directory that you
can access.
If you get the error message Can’t connect to MySQL server on some_hostname, you can
try the following things to find out what the problem is :
696 Referência técnica para o MySQL versão 3.23.52
tables you used in the transaction didn’t support transactions. These non-transactional
tables will not be affected by the ROLLBACK statement.
The most typical case when this happens is when you have tried to create a table of a type
that is not supported by your mysqld binary. If mysqld doesn’t support a table type (or if
the table type is disabled by a startup option) , it will instead create the table type with
the table type that is most resembles to the one you requested, probably MyISAM.
You can check the table type for a table by doing:
SHOW TABLE STATUS LIKE ’table_name’. See hundefinedi [SHOW TABLE STATUS],
page hundefinedi.
You can check the extensions your mysqld binary supports by doing:
show variables like ’have_%’. See hundefinedi [SHOW VARIABLES], page hundefinedi.
set this variable. Please note that --set-variable is deprecated since MySQL 4.0, just
use --max-allowed-packet=8M instead.
You can use the option file to set max_allowed_packet to a larger size in mysqld. For
example, if you are expecting to store the full length of a MEDIUMBLOB into a table, you’ll
need to start the server with the set-variable=max_allowed_packet=16M option.
You can also get strange problems with large packets if you are using big blobs, but you
haven’t given mysqld access to enough memory to handle the query. If you suspect this
is the case, try adding ulimit -d 256000 to the beginning of the safe_mysqld script and
restart mysqld.
• max_allowed_packet is too small or queries require more memory than you have allo-
cated for mysqld. See hundefinedi [Packet too large], page hundefinedi.
shell> perror 28
Error code 28: No space left on device
old mysqld version that doesn’t support this, you can edit the safe_mysqld script. There
is a commented-out line ulimit -n 256 in the script. You can remove the ’#’ character to
uncomment this line, and change the number 256 to affect the number of file descriptors
available to mysqld.
ulimit (and open-files-limit) can increase the number of file descriptors, but only up
to the limit imposed by the operating system. There is also a ’hard’ limit that can only
be overridden if you start safe_mysqld or mysqld as root (just remember that you need
to also use the --user=... option in this case). If you need to increase the OS limit on
the number of file descriptors available to each process, consult the documentation for your
operating system.
Note that if you run the tcsh shell, ulimit will not work! tcsh will also report incorrect
values when you ask for the current limits! In this case you should start safe_mysqld with
sh!
• Add the path to the directory where you have ‘libmysqlclient.so’ the LD_LIBRARY_
PATH environment variable.
• Add the path to the directory where you have ‘libmysqlclient.so’ the LD_LIBRARY
environment variable.
• Copy ‘libmysqlclient.so’ to some place that is searched by your system, like ‘/lib’,
and update the shared library information by executing ldconfig.
Another way to solve this problem is to link your program statically, with -static, or by
removing the dynamic MySQL libraries before linking your code. In the second case you
should be sure that no other programs are using the dynamic libraries!
on the same data and that you must be careful if you use myisamchk, but it may be
instructive to try the option as a test.)
• Have you tried mysqladmin -u root processlist when mysqld appears to be running
but not responding? Sometimes mysqld is not comatose even though you might think
so. The problem may be that all connections are in use, or there may be some internal
lock problem. mysqladmin processlist will usually be able to make a connection
even in these cases, and can provide useful information about the current number of
connections and their status.
• Run the command mysqladmin -i 5 status or mysqladmin -i 5 -r status or in a
separate window to produce statistics while you run your other queries.
• Try the following:
1. Start mysqld from gdb (or in another debugger). See hundefinedi [Using gdb on
mysqld], page hundefinedi.
2. Run your test scripts.
3. Print the backtrace and the local variables at the 3 lowest levels. In gdb you can
do this with the following commands when mysqld has crashed inside gdb:
backtrace
info local
up
info local
up
info local
With gdb you can also examine which threads exist with info threads and switch
to a specific thread with thread #, where # is the thread id.
• Try to simulate your application with a Perl script to force MySQL to crash or misbe-
have.
• Send a normal bug report. See hundefinedi [Bug reports], page hundefinedi. Be even
more detailed than usual. Because MySQL works for many people, it may be that the
crash results from something that exists only on your computer (for example, an error
that is related to your particular system libraries).
• If you have a problem with tables with dynamic-length rows and you are not using
BLOB/TEXT columns (but only VARCHAR columns), you can try to change all VARCHAR
to CHAR with ALTER TABLE. This will force MySQL to use fixed-size rows. Fixed-size
rows take a little extra space, but are much more tolerant to corruption!
The current dynamic row code has been in use at MySQL AB for at least 3 years
without any problems, but by nature dynamic-length rows are more prone to errors,
so it may be a good idea to try the above to see if it helps!
1. Take down the mysqld server by sending a kill (not kill -9) to the mysqld server.
The pid is stored in a ‘.pid’ file, which is normally in the MySQL database directory:
shell> kill ‘cat /mysql-data-directory/hostname.pid‘
You must be either the Unix root user or the same user mysqld runs as to do this.
2. Restart mysqld with the --skip-grant-tables option.
3. Set a new password with the mysqladmin password command:
shell> mysqladmin -u root password ’mynewpassword’
4. Now you can either stop mysqld and restart it normally, or just load the privilege tables
with:
shell> mysqladmin -h hostname flush-privileges
5. After this, you should be able to connect using the new password.
Alternatively, you can set the new password using the mysql client:
1. Take down and restart mysqld with the --skip-grant-tables option as described
above.
2. Connect to the mysqld server with:
shell> mysql -u root mysql
3. Issue the following commands in the mysql client:
mysql> UPDATE user SET Password=PASSWORD(’mynewpassword’)
-> WHERE User=’root’;
mysql> FLUSH PRIVILEGES;
4. After this, you should be able to connect using the new password.
5. You can now stop mysqld and restart it normally.
[mysqld]
socket=path-for-socket-file
See hundefinedi [Option files], page hundefinedi.
Appendix A: Problems and Common Errors 709
• Specifying this on the command-line to safe_mysqld and most clients with the --
socket=path-for-socket-file option.
• Specify the path to the socket in the MYSQL_UNIX_PORT environment variable.
• Defining the path with the configure option --with-unix-socket-path=path-for-
socket-file. See hundefinedi [configure options], page hundefinedi.
You can test that the socket works with this command:
shell> mysqladmin --socket=/path/to/socket version
form when updating and in a WHERE clause that compares a date to a TIMESTAMP, DATE, or a
DATETIME column. (Relaxed form means that any punctuation character may be used as the
separator between parts. For example, ’1998-08-15’ and ’1998#08#15’ are equivalent.)
MySQL can also convert a string containing no separators (such as ’19980815’), provided
it makes sense as a date.
The special date ’0000-00-00’ can be stored and retrieved as ’0000-00-00’. When using
a ’0000-00-00’ date through MyODBC, it will automatically be converted to NULL in MyODBC
Version 2.50.12 and above, because ODBC can’t handle this kind of date.
Because MySQL performs the conversions described above, the following statements work:
mysql> INSERT INTO nome_tabela (idate) VALUES (19970505);
mysql> INSERT INTO nome_tabela (idate) VALUES (’19970505’);
mysql> INSERT INTO nome_tabela (idate) VALUES (’97-05-05’);
mysql> INSERT INTO nome_tabela (idate) VALUES (’1997.05.05’);
mysql> INSERT INTO nome_tabela (idate) VALUES (’1997 05 05’);
mysql> INSERT INTO nome_tabela (idate) VALUES (’0000-00-00’);
SELECT id,COUNT(*) AS cnt FROM table_name WHERE cnt > 0 GROUP BY id;
The WHERE statement is executed to determine which rows should be included in the GROUP
BY part while HAVING is used to decide which rows from the result set should be used.
| i | a | b |
+------+----------------------+-------+
| 1 | 21.3999999999999986 | 21.40 |
| 2 | 76.7999999999999972 | 76.80 |
| 3 | 7.4000000000000004 | 7.40 |
| 4 | 15.4000000000000004 | 15.40 |
| 5 | 7.2000000000000002 | 7.20 |
| 6 | -51.3999999999999986 | 0.00 |
+------+----------------------+-------+
Depending on the computer architecture you may or may not see similar results. Each CPU
may evaluate floating-point numbers differently. For example in some machines you may
get ’right’ results by multiplaying both arguments with 1, an example follows.
WARNING: NEVER TRUST THIS METHOD IN YOUR APPLICATION, THIS IS AN
EXAMPLE OF A WRONG METHOD!!!
mysql> SELECT i, ROUND(SUM(d1), 2)*1 AS a, ROUND(SUM(d2), 2)*1 AS b
-> FROM t1 GROUP BY i HAVING a <> b;
+------+--------+------+
| i | a | b |
+------+--------+------+
| 6 | -51.40 | 0.00 |
+------+--------+------+
The reason why the above example seems to be working is that on the particular machine
where the test was done, the CPU floating-point arithmetics happens to round the numbers
to same, but there is no rule that any CPU should do so, so it cannot be trusted.
The correct way to do floating-point number comparison is to first decide on what is the
wanted tolerance between the numbers and then do the comparison against the tolerance
number. For example, if we agree on that floating-point numbers should be regarded the
same, if they are same with precision of one of ten thousand (0.0001), the comparison should
be done like this:
mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
-> GROUP BY i HAVING ABS(a - b) > 0.0001;
+------+--------+------+
| i | a | b |
+------+--------+------+
| 6 | -51.40 | 0.00 |
+------+--------+------+
1 row in set (0.00 sec)
And vice versa, if we wanted to get rows where the numbers are the same, the test would
be:
mysql> SELECT i, SUM(d1) AS a, SUM(d2) AS b FROM t1
-> GROUP BY i HAVING ABS(a - b) < 0.0001;
+------+-------+-------+
| i | a | b |
+------+-------+-------+
| 1 | 21.40 | 21.40 |
| 2 | 76.80 | 76.80 |
| 3 | 7.40 | 7.40 |
Appendix A: Problems and Common Errors 715
| 4 | 15.40 | 15.40 |
| 5 | 7.20 | 7.20 |
+------+-------+-------+
You should never, in an application, use SELECT * and retrieve the columns based on their
position, because the order and position in which columns are returned cannot may not
remain the same (if you add/move/delete columns). A simple change to your database
structure would then cause your application to fail. Of course SELECT * is quite suitable
for testing queries.
B.1 APIs
• Perl Modules
− http://www.mysql.com/Downloads/Contrib/KAMXbase1.2.tar.gz Convert
between ‘.dbf’ files and MySQL tables. Perl module written by Pratap
Pereira [email protected], extended by Kevin A. McGrail
[email protected]. This converter can handle MEMO fields.
− http://www.mysql.com/Downloads/Contrib/HandySQL-1.1.tar.gz HandySQL
is a MySQL access module. It offers a C interface embedded in Perl and is ap-
proximately 20% faster than regular DBI.
• OLEDB
• http://www.mysql.com/Downloads/Win32/MyOLEDB3.exe MyOLEDB 3.0 instal-
lation package from SWSoft.
• http://www.mysql.com/Downloads/Win32/mysql-oledb-3.0.0.zip Source for
MyOLEDB 3.0.
• http://www.mysql.com/Downloads/Win32/MySamples.zip Examples and docu-
mentation for MyOLEDB.
• http://www.mysql.com/Downloads/Win32/MyOLEDB.chm Help files for
MyOLEDB.
• http://www.mysql.com/Downloads/Win32/libmyodbc.zip Static MyODBC li-
brary used for build MyOLEDB. Based on MyODBC code.
• C++
• http://www.mysql.com/Downloads/Contrib/mysql-c++-0.02.tar.gz MySQL
C++ wrapper library. By Roland Haenel, [email protected].
• http://www.mysql.com/Downloads/Contrib/MyDAO.tar.gz MySQL C++ API.
By Satish [email protected]. Inspired by Roland Haenel’s C++ API
and Ed Carp’s MyC library.
718 Referência técnica para o MySQL versão 3.23.52
B.2 Converters
• http://www.mysql.com/Downloads/Contrib/mssql2mysql.txt Converter from
720 Referência técnica para o MySQL versão 3.23.52
on, but the table is just a bit different (that is - fields in different order, etc.). By Steve
Shreeve.
• http://www.mysql.com/Downloads/Contrib/oracledump Perl program to convert
Oracle databases to MySQL. Has same output format as mysqldump. By Johan
Andersson.
• http://www.mysql.com/Downloads/Contrib/excel2mysql Perl program
to import Excel spreadsheets into a MySQL database. By Stephen Hurd
[email protected]
• http://www.mysql.com/Downloads/Contrib/T2S_100.ZIP. Windows program to
convert text files to MySQL databases. By Asaf Azulay.
B.3 Utilities
• http://worldcommunity.com/opensource/utilities/mysql_backup.html MySQL
Backup is a backup script for MySQL. By Peter F. Brown.
• http://www.mysql.com/Downloads/Contrib/mysql_watchdog.pl Monitor the
MySQL daemon for possible lockups. By Yermo Lamers, [email protected].
• http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tar.gz
• http://www.mysql.com/Downloads/Contrib/mysql_structure_dumper.tgz Prints
the structure of every table in a database. By Thomas Wana.
• http://www.mysql.com/Downloads/Contrib/mysqlsync. A Perl script to keep re-
mote copies of a MySQL database in sync with a central master copy. By Mark
Jeftovic. [email protected].
• http://www.mysql.com/Downloads/Contrib/MySQLTutor-0.2.tar.gz. MySQL-
Tutor. A MySQL tutorial for beginners.
• http://www.mysql.com/Downloads/Contrib/MySQLDB.zip
• http://www.mysql.com/Downloads/Contrib/MySQLDB-readme.html. A COM
library for MySQL by Alok Singh.
• http://www.mysql.com/Downloads/Contrib/mysql_replicate.pl Perl program
that handles replication. By [email protected]
• http://www.mysql.com/Downloads/Contrib/DBIx-TextIndex-0.02.tar.gz Perl
script that uses reverse indexing to handle text searching. By Daniel Koch.
• http://www.mysql.com/Downloads/Contrib/dbcheck Perl script that takes a backup
of tables before running isamchk on them. By Elizabeth.
• http://www.mysql.com/Downloads/Contrib/mybackup.
• http://www.mswanson.com/mybackup (mybackup home page) Wrapper for
mysqldump to backup all databases. By Marc Swanson.
• http://www.mysql.com/Downloads/Contrib/mdu.pl.gz Prints the storage usage of
a MySQL database.
722 Referência técnica para o MySQL versão 3.23.52
Appendix C Credits
This appendix lists the developers, contributors, and supporters that have helped to make
MySQL what it is today.
Jani Tolonen
• mysqlimport
• A lot of extensions to the command-line clients.
• PROCEDURE ANALYSE()
Sinisa Milivojevic
• Compression (with zlib) in the client/server protocol.
• Perfect hashing for the lexical analyser phase.
• Multi-row INSERT
• mysqldump -e option
• LOAD DATA LOCAL INFILE
• SQL_CALC_FOUND_ROWS SELECT option
• --max-user-connections=... option
• net_read and net_write_timeout
• GRANT/REVOKE and SHOW GRANTS FOR
• New client-server protocol for 4.0
• UNION in 4.0
• Multi-table DELETE/UPDATE
• Derived tables in 4.1
• User resources management
• Initial developer of the MySQL++ C++ API and the MySQLGUI client.
Tonu Samuel (past developer)
• VIO interface (the foundation for the encrypted client/server protocol).
• MySQL Filesystem (a way to use MySQL databases as files and directo-
ries).
• The CASE expression.
• The MD5() and COALESCE() functions.
• RAID support for MyISAM tables.
Sasha Pachev
• Initial implementation of replication (up to version 4.0).
• SHOW CREATE TABLE.
• mysql-bench
Matt Wagner
• MySQL test suite.
• Webmaster (until 2002).
• Coordinator of development.
Miguel Solorzano
• Win32 development and release builds.
• Windows NT server code.
• WinMySQLAdmin
Timothy Smith (past developer)
• Dynamic character sets support.
724 Referência técnica para o MySQL versão 3.23.52
Marc Liyanage
Maintaining the Mac OS X packages and providing invaluable feedback on how
to create Mac OS X PKGs.
Other contributors, bugfinders, and testers: James H. Thompson, Maurizio Menghini, Wo-
jciech Tryc, Luca Berra, Zarko Mocnik, Wim Bonis, Elmar Haneke, jehamby@lightside,
[email protected], [email protected], Ted Deppner [email protected], Mike
Simons, Jaakko Hyvatti.
And lots of bug report/patches from the folks on the mailing list.
A big tribute goes to those that help us answer questions on the [email protected]
mailing list:
Daniel Koch [email protected]
Irix setup.
Luuk de Boer [email protected]
Benchmark questions.
Tim Sailer [email protected]
DBD-mysql questions.
Boyd Lynn Gerber [email protected]
SCO-related questions.
Richard Mehalick [email protected]
xmysql-related questions and basic installation questions.
Zeev Suraski [email protected]
Apache module configuration questions (log & auth), PHP-related questions,
SQL syntax-related questions and other general questions.
Francesc Guasch [email protected]
General questions.
Jonathan J Smith [email protected]
Questions pertaining to OS-specifics with Linux, SQL syntax, and other things
that might need some work.
David Sklar [email protected]
Using MySQL from PHP and Perl.
Alistair MacDonald [email protected]
Not yet specified, but is flexible and can handle Linux and maybe HP-UX. Will
try to get user to use mysqlbug.
John Lyon [email protected]
Questions about installing MySQL on Linux systems, using either ‘.rpm’ files
or compiling from source.
Lorvid Ltd. [email protected]
Simple billing/license/support/copyright issues.
Patrick Sherrill [email protected]
ODBC and VisualC++ interface questions.
Appendix C: Credits 731
• Support for OpenGIS (Geographical data). See hundefinedi [GIS spatial extensions in
MySQL], page hundefinedi.
• SHOW WARNINGS shows warnings for the last command. See hundefinedi [SHOW WARN-
INGS], page hundefinedi.
• Faster binary protocol with prepared statements and parameter binding. See hunde-
finedi [C API Prepared statements], page hundefinedi.
• Multi-line queries: You can now issue several queries at once and then read the results
in one go. See hundefinedi [C API multiple queries], page hundefinedi.
• Create Table: CREATE [TEMPORARY] TABLE [IF NOT EXISTS] table LIKE table.
• Server based HELP command that can be used in the mysql command line client (and
other clients) to get help for SQL commands.
For a full list of changes, please refer to the changelog sections for each individual 4.1.x
release.
One can specify the different BLOB/TEXT types with the syntax BLOB(length) and
TEXT(length). MySQL will automatically change it to one of the internal BLOB/TEXT
types.
CHAR BYTE is an alias for CHAR BINARY.
VARCHARACTER is an alias for VARCHAR.
New operators integer MOD integer and integer DIV integer.
SERIAL DEFAULT VALUE added as an alias for AUTO_INCREMENT.
TRUE and FALSE added as alias for 1 and 0, respectively.
Aliases are now forced in derived tables, as per SQL-99.
Fixed SELECT .. LIMIT 0 to return proper row count for SQL_CALC_FOUND_ROWS.
One can specify many temporary directories to be used in a round-robin fashion with:
--tmpdir=dirname1:dirname2:dirname3.
Subqueries: SELECT * from t1 where t1.a=(SELECT t2.b FROM t2).
Derived tables:
SELECT a.col1, b.col2
FROM (SELECT MAX(col1) AS col1 FROM root_table) a,
other_table b
WHERE a.col1=b.col1;
Character sets to be defined per column, table and database.
Unicode (UTF8) support.
BTREE index on HEAP tables.
Faster embedded server (new internal communication protocol).
One can add a comment per column in CREATE TABLE.
SHOW FULL COLUMNS FROM table_name shows column comments.
ALTER DATABASE.
Support for GIS (Geometrical data). See hundefinedi [GIS spatial extensions in
MySQL], page hundefinedi.
SHOW [COUNT(*)] WARNINGS shows warnings from the last command.
One can specify a column type for a colum in CREATE TABLE ... SELECT by defining
the column in the CREATE part.
CREATE TABLE foo (a tinyint not null) SELECT b+1 AS ’a’ FROM bar;
expr SOUNDS LIKE expr same as SOUNDEX(expr)=SOUNDEX(expr).
VARIANCE(expr) returns the variance of expr
One can create a table from the existing table using CREATE [TEMPORARY] TABLE [IF
NOT EXISTS] table (LIKE table). The table can be either normal or temporary.
New options --reconnect and disable-reconnect for the mysql client, to reconnect
automatically or not if the connection is lost.
START SLAVE (STOP SLAVE) no longer returns an error if the slave is already started
(stopped); it returns a warning instead.
SLAVE START and SLAVE STOP are no longer accepted by the query parser; use START
SLAVE and STOP SLAVE instead.
736 Referência técnica para o MySQL versão 3.23.52
For a full list of changes, please refer to the changelog sections for each individual 4.0.x
release.
Bugs fixed:
LOAD DATA INFILE will now read 000000 as a zero date instead as "2000-00-00".
Fixed bug that caused DELETE FROM table WHERE const_expression always to delete
the whole table (even if expression result was false). (bug #355)
Appendix D: MySQL Change History 737
When using a non-existing table type with CREATE TABLE, first try if the default table
type exists before falling back to MyISAM.
Added MEMORY as an alias for HEAP.
Renamed function rnd to my_rnd as the name was too generic and is an exported
symbol in libmysqlclient (thanks to Dennis Haney for the initial patch).
Portability fix: renamed ‘include/dbug.h’ to ‘include/my_debug.h’.
mysqldump no longer silently deletes the binlogs when called with --master-data or
--first-slave; while this behaviour was convenient for some users, others may suffer
from it. Now one has to explicitely ask for this deletion with the new --delete-
master-logs option.
If the slave is configured (using for example replicate-wild-ignore-
table=mysql.%) to exclude mysql.user, mysql.host, mysql.db, mysql.tables_priv
and mysql.columns_priv from replication, then GRANT and REVOKE will not be
replicated.
Bugs fixed:
Fixed wrong result from truncation operator (*) in MATCH ... AGAINST() in some com-
plex joins.
Fixed a crash in REPAIR ... USE_FRM command, when used on read-only or nonexisting
table.
Fixed a crashing bug in mysql monitor program. It occured if program was started
with --no-defaults, with a prompt that contained hostname and connection to non-
existing db was requested
Fixed problem when comparing a key for a multi-byte-character set. (Bug #152)
Fixed bug in LEFT, RIGHT and MID when used with multi-byte character sets and some
GROUP BY queries. (Bug #314)
Fix problem with ORDER BY being discarded for some DISTINCT queries. (Bug #275)
Fixed some serious bugs in UPDATE ... ORDER BY. (Bug #241)
Fixed unlikely problem in optimising WHERE clause with constant expression like in
WHERE 1 AND (a=1 AND b=1).
Fixed that SET SQL_BIG_SELECTS=1 works again.
Introduced proper backtick quoting for db.table in SHOW GRANTS
Bug #283 (FULLTEXT index stops working after ALTER TABLE that converts TEXT field
to CHAR) fixed.
Mark a MyISAM table as "analyzed" only when all the keys are indeed analyzed.
Only ignore world-writeable ‘my.cnf’ files that are regular files (and not e.g. named
pipes or character devices).
Fixed few smaller issues with SET PASSWORD.
Fixed error message which contained deprecated text.
Fixed a bug with two NATURAL JOINs in the query.
SUM() didn’t return NULL when there was no rows in result or when all values was NULL.
On Unix symbolic links handling was not enabled by default and there was no way to
turn this on.
Appendix D: MySQL Change History 739
Fixed a bug in handling CHAR(0) columns that could cause wrong results from the
query.
Fixed rare bug with wrong initialization of AUTO_INCREMENT column, as a secondary
column in a multi-column key (see AUTO˙INCREMENT-snt [AUTO_INCREMENT on sec-
ondary column in a multi-column key], page AUTO˙INCREMENT-pg), when data was
inserted with INSERT ... SELECT or LOAD DATA into an empty table.
On windows, STOP SLAVE didn’t stop the slave until the slave got one new command
from the master (this bug has been fixed for MySQL 4.0.11 by releasing updated 4.0.11a
windows packages, which include this individual fix on top of the 4.0.11 sources). (bug
#69).
Fixed a crash when no database was selected and LOAD DATA command was issued with
full table name specified, including database prefix.
Fixed a crash when shutting down replication on some platforms (e.g. Mac OS X).
Fixed a portability bug with pthread_attr_getstacksize on HP-UX 10.20 (Patch
was also included in 4.0.11a sources).
Fixed the bigint test to not fail on some platforms (e.g. HP-UX and Tru64) due to
different return values of the atof() function.
Fixed the rpl_rotate_logs test to not fail on certain platforms (e.g. Mac OS X) due
to a too long file name (changed slave-master-info.opt to .slave-mi).
Fixed integer-wraparound when giving big integer (>= 10 digits) to function that re-
quires an unsigned argument, like CREATE TABLE (...) AUTO_INCREMENT=#.
MIN(key_column) could in some cases return NULL on a column with NULL and other
values.
MIN(key_column) and MAX(key_column) could in some cases return wrong values when
used in OUTER JOIN.
MIN(key_column) and MAX(key_column) could return wrong values if one of the tables
was empty.
Fixed rare crash in compressed MyISAM tables with blobs.
Fixed bug in using aggregate functions as argument for INTERVAL, CASE, FIELD,
CONCAT_WS, ELT and MAKE_SET functions.
When running with --lower-case-table-names (default on windows) and you had ta-
bles or databases with mixed case on disk, then executing SHOW TABLE STATUS followed
with DROP DATABASE or DROP TABLE could fail with Errcode 13.
Fixed a bug that caused mysqld to hang when a table was opened with the HANDLER
command and then dropped without being closed.
Fixed bug in logging to binary log (which affects replication) a query that inserts a
NULL in an auto_increment field and also uses LAST_INSERT_ID().
Fixed an unlikely bug that could cause a memory overrun when using ORDER BY
constant_expression.
Fixed a table corruption in ‘myisamchk’’s parallel repair mode.
Fixed bug in query cache invalidation on simple table renaming.
Fixed bug in mysqladmin --relative.
On some 64 bit systems, show status reported a strange number for Open_files and
Open_streams.
Fixed wrong number of columns in EXPLAIN on empty table.
Fixed bug in LEFT JOIN that caused zero rows to be returned in the case the WHERE
condition was evaluated as FALSE after reading const tables. (Unlikely condition).
FLUSH PRIVILEGES didn’t correctly flush table/column privileges when mysql.tables_
priv is empty.
Fixed bug in replication when using LOAD DATA INFILE one a file that updated and
auto increment field with NULL or 0. This bug only affected MySQL 4.0 masters (not
slaves or MySQL 3.23 masters). NOTE: If you have a slave that has replicated a file
with generated auto increment fields then the slave data is corrupted and you should
reinitialise the affected tables from the master.
Fixed possible memory overrun when sending a blob > 16M to the client.
Fixed wrong error message when setting a NOT NULL field to an expression that returned
NULL.
Fixed core dump bug in str LIKE "%other_str%" where str or other_str contained
characters >= 128.
Fixed bug: When executing on master LOAD DATA and InnoDB failed with table full
error the binary log was corrupted.
A security patch in 4.0.8 causes the mysqld server to die if the remote hostname can’t
be resolved. This is now fixed.
Fixed crash when replication big LOAD DATA INFILE statement that caused log rotation.
mysql_server_init() now makes a copy of all arguments. This fixes a problem when
using the embedded server in C# program.
Fixed buffer overrun in libmysqlclient library that allowed a malicious MySQL server
to crash the client application.
Fixed security-related bug in mysql_change_user() handling. All users are strongly
recommended to upgrade to version 4.0.6.
Fixed bug that prevented --chroot command-line option of mysqld from working.
Fixed bug in phrase operator "..." in boolean full-text search.
Fixed bug that caused OPTIMIZE TABLE to corrupt the table under some rare circum-
stances.
Part rewrite of multi-table-update to optimise it, make it safer and more bug free.
LOCK TABLES now works together with multi-table-update and multi-table-delete.
--replicate-do=xxx didn’t work for UPDATE commands. (Bug introduced in 4.0.0)
Fixed shutdown problem on Mac OS X.
Major InnoDB bugs in REPLACE, AUTO_INCREMENT, INSERT INTO ... SELECT ...
were fixed. See the InnoDB changelog in the InnoDB section of the manual.
DELETE FROM myisam_table now shrinks not only the ‘.MYD’ file but also the ‘.MYI’
file.
When one uses the --open-files-limit=# option to mysqld_safe it’s now passed on
to mysqld.
Changed output from EXPLAIN from ’where used’ to ’Using where’ to make it more
in line with other output.
Removed variable safe_show_database as it was no longer used.
Updated source tree to be built using automake 1.5 and libtool 1.4.
Fixed an inadvertently changed option (--ignore-space) back to the original --
ignore-spaces in mysqlclient. (Both syntaxes will work).
Don’t require UPDATE privilege when using REPLACE.
Added support for DROP TEMPORARY TABLE ..., to be used to make replication safer.
When transactions are enabled, all commands that update temporary tables inside a
BEGIN/COMMIT are now stored in the binary log on COMMIT and not stored if one does
ROLLBACK. This fixes some problems with non-transactional temporary tables used
inside transactions.
Allow braces in joins in all positions. Formerly, things like SELECT * FROM (t2 LEFT
JOIN t3 USING (a)), t1 worked, but not SELECT * FROM t1, (t2 LEFT JOIN t3 USING
(a)). Note that braces are simply removed, they do not change the way the join is
executed.
InnoDB now supports also isolation levels READ UNCOMMITTED and READ COMMITTED.
For a detailed InnoDB changelog, see hundefinedi [InnoDB change history], page hun-
definedi in this manual.
Bugs fixed:
Fixed bug in MAX() optimisation when used with JOIN and ON expressions.
Fixed that INSERT DELAY threads don’t hang on Waiting for INSERT when one sends
a SIGHUP to mysqld.
Fixed that MySQL will not use an index scan on an index that has been disabled with
IGNORE INDEX or USE INDEX.
Corrected test for root user in mysqld_safe.
Fixed error message issued when storage engine cannot do CHECK or REPAIR.
Fixed rare core dump problem in complicated GROUP BY queries that didn’t return any
result.
Fixed mysqlshow to work properly with wildcarded database names and with database
names that contain underscores.
Portability fixes to get MySQL to compile cleanly with Sun Forte 5.0.
Fixed MyISAM crash when using dynamic-row tables with huge numbers of packed fields.
Fixed query cache behaviour with BDB transactions.
Fixed possible floating point exception in MATCH relevance calculations.
Fixed bug in full-text search IN BOOLEAN MODE that made MATCH to return incorrect
relevance value in some complex joins.
748 Referência técnica para o MySQL versão 3.23.52
Fixed a bug that limited MyISAM key length to a value slightly less that 500. It is
exactly 500 now.
Fixed that GROUP BY on columns that may have a NULL value doesn’t always use disk
based temporary tables.
The filename argument for the --des-key-file argument to mysqld is interpreted
relative to the data directory if given as a relative pathname.
Removed a condition that temp table with index on column that can be NULL has to
be MyISAM. This was okay for 3.23, but not needed in 4.*. This resulted in slowdown
in many queries since 4.0.2.
Small code improvement in multi-table updates.
Fixed a newly introduced bug that caused ORDER BY ... LIMIT # to not return all rows.
Fixed a bug in multi-table deletes when outer join is used on an empty table, which
gets first to be deleted.
Fixed a bug in multi-table updates when a single table is updated.
Fixed bug that caused REPAIR TABLE and myisamchk to corrupt FULLTEXT indexes.
Fixed bug with caching the mysql grant table database. Now queries in this database
are not cached in the query cache.
Small fix in mysqld_safe for some shells.
Give error if a MyISAM MERGE table has more than 2 ^ 32 rows and MySQL was not
compiled with -DBIG_TABLES.
Fixed some ORDER BY ... DESC problems with InnoDB tables.
• Added XOR operator (logical and bitwise XOR) with ^ as a synonym for bitwise XOR.
• Added function IS_FREE_LOCK("lock_name"). Based on code contributed by Hartmut
Holzgraefe [email protected].
• Removed mysql_ssl_clear() from C API, as it was not needed.
• DECIMAL and NUMERIC types can now read exponential numbers.
• Added SHA1() function to calculate 160 bit hash value as described in RFC 3174
(Secure Hash Algorithm). This function can be considered a cryptographically more
secure equivalent of MD5(). See hundefinedi [Miscellaneous functions], page hundefinedi.
• Added AES_ENCRYPT() and AES_DECRYPT() functions to perform encryption according
to AES standard (Rijndael). See hundefinedi [Miscellaneous functions], page hunde-
finedi.
• Added --single-transaction option to mysqldump, allowing a consistent dump of
InnoDB tables. See hundefinedi [mysqldump], page hundefinedi.
• Fixed bug in innodb_log_group_home_dir in SHOW VARIABLES.
• Fixed a bug in optimiser with merge tables when non-unique values are used in summing
up (causing crashes).
• Fixed a bug in optimiser when a range specified makes index grouping impossible
(causing crashes).
• Fixed a rare bug when FULLTEXT index is present and no tables are used.
• Added privileges CREATE TEMPORARY TABLES, EXECUTE, LOCK TABLES, REPLICATION
CLIENT, REPLICATION SLAVE, SHOW DATABASES and SUPER. To use these, you must
have run the mysql_fix_privilege_tables script after upgrading.
• Fixed query cache align data bug.
• Fixed mutex bug in replication when reading from master fails.
• Added missing mutex in TRUNCATE TABLE; This fixes some core dump/hangup problems
when using TRUNCATE TABLE.
• Fixed bug in multi-table DELETE when optimiser uses only indices.
• Fixed that ALTER TABLE table_name RENAME new_table_name is as fast as RENAME
TABLE.
• Fixed bug in GROUP BY with two or more fields, where at least one field can contain
NULL values.
• Use Turbo Boyer-Moore algorithm to speed up LIKE "%keyword%" searches.
• Fixed bug in DROP DATABASE with symlink.
• Fixed crash in REPAIR ... USE_FRM.
• Fixed bug in EXPLAIN with LIMIT offset != 0.
• Fixed bug in phrase operator "..." in boolean full-text search.
• Fixed bug that caused duplicated rows when using truncation operator * in boolean
full-text search.
• Fixed bug in truncation operator of boolean full-text search (wrong results when there
are only +word*s in the query).
• Fixed bug in boolean full-text search that caused a crash when an identical MATCH
expression that did not use an index appeared twice.
Appendix D: MySQL Change History 753
• Added CAST() and CONVERT() functions. The CAST and CONVERT functions are nearly
identical and mainly useful when you want to create a column with a specific type
in a CREATE ... SELECT statement. For more information, read hundefinedi [Cast
Functions], page hundefinedi.
• CREATE ... SELECT on DATE and TIME functions now create columns of the expected
type.
• Changed order in which keys are created in tables.
• Added new columns Null and Index_type to SHOW INDEX output.
• Added --no-beep and --prompt options to mysql command-line client.
• New feature: management of user resources.
GRANT ... WITH MAX_QUERIES_PER_HOUR N1
MAX_UPDATES_PER_HOUR N2
MAX_CONNECTIONS_PER_HOUR N3;
See hundefinedi [User resources], page hundefinedi.
• Added mysql_secure_installation to the ‘scripts/’ directory.
• Added support for MATCH ... AGAINST(... IN BOOLEAN MODE). Note: you must re-
build your tables with ALTER TABLE tablename TYPE=MyISAM to be able to use boolean
full-text search.
• LOCATE() and INSTR() are now case-sensitive if either argument is a binary string.
• Changed RAND() initialisation so that RAND(N) and RAND(N+1) are more distinct.
• Fixed core dump bug in UPDATE ... ORDER BY.
• Changed INSERT INTO ... SELECT to stop on errors by default.
• Ignore DATA DIRECTORY and INDEX DIRECTORY directives on Windows.
• Added boolean full-text search code. It should be considered early alpha.
• Extended MODIFY and CHANGE in ALTER TABLE to accept the FIRST and AFTER keywords.
• Indexes are now used with ORDER BY on a whole InnoDB table.
InnoDB A transaction-safe storage engine that supports row level locking, and many
Oracle-like features.
BerkeleyDB or BDB
Uses the Berkeley DB library from Sleepycat Software to implement
transaction-safe tables.
Note that only MyISAM is available in the standard binary distribution.
The 3.23 release also includes support for database replication between a master and many
slaves, full-text indexing, and much more.
All new features are being developed in the 4.x version. Only bug fixes and minor enhance-
ments to existing features will be added to 3.23.
The replication code and BerkeleyDB code is still not as tested and as the rest of the code,
so we will probably need to do a couple of future releases of 3.23 with small fixes for this
part of the code. As long as you don’t use these features, you should be quite safe with
MySQL 3.23!
Note that the above doesn’t mean that replication or Berkeley DB don’t work. We have
done a lot of testing of all code, including replication and BDB without finding any problems.
It only means that not as many users use this code as the rest of the code and because of
this we are not yet 100% confident in this code.
Fixed bug in using aggregate functions as argument for INTERVAL, CASE, FIELD,
CONCAT_WS, ELT and MAKE_SET functions.
When running with --lower-case-table-names (default on windows) and you had ta-
bles or databases with mixed case on disk, then executing SHOW TABLE STATUS followed
with DROP DATABASE or DROP TABLE could fail with Errcode 13.
Fixed bug in logging to binary log (which affects replication) a query that inserts a
NULL in an auto_increment field and also uses LAST_INSERT_ID().
Fixed bug in mysqladmin --relative.
On some 64 bit systems, show status reported a strange number for Open_files and
Open_streams.
Fixed bug that prevented --chroot command-line option of mysqld from working.
Fixed bug that made OPTIMIZE TABLE to corrupt the table under some rare circum-
stances.
Fixed mysqlcheck so it can deal with table names containing dashes.
Fixed shutdown problem on Mac OS X.
Fixed bug with comparing an indexed NULL field with <=> NULL.
Fixed bug that caused IGNORE INDEX and USE INDEX sometimes to be ignored.
Fixed rare core dump problem in complicated GROUP BY queries that didn’t return any
result.
Fixed a bug where MATCH ... AGAINST () >=0 was treated as if it was >.
Fixed core dump in SHOW PROCESSLIST when running with an active slave (unlikely
timing bug).
Allow one to start multiple MySQL servers on windows (code backported from 4.0.2).
One can create TEMPORARY MERGE tables now.
Fixed that --core-file works on Linux (at least on kernel 2.4.18).
Fixed a problem with BDB and ALTER TABLE.
Fixed reference to freed memory when doing complicated GROUP BY ... ORDER BY
queries. Symptom was that mysqld died in function send_fields.
Allocate heap rows in smaller blocks to get better memory usage.
Fixed memory allocation bug when storing BLOB values in internal temporary tables
used for some (unlikely) GROUP BY queries.
Fixed a bug in key optimising handling where the expression WHERE column_name =
key_column_name was calculated as true for NULL values.
Fixed core dump bug when doing LEFT JOIN ... WHERE key_column=NULL.
Fixed MyISAM crash when using dynamic-row tables with huge numbers of packed fields.
Updated source tree to be built using automake 1.5 and libtool 1.4.
• InnoDB now retains foreign key constraints through ALTER TABLE and CREATE/DROP
INDEX.
• InnoDB now allows foreign key constraints to be added through the ALTER TABLE syntax.
• InnoDB tables can now be set to automatically grow in size (autoextend).
• Our Linux RPMS and binaries are now compiled with gcc 3.0.4, which should make
them a bit faster.
• Fixed some buffer overflow problems when reading startup parameters.
• Because of problems on shutdown we have now disabled named pipes on windows by
default. One can enable named pipes by starting mysqld with --enable-named-pipe.
• Fixed bug when using WHERE key_column = ’J’ or key_column=’j’.
• Fixed core-dump bug when using --log-bin with LOAD DATA INFILE without an active
database.
• Fixed bug in RENAME TABLE when used with lower_case_table_names=1 (default on
Windows).
• Fixed unlikely core-dump bug when using DROP TABLE on a table that was in use by a
thread that also used queries on only temporary tables.
• Fixed problem with SHOW CREATE TABLE and PRIMARY KEY when using 32 indexes.
• Fixed that one can use SET PASSWORD for the anonymous user.
• Fixed core dump bug when reading client groups from option files using
mysql_options().
• Memory leak (16 bytes per every corrupted table) closed.
• Fixed binary builds to use --enable-local-infile.
• Update source to work with new version of bison.
• Updated shell scripts to now agree with new POSIX standard.
• Fixed bug where DATE_FORMAT() returned empty string when used with GROUP BY.
• Fixed bug that caused error message Can’t write, because of unique constraint
with some GROUP BY queries.
• Fixed problem with sjis character strings used within quoted table names.
• Fixed core dump when using CREATE ... FULLTEXT keys with other storage engines
than MyISAM.
• Don’t use signal() on Windows because this appears to not be 100% reliable.
• Fixed bug when doing WHERE nome_coluna=NULL on an indexed column that had NULL
values.
• Fixed bug when doing LEFT JOIN ... ON (nome_coluna = constant) WHERE
nome_coluna = constant.
• When using replications, aborted queries that contained % could cause a core dump.
• TCP_NODELAY was not used on some systems. (Speed problem.)
• Applied portability fixes for OS/2. (Patch by Yuri Dario.)
The following changes are for InnoDB tables:
• Add missing InnoDB variables to SHOW VARIABLES.
• Foreign keys checking is now done for InnoDB tables.
• DROP DATABASE now works also for InnoDB tables.
• InnoDB now supports datafiles and raw disk partitions bigger than 4 GB on those
operating systems that have big files.
• InnoDB calculates better table cardinality estimates for the MySQL optimiser.
• Accent characters in the default character set latin1 are ordered according to the
MySQL ordering.
Note: if you are using latin1 and have inserted characters whose code is greater than
127 into an indexed CHAR column, you should run CHECK TABLE on your table when you
upgrade to 3.23.44, and drop and reimport the table if CHECK TABLE reports an error!
• A new ‘my.cnf’ parameter, innodb_thread_concurrency, helps in performance tuning
in heavily concurrent environments.
• A new ‘my.cnf’ parameter, innodb_fast_shutdown, speeds up server shutdown.
• A new ‘my.cnf’ parameter, innodb_force_recovery, helps to save your data in case
the disk image of the database becomes corrupt.
• innodb_monitor has been improved and a new innodb_table_monitor added.
• Increased maximum key length from 500 to 7000 bytes.
• Fixed a bug in replication of AUTO_INCREMENT columns with multiple-line inserts.
• Fixed a bug when the case of letters changes in an update of an indexed secondary
column.
• Fixed a hang when there are > 24 datafiles.
• Fixed a crash when MAX(col) is selected from an empty table, and col is not the first
column in a multi-column index.
• Fixed a bug in purge which could cause crashes.
768 Referência técnica para o MySQL versão 3.23.52
• Don’t force everything to lowercase on Windows. (To fix problem with Windows and
ALTER TABLE). Now --lower_case_names also works on Unix.
• Fixed that automatic rollback is done when thread end doesn’t lock other threads.
• Added option --warnings to mysqld. Now mysqld prints the error Aborted
connection only if this option is used.
• Fixed problem with SHOW CREATE TABLE when you didn’t have a PRIMARY KEY.
• Properly fixed the rename of innodb_unix_file_flush_method variable to innodb_
flush_method.
• Fixed bug when converting BIGINT UNSIGNED to DOUBLE. This caused a problem when
doing comparisons with BIGINT values outside of the signed range.
• Fixed bug in BDB tables when querying empty tables.
• Fixed a bug when using COUNT(DISTINCT) with LEFT JOIN and there weren’t any
matching rows.
• Removed all documentation referring to the GEMINI table type. GEMINI is not released
under an Open Source license.
• If you do a DROP DATABASE on a symbolically linked database, both the link and the
original database is deleted.
• Fixed DROP DATABASE to work on OS/2.
• Fixed bug when doing a SELECT DISTINCT ... table1 LEFT JOIN table2 ... when
table2 was empty.
• Added --abort-slave-event-count and --disconnect-slave-event-count options
to mysqld for debugging and testing of replication.
• Fixed replication of temporary tables. Handles everything except slave server restart.
• SHOW KEYS now shows whether key is FULLTEXT.
• New script mysqld_multi. See hundefinedi [mysqld_multi], page hundefinedi.
• Added new script, mysql-multi.server.sh. Thanks to Tim Bunce
[email protected] for modifying mysql.server to easily handle hosts
running many mysqld processes.
• safe_mysqld, mysql.server, and mysql_install_db have been modified to use
mysql_print_defaults instead of various hacks to read the ‘my.cnf’ files. In
addition, the handling of various paths has been made more consistent with how
mysqld handles them by default.
• Automatically remove Berkeley DB transaction logs that no longer are in use.
• Fixed bug with several FULLTEXT indexes in one table.
• Added a warning if number of rows changes on REPAIR/OPTIMIZE.
• Applied patches for OS/2 by Yuri Dario.
• FLUSH TABLES nome_tabela didn’t always flush the index tree to disk properly.
• --bootstrap is now run in a separate thread. This fixes a problem that caused mysql_
install_db to core dump on some Linux machines.
• Changed mi_create() to use less stack space.
• Fixed bug with optimiser trying to over-optimise MATCH() when used with UNIQUE key.
• Changed crash-me and the MySQL benchmarks to also work with FrontBase.
• Allow RESTRICT and CASCADE after DROP TABLE to make porting easier.
• Reset status variable which could cause problem if one used --slow-log.
• Added connect_timeout variable to mysql and mysqladmin.
• Added connect-timeout as an alias for timeout for option files read by mysql_
options().
UPDATE and INSERT queries were locked for a long time while new SELECT statements
were executed before the updates.
• When reading options_files with mysql_options() the return-found-rows option
was ignored.
• One can now specify interactive-timeout in the option file that is read by mysql_
options(). This makes it possible to force programs that run for a long time (like
mysqlhotcopy) to use the interactive_timeout time instead of the wait_timeout
time.
• Added to the slow query log the time and the user name for each logged query. If you
are using --log-long-format then also queries that do not use an index are logged,
even if the query takes less than long_query_time seconds.
• Fixed a problem in LEFT JOIN which caused all columns in a reference table to be NULL.
• Fixed a problem when using NATURAL JOIN without keys.
• Fixed a bug when using a multi-part keys where the first part was of type TEXT or
BLOB.
• DROP of temporary tables wasn’t stored in the update/binary log.
• Fixed a bug where SELECT DISTINCT * ... LIMIT # only returned one row.
• Fixed a bug in the assembler code in strstr() for SPARC and cleaned up the
‘global.h’ header file to avoid a problem with bad aliasing with the compiler
submitted with Red Hat 7.0. (Reported by Trond Eivind Glomsrd)
• The --skip-networking option now works properly on NT.
• Fixed a long outstanding bug in the ISAM tables when a row with a length of more
than 65K was shortened by a single byte.
• Fixed a bug in MyISAM when running multiple updating processes on the same table.
• Allow one to use FLUSH TABLE nome_tabela.
• Added --replicate-ignore-table, --replicate-do-table, --replicate-wild-
ignore-table, and --replicate-wild-do-table options to mysqld.
• Changed all log files to use our own IO_CACHE mechanism instead of FILE to avoid OS
problems when there are many files open.
• Added --open-files and --timezone options to safe_mysqld.
• Fixed a fatal bug in CREATE TEMPORARY TABLE ... SELECT ....
• Fixed a problem with CREATE TABLE ... SELECT NULL.
• Added variables large_file_support,net_read_timeout, net_write_timeout and
query_buffer_size to SHOW VARIABLES.
• Added status variables created_tmp_files and sort_merge_passes to SHOW STATUS.
• Fixed a bug where we didn’t allow an index name after the FOREIGN KEY definition.
• Added TRUNCATE table_name as a synonym for DELETE FROM table_name.
• Fixed a bug in a BDB key compare function when comparing part keys.
• Added bdb_lock_max variable to mysqld.
• Added more tests to the benchmark suite.
• Fixed an overflow bug in the client code when using overly long database names.
780 Referência técnica para o MySQL versão 3.23.52
• mysql_connect() now aborts on Linux if the server doesn’t answer in timeout seconds.
• SLAVE START did not work if you started with --skip-slave-start and had not ex-
plicitly run CHANGE MASTER TO.
• Fixed the output of SHOW MASTER STATUS to be consistent with SHOW SLAVE STATUS. (It
now has no directory in the log name.)
• Added PURGE MASTER LOGS TO.
• Added SHOW MASTER LOGS.
• Added --safemalloc-mem-limit option to mysqld to simulate memory shortage when
compiled with the --with-debug=full option.
• Fixed several core dumps in out-of-memory conditions.
• SHOW SLAVE STATUS was using an uninitialised mutex if the slave had not been started
yet.
• Fixed bug in ELT() and MAKE_SET() when the query used a temporary table.
• CHANGE MASTER TO without specifying MASTER_LOG_POS would set it to 0 instead of 4
and hit the magic number in the master binlog.
• ALTER TABLE ... ORDER BY ... syntax added. This will create the new table with the
rows in a specific order.
• Removed the TYPE= keyword from CHECK and REPAIR. Allow CHECK options to be
combined. (You can still use TYPE=, but this usage is deprecated.)
• Fixed mutex bug in the binary replication log -- long update queries could be read only
in part by the slave if it did it at the wrong time, which was not fatal, but resulted in
a performance-degrading reconnect and a scary message in the error log.
• Changed the format of the binary log -- added magic number, server version, binlog
version. Added server id and query error code for each query event.
• Replication thread from the slave now will kill all the stale threads from the same
server.
• Long replication user names were not being handled properly.
• Added --replicate-rewrite-db option to mysqld.
• Added --skip-slave-start option to mysqld.
• Updates that generated an error code (such as INSERT INTO foo(some_key) values
(1),(1)) erroneously terminated the slave thread.
• Added optimisation of queries where DISTINCT is only used on columns from some of
the tables.
• Allow floating-point numbers where there is no sign after the exponent (like 1e1).
• SHOW GRANTS didn’t always show all column grants.
• Added --default-extra-file=# option to all MySQL clients.
• Columns referenced in INSERT statements now are initialised properly.
• UPDATE didn’t always work when used with a range on a timestamp that was part of
the key that was used to find rows.
• Fixed a bug in FULLTEXT index when inserting a NULL column.
• Changed to use mkstemp() instead of tempnam(). Based on a patch from John Jones.
• ANALYZE TABLE will now only update tables that have been changed since the last
ANALYZE. Note that this is a new feature and tables will not be marked to be analysed
until they are updated in any way with 3.23.23 or newer. For older tables, you have to
do CHECK TABLE to update the key distribution.
• Fixed some minor privilege problems with CHECK, ANALYZE, REPAIR and SHOW CREATE
commands.
• Added CHANGE MASTER TO statement.
• Added FAST, QUICK EXTENDED check types to CHECK TABLES.
• Changed myisamchk so that --fast and --check-only-changed are also honored with
--sort-index and --analyze.
• Fixed fatal bug in LOAD TABLE FROM MASTER that did not lock the table during index
re-build.
• LOAD DATA INFILE broke replication if the database was excluded from replication.
• More variables in SHOW SLAVE STATUS and SHOW MASTER STATUS.
• SLAVE STOP now will not return until the slave thread actually exits.
• Full-text search via the MATCH() function and FULLTEXT index type (for MyISAM files).
This makes FULLTEXT a reserved word.
• Fixed problems in update log when using LAST_INSERT_ID() to update a table with
an AUTO_INCREMENT key.
• Added NULLIF() function.
• Fixed bug when using LOAD DATA INFILE on a table with BLOB/TEXT columns.
• Optimised MyISAM to be faster when inserting keys in sorted order.
• EXPLAIN SELECT ... now also prints out whether MySQL needs to create a temporary
table or use file sorting when resolving the SELECT.
• Added optimisation to skip ORDER BY parts where the part is a constant expression in
the WHERE part. Indexes can now be used even if the ORDER BY doesn’t match the index
exactly, as long as all the unused index parts and all the extra ORDER BY columns are
constants in the WHERE clause. See hundefinedi [MySQL indexes], page hundefinedi.
• UPDATE and DELETE on a whole unique key in the WHERE part are now faster than before.
• Changed RAID_CHUNKSIZE to be in 1024-byte increments.
• Fixed core dump in LOAD_FILE(NULL).
• Fixed optimiser problem on SELECT when using many overlapping indexes. MySQL
should now be able to choose keys even better when there are many keys to choose
from.
• Changed optimiser to prefer a range key instead of a ref key when the range key can
uses more columns than the ref key (which only can use columns with =). For example,
the following type of queries should now be faster: SELECT * from key_part_1=const
and key_part_2 > const2
• Fixed bug that a change of all VARCHAR columns to CHAR columns didn’t change row
type from dynamic to fixed.
• Disabled floating-point exceptions for FreeBSD to fix core dump when doing SELECT
FLOOR(POW(2,63)).
• Renamed mysqld startup option from --delay-key-write to --delay-key-write-
for-all-tables.
• Added read-next-on-key to HEAP tables. This should fix all problems with HEAP tables
when using non-UNIQUE keys.
• Added option to print default arguments to all clients.
• Added --log-slow-queries option to mysqld to log all queries that take a long time
to a separate log file with a time indicating how long the query took.
• Fixed core dump when doing WHERE key_col=RAND(...).
• Fixed optimisation bug in SELECT ... LEFT JOIN ... key_col IS NULL, when key_col
could contain NULL values.
• Fixed problem with 8-bit characters as separators in LOAD DATA INFILE.
• Fixed bug that one could make a part of a PRIMARY KEY NOT NULL.
• Fixed encrypt() to be thread-safe and not reuse buffer.
• Added mysql_odbc_escape_string() function to support big5 characters in MyO-
DBC.
• Rewrote the storage engine to use classes. This introduces a lot of new code, but will
make table handling faster and better.
• Added patch by Sasha for user-defined variables.
• Changed that FLOAT and DOUBLE (without any length modifiers) no longer are fixed
decimal point numbers.
• Changed the meaning of FLOAT(X): Now this is the same as FLOAT if X <= 24 and a
DOUBLE if 24 < X <= 53.
• DECIMAL(X) is now an alias for DECIMAL(X,0) and DECIMAL is now an alias for
DECIMAL(10,0). The same goes for NUMERIC.
• Added option ROW_FORMAT={default | dynamic | fixed | compressed} to CREATE_
TABLE.
• DELETE FROM table_name didn’t work on temporary tables.
• Changed function CHAR_LENGTH() to be multi-byte character safe.
• Added function ORD(string).
• Added support for netmasks to the hostname in the MySQL grant tables. You can
specify a netmask using the IP/NETMASK syntax.
• If you compare a NOT NULL DATE/DATETIME column with IS NULL, this is changed to a
compare against 0 to satisfy some ODBC applications. (By [email protected].)
• NULL IN (...) now returns NULL instead of 0. This will ensure that null_column NOT
IN (...) doesn’t match NULL values.
• Fix storage of floating-point values in TIME columns.
• Changed parsing of TIME strings to be more strict. Now the fractional second part is
detected (and currently skipped). The following formats are supported:
[[DAYS] [H]H:]MM:]SS[.fraction]
[[[[[H]H]H]H]MM]SS[.fraction]
• Detect (and ignore) fractional second part from DATETIME.
• Added the LOW_PRIORITY attribute to LOAD DATA INFILE.
• The default index name now uses the same case as the column name on which the
index name is based.
• Changed default number of connections to 100.
• Use bigger buffers when using LOAD DATA INFILE.
• DECIMAL(x,y) now works according to SQL-99.
• Added aggregate UDF functions. Thanks to Andreas F. Bobak ([email protected]) for
this!
• LAST_INSERT_ID() is now updated for INSERT INTO ... SELECT.
• Some small changes to the join table optimiser to make some joins faster.
• SELECT DISTINCT is much faster; it uses the new UNIQUE functionality in MyISAM. One
difference compared to MySQL Version 3.22 is that the output of DISTINCT is no longer
sorted.
• All C client API macros are now functions to make shared libraries more reliable.
Because of this, you can no longer call mysql_num_fields() on a MYSQL object, you
must use mysql_field_count() instead.
• Added use of LIBWRAP; patch by Henning P. Schmiedehausen.
• Don’t allow AUTO_INCREMENT for other than numerical columns.
• Using AUTO_INCREMENT will now automatically make the column NOT NULL.
• Show NULL as the default value for AUTO_INCREMENT columns.
• Added SQL_BIG_RESULT; SQL_SMALL_RESULT is now default.
• Added a shared library RPM. This enhancement was contributed by David Fox
([email protected]).
• Added --enable-large-files and --disable-large-files switches to configure.
See ‘configure.in’ for some systems where this is automatically turned off because of
broken implementations.
• Upgraded readline to 4.0.
• New CREATE TABLE options: PACK_KEYS and CHECKSUM.
• Added --default-table-type option to mysqld.
798 Referência técnica para o MySQL versão 3.23.52
• Fixed range optimiser bug in SELECT * FROM table_name WHERE key_part1 >= const
AND (key_part2 = const OR key_part2 = const).
• Fixed bug in compression key handling in ISAM.
• Added casts and changed include files to make MySQL easier to compile on AIX and
DEC OSF/1 4.x
• Fixed conversion problem when using ALTER TABLE from a INT to a short CHAR() col-
umn.
• Added SELECT HIGH_PRIORITY; this will get a lock for the SELECT even if there is a
thread waiting for another SELECT to get a WRITE LOCK.
• Moved wild_compare() to string class to be able to use LIKE on BLOB/TEXT columns
with \0.
• Added ESCAPE option to LIKE.
• Added a lot more output to mysqladmin debug.
• You can now start mysqld on Windows with the --flush option. This will flush
all tables to disk after each update. This makes things much safer on the Windows
platforms but also much slower.
• OPTIMIZE TABLE nome_tabela can now be used to reclaim disk space after many
deletes. Currently, this uses ALTER TABLE to regenerate the table, but in the future it
will use an integrated isamchk for more speed.
• Upgraded libtool to get the configure more portable.
• Fixed slow UPDATE and DELETE operations when using DATETIME or DATE keys.
• Changed optimiser to make it better at deciding when to do a full join and when using
keys.
• You can now use mysqladmin proc to display information about your own threads.
Only users with the PROCESS privilege can get information about all threads. (In 4.0.2
one needs the SUPER privilege for this.)
• Added handling of formats YYMMDD, YYYYMMDD, YYMMDDHHMMSS for numbers when using
DATETIME and TIMESTAMP types. (Formerly these formats only worked with strings.)
• Added connect option CLIENT_IGNORE_SPACE to allow use of spaces after function
names and before ‘(’ (Powerbuilder requires this). This will make all function names
reserved words.
• Added the --log-long-format option to mysqld to enable timestamps and
INSERT IDs in the update log.
• Added --where option to mysqldump (patch by Jim Faucette).
• The lexical analyser now uses “perfect hashing” for faster parsing of SQL statements.
• The return type of mysql_fetch_lengths() has changed from uint * to ulong *. This
may give a warning for old clients but should work on most machines.
• Change mysys and dbug libraries to allocate all thread variables in one struct. This
makes it easier to make a threaded ‘libmysql.dll’ library.
• Use the result from gethostname() (instead of uname()) when constructing ‘.pid’ file
names.
• New better compressed server/client protocol.
• COUNT(), STD() and AVG() are extended to handle more than 4G rows.
• You can now store values in the range -838:59:59 <= x <= 838:59:59 in a TIME
column.
• Warning: incompatible change!! If you set a TIME column to too short a value, MySQL
now assumes the value is given as: [[[D ]HH:]MM:]SS instead of HH[:MM[:SS]].
• TIME_TO_SEC() and SEC_TO_TIME() can now handle negative times and hours up to
32767.
• Added new option SET SQL_LOG_UPDATE={0|1} to allow users with the PROCESS
privilege to bypass the update log. (Modified patch from Sergey A Mukhin
[email protected].)
• Fixed fatal bug in LPAD().
• Initialise line buffer in ‘mysql.cc’ to make BLOB reading from pipes safer.
• Added -O max_connect_errors=# option to mysqld. Connect errors are now reset for
each correct connection.
• Increased the default value of max_allowed_packet to 1M in mysqld.
• Added --low-priority-updates option to mysqld, to give table-modifying opera-
tions (INSERT, REPLACE, UPDATE, DELETE) lower priority than retrievals. You can now
use {INSERT | REPLACE | UPDATE | DELETE} LOW_PRIORITY ... You can also use SET
SQL_LOW_PRIORITY_UPDATES={0|1} to change the priority for one thread. One side
effect is that LOW_PRIORITY is now a reserved word. :(
• Add support for INSERT INTO table ... VALUES(...),(...),(...), to allow insert-
ing multiple rows with a single statement.
• INSERT INTO nome_tabela is now also cached when used with LOCK TABLES. (Previ-
ously only INSERT ... SELECT and LOAD DATA INFILE were cached.)
• Allow GROUP BY functions with HAVING:
mysql> SELECT col FROM table GROUP BY col HAVING COUNT(*)>0;
• mysqld will now ignore trailing ‘;’ characters in queries. This is to make it easier to
migrate from some other SQL servers that require the trailing ‘;’.
• Fix for corrupted fixed-format output generated by SELECT INTO OUTFILE.
• Warning: incompatible change! Added Oracle GREATEST() and LEAST() functions.
You must now use these instead of the MAX() and MIN() functions to get the
largest/smallest value from a list of values. These can now handle REAL, BIGINT and
string (CHAR or VARCHAR) values.
• Warning: incompatible change! DAYOFWEEK() had offset 0 for Sunday. Changed the
offset to 1.
808 Referência técnica para o MySQL versão 3.23.52
• Give an error for queries that mix GROUP BY columns and fields when there is no GROUP
BY specification.
• Added --vertical option to mysql, for printing results in vertical mode.
• Index-only optimisation; some queries are now resolved using only indexes. Until
MySQL 4.0, this works only for numeric columns. See hundefinedi [MySQL indexes],
page hundefinedi.
• Lots of new benchmarks.
• A new C API chapter and lots of other improvements in the manual.
• String functions now return VARCHAR rather than CHAR and the column type is now
VARCHAR for fields saved as VARCHAR. This should make the MyODBC driver better, but
may break some old MySQL clients that don’t handle FIELD_TYPE_VARCHAR the same
way as FIELD_TYPE_CHAR.
• CREATE INDEX and DROP INDEX are now implemented through ALTER TABLE. CREATE
TABLE is still the recommended (fast) way to create indexes.
• Added --set-variable option wait_timeout to mysqld.
• Added time column to mysqladmin processlist to show how long a query has taken
or how long a thread has slept.
• Added lots of new variables to show variables and some new to show status.
• Added new type YEAR. YEAR is stored in 1 byte with allowable values of 0, and 1901 to
2155.
• Added new DATE type that is stored in 3 bytes rather than 4 bytes. All new tables are
created with the new date type if you don’t use the --old-protocol option to mysqld.
• Fixed bug in record caches; for some queries, you could get Error from table
handler: # on some operating systems.
• Added --enable-assembler option to configure, for x86 machines (tested on Linux
+ gcc). This will enable assembler functions for the most important string functions
for more speed!
• SELECT DISTINCT with a WHERE clause that didn’t match any rows returned a row in
some contexts (bug only in 3.21.31).
• GROUP BY + ORDER BY returned one empty row when no rows where found.
• Fixed a bug in the range optimiser that wrote Use_count: Wrong count for ... in
the error log file.
• Added a retry loop around accept() to possibly fix some problems on some Linux
machines.
• Added --table option to mysql to print in table format. Moved time and row infor-
mation after query result. Added automatic reconnect of lost connections.
• Added != as a synonym for <>.
• Added function VERSION() to make easier logs.
• New multi-user test ‘tests/fork_test.pl’ to put some strain on the thread library.
• Added handling of calculation of SUM() functions. For example, you can now use
SUM(column)/COUNT(column).
• Added handling of trigometric functions: PI(), ACOS(), ASIN(), ATAN(), COS(), SIN()
and TAN().
• New languages: Norwegian, Norwegian-ny and Portuguese.
• Fixed parameter bug in net_print() in ‘procedure.cc’.
• Fixed a couple of memory leaks.
• Now allow also the old SELECT ... INTO OUTFILE syntax.
• Fixed bug with GROUP BY and SELECT on key with many values.
• mysql_fetch_lengths() sometimes returned incorrect lengths when you used mysql_
use_result(). This affected at least some cases of mysqldump --quick.
• Fixed bug in optimisation of WHERE const op field.
• Fixed problem when sorting on NULL fields.
• Fixed a couple of 64-bit (Alpha) problems.
• Added --pid-file=# option to mysqld.
• Added date formatting to FROM_UNIXTIME(), originally by Zeev Suraski.
• Fixed bug in BETWEEN in range optimiser (did only test = of the first argument).
• Added machine-dependent files for MIT-pthreads i386-SCO. There is probably more
to do to get this to work on SCO 3.5.
• More portable. Should compile on AIX and alpha-digital. At least the isam library
should be relatively 64-bit clean.
• New isamchk which can detect and fix more problems.
• New options for isamlog.
• Using new version of Automake.
• Many small portability changes (from the AIX and alpha-digital port) Better checking
of pthread(s) library.
• czech error messages by [email protected].
• Decreased size of some buffers to get fewer problems on systems with little memory.
Also added more checks to handle “out of memory” problems.
• mysqladmin: you can now do mysqladmin kill 5,6,7,8 to kill multiple threads.
• When the maximum connection limit is reached, one extra connection by a user with
the process acl privilege is granted.
• Added -O backlog=# option to mysqld.
• Increased maximum packet size from 512K to 1024K for client.
• Almost all of the function code is now tested in the internal test suite.
• ALTER TABLE now returns warnings from field conversions.
• Port changed to 3306 (got it reserved from ISI).
• Added a fix for Visual FoxBase so that any schema name from a table specification is
automatically removed.
• New function ASCII().
• Removed function BETWEEN(a,b,c). Use the standard SQL syntax instead: expr
BETWEEN expr AND expr.
• MySQL no longer has to use an extra temporary table when sorting on functions or
SUM() functions.
• Fixed bug that you couldn’t use nome_tabela.field_name in UPDATE.
• Fixed SELECT DISTINCT when using ’hidden group’. For example:
mysql> SELECT DISTINCT MOD(some_field,10) FROM test
-> GROUP BY some_field;
Note: some_field is normally in the SELECT part. Standard SQL should require it.
• For easier client code, the client should no longer use FIELD_TYPE_TINY_BLOB, FIELD_
TYPE_MEDIUM_BLOB, FIELD_TYPE_LONG_BLOB or FIELD_TYPE_VAR_STRING (as previ-
ously returned by mysql_list_fields). You should instead only use FIELD_TYPE_
BLOB or FIELD_TYPE_STRING. If you want exact types, you should use the command
SHOW FIELDS.
• Added varbinary syntax: 0x###### which can be used as a string (default) or a number.
• FIELD_TYPE_CHAR is renamed to FIELD_TYPE_TINY.
• Changed all fields to C++ classes.
• Removed FORM struct.
• Fields with DEFAULT values no longer need to be NOT NULL.
• New field types:
ENUM A string which can take only a couple of defined values. The value is stored
as a 1-3 byte number that is mapped automatically to a string. This is
sorted according to string positions!
SET A string which may have one or many string values separated with ’,’. The
string is stored as a 1-, 2-, 3-, 4- or 8-byte number where each bit stands
for a specific set member. This is sorted according to the unsigned value
of the stored packed number.
• Now all function calculation is done with double or long long. This will provide
the full 64-bit range with bit functions and fix some conversions that previously could
result in precision losses. One should avoid using unsigned long long columns with
full 64-bit range (numbers bigger than 9223372036854775807) because calculations are
done with signed long long.
• ORDER BY will now put NULL field values first. GROUP BY will also work with NULL values.
• Full WHERE with expressions.
• New range optimiser that can resolve ranges when some keypart prefix is constant.
Example:
mysql> SELECT * FROM nome_tabela
-> WHERE key_part_1="customer"
-> AND key_part_2>=10 AND key_part_2<=10;
• mysqldump now works correctly for all field types (even AUTO_INCREMENT). The format
for SHOW FIELDS FROM nome_tabela is changed so the Type column contains informa-
tion suitable for CREATE TABLE. In previous releases, some CREATE TABLE information
had to be patched when re-creating tables.
• Some parser bugs from 3.19.5 (BLOB and TIMESTAMP) are corrected. TIMESTAMP now
returns different date information depending on its create length.
• Changed parser to allow a database, table or field name to start with a number or ’_’.
• All old C code from Unireg changed to C++ and cleaned up. This makes the daemon
a little smaller and easier to understand.
• A lot of small bug fixes done.
• New ‘INSTALL’ files (not final version) and some information regarding porting.
If you suspect a memory overrun error, you can configure MySQL with --with-debug=full,
which will install a memory allocation (SAFEMALLOC) checker. Running with SAFEMALLOC is
however quite slow, so if you get performance problems you should start mysqld with the
--skip-safemalloc option. This will disable the memory overrun checks for each call to
malloc and free.
If mysqld stops crashing when you compile it with --with-debug, you have probably found
a compiler bug or a timing bug within MySQL. In this case you can try to add -g to the
CFLAGS and CXXFLAGS variables above and not use --with-debug. If mysqld now dies, you
can at least attach to it with gdb or use gdb on the core file to find out what happened.
When you configure MySQL for debugging you automatically enable a lot of extra safety
check functions that monitor the health of mysqld. If they find something “unexpected,”
an entry will be written to stderr, which safe_mysqld directs to the error log! This also
means that if you are having some unexpected problems with MySQL and are using a
source distribution, the first thing you should do is to configure MySQL for debugging!
(The second thing, of course, is to send mail to [email protected] and ask for help.
Please use the mysqlbug script for all bug reports or questions regarding the MySQL version
you are using!
In the Windows MySQL distribution, mysqld.exe is by default compiled with support for
trace files.
Include the above output in a mail generated with mysqlbug and mail this to
[email protected].
If mysqld hangs you can try to use some system tools like strace or /usr/proc/bin/pstack
to examine where mysqld has hung.
strace /tmp/log libexec/mysqld
If you are using the Perl DBI interface, you can turn on debugging information by using
the trace method or by setting the DBI_TRACE environment variable. See hundefinedi [Perl
DBI Class], page hundefinedi.
t Enable function call/exit trace lines. May be followed by a list (containing only one
modifier) giving a numeric maximum trace level, beyond which no output will occur
for either debugging or tracing macros. The default is a compile time option.
Some examples of debug control strings which might appear on a shell command-line (the
"-#" is typically used to introduce a control string to an application program) are:
-#d:t
-#d:f,main,subr1:F:L:t,20
-#d,input,output,files:n
-#d:t:i:O,\\mysqld.trace
In MySQL, common tags to print (with the d option) are: enter,exit,error,warning,info
and loop.
Another problem is that user-level threads use the ALRM signal and this aborts a lot of
functions (read, write, open...). MySQL should do a retry on interrupt on all of these but
it is not that easy to verify it.
The biggest unsolved problem is the following:
To get thread-level alarms I changed ‘mysys/thr_alarm.c’ to wait between alarms with
pthread_cond_timedwait(), but this aborts with error EINTR. I tried to debug the thread
library as to why this happens, but couldn’t find any easy solution.
If someone wants to try MySQL with RTS threads I suggest the following:
• Change functions MySQL uses from the thread library to POSIX. This shouldn’t take
that long.
• Compile all libraries with the -DHAVE_rts_threads.
• Compile thr_alarm.
• If there are some small differences in the implementation, they may be fixed by changing
‘my_pthread.h’ and ‘my_pthread.c’.
• Run thr_alarm. If it runs without any “warning”, “error” or aborted messages, you
are on the right track. Here is a successful run on 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
844 Referência técnica para o MySQL versão 3.23.52
...
thread_alarm
Thread: 5 Slept for 0 (1) sec
end
For example, if o and (+) are the members of an equivalence class, then
[[=o=]], [[=(+)=]], and [o(+)] are all synonymous. An equivalence class
may not be an endpoint of a range.
[:character_class:]
Within a bracket expression, the name of a character class enclosed in [: and :]
stands for the list of all characters belonging to that class. Standard character
class names are:
Name Name Name
alnum digit punct
alpha graph space
blank lower upper
cntrl print xdigit
These stand for the character classes defined in the ctype(3) manual page. A
locale may provide others. A character class may not be used as an endpoint
of a range.
mysql> SELECT "justalnums" REGEXP "[[:alnum:]]+"; -> 1
mysql> SELECT "!!" REGEXP "[[:alnum:]]+"; -> 0
[[:<:]]
[[:>:]] These match the null string at the beginning and end of a word respectively.
A word is defined as a sequence of word characters which is neither preceded
nor followed by word characters. A word character is an alnum character (as
defined by ctype(3)) or an underscore (_).
mysql> SELECT "a word a" REGEXP "[[:<:]]word[[:>:]]"; -> 1
mysql> SELECT "a xword a" REGEXP "[[:<:]]word[[:>:]]"; -> 0
mysql> SELECT "weeknights" REGEXP "^(wee|week)(knights|nights)$"; -> 1
Appendix H: GNU General Public License 849
Preamble
The licenses for most software are designed to take away your freedom to share and change
it. By contrast, the GNU General Public License is intended to guarantee your freedom
to share and change free software---to make sure the software is free for all its users. This
General Public License applies to most of the Free Software Foundation’s software and to
any other program whose authors commit to using it. (Some other Free Software Foundation
software is covered by the GNU Library General Public License instead.) You can apply it
to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our General Public
Licenses are designed to make sure that you have the freedom to distribute copies of free
software (and charge for this service if you wish), that you receive source code or can get
it if you want it, that you can change the software or use pieces of it in new free programs;
and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to deny you these
rights or to ask you to surrender the rights. These restrictions translate to certain respon-
sibilities for you if you distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for a fee, you
must give the recipients all the rights that you have. You must make sure that they, too,
receive or can get the source code. And you must show them these terms so they know
their rights.
We protect your rights with two steps: (1) copyright the software, and (2) offer you this
license which gives you legal permission to copy, distribute and/or modify the software.
Also, for each author’s protection and ours, we want to make certain that everyone un-
derstands that there is no warranty for this free software. If the software is modified by
someone else and passed on, we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not reflect on the original authors’
reputations.
Finally, any free program is threatened constantly by software patents. We wish to avoid
the danger that redistributors of a free program will individually obtain patent licenses, in
effect making the program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone’s free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification follow.
850 Referência técnica para o MySQL versão 3.23.52
Thus, it is not the intent of this section to claim rights or contest your rights to
work written entirely by you; rather, the intent is to exercise the right to control the
distribution of derivative or collective works based on the Program.
In addition, mere aggregation of another work not based on the Program with the
Program (or with a work based on the Program) on a volume of a storage or distribution
medium does not bring the other work under the scope of this License.
3. You may copy and distribute the Program (or a work based on it, under Section 2)
in object code or executable form under the terms of Sections 1 and 2 above provided
that you also do one of the following:
a. Accompany it with the complete corresponding machine-readable source code,
which must be distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
b. Accompany it with a written offer, valid for at least three years, to give any third-
party, for a charge no more than your cost of physically performing source distri-
bution, a complete machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium customarily
used for software interchange; or,
c. Accompany it with the information you received as to the offer to distribute cor-
responding source code. (This alternative is allowed only for noncommercial dis-
tribution and only if you received the program in object code or executable form
with such an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for making modifi-
cations to it. For an executable work, complete source code means all the source code
for all modules it contains, plus any associated interface definition files, plus the scripts
used to control compilation and installation of the executable. However, as a spe-
cial exception, the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major components (compiler,
kernel, and so on) of the operating system on which the executable runs, unless that
component itself accompanies the executable.
If distribution of executable or object code is made by offering access to copy from
a designated place, then offering equivalent access to copy the source code from the
same place counts as distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program except as expressly
provided under this License. Any attempt otherwise to copy, modify, sublicense or
distribute the Program is void, and will automatically terminate your rights under this
License. However, parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such parties remain in full
compliance.
5. You are not required to accept this License, since you have not signed it. However,
nothing else grants you permission to modify or distribute the Program or its derivative
works. These actions are prohibited by law if you do not accept this License. Therefore,
by modifying or distributing the Program (or any work based on the Program), you
indicate your acceptance of this License to do so, and all its terms and conditions for
copying, distributing or modifying the Program or works based on it.
852 Referência técnica para o MySQL versão 3.23.52
6. Each time you redistribute the Program (or any work based on the Program), the
recipient automatically receives a license from the original licensor to copy, distribute
or modify the Program subject to these terms and conditions. You may not impose
any further restrictions on the recipients’ exercise of the rights granted herein. You are
not responsible for enforcing compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent infringement or for any
other reason (not limited to patent issues), conditions are imposed on you (whether by
court order, agreement or otherwise) that contradict the conditions of this License, they
do not excuse you from the conditions of this License. If you cannot distribute so as
to satisfy simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Program at all. For
example, if a patent license would not permit royalty-free redistribution of the Program
by all those who receive copies directly or indirectly through you, then the only way
you could satisfy both it and this License would be to refrain entirely from distribution
of the Program.
If any portion of this section is held invalid or unenforceable under any particular
circumstance, the balance of the section is intended to apply and the section as a
whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other
property right claims or to contest validity of any such claims; this section has the
sole purpose of protecting the integrity of the free software distribution system, which
is implemented by public license practices. Many people have made generous contri-
butions to the wide range of software distributed through that system in reliance on
consistent application of that system; it is up to the author/donor to decide if he or
she is willing to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence
of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain countries either
by patents or by copyrighted interfaces, the original copyright holder who places the
Program under this License may add an explicit geographical distribution limitation
excluding those countries, so that distribution is permitted only in or among countries
not thus excluded. In such case, this License incorporates the limitation as if written
in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions of the General
Public License from time to time. Such new versions will be similar in spirit to the
present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Program specifies a
version number of this License which applies to it and “any later version”, you have
the option of following the terms and conditions either of that version or of any later
version published by the Free Software Foundation. If the Program does not specify a
version number of this License, you may choose any version ever published by the Free
Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs whose distri-
bution conditions are different, write to the author to ask for permission. For software
Appendix H: GNU General Public License 853
which is copyrighted by the Free Software Foundation, write to the Free Software Foun-
dation; we sometimes make exceptions for this. Our decision will be guided by the two
goals of preserving the free status of all derivatives of our free software and of promoting
the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLI-
CABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPY-
RIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM “AS
IS” WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE
RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH
YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST
OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO
MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED
ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF
THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT
LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this when it starts in an
interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type ‘show w’.
This is free software, and you are welcome to redistribute it
under certain conditions; type ‘show c’ for details.
The hypothetical commands ‘show w’ and ‘show c’ should show the appropriate parts of the
General Public License. Of course, the commands you use may be called something other
than ‘show w’ and ‘show c’; they could even be mouse-clicks or menu items---whatever suits
your program.
You should also get your employer (if you work as a programmer) or your school, if any,
to sign a “copyright disclaimer” for the program, if necessary. Here is a sample; alter the
names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
‘Gnomovision’ (which makes passes at compilers) written by James Hacker.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence the
version number 2.1.]
Preamble
The licenses for most software are designed to take away your freedom to share and change
it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom
to share and change free software---to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some specially designated
software---typically libraries---of the Free Software Foundation and other authors who
decide to use it. You can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better strategy to use in any
particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use, not price. Our General
Public Licenses are designed to make sure that you have the freedom to distribute copies
of free software (and charge for this service if you wish); that you receive source code or
can get it if you want it; that you can change the software and use pieces of it in new free
programs; and that you are informed that you can do these things.
To protect your rights, we need to make restrictions that forbid distributors to deny you
these rights or to ask you to surrender these rights. These restrictions translate to certain
responsibilities for you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis or for a fee, you must
give the recipients all the rights that we gave you. You must make sure that they, too,
receive or can get the source code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them with the library after
making changes to the library and recompiling it. And you must show them these terms so
they know their rights.
We protect your rights with a two-step method: (1) we copyright the library, and (2) we
offer you this license, which gives you legal permission to copy, distribute and/or modify
the library.
To protect each distributor, we want to make it very clear that there is no warranty for the
free library. Also, if the library is modified by someone else and passed on, the recipients
should know that what they have is not the original version, so that the original author’s
reputation will not be affected by problems that might be introduced by others.
Finally, software patents pose a constant threat to the existence of any free program. We
wish to make sure that a company cannot effectively restrict the users of a free program by
856 Referência técnica para o MySQL versão 3.23.52
obtaining a restrictive license from a patent holder. Therefore, we insist that any patent
license obtained for a version of the library must be consistent with the full freedom of use
specified in this license.
Most GNU software, including some libraries, is covered by the ordinary GNU General
Public License. This license, the GNU Lesser General Public License, applies to certain
designated libraries, and is quite different from the ordinary General Public License. We
use this license for certain libraries in order to permit linking those libraries into non-free
programs.
When a program is linked with a library, whether statically or using a shared library, the
combination of the two is legally speaking a combined work, a derivative of the original
library. The ordinary General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General Public License permits
more lax criteria for linking other code with the library.
We call this license the Lesser General Public License because it does Less to protect the
user’s freedom than the ordinary General Public License. It also provides other free software
developers Less of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many libraries. However, the
Lesser license provides advantages in certain special circumstances.
For example, on rare occasions, there may be a special need to encourage the widest possible
use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free
programs must be allowed to use the library. A more frequent case is that a free library
does the same job as widely used non-free libraries. In this case, there is little to gain by
limiting the free library to free software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free programs enables a greater
number of people to use a large body of free software. For example, permission to use the
GNU C Library in non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating system.
Although the Lesser General Public License is Less protective of the users’ freedom, it does
ensure that the user of a program that is linked with the Library has the freedom and the
wherewithal to run that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and modification follow. Pay
close attention to the difference between a “work based on the library” and a “work that
uses the library”. The former contains code derived from the library, whereas the latter
must be combined with the library in order to run.
The “Library”, below, refers to any such software library or work which has been
distributed under these terms. A “work based on the Library” means either the Library
or any derivative work under copyright law: that is to say, a work containing the
Library or a portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is included without
limitation in the term “modification”.)
“Source code” for a work means the preferred form of the work for making modifications
to it. For a library, complete source code means all the source code for all modules it
contains, plus any associated interface definition files, plus the scripts used to control
compilation and installation of the library.
Activities other than copying, distribution and modification are not covered by this
License; they are outside its scope. The act of running a program using the Library is
not restricted, and output from such a program is covered only if its contents constitute
a work based on the Library (independent of the use of the Library in a tool for writing
it). Whether that is true depends on what the Library does and what the program
that uses the Library does.
1. You may copy and distribute verbatim copies of the Library’s complete source code
as you receive it, in any medium, provided that you conspicuously and appropriately
publish on each copy an appropriate copyright notice and disclaimer of warranty; keep
intact all the notices that refer to this License and to the absence of any warranty; and
distribute a copy of this License along with the Library.
You may charge a fee for the physical act of transferring a copy, and you may at your
option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Library or any portion of it, thus forming a
work based on the Library, and copy and distribute such modifications or work under
the terms of Section 1 above, provided that you also meet all of these conditions:
a. The modified work must itself be a software library.
b. You must cause the files modified to carry prominent notices stating that you
changed the files and the date of any change.
c. You must cause the whole of the work to be licensed at no charge to all third
parties under the terms of this License.
d. If a facility in the modified Library refers to a function or a table of data to
be supplied by an application program that uses the facility, other than as an
argument passed when the facility is invoked, then you must make a good faith
effort to ensure that, in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of its purpose remains
meaningful.
(For example, a function in a library to compute square roots has a purpose that
is entirely well-defined independent of the application. Therefore, Subsection 2d
requires that any application-supplied function or table used by this function must
be optional: if the application does not supply it, the square root function must
still compute square roots.)
These requirements apply to the modified work as a whole. If identifiable sections of
that work are not derived from the Library, and can be reasonably considered indepen-
dent and separate works in themselves, then this License, and its terms, do not apply
858 Referência técnica para o MySQL versão 3.23.52
to those sections when you distribute them as separate works. But when you distribute
the same sections as part of a whole which is a work based on the Library, the distri-
bution of the whole must be on the terms of this License, whose permissions for other
licensees extend to the entire whole, and thus to each and every part regardless of who
wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to
work written entirely by you; rather, the intent is to exercise the right to control the
distribution of derivative or collective works based on the Library.
In addition, mere aggregation of another work not based on the Library with the
Library (or with a work based on the Library) on a volume of a storage or distribution
medium does not bring the other work under the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public License instead
of this License to a given copy of the Library. To do this, you must alter all the notices
that refer to this License, so that they refer to the ordinary GNU General Public
License, version 2, instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify that version
instead if you wish.) Do not make any other change in these notices.
Once this change is made in a given copy, it is irreversible for that copy, so the ordinary
GNU General Public License applies to all subsequent copies and derivative works made
from that copy.
This option is useful when you wish to copy part of the code of the Library into a
program that is not a library.
4. You may copy and distribute the Library (or a portion or derivative of it, under Section
2) in object code or executable form under the terms of Sections 1 and 2 above provided
that you accompany it with the complete corresponding machine-readable source code,
which must be distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange.
If distribution of object code is made by offering access to copy from a designated place,
then offering equivalent access to copy the source code from the same place satisfies the
requirement to distribute the source code, even though third parties are not compelled
to copy the source along with the object code.
5. A program that contains no derivative of any portion of the Library, but is designed
to work with the Library by being compiled or linked with it, is called a “work that
uses the Library”. Such a work, in isolation, is not a derivative work of the Library,
and therefore falls outside the scope of this License.
However, linking a “work that uses the Library” with the Library creates an executable
that is a derivative of the Library (because it contains portions of the Library), rather
than a “work that uses the library”. The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a “work that uses the Library” uses material from a header file that is part of
the Library, the object code for the work may be a derivative work of the Library even
though the source code is not. Whether this is true is especially significant if the work
can be linked without the Library, or if the work is itself a library. The threshold for
this to be true is not precisely defined by law.
Appendix I: GNU Lesser General Public License 859
If such an object file uses only numerical parameters, data structure layouts and ac-
cessors, and small macros and small inline functions (ten lines or less in length), then
the use of the object file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the Library will still
fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may distribute the object code
for the work under the terms of Section 6. Any executables containing that work also
fall under Section 6, whether they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or link a “work that
uses the Library” with the Library to produce a work containing portions of the Li-
brary, and distribute that work under terms of your choice, provided that the terms
permit modification of the work for the customer’s own use and reverse engineering for
debugging such modifications.
You must give prominent notice with each copy of the work that the Library is used
in it and that the Library and its use are covered by this License. You must supply
a copy of this License. If the work during execution displays copyright notices, you
must include the copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one of these things:
a. Accompany the work with the complete corresponding machine-readable source
code for the Library including whatever changes were used in the work (which must
be distributed under Sections 1 and 2 above); and, if the work is an executable
linked with the Library, with the complete machine-readable “work that uses the
Library”, as object code and/or source code, so that the user can modify the
Library and then relink to produce a modified executable containing the modified
Library. (It is understood that the user who changes the contents of definitions
files in the Library will not necessarily be able to recompile the application to use
the modified definitions.)
b. Use a suitable shared library mechanism for linking with the Library. A suitable
mechanism is one that (1) uses at runtime a copy of the library already present
on the user’s computer system, rather than copying library functions into the
executable, and (2) will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is interface-compatible with
the version that the work was made with.
c. Accompany the work with a written offer, valid for at least three years, to give the
same user the materials specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d. If distribution of the work is made by offering access to copy from a designated
place, offer equivalent access to copy the above specified materials from the same
place.
e. Verify that the user has already received a copy of these materials or that you have
already sent this user a copy.
For an executable, the required form of the “work that uses the Library” must include
any data and utility programs needed for reproducing the executable from it. However,
as a special exception, the materials to be distributed need not include anything that
is normally distributed (in either source or binary form) with the major components
860 Referência técnica para o MySQL versão 3.23.52
(compiler, kernel, and so on) of the operating system on which the executable runs,
unless that component itself accompanies the executable.
It may happen that this requirement contradicts the license restrictions of other pro-
prietary libraries that do not normally accompany the operating system. Such a con-
tradiction means you cannot use both them and the Library together in an executable
that you distribute.
7. You may place library facilities that are a work based on the Library side-by-side in
a single library together with other library facilities not covered by this License, and
distribute such a combined library, provided that the separate distribution of the work
based on the Library and of the other library facilities is otherwise permitted, and
provided that you do these two things:
a. Accompany the combined library with a copy of the same work based on the
Library, uncombined with any other library facilities. This must be distributed
under the terms of the Sections above.
b. Give prominent notice with the combined library of the fact that part of it is a work
based on the Library, and explaining where to find the accompanying uncombined
form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute the Library except
as expressly provided under this License. Any attempt otherwise to copy, modify,
sublicense, link with, or distribute the Library is void, and will automatically terminate
your rights under this License. However, parties who have received copies, or rights,
from you under this License will not have their licenses terminated so long as such
parties remain in full compliance.
9. You are not required to accept this License, since you have not signed it. However,
nothing else grants you permission to modify or distribute the Library or its derivative
works. These actions are prohibited by law if you do not accept this License. Therefore,
by modifying or distributing the Library (or any work based on the Library), you
indicate your acceptance of this License to do so, and all its terms and conditions for
copying, distributing or modifying the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the Library), the recipient
automatically receives a license from the original licensor to copy, distribute, link with
or modify the Library subject to these terms and conditions. You may not impose any
further restrictions on the recipients’ exercise of the rights granted herein. You are not
responsible for enforcing compliance by third parties with this License.
11. If, as a consequence of a court judgment or allegation of patent infringement or for any
other reason (not limited to patent issues), conditions are imposed on you (whether by
court order, agreement or otherwise) that contradict the conditions of this License, they
do not excuse you from the conditions of this License. If you cannot distribute so as
to satisfy simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Library at all. For
example, if a patent license would not permit royalty-free redistribution of the Library
by all those who receive copies directly or indirectly through you, then the only way
you could satisfy both it and this License would be to refrain entirely from distribution
of the Library.
Appendix I: GNU Lesser General Public License 861
If any portion of this section is held invalid or unenforceable under any particular
circumstance, the balance of the section is intended to apply, and the section as a
whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or other
property right claims or to contest validity of any such claims; this section has the
sole purpose of protecting the integrity of the free software distribution system which
is implemented by public license practices. Many people have made generous contri-
butions to the wide range of software distributed through that system in reliance on
consistent application of that system; it is up to the author/donor to decide if he or
she is willing to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to be a consequence
of the rest of this License.
12. If the distribution and/or use of the Library is restricted in certain countries either
by patents or by copyrighted interfaces, the original copyright holder who places the
Library under this License may add an explicit geographical distribution limitation
excluding those countries, so that distribution is permitted only in or among countries
not thus excluded. In such case, this License incorporates the limitation as if written
in the body of this License.
13. The Free Software Foundation may publish revised and/or new versions of the Lesser
General Public License from time to time. Such new versions will be similar in spirit
to the present version, but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library specifies a version
number of this License which applies to it and “any later version”, you have the option of
following the terms and conditions either of that version or of any later version published
by the Free Software Foundation. If the Library does not specify a license version
number, you may choose any version ever published by the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free programs whose distribu-
tion conditions are incompatible with these, write to the author to ask for permission.
For software which is copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our decision will be
guided by the two goals of preserving the free status of all derivatives of our free soft-
ware and of promoting the sharing and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLI-
CABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPY-
RIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY “AS IS”
WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE
RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH
YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST
OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
862 Referência técnica para o MySQL versão 3.23.52
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your school, if any, to
sign a “copyright disclaimer” for the library, if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the library
‘Frob’ (a library for tweaking knobs) written by James Random Hacker.
(Index is nonexistent)
Concept Index 865
Concept Index
(Index is nonexistent)