在這篇文章中,咱們來聊聊怎麼管理MySQL
的用戶及如何爲不一樣用戶分配不一樣的管理權限,其實,在平常使用MySQL
的過程當中,這部分的工做是由DBA
(數據管理員)來完成的。mysql
而咱們做爲通常的開發人員,只要拿到分配好的帳號和密碼鏈接到MySQL
服務器訪問特定的數據庫,並不涉及到用戶管理的內容。sql
不過,今天咱們不妨切換到一個DBA
視角,一塊兒來詳細瞭解MySQL
有關用戶及權限管理的相關知識。數據庫
MySQL
中與系統用戶及用戶權限管理有關的信息都存儲在系統數據庫mysql
中,這些數據表須要通過數據初始化,每一個數據表有特定的數據結構。安全
在安裝好MySQL
以後,須要初始化MySQL
系統數據庫,好比咱們通常安裝好MySQL
以後,MySQL
會幫咱們建立默認的超級管理員root
,咱們也可使用下面的語句在初始化時建立其餘帳號:bash
MySQL支持不少種不一樣的安裝方式,通常狀況下會幫咱們初始化mysql系統數據庫。服務器
bin/mysqld --initialize --user=mysql
bin/mysqld --initialize-insecure --user=mysql
複製代碼
在MySQL
系統數據庫mysql
中與用戶及權限相關的數據表一共有6張,下面表格這幾張數據表的說明。數據結構
系統數據庫mysql中除了與權限管理有關的數據外,還有其餘的數據表。函數
數據表 | 說明 |
---|---|
user | 用戶賬戶,全局特權和其餘非特權列 |
db | 數據庫級別的管理權限 |
tables_priv | 數據表級別的管理權限 |
columns_priv | 數據列級別的管理權限 |
procs_priv | 存儲過程及函數的使用權限 |
proxies_priv | 代理用戶權限 |
下面咱們來看這些數據表的更詳細表結構,咱們看到下面的數據表中的字段能夠大致分爲四類,分別爲scope columes
,Privilege columns
,Security columns
,Resource control columns
。ui
scope columes
用於限定是某個用戶,某個數據庫或者某個數據表,Privilege columns
表示權限,在user
表中表示全局權限,在db
表中表示對某個數據庫的操做權限,而Security columns
與Resource control columns
的字段則爲user
表所獨有。編碼
user
數據表存儲的是用戶的帳號信息及全局權限信息,而db
數據表存儲的是用戶對於具體數據庫的操做權限。
表名 | user | db |
---|---|---|
Scope columns | Host | Host |
User | Db | |
User | ||
Privilege columns | Select_priv | Select_priv |
Insert_priv | Insert_priv | |
Update_priv | Update_priv | |
Delete_priv | Delete_priv | |
Index_priv | Index_priv | |
Alter_priv | Alter_priv | |
Create_priv | Create_priv | |
Drop_priv | Drop_priv | |
Grant_priv | Grant_priv | |
Create_view_priv | Create_view_priv | |
Show_view_priv | Show_view_priv | |
Create_routine_priv | Create_routine_priv | |
Alter_routine_priv | Alter_routine_priv | |
Execute_priv | Execute_priv | |
Ttrigger_priv | Ttrigger_priv | |
Event_priv | Event_priv | |
Create_tmp_table_priv | Create_tmp_table_priv | |
Lock_tables_priv | Lock_tables_priv | |
References_priv | References_priv | |
Reload_priv | ||
Shutdown_priv | ||
Process_priv | ||
File_priv | ||
Show_db_priv | ||
Super_priv | ||
Repl_slave_priv | ||
Repl_client_priv | ||
Create_user_priv | ||
Create_tablespace_priv | ||
Security columns | ssl_type | |
ssl_cipher | ||
x509_issuer | ||
x509_subject | ||
plugin | ||
authentication_string | ||
password_expired | ||
password_last_changed | ||
password_lifetime | ||
account_locked | ||
Resource control columns | max_questions | |
max_updates | ||
max_connections | ||
max_user_connections |
上面是db
與user
數據表的對比,在上面的對比中,咱們看到db
數據表與user
有相同的字段,這些字段在db
數據表,表示某個用戶對某個數據表有哪些權限,而在user
數據表中,則表示用戶的全局權限。
tables數據用於存儲用戶對數據表的權限,而columns_priv數據用於存儲用戶對數據列的權限。
表名 | tables_priv | 與columns_priv |
---|---|---|
Scope columns | Host | Host |
Db | Db | |
User | User | |
Table_name | Table_name | |
Column_name | ||
Privilege columns | Table_priv | Column_priv |
Column_priv | ||
Other columns | Timestamp | Timestamp |
Grantor |
procs_priv
數據表用於存儲用戶對自定義函數以及存儲過程的權限,其表結構比較簡單,以下所示:
表名 | procs_priv |
---|---|
Scope columns | Host |
Db | |
User | |
Routine_name | |
Routine_type | |
Privilege columns | Proc_priv |
Other columns | Timestamp |
Grantor |
在上面的字段中,Routine_type
爲ENUM
類型,其取值爲FUNCTION
或PROCEDURE
,而Timestamp
和Grantor
兩個字段暫時沒有什麼做用。
proxies_priv
存儲的是代理用戶的關係數據,什麼是代理用戶?能夠簡單地理解爲一個用戶將本身的權限授予給被另外一個用戶使用,比較A用戶經過代理將權限授予B用戶使用,那麼B用戶則稱爲代理用戶。
proxies_priv
數據表包含Host
,User
,Proxied_host
,Proixed_user
,Grantor
,Timestamp
,With_grant
等字段。
介紹了與權限管理相關的數據表以後,咱們也知道MySQL
將用戶存儲在哪一個數據表中,以及MySQL
如何組織用戶的權限信息,接來在用戶管理這塊內容中,咱們來了解的是MySQL
數據庫系統中,如何識別一個用戶,如何建立、修改、刪除用戶以及如何爲用戶設置密碼。
MySQL
的用戶由用戶名(User)
和主機名(Host)
組成,主機名錶示容許該用戶從哪臺主機鏈接到MySQL
服務器,因此在MySQL
中,表示一個用戶的格式以下所示:
# username表示用戶名,host_name表示主機名
'user_name'@'host_name'
複製代碼
好比我使用root
帳號在MySQL
本地服務器登陸,那麼此時的root
帳號的用戶爲:
'root'@'localhost'
複製代碼
另外,在MySQL
中,咱們可使用USER()
和CURRENT_USER()
函數或者CURRENT_USER
查詢當前的用戶,如:
mysql> SELECT USER();
mysql> SELECT CURRENT_USER();
mysql> SELECT CURRENT_USER;
複製代碼
上面兩個語句的查詢結果爲:
+----------------+
| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
+----------------+
| current_user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
+----------------+
| current_user |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
複製代碼
用戶名和主機名能夠惟一地肯定一個用戶,因此即便用戶名相同,主機名不一樣時,也表示兩個不一樣的用戶,好比下面的例子中用戶名雖然都是test
,因爲主機名不一樣因此是兩個用戶。
'test'@'192.168.0.1'
'test'@'192.168.0.2'
複製代碼
當咱們在建立帳號沒有指定主機時,則主機名的值爲'%'
,這表示容許帳號從任意主機鏈接到MySQL
服務器,好比:
'test'@'%'
複製代碼
在上面的示例中,用戶名和主機都是使用單引號括起來,不過,若是沒有特殊的字符,能夠不使用單引號,因此上面的用戶能夠這樣表示:
test@localhost
複製代碼
若是帶有橫槓(-),點(.),百分號(%),空格等特殊字符,則必須使用單引號,如:
# 正確示例
test@'192.168.0.1'
root@'%'
# 錯誤示例
test@192.168.0.1
test@%
複製代碼
從上面的示例中咱們也看到,用戶名和主機名是分別使用單引號括起來的,若是使用一個單引號把用戶名和主機號括號,則MySQL會認爲是整個看成用戶名,而主機名則用默認的'%',以下所示:
'root@localhost'
#上面的寫法,MySQL會解析爲
'root@localhost'@'%'
複製代碼
另外,爲了提升安全性,也能夠爲用戶設置登陸密碼,不過密碼並非必填的,不過爲了安全,最好仍是設置密碼。
MySQL
用戶名的最大長度爲32
個字符,這個字符長度在MySQL
程序中是硬編碼的,因此即便咱們修改了存儲帳號的user
數據表用戶名長度,也是沒有效果的。
查詢用戶權限分爲兩種,一種是查詢本身當前登陸用戶的權限,一種是查詢其餘用戶的權限。
SHOW GRANTS [FOR user]
複製代碼
不使用FOR
子句的話,能夠當查詢當前登陸用戶的權限,好比我當前登陸了root用戶,使用下面的語句進行查詢:
mysql> 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)
複製代碼
若是你的帳號有查詢其餘用戶信息的權限,那麼可使用FOR
子句後面加上想查詢用戶的帳號信息,不過要注意的是,須要有查詢別人權限的權限,才能使用下面的語句。
mysql> SHOW GRANTS FOR 'test'@'localhost';
複製代碼
結果以下:
+------------------------------------------+
| Grants for 'test'@'localhost' |
+------------------------------------------+
| GRANT USAGE ON *.* TO 'test'@'localhost' |
+------------------------------------------+
1 row in set (0.00 sec)
複製代碼
MySQ
L建立用戶使用CREATE USER
語句,該語句比較複雜,其語句結構以下所示:
CREATE USER [IF NOT EXISTS]
user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...
#參考咱們上面的介紹
user:
(see Section 6.2.4, 「Specifying Account Names」)
auth_option: {
IDENTIFIED BY 'auth_string'
| IDENTIFIED WITH auth_plugin
| IDENTIFIED WITH auth_plugin BY 'auth_string'
| IDENTIFIED WITH auth_plugin AS 'auth_string'
| IDENTIFIED BY PASSWORD 'auth_string'
}
tls_option: {
SSL
| X509
| CIPHER 'cipher'
| ISSUER 'issuer'
| SUBJECT 'subject'
}
resource_option: {
MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
}
password_option: {
PASSWORD EXPIRE
| PASSWORD EXPIRE DEFAULT
| PASSWORD EXPIRE NEVER
| PASSWORD EXPIRE INTERVAL N DAY
}
lock_option: {
ACCOUNT LOCK
| ACCOUNT UNLOCK
}
複製代碼
上面的語法看着好像很複雜,其實不少選項是能夠選擇的,好比最簡單的,咱們可使用下面的語句建立一個用戶:
mysql> CREATE USER 'test'@'localhost' IDENTIFIED BY '123456';
複製代碼
MySQL
修改用戶的信息使用ALTER USER
語句,其用法以下所示:
ALTER USER [IF EXISTS]
user [auth_option] [, user [auth_option]] ...
[REQUIRE {NONE | tls_option [[AND] tls_option] ...}]
[WITH resource_option [resource_option] ...]
[password_option | lock_option] ...
複製代碼
從上面的用法中能夠看出,ALTER USER
語句和CREATE USER
語句基本相似,各類選項基本相同,所以咱們參考CREATE USER
的用法。
好比咱們要修改當前用戶的密碼,能夠這樣:
mysql> ALTER USER USER() IDENTIFIED BY 'test123457';
複製代碼
MySQL刪除用戶使用DROP USER
語句,該語句用法以下:
DROP USER [IF EXISTS] user [, user] ...
複製代碼
從上面的語法看現,MySQL支持刪除一個或多個用戶,其用法以下所示:
mysql> DROP USER 'test'@'test.example.com','test1'@'test1.example.com';;
複製代碼
若是在建立用戶的時候沒有指定密碼,或者想從新設置某個用戶的密碼,可使用SET PASSWORD
語句,該語句的用法以下所示:
SET PASSWORD [FOR user] = password_option
password_option: {
'auth_string'
| PASSWORD('auth_string')
}
複製代碼
上面的語句中,auth_string
表示未加密的明文密碼,也可使用PASSWORD()函數進行加密,不過在MySQL5.7.6以後不推薦這種用法,在將來的版本這種用法會移除。
設置密碼語句中的FOR子句
能夠省略,若是省略則表示修改當前用戶的密碼,如:
SET PASSWORD = "123456"
複製代碼
使用FOR子句
,則能夠修改指定帳號的密碼,以下:
SET PASSWORD FOR CURRENT_USER() = "123456"
複製代碼
在
MySQL
用戶管理中,並不推薦使用SET PASSWORD
語句來設置用戶密碼,由於這個步驟在CREATE USER
和ALTER USER
即可以完成了。
前面講了MySQL
權限的存儲細節以及用戶管理的相關知識,對這些有所瞭解以後,咱們來詳細瞭解如何給用戶受權權限。
在MySQL
中,對於用戶的權限劃分能夠分爲兩種,一種是數據管理相關的權限,好比對數據庫、數據表進行操做,建立存儲過程和視圖的權限,另外一種是對用戶的管理權限,好比建立、刪除用戶,爲用戶分配權限。
MySQL
爲咱們提供了GRANT
語句進行受權管理,其語法結構以下所示:
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} ...]
GRANT PROXY ON user
TO user [, user] ...
[WITH GRANT OPTION]
object_type: {
TABLE
| FUNCTION
| PROCEDURE
}
priv_level: {
*
| *.*
| db_name.*
| db_name.tbl_name
| tbl_name
| db_name.routine_name
}
user:
(see Section 6.2.4, 「Specifying Account Names」)
auth_option: {
IDENTIFIED BY 'auth_string'
| IDENTIFIED WITH auth_plugin
| IDENTIFIED WITH auth_plugin BY 'auth_string'
| IDENTIFIED WITH auth_plugin AS 'auth_string'
| IDENTIFIED BY PASSWORD 'auth_string'
}
tls_option: {
SSL
| X509
| CIPHER 'cipher'
| ISSUER 'issuer'
| SUBJECT 'subject'
}
resource_option: {
| MAX_QUERIES_PER_HOUR count
| MAX_UPDATES_PER_HOUR count
| MAX_CONNECTIONS_PER_HOUR count
| MAX_USER_CONNECTIONS count
}
複製代碼
爲別的用戶受權,當前用戶必須擁有受權的權限才能夠,好比咱們以普通用戶test
登陸MySQL
爲別的用戶分配權限,因爲test沒有這種權限,所以會報如下的錯誤:
ERROR 1045 (28000): Access denied for user 'test'@'localhost' (using password: NO)
複製代碼
使用GRANT
進行受權時,若是該用戶不存在,能夠跟上GRANT
語句後面跟上IDENTIFIED BY
直接建立該用戶,不過若是在建立用戶時要設置更詳細的信息,則應該使用CREATE USER
語句來建立用戶。
GRANT ALL ON *.* TO test_1@localhost IDENTIFIED BY "123456";
複製代碼
上面的語句在用戶不存在,會自動建立用戶。
在分配權限時,想分配什麼級別的權限,能夠加在關鍵字ON
後面,其格式以下所示:
*
*.*
db_name.*
db_name.tbl_name
tbl_name
db_name.routine_name
複製代碼
好比我想給test@localhost用戶分配school數據庫的student表查詢權限,能夠這樣寫:
mysql> GRANT SELECT ON school.student TO 'test'@'localhost';
複製代碼
下面是使用GRANT語句能夠授予的所有權限,不一樣的權限有不一樣的做用域,好比有的是全局權限,有的只做用於數據庫等,以下所示:
權限 | 權限說明及做用的級別 |
---|---|
ALTER[PRIVILEGES] | 除了GRANT OPTION和PROXY以外,以指定的訪問級別授予全部特權。 |
ALTER | 修改權限,做用於全局,數據庫,數據表 |
ALTER_ROUTINE | 修改存儲過程,做用於全局,數據庫,存儲過程 |
CREATE | 建立權限,做用於全局,數據庫,數據表 |
CREATE_ROUTINE | 建立存儲過程的權限,做用於全局,數據庫 |
CREATE_TABLESPACE | 表空間和日誌文件組的建立、更改、刪除,全局權限 |
CREATE_TEMPORARY_TABLES | 建立臨時表的權限,做用於數據庫,數據表 |
CREATE_USER | 建立、刪除,重命用和移除用戶權限的權限,全局權限 |
CREATE_VIEW | 建立視圖權限,做用於全局,數據庫,數據表 |
DELETE | 刪除數據權限,做用於全局,數據庫,數據表 |
DROP | 刪除數據庫、數據表、視圖的權限,做用於全局,數據庫,數據表 |
EVENT | 使用事件的權限,做用於全局,數據庫 |
EXECUTE | 執行存儲過程的權限,做用於全局,數據庫,存儲過程 |
FILE | 讀取或寫入文件的權限,全局權限 |
GRANT_OPTION | 容許受權或取消受權的權限,做用於全局,數據庫,數據表,存儲過程,代理 |
INDEX | 使用索引的權限,做用於全局,數據庫,數據表 |
INSERT | 寫入權限,做用於全局,數據庫,數據表,數據列 |
LOCK_TABLES | 在執行SELECT時能夠啓動LOCK_TABLES的權限,全局或數據庫級別的權限 |
PROCESS | 使用SHOW PROCESSLIST查詢所有存儲過程的權限,全局權限 |
PROXY | 啓用用戶代理,做用級別從用戶到用戶 |
REFERENCES | 建立外健權限,做用於全局,數據庫,數據表,數據列 |
RELOAD | 啓動FLUSH操做,全局權限 |
REPLICATION CLIENT | 使用戶可以詢問主服務器或從服務器在哪裏,全局權限 |
REPLICATION SLAVE | 啓用複製從屬服務器以從主服務器讀取二進制日誌事件,全局權限 |
SELECT | 查詢權限,做用於全局,數據庫,數據表,數據列 |
SHOW_DATABASES | 查詢所有數據庫,全局權限 |
SHOW_VIEWS | 啓用使用SHOW CREATE VIEW,做用於全局,數據庫,數據表 |
SHUTDOWN | 關閉數據庫服務器權限,全局權限 |
SUPER | 啓用其餘管理操做的使用,例如CHANGE MASTER TO,KILL,PURGE BINARY LOGS,SET GLOBAL和mysqladmin debug命令。 全局權限 |
TRIGGER | 啓用觸發器的權限,做用於全局,數據庫,數據表 |
UPDATE | 更新權限,做用於全局,數據庫,數據表,數據列 |
USAGE | 無特權 |
使用All權限分配給用戶時,用戶雖然擁有全部數據庫的操做權限,但並無帳號管理等權限,若是想建立一直跟root同樣的超級管理員,能夠加上WITH GRANT OPTION
參數,以下所示:
mysql> GRANT ALL ON *.* TO 'super'@'localhost' WITH GRANT OPTION
複製代碼
刪除權限與上面的受權是反向操做,能夠刪除不一樣級別的權限,就像上面能夠授予不一樣級別的權限同樣。
刪除權限使用REVOKE
語句,其語法結構以下:
REVOKE
priv_type [(column_list)]
[, priv_type [(column_list)]] ...
ON [object_type] priv_level
FROM user [, user] ...
REVOKE ALL [PRIVILEGES], GRANT OPTION
FROM user [, user] ...
REVOKE PROXY ON user
FROM user [, user] ...
複製代碼
刪除數據庫級別的權限:
mysql > REVOKE CREATE,DROP ON expenses.* FROM 'custom'@'host47.example.com';
複製代碼
刪除用戶的所有權限:
mysql> REVOKE ALL ON *.* FROM 'finley'@'%.example.com';
複製代碼
MySQL
做爲數據庫管理系統,裏面保存企業的重要業務數據,所以保證數據庫的安全性很是重要,如何保證數據庫的安全性呢?用戶和用戶權限管理是一個很重要的方面。
若是你以爲文章不錯,歡迎掃碼關注,你的關注就是我寫做的最大動力