22/03/2024
A programação eficiente com bancos de dados é uma das habilidades mais valorizadas no mundo do desenvolvimento web. Cometer erros nessa área pode não apenas prejudicar o desempenho do seu site ou sistema, mas também deixá-los vulneráveis a ataques.
Neste artigo, destacamos os 7 erros mais críticos em programação com bancos de dados e como evitá-los, focando nas soluções práticas.
Por que é um problema: Ataques de SQL Injection podem permitir que invasores manipulem suas consultas ao banco de dados, resultando em exposição, modificação ou destruição de dados. Este é um dos ataques mais antigos e perigosos na web devido à sua simplicidade e alta taxa de sucesso quando a aplicação não está devidamente protegida.
O que deve ser feito: Para se proteger contra SQL Injection, é fundamental utilizar consultas parametrizadas. Em PHP, isso pode ser feito com o uso de PDO (PHP Data Objects) ou mysqli, ambos suportam consultas preparadas. No ASP.NET, use parâmetros com SqlCommand ou o Entity Framework para evitar a injeção de SQL. Além disso, validar e sanitizar as entradas do usuário são práticas recomendadas que adicionam uma camada extra de segurança.
Recomendamos a leitura dos seguintes artigos:
Por que é um problema: A falta de chaves primárias, índices e relacionamentos adequados pode levar a uma degradação significativa no desempenho das consultas e na integridade dos dados. Chaves e índices facilitam a rápida recuperação de dados, enquanto os relacionamentos garantem a consistência dos dados entre as tabelas.
O que deve ser feito: Sempre defina chaves primárias para identificar unicamente as linhas em uma tabela. Use chaves estrangeiras para criar relacionamentos integrais entre tabelas e índices em colunas que são frequentemente usadas em buscas (WHERE) ou ordenações (ORDER BY). Isso não apenas acelera as consultas, mas também ajuda a manter a integridade dos dados.
Veja um exemplo de como criar um índice no campo nome
da tabela clientes
. O comando abaixo funciona tanto para MySQL como para SQL Server:
CREATE INDEX idx_nome ON clientes(nome);
Por que é um problema: O uso de tipos de dados inadequados pode aumentar desnecessariamente o uso de espaço em disco e memória, além de prejudicar o desempenho das consultas. Por exemplo, armazenar números em campos varchar
impede a otimização das consultas e cálculos numéricos eficientes.
O que deve ser feito: Sempre escolha o tipo de dado mais apropriado para a informação que será armazenada. Para dados numéricos, utilize tipos numéricos como INT
, FLOAT
ou DECIMAL
, dependendo da precisão necessária. Isso facilita operações matemáticas e melhora a performance das consultas. Certifique-se também de ajustar o tamanho dos campos para o que é realmente necessário, evitando desperdício de recursos.
Por que é um problema: O uso do operador LIKE com o caractere % no início e no final da string obriga o banco de dados a realizar uma varredura completa nos registros, o que pode ser extremamente ineficiente, especialmente em tabelas grandes.
O que deve ser feito: Para melhorar a performance de buscas textuais, considere a utilização de índices FULLTEXT, disponíveis tanto no MySQL quanto no SQL Server. Esses índices são otimizados para pesquisa de texto e permitem consultas mais eficientes sem a necessidade de varredura total. Além disso, avalie a possibilidade de reestruturar a consulta para evitar o uso de % no início da string, quando possível.
É importante destacar que buscas utilizando termo%
não afetam a performance negativamente como fazem %termo%
e %termo
, devido à forma como os índices são utilizados pelo banco de dados.
Por que é um problema: Ignorar a performance das consultas durante o desenvolvimento pode levar a surpresas desagradáveis quando a aplicação é colocada em produção, especialmente sob carga pesada. Isso resulta em tempos de resposta lentos e uma má experiência do usuário.
O que deve ser feito: Utilize ferramentas como o EXPLAIN
no MySQL ou o plano de execução no SQL Server para analisar como suas consultas são executadas e identificar possíveis gargalos. Ajustes e otimizações devem ser feitos antes da aplicação ir ao ar, tornando a revisão de consultas uma parte integrante do processo de desenvolvimento.
Veja um exemplo de output ao executar o EXPLAIN
no MySQL para uma consulta em uma tabela sem índices e com 10 mil registros:
EXPLAIN SELECT * FROM clientes WHERE nome = 'João';
Abaixo o exemplo de uma saída para o comando EXPLAIN
acima, caso a tabela clientes não tenha índices no campo nome:
id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra
1 | SIMPLE | clientes | NULL | ALL | NULL | NULL | NULL | NULL | 10000 | 10.00 | Using where
Este output mostra que o MySQL planeja escanear todos os 10 mil registros da tabela (rows
= 10000) usando um full table scan (type
= ALL), pois não existem índices que possam ser utilizados (possible_keys
= NULL), resultando em um processo ineficiente indicado pelo Extra
= Using where.
Para usuários do SQL Server, a visualização do plano de execução pode ser ativada selecionando a opção "Display Estimated Execution Plan" no menu de contexto do Management Studio, após escrever a consulta. Isso fornecerá uma visão detalhada do caminho de execução da consulta, incluindo o uso de índices.
Por que é um problema: Testar a aplicação apenas em condições ideais, com poucos dados, não reflete o ambiente real de produção. Isso pode mascarar problemas de performance que só se tornarão aparentes quando o sistema estiver sob carga pesada.
O que deve ser feito: Realize testes de stress e carga em seu ambiente de desenvolvimento, simulando o uso real da aplicação. Por exemplo, se você espera que uma tabela tenha 10 mil registros em um ano quando o sistema estiver em produção, faça os testes com 100 mil registros, desta forma você garante que seu sistema foi devidamente testado para utilização em uma situação real e que não apresentará lentidões ao longo do tempo.
É importante destacar que os testes devem ser feitos em ambiente de desenvolvimento e não de produção, para não afetar a experiência do usuário final.
Por que é um problema: De nada adianta ter um sistema seguro se o banco de dados está exposto para acesso remoto com uma senha de acesso sem critérios de complexidade. Uma senha fraca ou previsível pode ser o ponto fraco que permite a invasores obterem acesso irrestrito aos seus dados sensíveis.
O que deve ser feito: É essencial criar senhas de alta complexidade, que sejam longas e contenham uma combinação de letras maiúsculas e minúsculas, números e símbolos. Para mais dicas sobre como criar uma senha segura, confira o artigo Como escolher uma senha realmente segura.
Para clientes que hospedam na MCO2, oferecemos via painel a possibilidade de proteger o acesso remoto ao MySQL, tornando impossível o acesso aos dados a partir de conexões remotas não autorizadas.
Além disso, tanto hospedagens com MySQL quanto SQL Server na MCO2 contam com um mecanismo exclusivo de proteção que bloqueia o acesso remoto a IPs que tentem se autenticar com senhas incorretas repetidas vezes. Esta prática ajuda a evitar ataques de força-bruta, nos quais um invasor tenta inúmeras combinações de senhas na esperança de acertar a correta.
A adoção de boas práticas em programação de bancos de dados não só previne vulnerabilidades como também assegura a performance otimizada de suas aplicações. Concentrar esforços em segurança, testes de carga, e gestão eficaz de dados são etapas cruciais para o sucesso de qualquer projeto web. Com as diretrizes abordadas, sua aplicação estará mais preparada para oferecer uma experiência segura e eficiente aos usuários.