MySQL Connection Issue: Why ‘localhost’ Fails When ‘127.0.0.1’ Works?


2 views

I recently encountered a puzzling scenario on an Ubuntu 12.04 LTS server where MySQL connections worked perfectly with '127.0.0.1' but consistently failed when using 'localhost'. Here's what I discovered and how I resolved it.

The /etc/hosts file appeared correctly configured:


127.0.0.1 localhost

# IPv6 configurations
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

Yet services like MySQL, Postfix, and Apache required explicit 127.0.0.1 addresses to function properly.

The issue stems from how different applications handle name resolution:

  • Some applications use gethostbyname() which checks /etc/hosts first
  • Others may bypass local resolution and try DNS
  • MySQL has its own connection method that can be affected by this

MySQL handles 'localhost' specially - it attempts to use Unix domain sockets when you specify 'localhost', while TCP/IP is used for '127.0.0.1'. This explains why one works when the other fails.


// PHP connection examples:
// This might fail:
$link = mysqli_connect('localhost', 'user', 'password', 'database');

// While this succeeds:
$link = mysqli_connect('127.0.0.1', 'user', 'password', 'database');

Here are multiple approaches to resolve this:

1. MySQL Configuration Adjustment

Edit /etc/mysql/my.cnf and ensure:


[mysqld]
bind-address = 127.0.0.1
skip-name-resolve

2. Socket Path Specification

If you prefer to use localhost with sockets:


$link = mysqli_connect('localhost:/var/run/mysqld/mysqld.sock', 'user', 'password', 'database');

3. Hosts File Verification

Ensure no conflicting entries exist:


$ cat /etc/hosts | grep -v '^#' | grep -v '^$'
$ ping -c 1 localhost
$ ping6 -c 1 localhost

On systems with IPv6 enabled, 'localhost' might resolve to ::1 (IPv6 loopback) instead of 127.0.0.1. To test:


$ getent hosts localhost

For most consistent results:

  • Use 127.0.0.1 explicitly in your connection strings
  • Disable IPv6 if you don't need it (net.ipv6.conf.all.disable_ipv6=1 in /etc/sysctl.conf)
  • Consider setting up a specific hostname in /etc/hosts for your MySQL connections

Many developers encounter this puzzling situation where MySQL connections fail when using 'localhost' but work perfectly with '127.0.0.1'. This behavior isn't limited to MySQL - services like Postfix, Apache, and Dovecot may exhibit similar issues.

The primary difference lies in how the system resolves these addresses:

  • 'localhost' typically resolves to both IPv4 (127.0.0.1) and IPv6 (::1)
  • '127.0.0.1' is strictly IPv4

When MySQL is configured to listen only on IPv4, connections via 'localhost' that resolve to IPv6 will fail.

First verify MySQL's bind address:

grep bind-address /etc/mysql/my.cnf
# Or for newer MySQL versions:
grep bind-address /etc/mysql/mysql.conf.d/mysqld.cnf

Test name resolution:

ping localhost
ping6 localhost
getent hosts localhost

Here are several approaches to resolve this issue:

Solution 1: Force IPv4 for MySQL Connections

Add this to your connection string in application code:

// PHP example
$mysqli = new mysqli("127.0.0.1", "username", "password", "database");

# Python example
import mysql.connector
cnx = mysql.connector.connect(user='username', password='password',
                              host='127.0.0.1',
                              database='database')

Solution 2: Configure MySQL to Listen on All Interfaces

Edit your MySQL configuration:

sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf

Add or modify these lines:

[mysqld]
bind-address = 0.0.0.0
skip-name-resolve

Then restart MySQL:

sudo service mysql restart

Solution 3: Modify Hosts File

Ensure your /etc/hosts contains:

127.0.0.1 localhost
::1     ip6-localhost ip6-loopback

For more persistent cases, check these system settings:

# Check IPv6 status
cat /proc/sys/net/ipv6/conf/all/disable_ipv6

# Test MySQL connection methods
telnet localhost 3306
telnet 127.0.0.1 3306

When setting up new servers, consider these best practices:

  • Always test both 'localhost' and '127.0.0.1' during configuration
  • Document your MySQL connection method in deployment scripts
  • Standardize on either IPv4 or IPv6 throughout your stack