Rootop 服务器运维与web架构

mysql数据库中用户表host字段localhost、127.0.0.1、%区别

忘记mysql密码后,通过添加my.cnf中[mysqld]段skip_grant_tables参数跳过认证后修改密码。
改完后重启发现还是无法登陆,排查后发现是mysql.user表中host字段值导致的。

mysql5.5 默认用户信息

mysql> select host,user,password,authentication_string,plugin from user where user = 'root'\G;
*************************** 1. row ***************************
                 host: localhost
                 user: root
             password: *1AF59BA2193249964488569CA898EFB2675BD9AB
authentication_string: 
               plugin: 
*************************** 2. row ***************************
                 host: bt
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 3. row ***************************
                 host: 127.0.0.1
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 4. row ***************************
                 host: ::1
                 user: root
             password: 
authentication_string: 
               plugin: 
4 rows in set (0.00 sec)

当我们把host = localhost , user = root 的记录信息host改为 % 百分号后再看下。

mysql> select host,user,password,authentication_string,plugin from user where user = 'root'\G;
*************************** 1. row ***************************
                 host: %
                 user: root
             password: *1AF59BA2193249964488569CA898EFB2675BD9AB
authentication_string: 
               plugin: 
*************************** 2. row ***************************
                 host: bt
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 3. row ***************************
                 host: 127.0.0.1
                 user: root
             password: 
authentication_string: 
               plugin: 
*************************** 4. row ***************************
                 host: ::1
                 user: root
             password: 
authentication_string: 
               plugin: 
4 rows in set (0.00 sec)

再用mysql -uroot -p 则无法登陆了,会提示下面错误。

[root@bt /]# mysql -uroot -p
Enter password: // 输入密码
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

此时用 mysql -uroot -h 127.0.0.1 -p 和 mysql -uroot -h bt -p 时,则无需密码即可登陆(也能查看库和表)。
因为host = bt & user = root或者 host = 127.0.0.1 & user = root 的password密码字段为空,所以可以空密码登陆。

那么为什么mysql -uroot -p 输入密码后会无法连接?
注意 % 百分号表示是任何主机,是不匹配 localhost 的,它只是针对于通过TCP/IP连接过来的主机。
当不带-h参数时,默认为localhost,会去表里匹配host=localhost的记录,没有找到对应记录,所以就拒绝连接了。

这个规则同样适用于代码中连接数据库。

参考mysql文档:https://dev.mysql.com/doc/refman/5.7/en/problems-connecting.html

localhost is a synonym for your local host name, and is also the default host to which clients try to connect if you specify no host explicitly.

这句话意思是 localhost 是你本地主机的别名,同样他是客户端(mysql -uxxx -pxxx)连接数据库,但未指定主机(-h)时的默认值。(通过socket连接)

You can use a --host=127.0.0.1 option to name the server host explicitly. 
This will make a TCP/IP connection to the local mysqld server. 

上面两句意思是说用127.0.0.1做为主机地址连接,这是通过tcp/ip连接实现的。

You can also use TCP/IP by specifying a --host option that uses the actual host name of the local host. 

这句意思是通过tcp/ip协议来连接主机的实际名称,比如 server-db ,连接时,会把主机名解析为ip地址。

In this case, the host name must be specified in a user table row on the server host, even though you are running the client program on the same host as the server.

意思是即使你客户端程序跟数据库在同一台机器,但是主机名也必须在mysql.user表中有记录。

在以上3中情况下(localhost/127.0.0.1/hostname)必须在mysql.user中能匹配到用户信息,否则就拒绝连接。
更多资料可参考mysql官方文档中关于 Access Control and Account Management 部分。

原创文章,转载请注明。本文链接地址: https://www.rootop.org/pages/4721.html

赞赏

微信赞赏支付宝赞赏

作者:Venus

专注于 服务器运维与web架构 E-mail:venus#rootop.org

评论已关闭。