MySQL 在安裝時會自動創建一個名為 mysql 的數據庫,mysql 數據庫中存儲的都是用戶權限表。用戶登錄以后,MySQL 會根據這些權限表的內容為每個用戶賦予相應的權限。
user 表是 MySQL 中最重要的一個權限表,用來記錄允許連接到服務器的賬號信息。需要注意的是,在 user 表里啟用的所有權限都是全局級的,適用於所有數據庫。
user 表中的字段大致可以分為 4 類,分別是用戶列、權限列、安全列和資源控制列,下面主要介紹這些字段的含義。
用戶列
用戶列存儲了用戶連接 MySQL 數據庫時需要輸入的信息。需要注意的是 MySQL 5.7 版本不再使用 Password 來作為密碼的字段,而改成了 authentication_string。
MySQL 5.7 版本的用戶列如表 1 所示。
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機名 |
| User | char(32) | NO | 無 | 用戶名 |
| authentication_string | text | YES | 無 | 密碼 |
用戶登錄時,如果這 3 個字段同時匹配,MySQL 數據庫系統才會允許其登錄。創建新用戶時,也是設置這 3 個字段的值。修改用戶密碼時,實際就是修改 user 表的 authentication_string 字段的值。因此,這 3 個字段決定了用戶能否登錄。
權限列
權限列的字段決定了用戶的權限,用來描述在全局范圍內允許對數據和數據庫進行的操作。
權限大致分為兩大類,分別是高級管理權限和普通權限:
- 高級管理權限主要對數據庫進行管理,例如關閉服務的權限、超級權限和加載用戶等;
- 普通權限主要操作數據庫,例如查詢權限、修改權限等。
user 表的權限列包括 Select_priv、Insert_ priv 等以 priv 結尾的字段,這些字段值的數據類型為 ENUM,可取的值只有 Y 和 N:Y 表示該用戶有對應的權限,N 表示該用戶沒有對應的權限。從安全角度考慮,這些字段的默認值都為 N。
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Select_priv | enum('N','Y') | NO | N | 是否可以通過SELECT 命令查詢數據 |
| Insert_priv | enum('N','Y') | NO | N | 是否可以通過 INSERT 命令插入數據 |
| Update_priv | enum('N','Y') | NO | N | 是否可以通過UPDATE 命令修改現有數據 |
| Delete_priv | enum('N','Y') | NO | N | 是否可以通過DELETE 命令刪除現有數據 |
| Create_priv | enum('N','Y') | NO | N | 是否可以創建新的數據庫和表 |
| Drop_priv | enum('N','Y') | NO | N | 是否可以刪除現有數據庫和表 |
| Reload_priv | enum('N','Y') | NO | N | 是否可以執行刷新和重新加載MySQL所用的各種內部緩存的特定命令,包括日志、權限、主機、查詢和表 |
| Shutdown_priv | enum('N','Y') | NO | N | 是否可以關閉MySQL服務器。將此權限提供給root賬戶之外的任何用戶時,都應當非常謹慎 |
| Process_priv | enum('N','Y') | NO | N | 是否可以通過SHOW PROCESSLIST命令查看其他用戶的進程 |
| File_priv | enum('N','Y') | NO | N | 是否可以執行SELECT INTO OUTFILE和LOAD DATA INFILE命令 |
| Grant_priv | enum('N','Y') | NO | N | 是否可以將自己的權限再授予其他用戶 |
| References_priv | enum('N','Y') | NO | N | 是否可以創建外鍵約束 |
| Index_priv | enum('N','Y') | NO | N | 是否可以對索引進行增刪查 |
| Alter_priv | enum('N','Y') | NO | N | 是否可以重命名和修改表結構 |
| Show_db_priv | enum('N','Y') | NO | N | 是否可以查看服務器上所有數據庫的名字,包括用戶擁有足夠訪問權限的數據庫 |
| Super_priv | enum('N','Y') | NO | N | 是否可以執行某些強大的管理功能,例如通過KILL命令刪除用戶進程;使用SET GLOBAL命令修改全局MySQL變量,執行關於復制和日志的各種命令。(超級權限) |
| Create_tmp_table_priv | enum('N','Y') | NO | N | 是否可以創建臨時表 |
| Lock_tables_priv | enum('N','Y') | NO | N | 是否可以使用LOCK TABLES命令阻止對表的訪問/修改 |
| Execute_priv | enum('N','Y') | NO | N | 是否可以執行存儲過程 |
| Repl_slave_priv | enum('N','Y') | NO | N | 是否可以讀取用於維護復制數據庫環境的二進制日志文件 |
| Repl_client_priv | enum('N','Y') | NO | N | 是否可以確定復制從服務器和主服務器的位置 |
| Create_view_priv | enum('N','Y') | NO | N | 是否可以創建視圖 |
| Show_view_priv | enum('N','Y') | NO | N | 是否可以查看視圖 |
| Create_routine_priv | enum('N','Y') | NO | N | 是否可以更改或放棄存儲過程和函數 |
| Alter_routine_priv | enum('N','Y') | NO | N | 是否可以修改或刪除存儲函數及函數 |
| Create_user_priv | enum('N','Y') | NO | N | 是否可以執行CREATE USER命令,這個命令用於創建新的MySQL賬戶 |
| Event_priv | enum('N','Y') | NO | N | 是否可以創建、修改和刪除事件 |
| Trigger_priv | enum('N','Y') | NO | N | 是否可以創建和刪除觸發器 |
| Create_tablespace_priv | enum('N','Y') | NO | N | 是否可以創建表空間 |
如果要修改權限,可以使用 GRANT 語句為用戶賦予一些權限,也可以通過 UPDATE 語句更新 user 表的方式來設置權限。
安全列
安全列主要用來判斷用戶是否能夠登錄成功,user 表中的安全列如表 3 所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| ssl_type | enum('','ANY','X509','SPECIFIED') | NO | 支持ssl標准加密安全字段 | |
| ssl_cipher | blob | NO | 支持ssl標准加密安全字段 | |
| x509_issuer | blob | NO | 支持x509標准字段 | |
| x509_subject | blob | NO | 支持x509標准字段 | |
| plugin | char(64) | NO | mysql_native_password | 引入plugins以進行用戶連接時的密碼驗證,plugin創建外部/代理用戶 |
| password_expired | enum('N','Y') | NO | N | 密碼是否過期 (N 未過期,y 已過期) |
| password_last_changed | timestamp | YES | 記錄密碼最近修改的時間 | |
| password_lifetime | smallint(5) unsigned | YES | 設置密碼的有效時間,單位為天數 | |
| account_locked | enum('N','Y') | NO | N | 用戶是否被鎖定(Y 鎖定,N 未鎖定) |
注意:即使 password_expired 為“Y”,用戶也可以使用密碼登錄 MySQL,但是不允許做任何操作。
通常標准的發行版不支持 ssl,讀者可以使用 SHOW VARIABLES LIKE "have_openssl" 語句來查看是否具有 ssl 功能。如果 have_openssl 的值為 DISABLED,那么則不支持 ssl 加密功能。
資源控制列
資源控制列的字段用來限制用戶使用的資源,user 表中的資源控制列如表 4 所示。
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| max_questions | int(11) unsigned | NO | 0 | 規定每小時允許執行查詢的操作次數 |
| max_updates | int(11) unsigned | NO | 0 | 規定每小時允許執行更新的操作次數 |
| max_connections | int(11) unsigned | NO | 0 | 規定每小時允許執行的連接操作次數 |
| max_user_connections | int(11) unsigned | NO | 0 | 規定允許同時建立的連接次數 |
以上字段的默認值為 0,表示沒有限制。一個小時內用戶查詢或者連接數量超過資源控制限制,用戶將被鎖定,直到下一個小時才可以在此執行對應的操作。可以使用 GRANT 語句更新這些字段的值。
MySQL db、tables_priv、columns_priv和procs_priv權限表
在 MySQL 數據庫中,權限表除了 user 表外,還有 db 表、tables_priv 表、columns_priv 表和 procs_priv 表。下面主要介紹其它幾種權限表。
db表
db 表比較常用,是 MySQL 數據庫中非常重要的權限表,表中存儲了用戶對某個數據庫的操作權限。表中的字段大致可以分為兩類,分別是用戶列和權限列。
用戶列
db 表用戶列有 3 個字段,分別是 Host、User、Db,標識從某個主機連接某個用戶對某個數據庫的操作權限,這 3 個字段的組合構成了 db 表的主鍵。
db 表的用戶列如下表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機名 |
| Db | char(64) | NO | 無 | 數據庫名 |
| User | char(32) | NO | 無 | 用戶名 |
權限列
db 表中的權限列和 user 表中的權限列大致相同,只是user 表中的權限是針對所有數據庫的,而 db 表中的權限只針對指定的數據庫。如果希望用戶只對某個數據庫有操作權限,可以先將 user 表中對應的權限設置為 N,然后在 db 表中設置對應數據庫的操作權限。
tables_priv表和columns_priv表
tables_priv 表用來對單個表進行權限設置,columns_priv 表用來對單個數據列進行權限設置。tables_priv 表結構如下表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機 |
| Db | char(64) | NO | 無 | 數據庫名 |
| User | char(32) | NO | 無 | 用戶名 |
| Table_name | char(64) | NO | 無 | 表名 |
| Grantor | char(93) | NO | 無 | 修改該記錄的用戶 |
| Timestamp | timestamp | NO | CURRENT_TIMESTAMP | 修改該記錄的時間 |
| Table_priv | set('Select','Insert','Update','Delete',' Create','Drop','Grant','References', 'Index','Alter','Create View','Show view','Trigger') |
NO | 無 | 表示對表的操作權限,包括 Select、Insert、Update、Delete、Create、Drop、Grant、References、Index 和 Alter 等 |
| Column_priv | set('Select','Insert','Update','References') | NO | 無 | 表示對表中的列的操作權限,包括 Select、Insert、Update 和 References |
columns_priv 表結構如下表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機 |
| Db | char(64) | NO | 無 | 數據庫名 |
| User | char(32) | NO | 無 | 用戶名 |
| Table_name | char(64) | NO | 無 | 表名 |
| Column_name | char(64) | NO | 無 | 數據列名稱,用來指定對哪些數據列具有操作權限 |
| Timestamp | timestamp | NO | CURRENT_TIMESTAMP | 修改該記錄的時間 |
| Column_priv | set('Select','Insert','Update','References') | NO | 無 | 表示對表中的列的操作權限,包括 Select、Insert、Update 和 References |
procs_priv表
procs_priv 表可以對存儲過程和存儲函數進行權限設置,procs_priv 的表結構如表所示:
| 字段名 | 字段類型 | 是否為空 | 默認值 | 說明 |
|---|---|---|---|---|
| Host | char(60) | NO | 無 | 主機名 |
| Db | char(64) | NO | 無 | 數據庫名 |
| User | char(32) | NO | 無 | 用戶名 |
| Routine_name | char(64) | NO | 無 | 表示存儲過程或函數的名稱 |
| Routine_type | enum('FUNCTION','PROCEDURE') | NO | 無 | 表示存儲過程或函數的類型,Routine_type 字段有兩個值,分別是 FUNCTION 和 PROCEDURE。FUNCTION 表示這是一個函數;PROCEDURE 表示這是一個 存儲過程。 |
| Grantor | char(93) | NO | 無 | 插入或修改該記錄的用戶 |
| Proc_priv | set('Execute','Alter Routine','Grant') | NO | 無 | 表示擁有的權限,包括 Execute、Alter Routine、Grant 3種 |
| Timestamp | timestamp | NO | CURRENT_TIMESTAMP | 表示記錄更新時間 |
