0. 背景介紹
隨著項(xiàng)目的演進(jìn),數(shù)據(jù)庫(kù)的操作也越來(lái)越頻繁,近期mysql數(shù)據(jù)庫(kù)做了權(quán)限控制甲脏,防止開(kāi)發(fā)、運(yùn)營(yíng)妹笆、維護(hù)等環(huán)節(jié)中因?yàn)檎`操作而導(dǎo)致的數(shù)據(jù)庫(kù)風(fēng)險(xiǎn)块请。相信不少人都做過(guò)這樣的工作,這里如何設(shè)置mysql權(quán)限不是重點(diǎn)拳缠,而是權(quán)限設(shè)置中的一個(gè)可選參數(shù)max_user_connections
是今天討論的主題墩新。
1.問(wèn)題描述
在GRANT官方手冊(cè)中,可選參數(shù)的最后有這么幾個(gè)選項(xiàng):
GRANT
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
TO user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH {GRANT OPTION | resource_option} ...]
其中這個(gè)resource_option
有四個(gè)選項(xiàng):
resource_option: {
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
}
分別對(duì)應(yīng):
The number of queries an account can issue per hour
一個(gè)賬號(hào)每小時(shí)可以發(fā)起查詢(xún)操作的個(gè)數(shù)
The number of updates an account can issue per hour
一個(gè)賬號(hào)每小時(shí)可以發(fā)起更新操作的個(gè)數(shù)
The number of times an account can connect to the server per hour
一個(gè)賬號(hào)每小時(shí)可以連接服務(wù)器的次數(shù)
The number of simultaneous connections to the server by an account
一個(gè)賬號(hào)同時(shí)可以連接服務(wù)器的個(gè)數(shù),
說(shuō)明:如果上述4個(gè)參數(shù)配置為0窟坐,則表示不限制海渊。
在你操作的同時(shí),為了防止他人盜用你的賬戶(hù)同時(shí)進(jìn)行操作哲鸳,而導(dǎo)致無(wú)法判定是誰(shuí)進(jìn)行了操作臣疑,因此感覺(jué)通過(guò)MAX_USER_CONNECTIONS
限制可以同時(shí)連接的個(gè)數(shù)是極好的,所以毫不猶豫的選擇配置這個(gè)參數(shù)
2. 配置方式
方式1
GRANT USAGE ON *.* TO db_user@localhost MAX_USER_CONNECTIONS 1;
方式2
UPDATE mysql.user SET max_user_connections = 1 WHERE user='db_user' AND host='localhost'; FLUSH PRIVILEGES;
方式3
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
max_connections = 400
max_user_connections=1
前兩個(gè)是針對(duì)指定用戶(hù)設(shè)置的徙菠,而方式3是針對(duì)全局的讯沈,并且方式3需要重啟服務(wù)。使用方式1的grant執(zhí)行后記得執(zhí)行FLUSH PRIVILEGES;
使之生效婿奔。
3. 問(wèn)題來(lái)了
設(shè)置完成后打開(kāi)終端執(zhí)行mysql -uxxx -p -h xxx.xxx.xxx.xxx -P xxxx
芙盘,輸入密碼,正常進(jìn)入脸秽。
開(kāi)啟第二個(gè)終端執(zhí)行mysql -uxxx -p -h xxx.xxx.xxx.xxx -P xxxx
儒老,輸入密碼,提示如下信息:
ERROR 1226 (42000): User 'xxx' has exceeded the 'max_user_connections' resource (current value: 1)
记餐。
看來(lái)設(shè)置完美生效驮樊。
就在認(rèn)為完美結(jié)束權(quán)限設(shè)置的時(shí)候,一些喜歡MySQL GUI Tools的片酝,如Navicat囚衔、Workbench、DataGrip的同事反饋無(wú)法連接成功雕沿。報(bào)的同樣是上述的ERROR 1226 (42000): User 'xxx' has exceeded the 'max_user_connections' resource (current value: 1)
练湿。奇怪了,明明配置成功了审轮,為什么會(huì)報(bào)超過(guò)connection的限制呢肥哎。
經(jīng)過(guò)研究發(fā)現(xiàn)辽俗,MySQL GUI Tools的連接機(jī)制和終端這種方式不太一樣。通過(guò)執(zhí)行show databases;
篡诽,返回:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| xxx_db |
+--------------------+
2 rows in set (0.05 sec)
發(fā)現(xiàn)崖飘,這里用戶(hù)能訪(fǎng)問(wèn)2個(gè)database,而Navicat杈女、DataGrip這類(lèi)的MySQL GUI Tools在配置完成后朱浴,會(huì)將這兩個(gè)schema都列出來(lái)連接,這個(gè)時(shí)候就相當(dāng)于預(yù)啟動(dòng)兩個(gè)終端分別連接use xxx_db 和 use information_schema.
為了驗(yàn)證這個(gè)猜想达椰,這里通過(guò)上面的調(diào)整語(yǔ)句翰蠢,將max_user_connections
設(shè)置為2,然后通過(guò)DataGrip連接嘗試啰劲,發(fā)現(xiàn)聯(lián)通梁沧。通過(guò)create database test;
再建立一個(gè)數(shù)據(jù)庫(kù)。先斷開(kāi)Navicat這類(lèi)的MySQL GUI Tools連接呈枉,再次連接趁尼,此時(shí)又會(huì)提醒ERROR 1226 (42000): User 'xxx' has exceeded the 'max_user_connections' resource (current value: 2)
。
4.總結(jié)
1猖辫、MySQL GUI Tools會(huì)一次性展示所有的database酥泞,會(huì)為每個(gè)該用戶(hù)有權(quán)限可操作的database預(yù)分配一個(gè)connection,所以設(shè)置max_user_connections
用到該類(lèi)工具的時(shí)候啃憎,一定要考慮到有權(quán)限可操作的database的個(gè)數(shù)芝囤。
2、建議max_user_connections
配合還是使用終端這種方式辛萍,這樣可以降低賬號(hào)盜用的風(fēng)險(xiǎn)(此處只限于經(jīng)常使用的情景悯姊,錯(cuò)峰使用無(wú)法保障)。