MySQL 中的 DEFINER(定義者)是什麼

前言:

在 MySQL 資料庫中,在建立檢視及函式的時候,你有注意過 definer 選項嗎?在遷移檢視或函式後是否有過報錯情況,這些其實都可能和 definer 有關係。本篇文章主要介紹下 MySQL 中 definer 的含義及作用。

1。DEFINER簡單介紹

以檢視為例,我們來看下官方給出的檢視建立基礎語法:

CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] [DEFINER = user] [SQL SECURITY { DEFINER | INVOKER }] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION]

仔細看上面語法,發現 definer 出現了兩次,一次是 DEFINER = user 一次是 SQL SECURITY 選項可以設定為 DEFINER 或 INVOKER ,看到這裡,你有猜到 definer 的作用了嗎?

definer 翻譯成中文是“定義者”的意思。MySQL中,建立檢視(view)、函式(function)、儲存過程(procedure)、觸發器(trigger)、事件(event)時,都可以指定 DEFINER = user 選項,即指定此物件的定義者是誰,若不顯式指定,則建立此物件的使用者就是定義者。

對於檢視、函式及儲存過程,還可以指定 SQL SECURITY 屬性,其值可以為 DEFINER(定義者) 或 INVOKER(呼叫者),表示在執行過程中,使用誰的許可權來執行。DEFINER 表示按定義者擁有的許可權來執行,INVOKER 表示用呼叫者的許可權來執行。

預設情況下,SQL SECURITY 屬性為 DEFINER 。其值為 DEFINER 時,資料庫中必須存在 DEFINER 指定的定義者使用者,並且該定義者使用者擁有對應的操作許可權及引用的相關物件的許可權,執行者只需擁有呼叫許可權就能成功執行。當 SQL SECURITY 屬性為 INVOKER 時,則需要執行者有呼叫許可權並且有引用的相關物件的許可權,才能成功執行。

簡單來說,假設一個檢視查詢了 a b c 三張表,若此檢視的 SQL SECURITY 屬性為 DEFINER ,當使用使用者 u 查詢此檢視時,使用者 u 只需此檢視的查詢許可權即可;若此檢視的 SQL SECURITY 屬性為 INVOKER ,則使用者 u 需要有此檢視的查詢許可權且有 a b c 三張表的查詢許可權。下面透過示例來具體演示下:

# 建立兩個檢視 定義者都是testuser 查詢的是test_tb表mysql> show grants for ‘testuser’@‘%’;+————————————————————————————————————————————————————+| Grants for testuser@% |+————————————————————————————————————————————————————+| GRANT USAGE ON *。* TO ‘testuser’@‘%’ || GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, CREATE VIEW, SHOW VIEW ON `testdb`。* TO ‘testuser’@‘%’ |+————————————————————————————————————————————————————+2 rows in set (0。00 sec)mysql> show create view view_definer\G*************************** 1。 row *************************** View: view_definer Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`testuser`@`%` SQL SECURITY DEFINER VIEW `view_definer` AS select `test_tb`。`stu_id` AS `stu_id`,`test_tb`。`stu_name` AS `stu_name` from `test_tb`character_set_client: utf8mb4collation_connection: utf8mb4_general_ci1 row in set (0。00 sec)mysql> show create view view_invoker\G*************************** 1。 row *************************** View: view_invoker Create View: CREATE ALGORITHM=UNDEFINED DEFINER=`testuser`@`%` SQL SECURITY INVOKER VIEW `view_invoker` AS select `test_tb`。`stu_id` AS `stu_id`,`test_tb`。`stu_name` AS `stu_name` from `test_tb`character_set_client: utf8mb4collation_connection: utf8mb4_general_ci1 row in set (0。00 sec)# 只給uview使用者查詢這兩個檢視的許可權 來進行查詢測試mysql> select user();+————————-+| user() |+————————-+| uview@localhost |+————————-+1 row in set (0。00 sec)mysql> show grants;+————————————————————————————+| Grants for uview@% |+————————————————————————————+| GRANT USAGE ON *。* TO ‘uview’@‘%’ || GRANT SELECT ON `testdb`。`view_definer` TO ‘uview’@‘%’ || GRANT SELECT ON `testdb`。`view_invoker` TO ‘uview’@‘%’ |+————————————————————————————+3 rows in set (0。00 sec)mysql> select * from view_definer;+————+——————+| stu_id | stu_name |+————+——————+| 1001 | from1 || 1002 | dfsfd || 1003 | fdgfg |+————+——————+9 rows in set (0。00 sec)mysql> select * from view_invoker;ERROR 1356 (HY000): View ‘testdb。view_invoker’ references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them# 結果是view_definer查詢正常,而view_invoker無法查詢 因為uview使用者不具有test_tb表的查詢許可權

自定義函式及儲存過程也是類似,若 SQL SECURITY 屬性為 INVOKER ,同樣需要呼叫者有執行許可權並且有引用的相關物件的許可權,才能成功執行。

2。一些注意事項

額外補充點知識,只有擁有建立許可權且有 SUPER 許可權的使用者才可以建 DEFINER = 其他使用者的物件。例如:root 賬號可以建立 DEFINER = testuser 的檢視,而 testuser 在有建立檢視的前提下只能建立 DEFINER 為自己的檢視。

為了更細緻的瞭解 DEFINER 相關作用,以檢視為例再來說幾個特殊情況下的示例:

假設使用者 u1 不存在,使用 root 賬號可以建立 DEFINER = u1 的檢視,若該檢視的 SQL SECURITY 屬性為 DEFINER ,則查詢時會報使用者不存在的錯誤,若該檢視的 SQL SECURITY 屬性為 INVOKER ,則使用 root 賬號可正常查詢該檢視。

假設使用者 u2 存在但不具有查詢表 a 的許可權,使用 root 賬號可以建立 DEFINER = u2 的檢視來查詢表 a ,若該檢視的 SQL SECURITY 屬性為 DEFINER ,則查詢時報缺少許可權的錯誤,若該檢視的 SQL SECURITY 屬性為 INVOKER ,則使用 root 賬號可正常查詢該檢視。當使用使用者 u2 登入時,則建立檢視來查詢表 a 會直接報錯缺少許可權,即建立不了查詢表 a 的檢視,無論此檢視的 SQL SECURITY 屬性是什麼。

看完上述示例後,不清楚你對 DEFINER 是否有了更清晰的認識,有興趣的同學可以自己測試看一看。結合筆者日常經驗,說下 DEFINER 相關注意事項吧:

SQL SECURITY 屬性建議使用預設的 DEFINER 。

某個庫內的檢視、函式、儲存過程建議使用統一的 DEFINER 使用者。

不要輕易修改及刪除資料庫使用者,因為此使用者可能是相關物件的定義者。

若要修改 SQL SECURITY 屬性,請做好測試,清楚修改前後的區別。

資料庫遷移時,要注意新環境存在相關物件的定義者使用者。

做資料庫遷移時,建議首先在新環境建立相關使用者及賦予許可權。

總結:

本篇文章主要介紹了 DEFINER 相關知識,這些主要在建立檢視、函式、儲存過程等物件時會遇到,平時比較容易被忽略。但這些細節還是應該注意的,多瞭解多學習下,這樣到真正用到的時候可以避免很多錯誤。