Tutoriais de VPS
MySQL / MariaDB não conecta na VPS (2026): solução de problemas da porta 3306, bind-address, privilégios e falhas de inicialização do serviço
Quando o MySQL ou MariaDB não conecta na VPS, a causa comum não é uma só: o serviço não iniciou, a 3306 não está escutando, o bind-address só vincula ao localhost, o firewall/grupo de segurança bloqueia, os privilégios do usuário estão errados, o disco está cheio ou o InnoDB não inicia. Este artigo diagnostica camada por camada: conexão local, escuta de portas, logs, acesso remoto e estado do banco de dados.

Quando o MySQL ou MariaDB não conecta, muitos sites simplesmente caem.
O WordPress exibe:
Error establishing a database connection
No log da aplicação pode aparecer:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket
ERROR 2003 (HY000): Can't connect to MySQL server on 'x.x.x.x'
Access denied for user
Connection refused
Lost connection to MySQL server
Todos esses erros parecem "o banco de dados quebrou", mas a causa raiz pode ser completamente diferente: o serviço não iniciou, a porta não está escutando, o caminho do socket está errado, o disco está cheio, o MySQL só escuta em 127.0.0.1, o firewall bloqueia a 3306, os privilégios do usuário estão errados ou até o InnoDB não inicia.
Este artigo segue uma ordem de diagnóstico: primeiro distinga se a falha é de conexão local ou remota, depois verifique o serviço, a porta, os logs, os privilégios e o disco. Não abra a 3306 para a internet pública de imediato nem reinstale o banco de dados diretamente.
Primeiro teste na própria VPS:
mysql -u root -p
Ou:
mysqladmin -u root -p ping
Se nem localmente você consegue conectar, verifique primeiro o serviço e os logs.
Se você consegue conectar localmente, mas um computador remoto não:
mysql -h 你的VPS_IP -P 3306 -u 用户名 -p
Então foque no endereço de escuta, firewall, grupo de segurança e privilégios do usuário.
Esse passo é fundamental. Muitas pessoas não conseguem conectar remotamente e vão alterar a senha do banco de dados; na verdade a conexão local funciona bem e o problema está na camada de rede. Outras não conseguem conectar nem localmente e ficam mexendo no grupo de segurança, uma direção completamente errada.
No Ubuntu/Debian o nome do serviço pode ser mysql ou mariadb.
Primeiro veja:
systemctl status mysql --no-pager
systemctl status mariadb --no-pager
Se não tiver certeza do nome do serviço:
systemctl list-units | grep -Ei 'mysql|mariadb'
Veja os logs recentes:
journalctl -u mysql --since "30 minutes ago" --no-pager
journalctl -u mariadb --since "30 minutes ago" --no-pager
Se o serviço não estiver iniciado, primeiro tente:
sudo systemctl restart mysql
Ou:
sudo systemctl restart mariadb
Após reiniciar, não verifique apenas se o comando retornou algo; veja novamente o status e os logs. Muitas falhas de inicialização do MySQL/MariaDB têm a causa real escrita nos logs.
Locais comuns do log:
/var/log/mysql/error.log
/var/log/mariadb/mariadb.log
/var/log/mysql/mysql.log
Você pode encontrá-lo assim:
sudo ls -lh /var/log/mysql/ /var/log/mariadb/ 2>/dev/null
sudo tail -n 100 /var/log/mysql/error.log
Se esse arquivo não existir, você também pode usar o journal:
journalctl -u mysql -n 100 --no-pager
journalctl -u mariadb -n 100 --no-pager
Palavras-chave comuns:
| Palavra-chave do log | Direção comum |
|---|---|
No space left on device | Disco ou inodes cheios |
Can't create/write to file | Problemas de permissão, disco ou diretório temporário |
InnoDB: Database was not shutdown normally | Recuperação após desligamento anormal |
InnoDB: Unable to lock ./ibdata1 | Outro processo mysqld ou bloqueio de arquivo |
Bind on TCP/IP port: Address already in use | A 3306 está em uso |
Access denied for user | Problemas de usuário, senha ou privilégios |
Too many connections | Limite de conexões atingido |
Os logs são mais confiáveis do que suposições. Veja os logs primeiro e depois decida o próximo passo.
O MySQL/MariaDB é muito sensível ao disco. Disco do sistema cheio, inodes cheios ou um /tmp sem permissão de escrita podem causar falha de inicialização ou de escrita.
Primeiro veja:
df -h
df -i
Depois veja o tamanho do diretório do banco de dados:
sudo du -h --max-depth=1 /var/lib/mysql | sort -h
Se o disco estiver cheio, não apague /var/lib/mysql sem cuidado. Esse é o diretório de dados do banco de dados; apagar errado significa perda de dados.
Você pode priorizar a limpeza de:
sudo apt clean
journalctl --disk-usage
sudo journalctl --vacuum-time=7d
Se os binlogs do MySQL estiverem grandes, também não faça rm diretamente. Primeiro entre no MySQL e consulte:
SHOW BINARY LOGS;
Depois decida se limpa conforme a situação de backup e replicação. Se não tiver certeza, faça primeiro um snapshot ou backup.
Se o serviço aparece como running, mas não conecta de fora, veja primeiro a porta:
ss -lntp | grep 3306
Você pode ver:
127.0.0.1:3306
0.0.0.0:3306
[::]:3306
A diferença é grande:
127.0.0.1:3306: permite apenas conexões locais0.0.0.0:3306: escuta em todos os endereços IPv4[::]:3306: escuta em IPv6; o comportamento exato depende da configuração
Se você só tem WordPress e MySQL na mesma VPS, 127.0.0.1 é na verdade mais seguro e você não precisa abrir para a internet pública.
Se você realmente precisa de conexões remotas, por exemplo com o servidor de aplicação e o banco de dados separados, então considere fazer o MySQL escutar em um IP interno ou em um IP público específico.
O endereço de escuta do MySQL/MariaDB normalmente é controlado por bind-address.
Consulte a configuração:
sudo grep -R "bind-address" /etc/mysql/ /etc/my.cnf* 2>/dev/null
Configurações comuns:
bind-address = 127.0.0.1
Se você quiser permitir conexões remotas, pode alterar para:
bind-address = 0.0.0.0
Mas aqui é preciso muito cuidado. 0.0.0.0 significa escutar em todas as interfaces de rede, o que não equivale a permitir o acesso com segurança. Também é preciso combinar com firewall, grupo de segurança e privilégios de usuário, permitindo acesso apenas de IPs confiáveis.
É mais recomendável vincular a um endereço interno, por exemplo:
bind-address = 10.0.0.5
Reinicie após a alteração:
sudo systemctl restart mysql
ss -lntp | grep 3306
Quando não conecta na 3306 remotamente, muitas vezes não é o MySQL em si, mas o firewall ou o grupo de segurança do provedor de nuvem.
Firewall local:
sudo ufw status verbose
sudo iptables -S
Se usar firewalld:
sudo firewall-cmd --list-all
Também verifique o grupo de segurança do provedor de nuvem:
- Se a 3306 de entrada está liberada
- Se o IP de origem está restrito ao seu servidor de aplicação ou IP do escritório
- Se o protocolo ou a interface de rede foram configurados errados
- Se só foi liberado IPv4 enquanto o tráfego vai na verdade por IPv6
Não abra a 3306 diretamente para 0.0.0.0/0. Expor o banco de dados à internet pública é muito arriscado; ataques de força bruta e varreduras vão encontrá-lo rapidamente.
Se for apenas para administração temporária, prefira um túnel SSH:
ssh -L 3307:127.0.0.1:3306 root@你的VPS_IP
Depois conecte localmente:
mysql -h 127.0.0.1 -P 3307 -u 用户名 -p
Assim o banco de dados continua escutando apenas localmente e o acesso remoto passa por um túnel SSH criptografado.
Os usuários do MySQL são diferenciados por 用户名@来源主机. app@localhost e app@% são duas autorizações diferentes.
Após entrar no MySQL, veja os usuários:
SELECT user, host FROM mysql.user;
Veja os privilégios:
SHOW GRANTS FOR 'app'@'localhost';
SHOW GRANTS FOR 'app'@'%';
Se o IP do servidor de aplicação remoto for 10.0.0.8, a abordagem mais segura é autorizar apenas essa origem:
CREATE USER 'app'@'10.0.0.8' IDENTIFIED BY '强密码';
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'app'@'10.0.0.8';
FLUSH PRIVILEGES;
Não faça isso diretamente para economizar esforço:
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'password';
Esse tipo de configuração é um foco comum de incidentes. Dê ao usuário da aplicação apenas os bancos de dados e privilégios necessários, e não exponha o root remotamente.
Se aparecer:
Access denied for user 'app'@'x.x.x.x'
Verifique especialmente:
- Se o nome de usuário está correto
- Se a senha está correta
- Se
hostcorresponde ao IP de origem - Se a aplicação está conectando à instância de banco de dados correta
- Se o plugin de autenticação do MySQL 8 é compatível com o cliente
Veja o usuário atual:
SELECT user, host, plugin FROM mysql.user;
O plugin de autenticação padrão do MySQL 8 pode tornar clientes antigos incompatíveis. Não altere o root às cegas; você pode definir um plugin compatível apenas para o usuário da aplicação, ou atualizar o cliente.
Se o log ou a aplicação exibir:
Too many connections
Primeiro veja as conexões atuais:
SHOW PROCESSLIST;
SHOW STATUS LIKE 'Threads_connected';
SHOW VARIABLES LIKE 'max_connections';
Você pode aumentar temporariamente:
SET GLOBAL max_connections = 200;
Mas isso é apenas temporário. A longo prazo, verifique:
- Se o pool de conexões da aplicação está configurado grande demais
- Se há consultas lentas travando conexões
- Se há tráfego de rastreadores ou ataques
- Se o número de processos PHP-FPM/aplicação excede a capacidade do banco de dados
- Se a máquina do banco de dados tem memória suficiente
Em uma VPS pequena, definir max_connections para 1000 às cegas pode estourar a memória diretamente.
Se o MySQL/MariaDB roda no Docker, veja primeiro o contêiner:
docker ps
docker logs 容器名 --tail 100
docker compose ps
docker compose logs --tail 100 mysql
Veja o mapeamento de portas:
docker ps --format 'table {{.Names}}\t{{.Ports}}'
Teste dentro do contêiner:
docker exec -it 容器名 mysql -u root -p
Teste no host:
mysql -h 127.0.0.1 -P 3306 -u root -p
Armadilhas comuns do Docker:
- Permissões erradas do volume de dados
- Diretório de dados montado errado
- Variáveis de ambiente só têm efeito na primeira inicialização; alterá-las depois não adianta
- A escuta dentro do contêiner funciona, mas a porta não está mapeada para o host
- O contêiner da aplicação deveria conectar ao nome de serviço
mysql, mas conecta a127.0.0.1
Em cenários Docker, 127.0.0.1 é relativo ao próprio contêiner, não necessariamente ao host.
Se o site informar falha de conexão ao banco de dados, eu normalmente verifico assim:
systemctl status mysql --no-pager
systemctl status mariadb --no-pager
journalctl -u mysql --since "30 minutes ago" --no-pager
sudo tail -n 100 /var/log/mysql/error.log
Veja o disco:
df -h
df -i
sudo du -h --max-depth=1 /var/lib/mysql | sort -h
Veja a porta:
ss -lntp | grep 3306
Conexão local:
mysqladmin -u root -p ping
mysql -u root -p
Só para acesso remoto, verifique:
sudo ufw status verbose
sudo iptables -S
sudo grep -R "bind-address" /etc/mysql/ /etc/my.cnf* 2>/dev/null
Após entrar no MySQL, consulte:
SELECT user, host, plugin FROM mysql.user;
SHOW PROCESSLIST;
SHOW VARIABLES LIKE 'max_connections';
Com essa ordem, você basicamente consegue classificar o problema em serviço, disco, escuta, rede, privilégios ou número de conexões.
- Se o
mysql -u root -plocal consegue conectar - Se
systemctl status mysql/mariadbestá normal - Se
journalctle error.log têm erros claros - Se
df -hedf -iestão normais - Se
/var/lib/mysqlcresceu de forma anormal - Se
ss -lntp | grep 3306está escutando - Se
bind-addresscorresponde ao esperado - Se UFW / iptables / firewalld está bloqueando
- Se o grupo de segurança do provedor de nuvem só libera IPs confiáveis
- Se o
user@hostdo usuário do MySQL corresponde à origem - Se há
Too many connections - Em cenários Docker, se foram verificados logs do contêiner, mapeamento de portas e volumes de dados
- A 3306 não foi exposta sem proteção para toda a rede
O pior em problemas de conexão ao banco de dados é verificar as coisas de forma misturada. Se não conecta localmente, verifique primeiro o serviço e os logs; se conecta localmente mas não remotamente, verifique então a escuta, o firewall, o grupo de segurança e os privilégios. Basta separar essas camadas para que as falhas de conexão do MySQL/MariaDB deixem de ser mágica.