This MySQL connection error occurs when the client cannot establish a TCP/IP connection to the MySQL server at the specified host and port. The error typically indicates that the MySQL server is not running, a firewall is blocking the connection, the bind-address configuration is restricting remote access, or there are network connectivity issues between the client and server.
The CR_CONN_HOST_ERROR (2003) is a MySQL client error that occurs when attempting to connect to a MySQL server over TCP/IP network connections. Unlike error 2002 which relates to socket connections, error 2003 specifically applies to network-based connections using hostname/IP and port. Key aspects of this error: 1. **TCP/IP Communication**: This error occurs during TCP/IP connection attempts, whether to localhost (127.0.0.1), local network servers, or remote database servers. The client is unable to establish a network socket connection to the MySQL server. 2. **Connection Refused vs Timeout**: The error may manifest as "connection refused" (server actively rejected) or timeout (no response received). Connection refused typically means the port is not listening, while timeout suggests network/firewall issues. 3. **Server Availability**: The MySQL server process must be running and actively listening on the specified port (default 3306). If the server is down, the connection will fail immediately. 4. **Network Path**: The entire network path between client and server must be functional - DNS resolution, routing, firewall rules, and port accessibility all play a role. This error is extremely common in production environments, remote database connections, containerized deployments, cloud infrastructure, and any scenario involving network-based database access.
First, confirm the MySQL server process is active on the target host:
# Check MySQL service status
sudo systemctl status mysql
# or
sudo systemctl status mysqld
# Check if MySQL process is running
ps aux | grep mysqld
sudo pgrep -a mysql
# Check which port MySQL is listening on
sudo netstat -tlnp | grep mysql
sudo ss -tlnp | grep mysql
# Should show: tcp 0 0 0.0.0.0:3306 or 127.0.0.1:3306
# Start MySQL if not running
sudo systemctl start mysql
# or
sudo service mysql start
# Check MySQL error logs for startup issues
sudo tail -50 /var/log/mysql/error.log
sudo journalctl -u mysql -n 50If MySQL won't start, check for port conflicts or configuration errors in the error log.
Verify the client can reach the MySQL server port:
# Test connection to MySQL port using telnet
telnet mysql-server.example.com 3306
# or
telnet 192.168.1.100 3306
# Alternative: use nc (netcat)
nc -zv mysql-server.example.com 3306
# Test from the client machine
# If connection succeeds, you'll see MySQL version banner
# If it fails with "Connection refused", MySQL isn't listening
# If it hangs/times out, firewall or network issue
# Check DNS resolution
ping mysql-server.example.com
dig mysql-server.example.com
nslookup mysql-server.example.com
# Test with IP address to rule out DNS issues
mysql -h 192.168.1.100 -u root -pConnection refused = server not listening. Timeout = firewall/network blocking.
MySQL's bind-address controls which network interfaces accept connections:
# Check current bind-address setting
mysql -e "SHOW VARIABLES LIKE 'bind_address';"
# Output meanings:
# 127.0.0.1 or localhost = local connections only (causes error 2003 remotely)
# 0.0.0.0 or * = listen on all interfaces (allows remote connections)
# Specific IP = listen only on that interface
# Edit MySQL configuration file
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
# or
sudo nano /etc/my.cnf
# Find and modify bind-address:
[mysqld]
# For remote connections from any interface:
bind-address = 0.0.0.0
# Or for specific network interface:
bind-address = 192.168.1.100
# Make sure skip-networking is NOT enabled:
# skip-networking # Remove or comment out this line
# Restart MySQL to apply changes
sudo systemctl restart mysql
# Verify MySQL is now listening on all interfaces
sudo netstat -tlnp | grep :3306
# Should show: 0.0.0.0:3306 instead of 127.0.0.1:3306Important: Allowing remote connections requires proper firewall rules and user permissions.
Allow incoming connections on port 3306 through your firewall:
# Ubuntu/Debian with UFW
sudo ufw allow 3306/tcp
sudo ufw allow from 192.168.1.0/24 to any port 3306 # Specific subnet
sudo ufw status
# CentOS/RHEL with firewalld
sudo firewall-cmd --permanent --add-service=mysql
# or specific port:
sudo firewall-cmd --permanent --add-port=3306/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
# Direct iptables (if not using ufw/firewalld)
sudo iptables -A INPUT -p tcp --dport 3306 -j ACCEPT
sudo iptables -L -n | grep 3306
sudo iptables-save > /etc/iptables/rules.v4 # Save rules
# AWS Security Group (using AWS CLI)
aws ec2 authorize-security-group-ingress \
--group-id sg-0123456789abcdef0 \
--protocol tcp \
--port 3306 \
--cidr 0.0.0.0/0 # Or restrict to specific IPs
# Google Cloud Firewall
gcloud compute firewall-rules create allow-mysql \
--allow tcp:3306 \
--source-ranges 0.0.0.0/0
# Test after firewall changes
nc -zv your-server-ip 3306Security note: Restrict access to trusted IPs rather than allowing 0.0.0.0/0 in production.
Even with network access, MySQL user accounts must allow connections from the client host:
-- Connect to MySQL on the server
mysql -u root -p
-- Check which hosts the user can connect from
SELECT user, host FROM mysql.user WHERE user = 'your_username';
-- Common host values:
-- 'localhost' = local connections only (won't work remotely)
-- '%' = any host (allows all remote connections)
-- '192.168.1.%' = specific subnet
-- 'client.example.com' = specific hostname
-- Grant remote access to existing user
GRANT ALL PRIVILEGES ON database_name.*
TO 'username'@'%'
IDENTIFIED BY 'password';
-- Or create new user with remote access
CREATE USER 'username'@'%' IDENTIFIED BY 'strong_password';
GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'%';
-- For specific IP or subnet
CREATE USER 'username'@'192.168.1.%' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'192.168.1.%';
-- Apply changes
FLUSH PRIVILEGES;
-- Test connection from client
mysql -h mysql-server-ip -u username -pMySQL authenticates based on username AND connecting host - both must match.
Verify your application is using the correct connection parameters:
# Check what port MySQL is actually listening on
mysql -e "SHOW VARIABLES LIKE 'port';"
sudo netstat -tlnp | grep mysql
# Common MySQL ports:
# 3306 = default MySQL
# 3307, 3308 = alternate ports (multiple instances)
# 33060 = MySQL X ProtocolVerify connection strings in your application:
// PHP PDO - correct format
$dsn = "mysql:host=192.168.1.100;port=3306;dbname=mydb";
$pdo = new PDO($dsn, $username, $password);
// PHP mysqli
$mysqli = new mysqli("192.168.1.100", $user, $pass, $db, 3306);# Python mysql-connector
import mysql.connector
config = {
'host': '192.168.1.100',
'port': 3306, # Explicit port
'user': 'username',
'password': 'password',
'database': 'mydb',
'connect_timeout': 10 # Avoid long hangs
}
connection = mysql.connector.connect(**config)// Node.js mysql2
const mysql = require('mysql2/promise');
const connection = await mysql.createConnection({
host: '192.168.1.100',
port: 3306,
user: 'root',
password: 'password',
database: 'mydb',
connectTimeout: 10000
});# Environment variables in .env files
DB_HOST=192.168.1.100
DB_PORT=3306
DB_USER=username
DB_PASSWORD=password
DB_NAME=databaseDouble-check for typos in hostname, IP address, and port number.
Security policies may block MySQL network connections:
# Check SELinux status (CentOS/RHEL)
getenforce
# If "Enforcing", check for MySQL denials
sudo ausearch -m avc -ts recent | grep mysql
sudo grep mysql /var/log/audit/audit.log
# Allow MySQL to connect to network
sudo setsebool -P mysql_connect_any 1
# Or temporarily disable to test (not for production)
sudo setenforce 0
# Re-enable after testing:
sudo setenforce 1
# Check AppArmor (Ubuntu/Debian)
sudo aa-status | grep mysql
# View AppArmor denials
sudo dmesg | grep DENIED | grep mysql
sudo journalctl | grep apparmor | grep mysql
# Edit AppArmor profile if needed
sudo nano /etc/apparmor.d/usr.sbin.mysqld
# Reload AppArmor profile
sudo systemctl reload apparmor
# Temporarily disable AppArmor for MySQL (testing only)
sudo aa-complain /usr/sbin/mysqldIf disabling SELinux/AppArmor fixes the issue, configure proper policies rather than leaving them disabled.
The CR_CONN_HOST_ERROR (2003) has several advanced considerations:
1. Cloud-Specific Configuration: Cloud database services (AWS RDS, Azure Database for MySQL, Google Cloud SQL) require security group/firewall rules at the cloud provider level. Local server firewall settings don't apply.
2. Docker and Container Networking: When MySQL runs in Docker, use host network mode or proper port mapping (-p 3306:3306). Container networking may require exposing ports and configuring bind-address to 0.0.0.0.
3. Connection Pooling and Timeouts: Production applications should implement connection pooling with proper timeout settings. Default TCP connection timeout is often 20-30 seconds, causing slow failures.
4. SSL/TLS Encryption: MySQL 8.0+ defaults to requiring encrypted connections. Connection failures may relate to SSL certificate validation. Use --ssl-mode=DISABLED for testing or properly configure SSL certificates.
5. ProxySQL and Load Balancers: When using MySQL proxies or load balancers, error 2003 may indicate proxy issues rather than MySQL server problems. Check proxy configuration and health checks.
6. IPv4 vs IPv6: MySQL may bind to IPv6 addresses (::) causing issues with IPv4-only clients. Verify IP version compatibility and use explicit IPv4 addresses if needed.
7. Multiple MySQL Instances: Running multiple MySQL instances requires different ports (3306, 3307, etc.) or different bind addresses. Check which instance you're targeting.
8. Monitoring and Alerting: Implement connection monitoring with tools like mysqladmin ping, Prometheus MySQL exporter, or cloud monitoring services to detect server unavailability quickly.
9. Connection Limits: MySQL has max_connections limit (default 151). Once reached, new connections receive error 1040 (Too many connections) rather than 2003, but may appear similar.
For production debugging, enable MySQL general query log temporarily to see all connection attempts, or use tcpdump/wireshark to analyze network traffic on port 3306.
EE_WRITE (3): Error writing file
How to fix "EE_WRITE (3): Error writing file" in MySQL
CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters
How to fix "CR_PARAMS_NOT_BOUND (2031): No data supplied for parameters" in MySQL
CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed
How to fix "CR_DNS_SRV_LOOKUP_FAILED (2070): DNS SRV lookup failed" in MySQL
ERROR 1146: Table 'database.table' doesn't exist
How to fix "ERROR 1146: Table doesn't exist" in MySQL
ERROR 1040: Too many connections
How to fix "ERROR 1040: Too many connections" in MySQL