關注我,獲得更多分享。
需求背景
我們平時在給用戶授權grant語句執行後,都習慣性的執行一個命令flush privileges;,但是我發現有時候不執行這個命令,授權語句執行之後,權限驗證也是OK的,但是有時候發現不執行這個flush privileges;命令,權限認證還不能通過。
那麼到底什麼情況下需要執行flsh privileges;?什麼情況下不需要執行這個命令呢?
創建用戶
當我們創建用戶的時候,為了安全起見,我們會在用戶名後面增加一個host的限制,標識該用戶通過指定的密碼,只能通過該IP位址段才可以登錄MySQL。
創建用戶,語句如下所示:
createuser'user1'@'172.19.%' identified by'123456';
上面的示例是創建了一個用戶,名稱為'user1'@'172.19.%',可以通過172.19.網段,使用123456密碼來登錄MySQL。
如果用戶使用不在172.19.網段,通過這個密碼是不能登錄MySQL的。言外之意:'user1'@'ip1'和'uesr1'@'ip2'是兩個不同的用戶,我們不能單純的靠用戶名來確認用戶,需要把IP位址也納入進來。
上述語句執行成功後,MySQL會做兩件事情:
會在mysql.user表中增加一條記錄。記錄內容如下所示:
在MySQL在內存中維護的一個數組變量:acl_users,在這個變量中插入了一個元素,就是我新增加的用戶。但此時這個數組中記錄的用戶的權限也是全部為N,表示這個新增加的用戶沒有任何範圍權限。給用戶授權
前面我們創建了用戶,下面我們給這個用戶授予訪問權限,語句如下所示:
grantallon*.*to'user1'@'172.19.%';
上述語句執行完成後,MySQL也是做了兩件事情:
更新了mysql.user表中的這個用戶的權限列表,更新後的數據如下:
這個用戶的權限如下,從下圖中可以看出,該用戶用於所有的權限,也就是我們給授予的*.*的權限。
但是除了一個項Grant_priv的值為N,表示該用戶不能把自己當前所持有的權限再次賦予其他任何用戶,只能自己擁*.*有這些權限。而如果在我們的授權語句後面追加上with grant option關鍵字之後,Grant_priv的值也會變成Y,表示這個用戶可以把當前自己持有的權限,在賦予其他用戶。生產環境將不建議給授權的用戶增加with grant option選項。
更新了MySQL內存中數組acl_users的中值,把這個用戶對應的權限都跟改為Y,表示該用戶擁有了我們賦予它的權限。驗證登錄
用戶創建完成,權限也配置好了,現在我們還沒有執行flush privileges;命令。嘗試用用戶user1@'172.19.%'來登錄,登錄的時候,要確保你的登錄的時候使用的網段為172.19,驗證結果如下:
我們發現我們並沒有執行flush privileges;命令的前提下,直接使用這個用戶登錄,就可以登錄成功了。
這是為什麼?
因為我們在創建用戶和為用戶授權的時候,MySQL除了維護mysql.user表中的數據,還維護了內存中的acl_users數組。在內存中也更新了對應的用戶和權限信息。所以我們可以直接使用新創建的用戶名和密碼來登錄。
收回授權
現在我們把用戶的權限給收回,收回後不執行flush privileges;命令,看下用戶是否還可以登錄MySQL。收回授權的語句如下:
revokeallprivilegeson*.*from'user1'@'172.19.%';
驗證用戶是否還可以訪問所有的資料庫,這裡在驗證的時候,需要退出原先的登錄,重新建立連接才可以。因為MySQL資料庫中,所有的權限的修改,都是對新連接才生效,已經存在的連接不受影響的。
我們退出上一次的登錄,重新登錄後的結果如下:
看到只能看到information-schema了,其他都看不到了。這是因為所有的用戶,在沒有任何權限的時候,默認都可以看到information_schema這個資料庫。此時我們在收回用戶授權後並沒有執行flush privileges;命令。
刪除用戶
現在我們將用戶刪除掉,看下是否還可以登錄MySQL資料庫。刪除用戶的語句如下:
dropuser'user1'@'172.19.%';
驗證是否可以登錄,在驗證的時候,同樣我們需要先退出上一次的登錄重新建立連接。驗證後的結果如下
我們發現已經不能登錄MySQL資料庫了。此時我們在刪除用戶後並沒有執行flush privileges;命令。
總結
通過上面的創建用戶、給用戶授權、收回授權、刪除用戶的操作,我們可以發現在不執行flush privileges;命令的時候,這些操作都是生效了。也就是說,此時我們是沒有必要執行flush privileges;命令的。
那麼什麼情況下才需要執行flush privileges;命令呢?
當我們不是通過create user、grant、revoke、drop命令來操作用戶和權限,而是通過update語句直接去修改了mysql.user表中的數據的時候,此時我們需要執行flush privileges;命令。
此時我們也應該知道flush privileges;命令的作用了,它的作用就是清空MySQL內存中acl_users數組的數據內容,重新從mysql.user表中加載用戶的權限信息。
而當我們直接修改了mysql.user表中的內容的時候,MySQL內存中的acl_users數據信息是沒有被更新的,所以此時我們想讓我們對mysql.user表的修改直接生效,就需要手動的去更新acl_users數組的信息,而這個更新內存權限信息的操作,也就是通過flush privileges;命令來實現的。
所以,在我們日常的維護MySQL的時候,還是使用create user、grant、revoke、drop命令去維護用戶相關的信息。儘量避免直接使用update命令去修改mysql.user表中的信息。
如果你覺得這篇文章對你有幫助,也歡迎你把它分享給更多的朋友。