Uma correção feita por SQL pode resolver um campo e deixar a busca, os relacionamentos ou os totais do sistema incoerentes. O banco executa o comando recebido e não passa pelas conferências nem pelos cálculos da aplicação. Por isso, uma alteração direta no banco segue um procedimento próprio, com preparação, conferência e validação.
O que o SQL direto deixa de fora
- Conferências da aplicação: as regras de negócio e as ligações entre tabelas mantidas apenas no código.
- Marca de exclusão: o DELETE remove a linha, sem a marca que a aplicação usaria.
- Colunas derivadas: um UPDATE na coluna de origem não recalcula a coluna derivada.
- Registro das alterações: muitas aplicações anotam cada alteração para a sincronização com a matriz ou para a auditoria, e uma alteração direta não entra nesse registro.
- Identidade: um INSERT sem a coluna da chave primária recebe um identificador novo.
O SQL direto continua sujeito às permissões da conta e às regras declaradas no banco, como os tipos das colunas, os valores únicos e o modo estrito. O que ele contorna são as regras que existem só na aplicação.
A origem do dado
Antes de corrigir um dado na loja, convém saber de onde ele vem. Um preço enviado pela matriz e corrigido direto no banco da loja volta ao valor da matriz na próxima sincronização, ou passa a divergir dela. A correção de um dado que vem de outra origem é feita na própria origem.
Preparar a alteração
SELECT @@hostname, DATABASE();: confirma o servidor e o banco da conexão;SELECT id, nome FROM clientes WHERE id = 10;: mostra as linhas que a condição atinge;CREATE TABLE clientes_antes_20261008 AS SELECT * FROM clientes WHERE id = 10;: guarda uma cópia dessas linhas no próprio banco.
A cópia guarda o estado anterior das linhas e não precisa de índices. Por ser uma mudança de estrutura, esse comando confirma qualquer transação aberta e por isso vem antes da transação da correção. Uma alteração em muitas linhas pede, além dessa cópia, uma cópia de segurança da tabela inteira.
A preparação também identifica o que depende das linhas: as colunas derivadas, as tabelas que apontam para elas e o registro de alterações da aplicação.
Executar e conferir
START TRANSACTION;: abre a transação;UPDATE clientes SET nome = 'José da Silva' WHERE id = 10;: faz a correção, com a mesma condição do SELECT da preparação;SELECT id, nome FROM clientes WHERE id = 10;: confere o resultado na mesma conexão.
O número de linhas encontradas pelo UPDATE precisa bater com o SELECT da preparação. Um UPDATE que encontra a linha já com o valor pedido informa zero linhas alteradas, e isso não significa que a linha não existe. O comando SHOW WARNINGS; mostra os avisos do último comando, como um valor cortado em um servidor fora do modo estrito. Com o resultado conferido, o COMMIT confirma a correção, e, diante de qualquer diferença, o ROLLBACK a desfaz.
Essa proteção vale só para as tabelas InnoDB. Em uma tabela MyISAM, a correção vale no fim do próprio UPDATE, o ROLLBACK termina com o aviso 1196, sem desfazer nada, e a volta ao estado anterior depende da cópia guardada na preparação.
Se outras estações gravam na mesma tabela, a preparação e a alteração podem encontrar estados diferentes. Uma correção que atinge muitas linhas pede um horário de pouco movimento ou uma janela de manutenção combinada.
Depois da confirmação
A correção só termina depois de algumas etapas:
- a validação na própria aplicação, na tela, na busca e nos relatórios que usam os dados;
- o recálculo das colunas derivadas pela rotina da aplicação, quando a correção atingiu uma coluna de origem;
- o registro do que foi feito, com a data, a hora, o servidor, o banco, o comando, as linhas atingidas e o motivo;
- a remoção da tabela de cópia, depois da validação, conforme o procedimento da equipe.
Quando a conexão cai ou surge um erro
Em uma tabela InnoDB, quando a conexão cai antes do COMMIT, o MySQL desfaz a alteração pendente, e, quando cai depois, a alteração vale. Em uma tabela MyISAM, nada fica pendente. O que o comando gravou vale, e um comando interrompido no meio, por um KILL ou por uma parada abrupta do serviço, pode deixar só parte das linhas alteradas. Como nem sempre é possível saber em qual momento a queda aconteceu, a repetição de uma correção começa pela consulta aos dados. A repetição cega de uma alteração acumulativa aplica o valor duas vezes:
UPDATE produtos SET estoque = estoque + 5 WHERE id = 315;: soma cinco unidades ao estoque a cada execução.
Um erro no meio da transação também exige atenção. O tempo de espera esgotado desfaz só a instrução que esperou, o deadlock desfaz a transação inteira, e o estado da conexão precisa ser conferido antes de qualquer COMMIT.
No suporte
Antes de confirmar uma correção feita por SQL, convém conferir a condição, guardar o estado anterior das linhas e validar o resultado na mesma conexão. Quando a correção atinge uma coluna de origem, a forma de manter as colunas derivadas precisa estar definida antes. O COMMIT só encerra uma correção cujo efeito foi compreendido.
Para guardar
- O SQL direto contorna as regras e os cálculos que existem só na aplicação.
- Um dado que vem da matriz é corrigido na origem.
- A preparação confirma o servidor e o banco, mostra as linhas atingidas e guarda o estado anterior.
- Nas tabelas InnoDB, a transação permite conferir o resultado antes do COMMIT, e, nas MyISAM, só a cópia permite voltar atrás.
- Depois de uma queda, a repetição começa pela consulta aos dados.
Depois de um UPDATE errado, o ROLLBACK não desfez nada. O que conferir?
Se a confirmação automática estava ligada, sem START TRANSACTION, se houve um COMMIT ou um comando de estrutura no meio, se o ROLLBACK foi enviado pela mesma conexão e se a tabela é MyISAM. Em qualquer desses casos, a alteração já valia. A recuperação usa a cópia do estado anterior guardada na preparação.
A conexão caiu logo depois de um UPDATE que somava cinco unidades ao estoque de um produto. É seguro repetir o comando?
Não sem conferir os dados. Em uma tabela InnoDB, se a queda aconteceu antes da confirmação, a alteração foi desfeita, e, se aconteceu depois, a alteração vale. Em uma tabela MyISAM, a alteração vale desde o fim do comando. Repetir sem conferir pode somar as cinco unidades duas vezes. A comparação do estoque atual com o valor guardado na preparação mostra o que aconteceu.