在本地 VirtualBox 实例上运行 MySql 5.7.33。我已从虚拟服务器转发端口 3306,以便在本地访问。在我的虚拟主机上,我的 /etc/mysql/my.cnf 文件中有这个...
[client]
#password = your_password
port = 3306
socket = /var/run/mysqld/mysqld.sock
[mysqld]
port = 3306
bind-address = 0.0.0.0
datadir = /var/lib/mysql
socket = /var/run/mysqld/mysqld.sock
pid-file = /var/run/mysqld/mysqld.pid
从我的本地机器,我可以使用连接到 MySql 实例
mysql -h 127.0.0.1 -u my_user my_db -p
但是一旦我更改为“localhost”,我就无法再连接
$ mysql -h localhost -u my_user my_db -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
不确定是什么问题。从我的本地机器(即不是虚拟服务器),这是为“localhost”返回的……
$ host localhost
localhost has address 127.0.0.1
localhost has IPv6 address ::1
当您指定客户端
-h localhost
将mysql
尝试使用套接字(即UNIX 域套接字)而不是 TCP。这是 MySQL 及其分支中的一种特殊行为。但是,由于 MySQL 服务器在 VM 中运行,因此 mysql 客户端无法直接访问服务器的套接字。UNIX 域套接字只能在共享相同内核的进程之间共享,而主机操作系统(带有
mysql
客户端)在 VM(带有 MySQL 服务器)中运行来宾操作系统的情况并非如此。顺便说一句,如果在容器(docker、podman 等)中运行 MySQL 服务器,那么您将共享相同的内核,并且还可以共享 UNIX 域套接字。
解决方案 1:SSH 隧道
如果您必须使用套接字,请从您的主机操作系统运行此命令以创建 SSH 隧道(如果出现提示,请输入密码):
然后,在主机操作系统上的一个单独的 shell 中:
您可以从客户端发出
status
命令以验证您确实通过套接字连接。请注意,您需要在关闭 SSH 隧道后手动删除本地套接字文件。
mysql
否则下次尝试通过新隧道连接时会出现错误:解决方案 2:“localhost”,但 TCP
如果您只想使用
-h localhost
,但不关心 Unix 套接字:通过简单地添加参数
--protocol=tcp
,您可以强制mysql
客户端通过 TCP 而不是 UNIX 域套接字进行连接。(当连接到端口 3306 已转发到我的主机操作系统的 podman 容器时,这对我有用127.0.0.1:3306
。)顺便说一句,如果您不想
mysql
每次连接时都编写这些长命令,您当然可以将部分或全部参数放在文件的一个[client]
部分中.my.cnf
(注意前导'.')在你的根目录中$HOME
目录。/etc/mysql/my.cnf
(与您在 VM 上的语法相同。)告诉 MySQL “用户”可以通过套接字连接:
但是,这只会让“用户”从同一虚拟主机内连接。
把它想象成一台单独的机器。
我认为问题在于理解是什么
localhost
。参考: 本地主机(维基百科)
您
mysql -h localhost -u my_user my_db -p
将失败,因为 localhost 连接mysql
将寻找一个/tmp/mysql.sock
无法访问的文件,因为它位于 VirtualBox 中的 MySQL 主机内。参考: (MySQL 文档)
你正在观察什么
当您连接时,
127.0.0.1
您会触发一个似乎与您的端口转发一起使用的 TCP 连接。当您(尝试)连接时,您会触发正在查找文件
localhost
的 SOCKET 连接。/tmp/mysql.sock
这在您的 上不可用localhost
,因为它位于 MySQL 实例的 localhost 中。