问题概述

最近遇到一个案例是 root@localhost 创建用户的时候(使用的 grant 来创建用户,如下图),出现ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES),借着这个机会整理下 MySQL ERROR 1045 (28000)的问题汇总。
image.png
也就是说 root 在创建用户的时候(MySQL 已经不建议通过grant 创建用户了,应该是8.0 之后会提示用户不存在,这里不再赘述,毕竟是从老版本(老dba)过来的,都是使用grant 来创建用户)。
写完这个文章发现,之前整理过 MySQL ERROR 1045 的问题,不过不太完善,是之前遇到的都是 登录的过程出现的,这次是授权的时候出现,本篇算一个汇总了。

原文再现:MySQL 登录报 ERROR 1045 (28000) 错误的问题汇总

问题分析

我心里想 root 都没权限,还是 本地的 root 用户,通常情况下本地的root用户 (root@localhost)是总管理员,有最大权限,并且是已经登录到了数据库(你看都可以执行查询版本信息的SQL了)。
不放心,然后执行 select user(),current_user(); 确实都是 root@localhost其实从报错信息以及提示符都可以确认是 root@localhost了。执行这个查询是个无用之举哈。

1
2
3
4
5
6
7
(root@localhost) [(none)]> select user(),current_user();
+----------------+----------------+
| user() | current_user() |
+----------------+----------------+
| root@localhost | root@localhost |
+----------------+----------------+
1 row in set (0.00 sec)

其实我在这里已经怀疑 root@localhost 的权限了,但是想着 本地root 应该是最大权限,然后尝试进行分步创建用户,也就是按照目前 MySQL 推荐的先 create user,然后再进行grant 授权。
具体如下:

1
2
3
4
5
(root@localhost) [(none)]> create user abc;
Query OK, 0 rows affected (0.00 sec)

(root@localhost) [(none)]> grant all on *.* to abc;
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

可以看到可以正常创建用户,但是无法grant 授权。
好吧,那现在就看下root 用户的权限了:

1
2
3
4
5
6
7
8
(root@localhost) [(none)]> show grants;
+--------------------------------------------------------------+
| Grants for root@localhost |
+--------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+--------------------------------------------------------------+
2 rows in set (0.00 sec)

发现下面的 PROXY 权限是有 WITH GRANT OPTION 选项的,但是ALL PRIVILEGES 权限没有 WITH GRANT OPTION选项,问题应该在这里。
然后在我本地测试环境发现,果然,正常的root权限应该是:

1
2
3
4
5
6
7
(root@localhost) [(none)]> show grants;
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+

那么问题来,本地 root用户没有 WITH GRANT OPTION,那怎么给他授权呢?,这里给自己授权很显然是报错的:

1
2
(root@localhost) [(none)]> GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost'  WITH GRANT OPTION;
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)

这里有两个解决方案:
1、挨个查看数据库中的用户是否有ALL PRIVILEGES WITH GRANT OPTION 权限的用户,如果有,就用有权限的用户登录,然后进行创建用户、授权操作,或者把权限给本地root用户之后,然后用本地root用户进行操作。
2、由于 本地root 用户是有 all 权限的,那就可以通过修改库表的方式来进行。

具体如下:

  • a、查询mysql.user表查看当前的用户权限信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
(root@localhost) [(none)]>  select * from mysql.user where user='root' and host='localhost'\G
*************************** 1. row ***************************
Host: localhost
User: root
Select_priv: Y
Insert_priv: Y
Update_priv: Y
Delete_priv: Y
Create_priv: Y
Drop_priv: Y
Reload_priv: Y
Shutdown_priv: Y
Process_priv: Y
File_priv: Y
Grant_priv: N <--- 可以看到Grant_priv是 N,其他的权限都是 Y。
References_priv: Y
Index_priv: Y
Alter_priv: Y
Show_db_priv: Y
Super_priv: Y
Create_tmp_table_priv: Y
Lock_tables_priv: Y
Execute_priv: Y
Repl_slave_priv: Y
Repl_client_priv: Y
Create_view_priv: Y
Show_view_priv: Y
Create_routine_priv: Y
Alter_routine_priv: Y
Create_user_priv: Y
Event_priv: Y
Trigger_priv: Y
Create_tablespace_priv: Y
ssl_type:
ssl_cipher:
x509_issuer:
x509_subject:
max_questions: 0
max_updates: 0
max_connections: 0
max_user_connections: 0
plugin: mysql_native_password
authentication_string: *E069E03B8F264EECB2EA11D0F73D9C9F23C5F8DB
password_expired: N
password_last_changed: 2024-03-07 22:21:31
password_lifetime: NULL
account_locked: N
1 row in set (0.00 sec)

可以看到 Grant_privN,其他的权限都是 Y。这里通过修改 mysql.user表将 Grant_priv设置为 Y

  • b、修改 mysql.user表将 Grant_priv设置为 Y
1
2
3
4
5
6
7
8
(root@localhost) [(none)]> update mysql.user set Grant_priv='Y' where  user='root' and host='localhost';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

(root@localhost) [(none)]> select Grant_priv from mysql.user where user='root' and host='localhost'\G
*************************** 1. row ***************************
Grant_priv: Y
1 row in set (0.00 sec)

这个时候查看权限是不变化的,由于是更新了库表结构,需要flush privileges; 生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
(root@localhost) [(none)]> show grants;
+--------------------------------------------------------------+
| Grants for root@localhost |
+--------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+--------------------------------------------------------------+
2 rows in set (0.00 sec)

(root@localhost) [(none)]> flush privileges;
Query OK, 0 rows affected (0.00 sec)

(root@localhost) [(none)]> show grants;
+---------------------------------------------------------------------+
| Grants for root@localhost |
+---------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
| GRANT PROXY ON ''@'' TO 'root'@'localhost' WITH GRANT OPTION |
+---------------------------------------------------------------------+
2 rows in set (0.00 sec)

flush privileges; 之后,可以看到权限发生了变化。

然后执行grant 授权测试下:

1
2
(root@localhost) [(none)]> grant all on *.* to ff identified by "abc";
Query OK, 0 rows affected, 1 warning (0.01 sec)

这就搞定了。

问题汇总

既然遇到这个案例了,那来总结下 MySQL ERROR 1045 问题的常见处理解决方案。

MySQL ERROR 1045 问题,MySQL 在日常登录或者操作过程中会出现,这里汇总出现此问题的几种解决方案。
什么是 MySQL ERROR 1045,当出现了MySQL ERROR 1045 报错,可以通过 MySQL 自带的perror 命令来查看 1045 的具体信息,perrotmysqld 在同一个目录下,如果设置了 PATH 环境变量,可以直接通过 perror 1045 进行查看,如果报 -bash: perror: command not found 可以通过,完整的 MySQL 安装目录比如 /usr/local/mysql/bin/perror 1045

1
2
/usr/local/mysql/bin/perror 1045
MySQL error code MY-001045 (ER_ACCESS_DENIED_ERROR): Access denied for user '%-.48s'@'%-.64s' (using password: %s)

可以看到 1045 的错误代码的具体信息是:MySQL error code MY-001045 (ER_ACCESS_DENIED_ERROR): Access denied for user '%-.48s'@'%-.64s' (using password: %s)

    1. 登录的时候报: ERROR 1045 (28000): Access denied for user ‘f‘@’localhost’ (using password: YES)
    • 用户/密码不正确
    • 用户不存在
    • 如果数据库有多个实例,请检查端口等连接是否准确,如果连接到其他实例没有此用户也是会报这个错误。
    1. 登录的时候报: ERROR 1045 (28000): Access denied for user ‘f‘@’localhost’ (using password: NO)

    这个错误与上个错误的区别是:后面括弧里的 using passwordNO,上面是 YESYES=表示输入了密码,NO表示没有输入密码,对于有密码的用户登录,不输入密码,那肯定报Access denied 咯。

    • 登录的数据没有输入密码或者配置的密码为空,请输入/或者配置正确的密码
    1. 授权的时候报:ERROR 1045 (28000): Access denied for user 'shouq'@'%' (using password: YES) 也就是本篇文章遇到的案例
    • 用户的权限缺少 WITH GRANT OPTION

解决方案

  1. 确保连接的数据库准确,且存在对应的用户名、密码正确
  2. 在授权的时候报错确保用户拥有 WITH GRANT OPTION 权限

原文作者: liups.com

原文链接: http://liups.cn/posts/61ea33c0/

许可协议: 知识共享署名-非商业性使用 4.0 国际许可协议