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_nameuser表的问题。检查这个问题,可以执行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_namemysql -u不可以,您没有为给定的用户授予对名为user_namesome_dbsome_db的数据库的访问权限。 -
如果
mysql -u可以在服务器主机上执行,但是user_namemysql -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_namedb_namemysql -u连接到服务器。如果您可以使用mysql客户端,那么问题出在您的程序,而不是权限上。 (在user_name-ppassworddb_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。