应用中抛出SELECT/UPDATE/INSERT/DELETE command denied to user 'XXX'@'XXX.XXX.XXX.XXX' for table 'xxx' 的5种原因

简介: SELECT/UPDATE/INSERT/DELETE command denied to user 'XXX'@'XXX.XXX.XXX.XXX' for table 'xxx'的错误大部分出现在应用程序中,有时用客户端登录mysql后执行操作也会遇到,后者更容易排查,前者由于涉及应用逻辑以及对象.

实为吾之愚见,望诸君酌之!闻过则喜,与君共勉 


第一章 准备环境

创建数据测试数据,以下测试多是基于自建mysql进行

902fce50b942680ebd84cfce6f0a5a192eeec9a2

mysql> create database test1;

Query OK, 1 row affected (0.00 sec)

 

mysql> create database test2;

Query OK, 1 row affected (0.00 sec)

 

mysql> create database test3;

Query OK, 1 row affected (0.00 sec)

 

mysql> create user uptest1@'%' identified by '123';

Query OK, 0 rows affected (0.01 sec)

 

mysql> create user uptest2@'%' identified by '123';

Query OK, 0 rows affected (0.00 sec)

 

mysql> create table test1.updatetest(a int,b int);

Query OK, 0 rows affected (0.00 sec)

 

mysql> create table test2.updatetest(a int,b int);

Query OK, 0 rows affected (0.01 sec)

 

mysql> create table test3.updatetest(a int,b int);

Query OK, 0 rows affected (0.00 sec)


分别授权不同更新权限

fa36cbb13a8d19bf580a1d7bb6709e9042b83637

mysql> grant update on test1.* to uptest1@'%';

Query OK, 0 rows affected (0.00 sec)

 

mysql> grant update on test2.* to uptest1@'%';

Query OK, 0 rows affected (0.01 sec)

 

mysql> show grants for uptest1@'%';

+--------------------------------------------------------------------------------------------------------+

| Grants for uptest1@%                                                                                   |

+--------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'uptest1'@'%' IDENTIFIED BY PASSWORD '*23AE809DDACAF96AF0FD78ED04B6A265E05AA257' |

| GRANT UPDATE ON "test1".* TO 'uptest1'@'%'                                                             |

| GRANT UPDATE ON "test2".* TO 'uptest1'@'%'                                                             |

+--------------------------------------------------------------------------------------------------------+

3 rows in set (0.00 sec)

 

5e1ee077d6155e41b609641a4188f765bf72e7db

 

mysql> grant update on test2.* to uptest2@'%';

Query OK, 0 rows affected (0.00 sec)

 

mysql> grant update on test1.* to uptest2@'%';

Query OK, 0 rows affected (0.00 sec)

 

mysql> grant update on test3.* to uptest2@'%';

Query OK, 0 rows affected (0.00 sec)

 

mysql> show grants for uptest2@'%';

+--------------------------------------------------------------------------------------------------------+

| Grants for uptest2@%                                                                                   |

+--------------------------------------------------------------------------------------------------------+

| GRANT USAGE ON *.* TO 'uptest2'@'%' IDENTIFIED BY PASSWORD '*23AE809DDACAF96AF0FD78ED04B6A265E05AA257' |

| GRANT UPDATE ON "test1".* TO 'uptest2'@'%'                                                             |

| GRANT UPDATE ON "test2".* TO 'uptest2'@'%'                                                             |

| GRANT UPDATE ON "test3".* TO 'uptest2'@'%'                                                             |

+--------------------------------------------------------------------------------------------------------+

4 rows in set (0.00 sec)

创建了两个账号,3个数据库,每个数据库创建一个测试表,账号权限如下表:

 

test1

test2

test3

uptest1@’%’

update

update

null

uptest2@’%’

update

update

update

 

第二章 现象描述

SELECT/UPDATE/INSERT/DELETE command denied to user 'XXX'@'XXX.XXX.XXX.XXX' for table 'xxx'的错误大部分出现在应用程序中,有时用客户端登录mysql后执行操作也会遇到,后者更容易排查,前者由于涉及应用逻辑以及对象权限等,会比较难排除

 

第三章 问题分析

其中前半部分描述主要是应用逻辑问题导致的该现象,也是98%的可能的原因,后半部分说明某些及其特别的情况也会导致,占比很低

3.1 可能原因1:数据库不存在或者数据库错误(权限不足)

表面现象是数据库不存在或更新中使用的数据库名称错误,数据库名称错误属于应用代码层面的逻辑错误导致,根本原因是权限不足导致,简单测试如下:

bee662f6d1682619f5e2c118af93d3a961d6a7ed

抓包数据如下:

79f5af7d39a527f9b624463ff15f4bf603150653

在该测试中,uptest1@’%’只有test1和test2的更新权限,但是更新test4时,由于test4不存在会出现ERROR 1142 (42000): UPDATE command denied to user 'uptest1'@'10.26.254.217' for table 'updatetest',这里需要说明下,没有出现Table 'XXXX' doesn't exist的错误提示,下面用super账号登录测试:

3e15798800d488dea1ca17808413a576a043f670

通过上面的截图可以看到,super账号没有出现ERROR 1142 (42000): UPDATE command denied to user 'uptest1'@'10.26.254.217' for table 'updatetest',而是出现了ERROR 1146 (42S02): Table 'test4.updatetest' doesn't exist,可以大概的判断出来:因为uptest1@’%’只有有限的权限,所以它无法判断test4数据库是否存在,也可以认为当一个账号有辨别对象是否存在的权限时,才会提示Table 'XXXX' doesn't exist,如下,使用uptest1@‘%’来更新test1数据库不存在的表:

ea217c91890207dff58cf54f9122d113558dfa9b

因为update1@'%'有test1数据库的更新权限,更新不存在的表时,提示的是ERROR 1146 (42S02): Table 'test1.updatetest1' doesn't exist

 

 

3.2 可能原因2:对象存在,账号权限不足测试

这是指所用账号的权限不足,本身不支持更新这个对象,这也是比较常见的原因

如下测试截图:

8b24cbf8bcd1f48c406406f7d38b473ea2ae5a70

对应的抓包截图如下:

2bd3b99758b34c09d57b078148dca1b76e841763

在该测试中,uptest1@’%’只有test1和test2的更新权限,所以更新test1和test2是正常的,但是更新test3是异常的,当使用有权限的uptest2@’%’时,更新正常:

ac704efaac998f1bf3050a9a8a411e124c214c50

 

3.3 可能原因3:非高权限账号的授权失效(可能性较低)

该问题可能需要满足:

1,rds for mysql是非高权限账号

2,数据库名字中有下划线,且show grants for出现\的情况

测试rds实例的数据库和授权如下:


ba01892cb88e35a12f43879eb3e8e29b4749c8a9

66a6a8380a721bc73009a3a01b19282ffeee0395

如上截图,在控制台创建了mh_test_db和test-2为名称的数据库,授权给了账号mh_test_rds,使用mh_test_rds登录后,执行show grants for mh_test_rds@’%’,结果如下:

9543b7ca02575ae9853bd7f8317bf453b60b2846

如上图,下划线的数据库名称前面加了反斜线,下面尝试更新一个表,进行测试:

54c61a9b2ea186f102757c495d8941f206621e85

更新测试正常,长达40次测试也未见异常,都没有出现UPDATE command denied类的错误,正常情况下,不会出现本文描述的问题,在特定情况下可能会出现偶发性的update command类问题,需要重新授权才可解决,概率较低

3.4 可能原因4:账号认证混淆(可能性很低)

这种原因可能性极低,也是出现在特定条件下的

创建两个账号,分别进行授权,如下:

mysql> create user uptest3@'10.26.254.217' identified by '123';

Query OK, 0 rows affected (0.00 sec)

 

mysql> create user uptest3@'172.29.25.21' identified by '123';

Query OK, 0 rows affected (0.00 sec)

 

mysql> grant update on test1.* to uptest3@'10.26.254.217';

Query OK, 0 rows affected (0.00 sec)

 

mysql> grant update on test2.* to uptest3@'172.29.25.21';

Query OK, 0 rows affected (0.00 sec)

当使用uptest3@'10.26.254.217'账号去更新test1的数据库的对象时,正常情况下是不会出错的,如下:

350875f0a9f522ad62daf5fd5146dfa6abfdda27

8a97d7a8a94c4b6a01aa235a5a5f5e995290b9ae


即使更新出错,比如更新test2里面的对象,错误提示会是如下情况:

8eb1185ee2f8e7d18bb30fd9b6237468f67f698d

8a97d7a8a94c4b6a01aa235a5a5f5e995290b9ae


错误提示是ERROR 1142 (42000): UPDATE command denied to user 'uptest3'@'10.26.254.217' for table 'updatetest'

这类的抛错也是正常的(后面提示的账号是'uptest3'@'10.26.254.217',其中ip是client的来源ip,select user()可见),因为是正常的权限问题导致,但是当更新test1数据库出现的错误变成下面这种错误时就很奇怪了:

9d12ac319fcdc205423168ff2390e288e6233ee9

如上的现象,同样是使用uptest3@'10.26.254.217'登录更新test1的表,本来是没有错误的,却莫名其妙的出现了:

ERROR 1142 (42000): UPDATE command denied to user 'uptest3'@'172.29.25.21' for table 'updatetest'的错误,并且提示的user是'uptest3'@'172.29.25.21'(来源ip并不是172.29.25.21),而不是'uptest3'@'10.26.254.217',从抓包看,是相同的tcp flow,如下(由于无法复现,下面的报文只是模拟问题发生的类似报文):


0ad19125e15daa7abb79d03fba30c7c4b7b6e574

44737479905daf81ea4abb8afd566c563f746891

5.6.16-log.<E..`-^q?&?K...!...............<*[n7cp)yH<2.mysql_native_password.............!.......................uptest3...5c.........h[`.@[.Cmysql_native_password.o._os.linux-glibc2.5._client_name.libmysql._pid.29870._client_version.5.6.35         _platform.x86_64.program_name.mysql...........!....select @@version_comment limit 1.....'....def....@@version_comment..!.9.......................Source distribution......... ....update test1.updatetest set a=2W....v.#42000UPDATE command denied to user 'uptest3'@'172.29.25.21' for table 'updatetest'.....N...

 

简单描述下现象即:应用在主机10.26.254.217上,使用uptest2的用户通过内网连接到了rds

,然后执行update test1.updatetest set a=2的操作,在权限正常的情况下,出现了UPDATE command denied to user 'uptest3'@'172.29.25.21' for table 'updatetest'的错误,即不是UPDATE command denied to user 'uptest3'@'10.26.254.217' for table 'updatetest',也不是更新成功,所以这类情况是比较奇怪且几率极低的

3.5 可能原因5:rds for mysql实例锁定

有很多情况下,实例空间满导致的锁定,以及实例过期导致的锁定会出现这种情况,所以此处也把这类原因列出来,通过测试无法复现,目前实例锁定都会出现ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement的抛错了,不会出现本篇描述的错误,如下:


 90db8f2c880f86292962c1e84fdc55b97cdccca3


 

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。 &nbsp; 相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/mysql&nbsp;
目录
相关文章
|
JSON Java 数据格式
有关Java调用第三方接口【Content-type为form-data】的示例代码
有关Java调用第三方接口【Content-type为form-data】的示例代码
1341 0
|
前端开发 算法 Java
1024程序员节|历经一个月总结使用java实现pdf文件的电子签字+盖章+防伪二维码+水印+PDF文件加密的全套解决方案
🍅程序员小王的博客:程序员小王的博客 🍅CSDN地址:程序员小王java 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 如有编辑错误联系作者,如果有比较好的文章欢迎分享给我,我会取其精华去其糟粕 🍅java自学的学习路线:java自学的学习路线
3781 0
1024程序员节|历经一个月总结使用java实现pdf文件的电子签字+盖章+防伪二维码+水印+PDF文件加密的全套解决方案
|
数据采集 存储 机器学习/深度学习
数据融合是什么?进行数据融合的4大关键环节!
当业务数据分散、格式不一,难以统一分析时,数据融合成为关键。它通过整合多源数据,形成统一、高质量的数据集,为AI模型提供精准输入。本文详解数据融合的定义、类型、挑战及应对方法,助你打破数据壁垒,挖掘深层价值,推动业务创新。
数据融合是什么?进行数据融合的4大关键环节!
阿里云实名认证api接口怎么调用
当我们注册一个购物网站,或者下载某个游戏,很多地方都需要做实名认证。那么作为购物网站,或者游戏公司,怎么才能判断客户提供的身份证号码是否真实呢?游戏玩家越来越多,我们可能人工去审核这个人提供个的身份证号码是否属实,或者是否是真人。根据国家规定,我们很多游戏都要对未成年游戏时长进行控制,也就是通常大家所谓的游戏防沉迷系统。我们只要把那些进行实名认证玩家的年龄给摘出来以后,就可以判断其是否成年。
阿里云实名认证api接口怎么调用
|
安全 算法 数据可视化
工厂人员定位管理系统:提升生产效率、保障作业安全
在智能制造与工业4.0背景下,工厂人员定位管理系统成为提升生产效率和保障作业安全的关键工具。本文详解该系统的核心功能,包括实时定位、历史轨迹回放、巡更打卡、离岗警告及超员/超时提醒,展示其智能化、高效化和安全化的全面优势。通过高精度定位基站与智能算法,系统不仅优化了生产流程,还有效预防了安全事故,助力企业实现高效、智能的生产管理。维小帮提供相关技术文档与专业咨询,助您探索更智能的生产管理之道。
860 11
|
Python
Python中常见的语法错误
【5月更文挑战第13天】Python中常见的语法错误
1408 3
|
XML Java API
List与String相互转化方法汇总
本文汇总了List与String相互转化的多种方法,包括使用`String.join()`、`StringBuilder`、Java 8的Stream API、Apache Commons Lang3的`StringUtils.join()`以及Guava的`Joiner.on()`方法实现List转String;同时介绍了使用`split()`方法、正则表达式、Apache Commons Lang3的`StringUtils.split()`及Guava的`Splitter.on()`方法实现String转List。
2873 1
List与String相互转化方法汇总
|
存储 SQL 关系型数据库
MySQL查询数据库锁表的SQL语句
MySQL查询数据库锁表的SQL语句
1770 2
|
存储 SQL 数据库
软件体系结构 - 架构风格(10)数据库系统架构风格
【4月更文挑战第21天】软件体系结构 - 架构风格(10)数据库系统架构风格
635 0
|
存储 运维 监控
基础篇丨链路追踪(Tracing)其实很简单(2)
基础篇丨链路追踪(Tracing)其实很简单
798 0
基础篇丨链路追踪(Tracing)其实很简单(2)

热门文章

最新文章