MySQL 连接时尽量使用 127.0.0.1 而不是 localhost

2019-11-27 14:37:49 +08:00
 lihongjie0209

原因

Whenever you specify "localhost" or "localhost:port" as server, the MySQL client library will override this and try to connect to a local socket (named pipe on Windows). If you want to use TCP/IP, use "127.0.0.1" instead of "localhost". If the MySQL client library tries to connect to the wrong local socket, you should set the correct path as in your PHP configuration and leave the server field blank.

localhost 使用的 Linux socket,127.0.0.1 使用的是 tcp/ip

为什么我使用 localhost 一直没出问题

因为你的本机中只有一个 mysql 进程, 如果你有一个 node1 运行在 3306, 有一个 node2 运行在 3307

mysql -u root -h localhost -P 3306
mysql -u root -h localhost -P 3307

都会连接到同一个 mysql 进程, 因为 localhost 使用 Linux socket, 所以 -P 字段直接被忽略了, 等价于

mysql -u root -h localhost 
mysql -u root -h localhost 

而 -h 默认是 localhost, 又等价于

mysql -u root 
mysql -u root 

为了避免这种情况(比如你在本地开发只有一个 mysql 进程,线上或者 qa 环境有多个 mysql 进程)最好的方式就是使用 IP

mysql -u root -h 127.0.0.1 -P 3307
15523 次点击
所在节点    MySQL
70 条回复
lihongjie0209
2019-11-27 20:18:12 +08:00
@laminux29 #39

1. 业界共识 ‘不要在一个 OS 里,跑 1 个以上的数据库实例’ 可能是你的共识, 我并没有在任何官方和非官方的场合下听到这种言论
2. 在 QA 环境下, 应用程序和 Redis 都跑在一台服务器上, 连接使用 127.0.0.1, 上线之后有专门的缓存服务器 120.xxx.xxx.xxx, 我只需要修改一下连接的地址就可以了, 难道我还在在 QA 环境部署一台专门的缓存服务器?
有些东西:比如说物理服务器的性能,资源数量啊当然是和生产环境一模一样最好, 可现实就是我们只需要一些最基本的配置就可以完成开发和测试的工作。
通过 TCP/IP 完全可以让开发无视这些物理服务器之间的区别,更快更好的完成开发工作, 何乐而不为。

3. 测试集群有很多的场景, 为了学习, 为了测试环境都有可能, 理想情况下需要 5 台高性能的实体服务器的集群在以学习为目的的情况下用 3 台性能一般的虚拟机就可以实现, 为什么非要加那么多的限制条件呢? 指望一个初学者为了学一个东西先准备 5 台实体服务器? k8s 还有专门为单机准备的教程呢。

4. 你这里的业界共识是指一个服务器一个数据库还是 localhost 就是指 linux socket ?

5. 和 CPU 密集型没有任何关系

6. 养 DBA 的公司不多, 但是想省钱又不太在意高可用的公司不少。 说实话又许多应用没那么重要,但对于一些公司又是必不可少
Aruforce
2019-11-27 21:29:23 +08:00
是所有的 connector 都这样?还是只有特定的版本?
xiaooloong
2019-11-28 00:01:51 +08:00
localhost 使用 Linux socket 不是常识么
wangyzj
2019-11-28 00:39:11 +08:00
连接可以指定 socket 地址的
另外
我都用 IP
大应用只能用 IP 作分离
小应用也不需要 socket 的高性能
conn4575
2019-11-28 01:05:43 +08:00
哇,一直都没注意居然还有这样的问题,真的坑
zuoer123
2019-11-28 01:39:30 +08:00
make
jinliming2
2019-11-28 02:10:20 +08:00
一般建议还是用 unix sock,一个方面是更快,另一方面是相对更安全
(不过 MySQL 为啥这么奇葩,localhost 和 unix sock 混为一谈?一个是 tcp://,一个是 unix://,两个差老远了啊!
LuciferGo
2019-11-28 09:09:29 +08:00
遇到过 localhost 的问题,没研究过这么细,赞
iwtbauh
2019-11-28 09:36:51 +08:00
现在的人的基础知识已经如此差了吗?

“linux socket”我是第一次听说。我猜 lz 是想说“unix domain socket”( Unix 域套接字),见手册页 unix(7)

"linux socket"更容易被理解为是“linux 上特有的非 POSIX 的 socket”,如“netlink socket”

还是需要继续提高姿势水平
paoqi2048
2019-11-28 10:11:09 +08:00
学习了
T3RRY
2019-11-28 10:51:41 +08:00
赞了
belain
2019-11-28 11:45:45 +08:00
学习了!谢谢!
lihongjie0209
2019-11-28 11:50:50 +08:00
@laminux29 #39 刚刚在 高性能 Mysql 中看到的
abmin521
2019-11-28 12:07:30 +08:00
别的客户端应该都会做解析的吧
laminux29
2019-11-28 13:48:59 +08:00
@lihongjie0209 数据库的负载,与很多因素有关。你发的截图,它这书里,只是针对它自己的环境与业务,给出 mysql 的负载信息而已。这种数据看看就行了,不用太关注。你应该更关注你自己的业务。
rrfeng
2019-11-28 13:51:56 +08:00
你试试 -h localhost:3307 呢?
你一个机器上俩实例,端口不一样,都用 localhost 吗?不加端口嘛?

事实上是这样你讲的没错,但是逻辑上不是的。
lihongjie0209
2019-11-28 13:56:57 +08:00
@rrfeng #56
[root@localhost ~]# mysql -h localhost:3307 -u root
ERROR 2005 (HY000): Unknown MySQL server host 'localhost:3307' (2)



```
socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.2.254")}, 16) = 0
poll([{fd=3, events=POLLOUT}], 1, 0) = 1 ([{fd=3, revents=POLLOUT}])
sendmmsg(3, {{{msg_name(0)=NULL, msg_iov(1)=[{")d\1\0\0\1\0\0\0\0\0\0\16localhost:3307\0\0\1\0\1", 32}], msg_controllen=0, msg_flags=MSG_OOB|MSG_DONTWAIT|MSG_EOR|MSG_FIN|0x80000}, 32}, {{msg_name(0)=NULL, msg_iov(1)=[{"{\245\1\0\0\1\0\0\0\0\0\0\16localhost:3307\0\0\34\0\1", 32}], msg_controllen=0, msg_flags=0}, 32}}, 2, MSG_NOSIGNAL) = 2
poll([{fd=3, events=POLLIN}], 1, 5000) = 1 ([{fd=3, revents=POLLIN}])
ioctl(3, FIONREAD, [32]) = 0
recvfrom(3, ")d\201\202\0\1\0\0\0\0\0\0\16localhost:3307\0\0\1\0\1", 2048, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.2.254")}, [16]) = 32
poll([{fd=3, events=POLLIN}], 1, 4998) = 1 ([{fd=3, revents=POLLIN}])
ioctl(3, FIONREAD, [32]) = 0
recvfrom(3, "{\245\201\202\0\1\0\0\0\0\0\0\16localhost:3307\0\0\34\0\1", 65536, 0, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("192.168.2.254")}, [16]) = 32


```

很明显把 localhost:3307 当做域名了, 直接去找 dns 解析了
lihongjie0209
2019-11-28 13:57:44 +08:00
@rrfeng #56 有加
lihongjie0209
2019-11-28 14:04:12 +08:00
@abmin521 #54 并没有测试, 在 StackOverflow 中有人提到了 PHP 也会有这个问题(没有测试过)

不过哪怕只是 mysql 相关的工具 mysql/mysqldump/mysqladmin 遇到这种问题, 很有可能导致备份 /重启 等过程发生在错误的 mysqld 进程中
passerbytiny
2019-11-28 14:10:21 +08:00
@lihongjie0209
Linux 上 localhost,以及.localhost 域名都是大坑,但是真得不建议用 127.0.0.1 替代 localhost。替代 localhost 的应该是 hostname,或者 hosts 中配置的假域名。localhost、hostname、domain 这三者是一个层次的,IP 跟他们不一个层次。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/623596

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX