Database connection error: fix 'Cannot connect to MySQL server on host'
Can't connect to MySQL? Here's what's actually happening and how to fix it. We'll cover the three most common causes in order.
MySQL server isn't running (most common)
Here's the thing: if the MySQL server process died or never started, your client can't connect. You'll see error 2003 with "Can't connect to MySQL server on 'hostname'" in the message.
Check it right away:
# On Linux (systemd)
systemctl status mysql
# Or for MariaDB
systemctl status mariadb
# On older systems
service mysql status
# On macOS (Homebrew)
brew services list | grep mysql
# On Windows (PowerShell as admin)
Get-Service MySQL*If it's not running, start it:
sudo systemctl start mysql
# Or
sudo service mysql startBut don't just start it and walk away. Find out why it stopped. Common reasons:
- Out of memory — MySQL got killed by OOM killer. Check
dmesg | grep -i oomorjournalctl -k | grep -i oom. - Corrupted tables after a crash — MySQL refuses to start. Check
journalctl -u mysqlfor InnoDB corruption errors. - Disk full — MySQL can't write to its data directory.
df -htells you. - Config error — a typo in
my.cnformy.iniprevents startup. Runmysqld --validate-config.
The real fix isn't just restarting the service — it's addressing whatever killed it in the first place. For OOM issues, reduce innodb_buffer_pool_size or add swap. For corruption, restore from backup or attempt repair with mysqlcheck -r.
MySQL is bound to localhost only (second most common)
This one trips everyone up. MySQL's default configuration only listens on 127.0.0.1 (localhost). If you're connecting from a different machine — or even from the same machine but using the external IP — MySQL will reject the connection.
Verify what MySQL is actually listening on:
# On Linux
ss -tlnp | grep 3306
# Shows something like:
# LISTEN 0 70 127.0.0.1:3306 0.0.0.0:* users:(("mysqld",pid=1234,fd=24))
# If it says 127.0.0.1:3306, it's localhost-only.
# On macOS
lsof -i :3306 | grep LISTEN
# On Windows (PowerShell as admin)
netstat -ano | findstr :3306If you see 127.0.0.1:3306 instead of 0.0.0.0:3306 or :::3306, you need to change the bind-address setting.
Edit your MySQL config file. On Linux it's /etc/mysql/my.cnf or /etc/my.cnf or inside /etc/mysql/mysql.conf.d/mysqld.cnf. On macOS with Homebrew it's /usr/local/etc/my.cnf. On Windows it's C:\ProgramData\MySQL\MySQL Server X.Y\my.ini.
Find or add this line under the [mysqld] section:
bind-address = 0.0.0.0
# Or for IPv6 also:
bind-address = ::Then restart MySQL:
sudo systemctl restart mysqlBut wait — setting 0.0.0.0 means MySQL listens on all network interfaces. If your server is directly exposed to the internet, this is a security risk. Better approach: bind to a specific internal IP if you can.
bind-address = 192.168.1.100 # Your server's internal IPAnd don't forget to check skip-networking in the config. If that line is present (uncommented), MySQL won't listen on TCP at all — only on Unix sockets. Comment it out:
# skip-networkingFirewall is blocking port 3306 (third most common)
Even if MySQL is running and listening on all interfaces, the firewall on the server (or somewhere between the client and server) can block port 3306. This is especially common on cloud VPS or servers with ufw, firewalld, or iptables.
First, test from the server itself:
telnet localhost 3306
# Should show something like:
# Trying 127.0.0.1...
# Connected to localhost.
# Escape character is '^]'.
# J
# 5.7.42-log...Then test from a remote machine:
telnet YOUR_SERVER_IP 3306
# If it hangs or says "Connection refused" or "No route to host", the firewall is blocking.On the server, check the firewall:
# For ufw (Ubuntu/Debian)
sudo ufw status
# For firewalld (RHEL/CentOS/Fedora)
sudo firewall-cmd --list-all
# For iptables directly
sudo iptables -L -n | grep 3306If port 3306 isn't allowed, open it:
# ufw
sudo ufw allow from ANY_IP to any port 3306
# Better: restrict to specific IPs
sudo ufw allow from 192.168.1.50 to any port 3306 proto tcp
# firewalld
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --reloadBut here's the nuanced part: on cloud providers (AWS, DigitalOcean, Linode, etc.), there's often a separate security group or firewall layer outside the OS. Check that too. AWS security groups need an inbound rule for port 3306 from your client IP or subnet. DigitalOcean's cloud firewall works the same way.
Quick-reference summary
| Cause | Symptoms | Fix |
|---|---|---|
| MySQL not running | systemctl status mysql shows dead; connection timeout | Start the service, fix underlying issue (OOM, corruption, disk full) |
| Bind to localhost only | Can connect from localhost but not from remote; ss -tlnp shows 127.0.0.1:3306 | Set bind-address = 0.0.0.0 or internal IP; restart MySQL |
| Firewall blocking port 3306 | Telnet from remote fails; local telnet works | Open port in OS firewall and cloud security group |
That's the three reasons in order. Start with the first one because it's the quickest to check and the most common. Don't skip the underlying cause when restarting the service — it'll just die again.
Was this solution helpful?