小白學習mysql之存儲過程的優劣分析以及接入控制

存儲過程的優劣

存儲過程是一組實現特定功能的SQL語句集合,存儲過程一經編譯便存儲在了服務器上,能夠經過調用存儲過程的名字以及傳入相應的參數來使用存儲過程。要高層次的掌握存儲過程,不能以爲依葫蘆畫瓢,以爲造出來的存儲過程可以跑出結果就OK。必定要站在必定的高度,看清它的全貌:mysql

選擇使用存儲過程的優點

  • 執行效率快; 存儲過程工做於服務器中,距離數據最近,所以對數據的操做快,和通常SQL語句比,它無需網絡通訊開銷,解析開銷,和優化器開銷等。
  • 實現代碼重用,接口處理邏輯一致; 存儲過程能夠理解爲一種抽象級比較低或者說比較具體的函數。所以,能夠實現供系統屢次反覆調用,實現了代碼的重用,保證了系統業務處理的一致性。
  • 能夠簡化代碼的維護和版本更新;存儲過程部署在服務器端,所以能夠全部的備份和維護均可以在服務器上進行。並且若是一些業務邏輯作出修正,也能夠在服務上修正存儲過程,必定程度上減小了客戶端的升級次數。
  • 提高安全,實現更細粒度的權限控制。

使用存儲過程的弊端

  • 缺少行之有效的開發和調試工具;存儲過程的開發和調試與應用程序代碼是沒法相提並論的,感受存儲過程的調試更像單純的使用「打印調試」。所以,開發效率和調試上有必定的折扣。
  • 實現業務 邏輯的靈活度和自由度略差;這點主要是和應用程序開發做比較的,存儲過程當中沒有應用程序語言中豐富多彩的函數,所以用起來總感受須要一些「巧妙的設計」在裏面,對於發燒的字符串操做和維護,使用起來並無編程序言那樣輕鬆自如。
  • 對數據庫服務器增長了額外的壓力,同時數據庫服務器的擴展性也相對較差。
  • mysql中並無什麼選項對存儲過程的資源消耗進行控制,若是存儲過程當中出現了一個錯誤,可能會對整個數據庫服務器形成較大的影響。

存儲過程定義細節

存儲過程在定義的時候,有一些關鍵字的含義以及語句仍是須要搞明白的好,諸如分隔符的臨時重定義,調用存儲過程的權限控制等。
在sqllog等這些工具中新建一個存儲過程就會出現一下屬性和定義:sql

DELIMITER $$

CREATE
    /*[DEFINER = { user | CURRENT_USER }]*/
    PROCEDURE `my_db`.`heat_test1`()
    /*LANGUAGE SQL
    | [NOT] DETERMINISTIC
    | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
    | SQL SECURITY { DEFINER | INVOKER }
    | COMMENT 'string'*/
    BEGIN

    END$$

DELIMITER ;

從新定義分隔符"; "

在mysql的客戶端中向服務器傳送存儲過程的時候,若是不從新定義分號,mysql服務器接收到第一個分號的時候,會覺得這條語句傳送完畢,所以分割了整個存儲過程;爲了可以完整的將存儲過程傳送到服務器,務必須要暫時定義mysql的分隔符即分號;
使用 delimiter 關鍵字能夠從新定義分隔符,好比 mysql> delimiter //;固然能夠想使用你喜歡的字符代替「//」,可是不要使用「」,由於該符號在mysql中是轉移字符。
當整個存儲過程傳送完畢後,必定要記得將分隔符從新定義爲分號。數據庫

選擇合適的接入控制權限

對於每個存儲過程,能夠有一個「DEFINER」的屬性,這個屬性是一個mysql中的帳戶名,好比root等。這個屬性幫助在調用存儲過程的時候,根據上下文的環境肯定其權限。若是這個屬性沒有明確給出,那麼mysql默認爲建立該存儲過程的用戶爲這個屬性的值。
此外,存儲過程當中還有一個SQL SECURITY { DEFINER | INVOKER }來決定使用存儲過程的定義者或者是調用者的上下文環境。若是是DEFINER,那麼這個存儲過程在調用的時候就會擁有建立者指定帳戶的權限,若是是INVOKER,那麼執行這個存儲過程的時候就會擁有調用者的權限。編程

CREATE DEFINER = 'admin'@'localhost' PROCEDURE p1()
SQL SECURITY DEFINER
BEGIN
  UPDATE t1 SET counter = counter + 1;
END;

上面的存儲過程的SQL SECURITY定義的是DEFINER,所以對於任何有權限調用p1的用戶均可以用call來調用該存儲過程,可是在存儲過程執行的過程當中,上下文環境將切換到'admin'@'localhost'用戶下,也就是說調用者的權限對此存儲過程無效(調用者能夠沒有對t1表updata權限,只要'admin'@'localhost'有便可),在這個存儲過程執行的時候,所擁有的權限是'admin'@'localhost'所擁有的。安全

CREATE DEFINER = 'admin'@'localhost' PROCEDURE p2()
SQL SECURITY INVOKER
BEGIN
  UPDATE t1 SET counter = counter + 1;
END;

當存儲過程p2的SQL SECURITY定義爲INVOKER的時候,這個時候存儲執行的上下文環境將在調用者上下文環境中執行,也就是說,這個時候調用者的權限必需要有對t1表的訪問和修改權限。服務器

存儲過程當中,DEFINER屬性的設置規則以及提升安全的策略

  • 1 你只能夠將本身的帳戶名設置爲DEFINER的屬性假如沒有超級權限,若是有超級權限才能夠設置其餘用戶的帳戶名做爲該屬性的值。
  • 2 應該儘可能使用SQL SECURITY INVOKER來定義存儲過程,這樣會規避沒必要要的越限。
  • 3 若是使用SQL SECURITY DEFINER,並且指定的帳戶具備超級權限,再三分析是否必須這樣。
  • 4 管理員爲了限制用戶隨意指定DEFINER的屬性爲超級權限,應該謹慎的分配給用戶超級權限。

經過這樣的權限設置,能夠實現更細粒度以及更自由的權限設置。同時,基於安全的問題也要時時考慮到。網絡

參考文獻
[1] 高性能mysql
[2] mysql官方網站函數

相關文章
相關標籤/搜索