我們使用預存程序的時候,往往只注意要給調用預存程序的帳號賦予相應許可權,但是實際上預存程序定義使用者與這個預存程序能否被執行有直接關係,如果不知道這點,即使調用預存程序的帳號具備存相關許可權,一樣還是不能執行預存程序。
文法:
CREATE DEFINER=`xx`@`%` PROCEDURE `mmm`
這裡DEFINER有兩種模式Security definer和Security invoker
Security definer:
definer:在執行預存程序前驗證definer對應的使用者如:xx@%是否存在,以及是否具有執行預存程序的許可權。
Security invoker
invoker:在執行預存程序時判斷調用該預存程序的使用者是否有相應許可權。
其實,用簡單明了語言解釋下可能更容易理解:
SECURITY DEFINER 表示定義者必須有相關許可權。
SECURITY INVOKER 表示只要調用者有相關許可權即可。
問題描述:
今天一個別的部門的DBA同事,要我幫忙處理一個問題。說他們業務開發的程式不能正確執行預存程序,由於他們的很多商務邏輯關係都是放在預存程序中判斷,而非程式判斷。所以這個問題極其重要,直接導致了業務不可用。前端報錯感覺是許可權不夠,且所有調用預存程序的帳號都是同一個aaa(這裡用aaa表示業務賬戶),檢查了這個使用者的許可權,沒有問題,最後甚至賦予了all許可權,但問題依舊。到這他和他們部門同事都認為不再是許可權不夠的問題。嘗試了一些別的方法都無法解決,問題一直就卡在這了,所有人在那著急。
我上去分析了一下,確實如他們描述一樣。到庫上隨機看了一個預存程序c:
CREATE DEFINER=`xx_user`@`%` PROCEDURE `DBQ_MMM` 其它所有預存程序皆是如此。
show grants for 'xxx_user'@'%' 查看發現沒有EXECUTE 運行預存程序的這個許可權
接著,show procedure status like 'c'
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131228/2231335609-0.jpg" title="procedure.jpg" />
注意Security_type這裡是DEFIN,所以雖然前端程式使用的是具有all許可權的aaa賬戶,但是定義者xxx_user沒有執行許可權。預存程序依舊不能被執行,也就難怪為啥糾了結半天最大許可權的使用者依然還是沒有許可權了。至於這個使用者的EXECUTE許可權是人為revoke誤操作,還是以前使用的是INVOKER模式,那就不知道了。但是前者99%的可能。虛驚一場,真是小問題險些造成大事故啊。
解決方案:
修改預存程序定義使用者,給一個具有執行許可權的使用者即可
如果是從別的庫導過來的,有大量預存程序一個個修改太麻煩,提供兩個思路:
在匯出的sql中用sed替換,然後再匯入到 新庫中。
直接建立一個與原先庫中的定義使用者一樣的使用者。
本文出自 “靈魂出竅” 部落格,請務必保留此出處http://mysqlbanner.blog.51cto.com/4109963/1223636