忘记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 部分。
专注于 服务器运维与web架构
E-mail:venus#rootop.org