-h 127.0.0.1 使用的是 TCP/IP 连接,而不是 Unix Socket 连接。

这是一个非常重要的区别,本文我来详细解释一下:

技术原理

-h 127.0.0.1 (TCP/IP)

  • 协议:使用 TCP/IP 协议栈
  • 通信方式:通过网络接口(即使是环回接口 lo)
  • 端口:使用 MySQL 的端口(默认 3306)
  • 本质:完整的网络通信,只是目的地是本机

-h localhost 或不指定 -h (Unix Socket)

  • 协议:使用 Unix Domain Socket
  • 通信方式:通过文件系统 socket 文件
  • 端口:不使用网络端口
  • 本质:进程间通信(IPC)

实际验证

你可以通过几种方式来验证这个区别:

1. 查看连接进程

# 使用 -h 127.0.0.1 连接后查看
mysql -u root -p -h 127.0.0.1

# 在另一个终端查看连接
netstat -an | grep 3306
# 或
ss -tulpn | grep 3306
# 你会看到: tcp  0  0 127.0.0.1:3306  0.0.0.0:*   LISTEN

2. 性能测试对比

# 测试 TCP/IP 连接性能
time mysql -h 127.0.0.1 -u root -p -e "SELECT 1" > /dev/null

# 测试 Unix Socket 连接性能  
time mysql -h localhost -u root -p -e "SELECT 1" > /dev/null
# 或者
time mysql -u root -p -e "SELECT 1" > /dev/null

你会发现 Unix Socket 的连接速度通常更快。

3. 查看 MySQL 进程列表

在 MySQL 中运行:

SHOW PROCESSLIST;

对于 TCP/IP 连接,Host 列会显示 127.0.0.1:端口号 对于 Unix Socket 连接,Host 列会显示 localhost

配置示例

在应用程序配置中,这个区别也很明显:

PHP PDO 示例:

// 使用 TCP/IP 连接
$dsn_tcp = "mysql:host=127.0.0.1;dbname=test;port=3306";

// 使用 Unix Socket 连接
$dsn_socket = "mysql:host=localhost;dbname=test";
// 或者显式指定
$dsn_socket = "mysql:unix_socket=/var/run/mysqld/mysqld.sock;dbname=test";

Python 示例:

import pymysql

# TCP/IP 连接
conn_tcp = pymysql.connect(host='127.0.0.1', port=3306, user='root')

# Unix Socket 连接
conn_socket = pymysql.connect(host='localhost', unix_socket='/tmp/mysql.sock', user='root')

为什么这个区别很重要?

  1. 性能:Unix Socket 通常比 TCP/IP 更快
  2. 权限控制:Unix Socket 可以通过文件系统权限控制访问
  3. 故障排查:连接问题时需要知道使用的是哪种方式
  4. 安全:某些安全策略可能只允许其中一种连接方式

总结

  • -h 127.0.0.1 = TCP/IP 连接(通过网络栈)
  • -h localhost = Unix Socket 连接(通过 socket 文件)
  • 不指定 -h = Unix Socket 连接(默认行为)

这就是为什么有时候使用 127.0.0.1 能连接而 localhost 不能连接(或反之)的原因——它们本质上是两种不同的连接机制。