Seeing MySQL accept connections through localhost
but reject them via 127.0.0.1
reveals fundamental differences in how MySQL handles connections:
# Working connection (uses Unix socket)
mysql -h localhost -u user -p
# Failing connection (uses TCP/IP)
mysql -h 127.0.0.1 -u user -p
The key distinction lies in MySQL's default connection handling:
- localhost: Uses Unix domain socket by default (faster, no network stack)
- 127.0.0.1: Forces TCP/IP connection (subject to network restrictions)
Check your actual connection method with:
# Verify socket connection
mysqladmin -h localhost variables | grep socket
# Verify TCP connection
netstat -ant | grep 3306
When TCP connections fail despite working socket connections:
# Check MySQL's bind address
grep bind-address /etc/mysql/my.cnf
# Test raw TCP connectivity
telnet 127.0.0.1 3306
nc -zv 127.0.0.1 3306
# Verify skip-networking isn't enabled
grep skip-networking /etc/mysql/my.cnf
For applications requiring TCP connections:
# /etc/mysql/my.cnf
[mysqld]
bind-address = 0.0.0.0 # Listen on all interfaces
skip-name-resolve # Avoid DNS lookups
# For IPv6 support
bind-address = ::
Java connection string adjustment:
jdbc:mysql://127.0.0.1:3306/dbname?useSSL=false&socketFactory=com.mysql.jdbc.NamedPipeSocketFactory
When basic fixes don't work:
# Check for AppArmor/SELinux restrictions
aa-status
getenforce
# Enable MySQL general log
SET GLOBAL general_log = 'ON';
SET GLOBAL general_log_file = '/var/log/mysql/mysql-general.log';
# Packet capture analysis
tcpdump -i lo -nn -X port 3306
Common causes for this discrepancy:
- JDBC drivers may enforce TCP when CLI uses sockets
- Connection pooling libraries with different defaults
- Firewall rules affecting application users differently
- MySQL user privileges with host restrictions
# Verify user privileges
SELECT Host, User FROM mysql.user WHERE User = 'your_user';
I recently encountered a baffling MySQL connection issue where connections via localhost
worked perfectly, but identical attempts using 127.0.0.1
failed with:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet'
First, let's verify the basic configuration:
# Check MySQL version
$ mysqld -V
mysqld Ver 5.5.37-0+wheezy1-log
# Verify bind address
$ grep bind /etc/mysql/my.cnf
bind-address = 127.0.0.1
# Check network connectivity
$ ping localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_req=1 ttl=64 time=0.022 ms
The key difference between these connection methods lies in how MySQL handles them:
localhost
: Uses Unix domain socket by default127.0.0.1
: Forces TCP/IP connection
To explicitly test socket vs TCP:
# Socket connection
$ mysql --protocol=SOCKET -u user -p
# TCP connection
$ mysql --protocol=TCP -h 127.0.0.1 -u user -p
When TCP connections fail, check these critical points:
# Verify MySQL is listening
$ netstat -tulnp | grep 3306
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
# Test raw connection
$ telnet 127.0.0.1 3306
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
Connection closed by foreign host.
For Java applications failing even with localhost, try adding socket explicitly:
jdbc:mysql://localhost:3306/dbname?socketFactory=com.mysql.jdbc.NamedPipeSocketFactory&socket=/var/run/mysqld/mysqld.sock
Or force TCP with connection properties:
jdbc:mysql://127.0.0.1:3306/dbname?useSSL=false&allowPublicKeyRetrieval=true
Enable MySQL query logging temporarily:
SET GLOBAL general_log = 'ON';
SET GLOBAL general_log_file = '/var/log/mysql/mysql-general.log';
Check authentication plugins with:
SELECT Host, User, plugin FROM mysql.user;
- Modify bind address to include both IPv4 and IPv6:
bind-address = ::
- Add skip-name-resolve to my.cnf
- Verify user privileges for both connection methods:
GRANT ALL PRIVILEGES ON *.* TO 'user'@'localhost' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON *.* TO 'user'@'127.0.0.1' IDENTIFIED BY 'password';