簡體   English   中英

從MySQL觸發器調用PHP腳本

[英]Invoking a PHP script from a MySQL trigger

將記錄插入MySQL數據庫表時,有沒有辦法調用PHP頁面/函數? 我們無法控制記錄插入過程。 是否有可以調用PHP腳本的觸發器機制?

觸發器在MySQL服務器上執行,而不是在PHP服務器上執行(即使它們都在同一台機器上)。

所以,我想說這不太可能 - 至少不是簡單的。


考慮到MySQL觸發器常見問題解答中的這一條目

23.5.11:觸發器可以通過UDF調用外部應用程序嗎?

是。 例如,觸發器可以調用此處提供的sys_exec() UDF: https//github.com/mysqludf/lib_mysqludf_sys#readme

因此,可能有一種方法可以通過UDF函數啟動php可執行文件/腳本。 不是那么容易,但似乎有可能。 ;-)

我和朋友已經想出如何調用Bernardo Damele的sys_eval UDF,但解決方案並不像我想的那樣優雅。 這是我們做的:

  1. 由於我們使用的是Windows,因此我們必須使用Roland Bouman的說明為Windows編譯UDF庫,並將它們安裝在我們的MySQL服務器上。
  2. 我們創建了一個調用sys_eval的存儲過程。
  3. 我們創建了一個調用存儲過程的觸發器。

存儲過程代碼:

DELIMITER $$
CREATE PROCEDURE udfwrapper_sp
(p1   DOUBLE,
 p2   DOUBLE,
 p3 BIGINT)
BEGIN
 DECLARE cmd CHAR(255);
 DECLARE result CHAR(255);
 SET cmd = CONCAT('C:/xampp/php/php.exe -f "C:/xampp/htdocs/phpFile.php" ', p1, ' ', p2, ' ', p3);
 SET result = sys_eval(cmd);
END$$;

觸發代碼:

CREATE TRIGGER udfwrapper_trigger AFTER INSERT ON sometable
FOR EACH ROW
CALL udfwrapper_sp(NEW.Column1, NEW.Column2, NEW.Column3);

我對使用存儲過程並不感到興奮,我不知道它是否會產生額外的開銷,但它確實有效。 每次向某個表添加一行時,觸發器都會觸發。

從數據庫觸發器調用PHP代碼應該被認為是一種非常糟糕的編程習慣 如果您將使用這種“瘋狂”技巧解釋您嘗試解決的任務,我們可能會提供令人滿意的解決方案。

新增19.03.2014:

我本來應該先加一些推理,但現在才有時間做這件事。 感謝@cmc的重要評論。 因此,PHP觸發器為您的應用程序添加了以下復雜性:

  • 正如@Johan所說,向應用程序添加了一定程度的安全問題(外部PHP腳本調用,權限設置,可能是SELinux設置等)。

  • 為您的應用程序增加了額外的復雜程度(了解數據庫如何工作,您現在需要知道SQL和PHP,而不僅僅是SQL),您還必須調試PHP,而不僅僅是SQL。

  • 為您的應用程序添加額外的故障點(例如PHP配置錯誤),這也需要進行診斷(我認為觸發器需要保存一些調試代碼,這些代碼將記錄所有不成功的PHP解釋器調用及其原因)。

  • 添加額外的性能分析點。 每個PHP調用都很昂貴,因為你需要啟動解釋器,將腳本編譯為字節碼,執行它等等。因此涉及此觸發器的每個查詢執行速度都會變慢。 有時候很難分離查詢性能問題,因為EXPLAIN沒有告訴你任何關於查詢由於觸發器例程性能而變慢的事情。 而且我不確定如何將觸發時間轉儲到慢速查詢日志中。

  • 在應用程序測試中添加了一些問題。 SQL可以很容易地測試。 但是要測試SQL + PHP觸發器,您將不得不應用一些技巧。

我找到了這個:

http://forums.mysql.com/read.php?99,170973,257815#msg-257815

DELIMITER $$
CREATE TRIGGER tg1 AFTER INSERT ON `test`
FOR EACH ROW
BEGIN
\! echo "php /foo.php" >> /tmp/yourlog.txt
END $$
DELIMITER ;

我正在考慮一個長輪詢案例的確切問題,我不希望php腳本不得不繼續輪詢數據庫。 輪詢需要在某個地方完成,內存可能是最好的。 因此,如果某種程度上觸發器可以將信息放入像memcache這樣的東西,那么php可以進行輪詢,這將會大大減少整體密集度。 只需要一個mysql的方法來使用memcache。 也許進入具有特定用戶ID的預定義變量。 一旦數據被檢索,php就可以重置var,直到db再次設置它為止。 雖然不確定時間問題。 也許第二個變量用於存儲選定的上一個鍵。

如果MySQL中有事務日志,則可以創建觸發器以創建日志實例。 一個cronjob可以監視這個日志,並根據你的觸發器創建的事件,它可以調用一個PHP腳本。 那就是如果你絕對無法控制你的插入。

為了從數據庫獲取通知,我使用websocket編寫了一個命令行腳本,以檢查每秒的最新更新時間戳。 這在服務器上作為無限循環運行。 如果有更改,則可以向所有連接的客戶端發送通知。

我不知道是否可能,但我總是想象自己能夠使用MySQL中的CSV存儲引擎來做到這一點。 我不知道這個引擎的細節: http//dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html但你可以查看它並在你的操作中有一個文件監視器如果文件被修改則觸發PHP調用的系統。

一個cronjob可以監視這個日志,並根據你的觸發器創建的事件,它可以調用一個PHP腳本。 也就是說,如果您完全無法控制插入..如果MySQL中有事務日志,則可以創建觸發器以創建日志實例。

盡可能遠離商店程序。 他們很難維護,非常老了;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM