Desde a versão 3.23.6 o MySQL suporta três tipos de tabelas: ISAM, HEAP e MyISAM. As versões mais recentes também suportam o tipo InnoDB e MERGE.
InnoDB
Adicionado ao MySQL desde a versão 3.23.34a, já está sendo utilizado por sites que recebem muitos acessos e que necessitam de alta perfomance, como é o caso do Slashdot.org. Foi considerado estável desde a versão 3.23.49, e são esperadas muitas melhorias na versão 3.23.50. Seguem abaixo algumas características adicionadas ao MySQL quando se utilizam as tabelas InnoDB:
Suporte a transações (transaction-safe):
Uma transação compreende um ou mais comandos para a manipulação de dados que devem ser executados como se fossem apenas um. O exemplo mais simples é o caso de um sistema para bancos.
Quando um correntista faz uma transferência entre duas contas, o sistema deve subtrair o valor da transferência do saldo da conta de origem e adicionar este valor à conta destino. Ao iniciar a transação, devemos informar ao banco de dados que ele deve criar a transação:
BEGIN;
E, em seguida, enviar os comandos SQL:
UPDATE contas SET saldo = saldo - 100 WHERE conta = "origem";
UPDATE contas SET saldo = saldo + 100 WHERE conta = "destino";
Ao enviarmos todos os comandos necessários (pode haver outros, como criar os lançamentos em outros arquivos e assim por diante) devemos informar ao BD que a transação acabou e que ele pode gravar os dados:
COMMIT;
Caso a conta destino não possa receber o valor informado por estar fechada, podemos cancelar todos os comandos enviados desde o BEGIN. Mas para isso, o comando COMMIT não pode ter sido enviado:
ROLLBACK;
E pronto, tudo volta a ser como antes. Embora apenas dois comandos SQL sejam executados pelo BD em menos de um segundo, este tempo "ínfimo" pode ser o necessário para tudo dar errado em caso de falta de luz ou falha de hardware.
Recuperação de falhas (crash recovery):
Seguindo o mesmo exemplo acima, no caso de uma falha no hardware ou qualquer outro inconveniente, um COMMIT mal sucedido será revertido ao estado anterior pelo engine InnoDB, que utiliza logs para gravar as últimas transações e recuperar as tabelas em caso de erro. Com isso, diminui-se a possibilidade de "sumir o dinheiro" no caso da aplicação citada acima. Para recuperar uma falha, basta apenas reiniciar o MySQL e o engine InnoDB se encarregará do resto.
Bloqueio de registros (row-level locking):
Como exemplo, dois operadores irão atualizar o valor de uma conta corrente: o cliente 1 irá adicionar R$ 100,00 e o cliente 2 irá subtrair R$ 50,00. Só que as duas operações ocorrem simultaneamente.
Sem o bloqueio, os clientes 1 e 2 lêem o saldo de uma conta como R$800,00, o primeiro adiciona R$ 100,00 e grava no BD o saldo de R$ 900,00. O cliente 2 subtrai R$ 50,00 e grava R$ 750,00. Nesta situação, os R$ 100,00 depositados sumiram!
Ao se utilizar o bloqueio, aquele cliente que leu o registro primeiro pode bloquear a tabela até gravar as alterações, e o segundo cliente fica esperando liberar o bloqueio.
As tabelas MyISAM têm suporte a bloqueio por tabela, ou seja, mesmo que outro cliente deseje alterar o valor de outro registro, deve aguardar que outros clientes gravem os dados primeiro e liberem a tabela. Já no caso das tabelas InnoDB o bloqueio pode ser feito por registro, deixando a aplicação muito mais rápida. E para melhorar a situação, o engine InnoDB ocupa pouca memória por registro bloqueado.
Para bloquear um ou mais registros para leitura, basta adicionar ao final da query os comandos: LOCK IN SHARE MODE (Ex.: SELECT * FROM tabela WHERE codigo=1 LOCK IN SHARE MODE). Este modo de bloqueio serve quando se deseja bloquear um registropai para adicionar um registro-filho, e ter certeza que o registro-pai existirá quando for feita a inserção do registro-filho.
Ao fazer alteração no registro, utilize no final da query o comando FOR UPDATE (Ex.: SELECT * FROM tabela WHERE codigo=1 FOR UPDATE). Todos os registros selecionados serão bloqueados. O bloqueio termina quando for enviado o comando COMMIT.
Integridade referencial (FOREIGN KEY constraints):
Em uma aplicação que utilize o MySQL, deve-se certificar que ao tentar apagar um registro-pai, os filhos também devem ser apagados ou a exclusão deve ser cancelada. Com a utilização de foreign keys deixamos esta tarefa para o MySQL.
Na versão atual do MySQL (3.23.49), o suporte é para apenas a restrição de índices. Mas a partir da versão 3.23.50, o suporte se estende para excluir os registros-filho ou deixar o valor deles como nulo (NULL).
Os índices na tabela-filho não são criados automaticamente, e devem ser criados anteriormente.
Para criar as tabelas siga o exemplo abaixo:
CREATE TABLE tabela_pai ( codigo INT NOT NULL, PRIMARY KEY (codigo)) TYPE=INNODB;
CREATE TABLE tabela_filho( codigo INT, codigo_pai INT,INDEX tabpai_ind (codigo_pai), FOREIGN KEY (codigo_pai) REFERENCES tabela_pai(codigo) ON DELETE CASCADE ) TYPE=INNODB;
A criação do índice segue a seguinte sintaxe: FOREIGN K E Y ( c o l u n a _ d a _ t a b e l a _ f i l h a ) R E F E R E N C E S nome_da_tabela_pai (campo_na_tabela_pai). Onde campo_na_tabela_pai deve ser um índice exclusivo e coluna_da_tabela_filha deve ter um índice apenas para um campo, assim como codigo na tabela_pai e codigo_pais na tabela_filho devem ser do mesmo tipo e, dependendo do tipo, do mesmo tamanho.
Deve-se atentar para um problema na versão atual do MySQL. Quando existem tabelas com relacionamentos, não se deve usar o comando ALTER TABLE nas mesmas, ou os relacionamentos serão perdidos. Para se alterar uma tabela com relacionamento ou até mesmo criar mais relacionamentos é necessário excluir a tabela e recriá-la com as alterações necessárias. A partir da versão 3.23.50 será possível utilizar o comando ALTER TABLE nessas tabelas.
Como ativar o InnoDB no MySQL
O InnoDB vem incorporado ao MySQL, mas desativado nas versões 3.23. Os seguintes requisitos são necessários para utilizar o InnoDB:
editar o arquivo my.cnf e inserir as seguintes configurações na seção [mysqld]:
innodb_data_home_dir = /var
innodb_data_file_path = ibdata1:100M
A primeira linha informa ao MySQL onde o InnoDB irá criar os arquivos que guardam as tabelas, o default é o mesmo onde ele cria os arquivos MyISAM (datadir). A segunda linha informa os nomes dos arquivos para guardar as tabelas. Pode ser informado mais de um arquivo, separando cada um por ponto-e-vírgula, como por exemplo:
innodb_data_file_path = ibdata1:100M;ibdata2:100M
Neste exemplo são criados dois arquivos para o InnoDB. Depois de definido um arquivo, seu tamanho não pode ser alterado. No caso de falta de espaço no arquivo, basta criar mais um.
A partir da versão 3.23.50 pode-se adicionar o parâmetro autoextend para aumento automático do arquivo, e a partir da versão 4.0 não será necessário especificar o arquivo, já que por padrão será criado um de 16Mb ou 64Mb com o "autoextend" acionado..
Uma boa escolha
O que já era bom está ficando cada vez melhor. O MySQL é sem dúvida uma ótima opção na hora da decisão sobre qual Banco de Dados utilizar em uma aplicação. Seja a aplicação para web, cliente-servidor ou até mesmo desktop, o MySQL consome poucos recursos e possibilita um aumento de performance em servidores pesados.
Um benchmark realizado pela eWeek mostra que o MySQL, utilizando tabelas MyISAM e InnoDB, consegue se equiparar ao Oracle em termos de performance, batendo pesos-pesados como DB2, MS-SQL Server e Sybase ASE.
Para saber mais
MySQL: www.mysql.com
InnoDB: www.innodb.com
BerkeleyDB: www.sleepycat.com
Paulo Machado Ottani Assis - paulo@coral.srv.br