閱讀689 返回首頁    go 技術社區[雲棲]


應用中拋出SELECT/UPDATE/INSERT/DELETE command denied to user 'XXX'@'XXX.XXX.XXX.XXX' for table 'xxx' 的

實為吾之愚見,望諸君酌之!聞過則喜,與君共勉 


第一章 準備環境

創建數據測試數據

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


 

最後更新:2017-11-28 14:34:35

  上一篇:go  seo高手已經掌握的秒收教程
  下一篇:go  Linux環境部署輕量化配置中心