8.2.22 解决 MySQL 连接问题
如果您遇到连接到 MySQL 服务器的问题,以下内容描述了一些解决问题的步骤。
-
确保服务器正在运行。如果它没有运行,客户端就不能连接到它。例如,如果连接到服务器失败,并显示类似以下的消息,一种可能的原因是服务器没有运行:
$> mysql ERROR 2003: Can't connect to MySQL server on 'host_name' (111) $> mysql ERROR 2002: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (111)
-
可能是服务器正在运行,但是您正在使用 TCP/IP 端口、命名管道或 Unix 套接字文件,而不是服务器监听的端口。要解决这个问题,在调用客户端程序时,使用
--port
选项指定正确的端口号,或者使用--socket
选项指定正确的命名管道或 Unix 套接字文件。要找到套接字文件的位置,可以使用以下命令:$> netstat -ln | grep mysql
-
确保服务器没有被配置为忽略网络连接(如果您尝试连接到远程服务器)或(如果您尝试连接到本地服务器)没有被配置为只在其网络接口上监听。如果服务器使用了
skip_networking
系统变量启动生成的服务器,不接受 TCP/IP 连接。如果服务器使用了bind_address
系统变量设置为127.0.0.1
,它只在本地回环接口上监听 TCP/IP 连接,不接受远程连接。 -
检查防火墙是否阻止了对 MySQL 的访问。您的防火墙可能根据执行的应用程序或 MySQL 通信端口(默认为 3306)进行配置。在 Linux 或 Unix 上,检查 IP 表(或类似配置)以确保端口没有被阻止。在 Windows 上,应用程序如 ZoneAlarm 或 Windows 防火墙可能需要配置以允许 MySQL 端口。
-
授权表必须正确设置,以便服务器可以使用它们来控制访问。对于某些分发类型(如 Windows 的二进制分发、Linux 的 RPM 和 DEB 分发),安装过程将初始化 MySQL 数据目录,包括
mysql
系统数据库,包含授权表。对于不执行此操作的分发,您必须手动初始化数据目录。详细信息请见 第 2.9 节,“Postinstallation Setup and Testing”。要确定是否需要初始化授权表,检查
mysql
目录是否在数据目录下。数据目录通常名为data
或var
,位于 MySQL 安装目录下。确保您在mysql
数据库目录下有一个名为user.MYD
的文件。如果没有,初始化数据目录。完成后,启动服务器,您应该能够连接到服务器。 -
在新安装后,如果您尝试以
root
用户名登录服务器,但没有使用密码,您可能会收到以下错误消息。$> mysql -u root ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
这意味着已经在安装过程中为root密码分配了一个值,并且需要提供该密码。请查看第2.9.4节,“初始MySQL账户的安全性”,了解不同方式的密码分配和在某些情况下如何找到密码。如果需要重置root密码,请查看第B.3.3.2节,“重置root密码”。在找到或重置密码后,请使用
--password
(或-p
)选项登录为root
。$> mysql -u root -p Enter password:
然而,服务器将允许您连接为
root
而不使用密码,如果您使用mysqld --initialize-insecure初始化MySQL(详见第2.9.1节,“初始化数据目录”)。这是一种安全风险,因此您应该为root
账户设置密码;详见第2.9.4节,“初始MySQL账户的安全性”。 -
如果您已经更新了现有MySQL安装到最新版本,是否执行了MySQL升级过程?如果没有,请执行。 grant表的结构偶尔会因为添加新功能而改变,因此在升级后总是确保您的表具有当前结构。详见第3章,“升级MySQL”。
-
如果客户端程序在连接时收到以下错误消息,它意味着服务器期望的密码格式超过了客户端可以生成的格式:
$> mysql Client does not support authentication protocol requested by server; consider upgrading MySQL client
-
记住,客户端程序使用连接参数指定在选项文件或环境变量中。如果客户端程序似乎在没有指定命令行时发送错误的默认连接参数,请检查任何相关的选项文件和环境变量!例如,如果您在没有指定任何选项时运行客户端时收到
Access denied
,请确保您没有在任何选项文件中指定了旧密码。您可以通过在客户端程序中使用
--no-defaults
选项来抑制使用选项文件的客户端程序。例如:$> mysqladmin --no-defaults -u root version
客户端使用的选项文件列表在第6.2.2.2节,“使用选项文件”中。环境变量列表在第6.9节,“环境变量”中。
-
如果您收到以下错误,它意味着您使用了错误的
root
密码:$> mysqladmin -u root -pxxxx ver Access denied for user 'root'@'localhost' (using password: YES)
如果出现的错误在你没有指定密码时仍然出现,那么意味着你在某个选项文件中列出了错误的密码。尝试使用
--no-defaults
选项,详见前一项。关于更改密码的信息,请见第8.2.14节,“Assigning Account Passwords”。
如果你已经忘记了
root
密码,请见第B.3.3.2节,“How to Reset the Root Password”。 -
localhost
是本地主机的同义词,也是客户端连接到服务器时的默认主机,如果你没有指定主机。你可以使用
--host=127.0.0.1
选项来指定服务器主机。这将导致对本地mysqld服务器的TCP/IP连接。你也可以使用TCP/IP来指定实际的主机名。这种情况下,主机名必须在服务器主机上的user
表行中指定,即使你在同一主机上运行客户端程序。 -
Access denied
错误消息将告诉你你试图以什么身份登录,来自哪个客户端主机,你是否使用了密码。通常,你应该在user
表中有一行精确匹配错误消息中的主机名和用户名。例如,如果你收到包含using password: NO
的错误消息,那么意味着你试图以无密码方式登录。 -
如果你在尝试连接到数据库时收到
Access denied
错误,使用mysql -u
,可能是user_name
user
表的问题。检查这个问题,可以执行mysql -u root mysql
,然后执行以下SQL语句:SELECT * FROM user;
结果应该包括一个行,其中
Host
和User
列匹配你的客户端主机名和你的MySQL用户名。 -
如果出现的错误在你从非服务器主机连接时出现,那么意味着
user
表中没有一个Host
值匹配客户端主机:Host ... is not allowed to connect to this MySQL server
你可以通过为客户端主机名和用户名设置账户来解决这个问题。
如果您不知道连接的机器的IP地址或主机名,您应该在
user
表中添加一行,Host
列值为'%'
。然后,在客户端机器上使用SELECT USER()
查询来查看实际连接的主机名。然后,在user
表中将'%'
更改为实际主机名,以免系统留下不安全的连接。在Linux上,可能的原因是您使用的MySQL版本与glibc库版本不同。在这种情况下,您可以升级操作系统或glibc,或者下载MySQL源代码并自己编译。
-
如果您指定主机名连接,但收到错误信息,其中主机名不显示或是IP地址,这意味着MySQL服务器在尝试解析客户端主机名到IP地址时出现了错误:
$> mysqladmin -u root -pxxxx -h some_hostname ver Access denied for user 'root'@'' (using password: YES)
如果您尝试连接为
root
并收到错误信息,这意味着您没有在user
表中添加了User
列值为'root'
的行,并且mysqld无法解析客户端主机名:Access denied for user ''@'unknown'
这些错误表明了DNS问题。要解决它,请执行mysqladmin flush-hosts以重置内部DNS主机缓存。请参阅第7.1.12.3节,“DNS查询和主机缓存”。
一些永久解决方案是:
-
确定DNS服务器的问题并修复它。
-
在MySQL授权表中指定IP地址而不是主机名。
-
在Unix上添加客户端机器名到
/etc/hosts
文件中,在Windows上添加到\windows\hosts
文件中。 -
启动mysqld并启用
skip_name_resolve
系统变量。 -
在Unix上,如果您在同一台机器上运行服务器和客户端,连接到
localhost
。MySQL程序将尝试连接到本地服务器使用Unix socket文件,除非指定连接参数以确保客户端使用TCP/IP连接。更多信息,请参阅第6.2.4节,“使用命令选项连接到MySQL服务器”。 -
在 Windows 平台上,如果您在同一台机器上运行服务器和客户端,并且服务器支持命名管道连接,可以连接到主机名
.
(点号)。对.
的连接使用命名管道,而不是 TCP/IP。
-
-
如果
mysql -u root
可以工作,但是mysql -h
结果为your_hostname
-u rootAccess denied
(其中your_hostname
是实际的主机名),您可能没有正确的主机名在user
表中。常见的问题是,Host
值在user
表行中指定了未qualified 主机名,但您的系统名称解析程序返回完全合格域名(或 vice versa)。例如,如果您在user
表中有一个行,其中主机名为'pluto'
,但您的 DNS 告诉 MySQL 您的主机名为'pluto.example.com'
,该行将无法工作。尝试将包含您主机的 IP 地址的行添加到user
表的Host
列中。 (或者,您也可以添加一个行到user
表,其中Host
值包含通配符(例如'pluto.%'
)。然而,使用以%
结尾的Host
值是 不安全 的,并且 不 建议使用!) -
如果
mysql -u
可以工作,但是user_name
mysql -u
不可以,您没有为给定的用户授予对名为user_name
some_db
some_db
的数据库的访问权限。 -
如果
mysql -u
可以在服务器主机上执行,但是user_name
mysql -h
在远程客户端主机上不能执行,您没有为给定的用户名从远程主机启用对服务器的访问权限。host_name
-uuser_name
-
如果您无法确定为什么会出现
Access denied
,请从user
表中删除所有包含通配符的Host
值(包含'%'
或'_'
字符的行)。一个非常常见的错误是插入一个新的行,Host
='%'
,User
='
,认为这可以使您从同一台机器连接。然而,这不起作用是因为默认权限包括一个行,some_user
'Host
='localhost'
,User
=''
。因为该行的Host
值'localhost'
比'%'
更具体,因此在连接到localhost
时将使用该行,而不是新行!正确的步骤是插入一个新的行,Host
='localhost'
,User
='
,或者删除some_user
'Host
='localhost'
,User
=''
的行。删除行后,记住执行一个FLUSH PRIVILEGES
语句以重新加载授权表。见第8.2.6节,“Access Control, Stage 1: Connection Verification”。 -
如果您能够连接到MySQL服务器,但每次执行
SELECT ... INTO OUTFILE
或LOAD DATA
语句时都出现Access denied
消息,您的行在user
表中没有启用FILE
权限。 -
如果您直接更改授权表(例如,使用
INSERT
、UPDATE
或DELETE
语句),并且您的更改似乎被忽略,记住您必须执行一个FLUSH PRIVILEGES
语句或一个mysqladmin flush-privileges命令,以便服务器重新加载授权表。否则,您的更改将无效,直到服务器重新启动。记住,在更改root
密码后,您不需要直到flush权限时指定新密码,因为服务器不知道您已经更改了密码。 -
如果您的权限似乎在会话中发生了变化,可能是MySQL管理员已经更改了它们。重新加载授权表对新连接有效,但也影响了现有连接,如第8.2.13节,“权限更改的生效时间”所示。
-
如果您在使用Perl、PHP、Python或ODBC程序时遇到访问问题,尝试使用
mysql -u
或user_name
db_name
mysql -u
连接到服务器。如果您可以使用mysql客户端,那么问题出在您的程序,而不是权限上。 (在user_name
-ppassword
db_name
-p
和密码之间没有空格;您也可以使用--password=
语法指定密码。如果您使用password
-p
或--password
选项无密码值,MySQL将提示您输入密码。) -
为了测试目的,使用mysqld服务器的
--skip-grant-tables
选项。然后,您可以更改MySQL授权表,并使用SHOW GRANTS
语句检查您的修改是否生效。当您满意您的更改后,执行mysqladmin flush-privileges以通知mysqld服务器重新加载权限。这使您可以开始使用新的授权表内容,而无需停止和重新启动服务器。 -
如果一切都失败,使用mysqld服务器的调试选项(例如
--debug=d,general,query
)。这将打印主机和用户信息关于尝试的连接,以及每个命令的信息。见第7.9.4节,“DBUG包”。 -
如果您遇到与 MySQL 授權表相关的问题,可以在 MySQL 社区 Slack 上询问,总是提供 MySQL 授權表的备份。您可以使用 mysqldump mysql 命令来备份表。要提交错误报告,请查看 第1.6节,“如何报告错误或问题”。在某些情况下,您可能需要使用 mysqld 命令,带有
--skip-grant-tables
选项,以便运行 mysqldump。