MySQL登录方式详解:Unix Socket与TCP/IP配置避坑指南
前两天维护一台内网 MySQL,碰到一件挺典型的事:新装好的数据库在本地用 mysql -uroot -p 登录一点问题没有,但是从另一台机器用连接串访问就一直超时,最后看监听端口才发现,mysqld 只监听了 127.0.0.1,远端流量压根进不来。后来把 bind-address 改掉、用户 host 也调对了,才算解决。这套排查过程绕不开一个基础概念——MySQL 的登录方式大体分两种:socket 和 TCP。
很多人对这两种登录方式的理解停留在“一个本地、一个远程”,但真正配置权限、排障、做安全加固的时候,才意识到它跟用户名匹配、认证插件、连接串写法、服务监听参数全都有关系。这篇把两种登录方式的原理、配置要点和实际踩过的坑一起理清楚,适合刚接触 MySQL 的读者,也适合部署过但没有细究过连接路径的人对照检查。
1. 登录 MySQL 的两条通道:Unix socket 与 TCP/IP
1.1 Unix socket:本机专属的“门对门”通道
先明确一点,这里说的 socket 是 Unix domain socket,不是 TCP socket 的简称。它不是一个 IP 加端口,而是一个文件,常见路径有 /var/run/mysqld/mysqld.sock、/tmp/mysql.sock。客户端要连 MySQL 时,直接拿这个文件路径去找 mysqld 进程,操作系统在内核层面完成数据转发,不经过网络协议栈,不需要 IP、不需要端口,也不经过网卡。
因为走的是本地文件系统级别的通信,Unix socket 有几个很实际的好处:
- 开销小。没有 TCP 三次握手、没有层层协议封装、没有回环网卡的数据拷贝,同等条件下建立连接更快,短连接场景尤其明显。
- 安全边界清晰。连接只能在能访问该 socket 文件的本机进程之间发生,天然不会暴露到外部网络。
- 认证匹配独立。socket 连接在 MySQL 内部会被识别为
localhost来源,可以跟 TCP 连接配置不同的用户权限,实现更细粒度的控制。
实际部署里,PHP-FPM 和 MySQL 同机部署时,PDO 连接串里写 unix_socket=/var/run/mysqld/mysqld.sock 就是典型的 socket 登录。我做过粗略压测,在高 QPS 小查询场景下,socket 相比走 127.0.0.1 的 TCP 回环,单次连接建立延迟能省下 0.1ms 甚至更多,大量短连接时收益相当可观。
1.2 TCP/IP:跨机器的“电话线”
TCP 方式就是标准的网络连接。客户端通过 IP:端口 找到 MySQL 服务端,先完成 TCP 三次握手,再进入 MySQL 自己的协议层,进行握手、认证、能力协商等步骤。默认端口是 3306,但也可以改成别的。
TCP 最大的价值是打破“同一台机器”的限制。远程运维、微服务跨节点访问、用可视化客户端连库,全部走这条路。但一旦开启 TCP 监听,网络层风险也就跟着来了:端口扫描、暴力破解、中间人窃听(没开 SSL 时)都会成为问题。所以生产环境里要把 bind-address、用户 host 和防火墙配合起来用,不要让 MySQL 裸奔到公网。
这里有个特别容易混淆的点:localhost 和 127.0.0.1 在 MySQL 连接里不是一回事。MySQL 客户端库有一个历史悠久的自动选择逻辑:-h localhost 时默认优先尝试 Unix socket,除非显式指定 --protocol=TCP;而写成 127.0.0.1 或具体 IP,才会走 TCP。很多时候你“本地能连、换了 IP 就报 Access denied”,不是密码错了,而是 MySQL 把 socket 连接和 TCP 连接识别成了两个不同的登录来源。
1.3 客户端是怎么自动选协议的
拿命令行客户端为例,实际判断顺序大致是这样:
- 指定
--protocol=socket:直接用 socket 路径连接。 - 指定
--protocol=TCP:强制走 TCP,即使 host 写 localhost。 - 没写
--protocol,但 ho