Mysql學習(2) -創建、刪除用戶、權限管理以及flush privileges的使用(很多人只是會使用sql語句,但是對用戶以及用戶權限的概念比較模糊)

Time:2019-8-15 21.42
Site:深圳科興科學院
Author: strivewang

摘要

  1. 第一部分是介紹Mysql創建用戶以及相應的權限介紹。
  2. 第二部分細節介紹了Mysql不同維度的權限控制
  3. 第三部分講解了權限控制

1. Mysql創建用戶

第一條語句的邏輯是創建一個用戶’user'@'%’,密碼是 password。用戶名是user, host是%,表示所有的ip
create user 'ua'@'%' identified by 'password';   

第二條語句的邏輯是創建一個用戶’user'@'192.168.0.1’,密碼是 password。用戶名是user, host是192.168.0.1,表示所有的ip
create user 'ua'@'192.168.0.1' identified by 'password';   

這條命令做了兩個動作:

  1. 磁盤上,往 mysql.user 表裏插入一行,由於沒有指定權限,所以這行數據上表示所有的權限字段都是 N。
  2. 內存上,往數組 acl_users 裏插入一個 acl_user 對象,這個對象的access 字段值爲 0 。
    圖一就是用戶 ua 的狀態圖
    圖一 權限詳細圖

2. 全局權限

2.1 授予全局權限

全局權限:作用於整個 MySQL 實例,這些權限信息保存在 Mysql 庫的 user 表中,如果需要給一個用戶賦予最高權限,就是:

grant all privileges on *.* to 'user'@'%' with grant option;

這個 grant 命令做了兩個動作:

  1. 磁盤上,將 mysql.user 表裏,用戶’user@’%’ 這一行所有表示權限的字段修改爲 ‘Y’
  2. 內存中,從數組acl_users 中找到這個用戶的對象,將acess值(權限位)修改爲二進制的 “全1”.

2.2 取消用戶全局權限:

revoke all privileges on *.* from 'user'@'%';

這個 grant 命令做了兩個動作:

  1. 磁盤上,將 mysql.user 表裏,用戶’user@’%’ 這一行所有表示權限的字段修改爲 ‘N’
  2. 內存中,從數組acl_users 中找到這個用戶的對象,將acess值(權限位)修改爲二進制的 “全0”.

3. DB權限

除了全局權限,Mysql也支持庫、表、列等權限的定義。

3.1 授予用戶指定庫權限

#授予ua用戶db1庫所有的權限
grant all privileges on db1.* to 'ua'@'%' with grant option;

基於庫的權限記錄保存在 mysql.db 中,在內存裏則保存在數組acl_dbs中,這個grant命令做了如下兩個操作:

  1. 磁盤上,往mysql.db 表中插入一行記錄,所有權限字段設置爲 “Y”。
  2. 內存裏, 增加一個對象到數組acl_dbs 中,這個對象的權限位設爲 “全1”。

下圖就是當前用戶 ua 在 DB表中的的權限狀態:
圖2 ua用戶的數據庫權限表
數據庫每次需要判斷一個用戶對一個數據庫讀寫權限的時候,都需要遍歷一次 acl_dbs 數組,根據User、host 和 db 找到匹配的對象,然後根據對象的權限位進行判斷。

grant 修改 db 權限的時候,對磁盤和內存是同時生效的。

4. 表權限、列權限

除了全局權限、DB級別的權限之外,Mysql還支持更細粒度的表權限和列權限。其中表權限定義在mysql.table_priv,列權限定義在mysql.columns_priv中。這兩種權限,組合起來存放在內存的Hash結構column_priv_hash中。

這兩種權限的命令如下:


create table db1.t1(id int, a int);

# 賦予用戶ua 庫db1的t1表權限
grant all privileges on db1.t1 to 'ua'@'%' with grant option;

# 賦予用戶ua 讀id、插入id,a列的權限
GRANT SELECT(id), INSERT (id,a) ON mydb.mytbl TO 'ua'@'%' with grant option;

和 db 權限類似,表、列的權限每次 grant 的時候都會修改數據表,也會同步修改內存中的 hash 結構。因此這兩個操作會馬上影響已存在的鏈接。

5. flush privileges 問題

既然 grant 每次執行完就是即時生效, 那爲什麼有時候需要執行 flush privileges 呢?

  1. flush privileges 命令會清空 acl_users 數組,然後從 mysql.user 中重新讀取數據加載到內存當中,重新構造一個 acl_users 數組。換句話說就是以數據表中的數據爲準,將內存中的權限數組重新加載一邊。

  2. 其實每次 grant 之後是不需要執行 flush privileges 的,只有當內存中的數據權限和磁盤表中的數據不同的時候,才需要執行 flush privileges 。如果我們規範的使用 grant、revoke,就不需要執行 flush privileges 。

因此,正常情況下,執行完 grant 之後,就不需要執行 flush privileges 。

5.1 flush privileges 使用場景

從上面分析得出,使用 flush privileges 的場景,無非就是 內存中權限數據跟磁盤數據表權限數據不一致,需要使用 flush privileges 來同步內存中的權限數據。

這種數據不一致,往往都是不規則的命令造成的,比如直接操作 mysql.user 表等等。
通過下面的表來解釋一下不規範的操作導致的需要使用 flush privileges 來使權限數據一致。
圖3
client A 在T3 時刻已經通過操作 mysql.user表,刪除了 user=ua的用戶,但是 client B 在T4依然可以使用這個賬戶鏈接數據庫,client B 在T4能成功鏈接數據庫的原因就是內存中的 acl_users 中還有這個用戶,所以client B 在T4可以成功連接。在T5 使用了 flush privileges 命令之後,Client B 再鏈接,就會報錯。

所以,直接操作數據庫系統表是不規範的操作,就會導致內存中的權限數據和磁盤中的數據不一致。

還有更奇怪的現象如下圖4:
圖4在T3時刻,通過直接操作 mysql.user表,直接刪除了數據表中的記錄,而內存中的數據還在,這就導致了下面這兩個問題:
T4時刻,賦予用戶權限失敗,這是因爲數據表中已經沒有了這個用戶。
T5時刻,再次創建該用戶失敗,這是因爲內存中依然存在該用戶。

總結一下Mysql 中權限的作用以及在內存中和磁盤中存在的位置,如圖5:

圖5

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章