从MySQL触发器调用PHP脚本

时间:2009-09-23 17:06:03

标签: php mysql triggers

当记录插入MySQL数据库表时,有没有办法调用PHP页面/函数?我们无法控制记录插入过程。是否有可以调用PHP脚本的触发机制?

10 个答案:

答案 0 :(得分:31)

触发器在MySQL服务器上执行,而不是在PHP服务器上执行(即使它们都在同一台机器上)。

所以,我认为这不太可能 - 至少不是简单的。


不过,考虑this entry from the MySQL FAQ on Triggers

  

23.5.11:触发器是否可以通过UDF调用外部应用程序?

     

是。例如,触发器可以   调用此处提供的sys_exec() UDF:   https://github.com/mysqludf/lib_mysqludf_sys#readme

因此,可能有一种方法可以通过UDF函数启动php可执行文件/脚本。不是那么容易,但似乎有可能。 ; - )

答案 1 :(得分:25)

我和朋友已经想出如何调用Bernardo Damele的sys_eval UDF,但解决方案并不像我想的那样优雅。这就是我们所做的:

  1. 由于我们使用的是Windows,因此我们必须使用Roland Bouman's instructions为Windows编译UDF库并将其安装在我们的MySQL服务器上。
  2. 我们创建了一个调用sys_eval的存储过程。
  3. 我们创建了一个调用存储过程的触发器。
  4. 存储过程代码:

    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);
    

    我对使用存储过程并不感到兴奋,我不知道它是否会产生额外的开销,但它确实有效。每次将某一行添加到sometable时,触发器都会触发。

答案 2 :(得分:16)

从数据库触发器调用PHP代码应该被视为非常糟糕的编程习惯。如果您将使用这种“疯狂”技巧解释您尝试解决的任务,我们可能会提供令人满意的解决方案。

ADDED 19.03.2014:

我之前应该添加一些推理,但现在只有时间来做这件事。感谢@cmc的重要评论。因此,PHP触发器为您的应用程序添加了以下复杂性:

  • 为@Johan说,向应用程序添加了一定程度的安全问题(外部PHP脚本调用,权限设置,可能是SELinux设置等)。

  • 为您的应用程序增加了额外的复杂性(了解数据库如何工作,您现在需要知道SQL和PHP,而不仅仅是SQL),您还必须调试PHP,而不仅仅是SQL。

  • 为您的应用程序添加额外的故障点(例如PHP配置错误),这也需要进行诊断(我认为触发器需要保存一些调试代码,这些代码将记录所有不成功的PHP解释器调用及其原因)

  • 添加额外的性能分析点。每个PHP调用都很昂贵,因为你需要启动解释器,将脚本编译为字节码,执行它等等。因此涉及此触发器的每个查询执行速度都会变慢。有时候很难分离查询性能问题,因为EXPLAIN没有告诉你任何关于查询由于触发器例程性能而变慢的事情。而且我不确定如何将触发时间转储到慢速查询日志中。

  • 在应用程序测试中添加了一些问题。 SQL可以很容易地测试。但是要测试SQL + PHP触发器,您必须应用一些技巧。

答案 3 :(得分:6)

我发现了这个:

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 ;

答案 4 :(得分:6)

我正在考虑一个长轮询案例的确切问题,我不希望php脚本不得不继续轮询数据库。轮询需要在某个地方完成,内存可能是最好的。因此,如果某种程度上触发器可以将信息放入像memcache这样的东西,那么php可以进行轮询,这将会大大减少整体密集度。只需要一个mysql的方法来使用memcache。也许进入具有特定用户ID的预定义变量。一旦数据被检索,php就可以重置var,直到db再次设置它为止。虽然不确定时间问题。也许第二个变量用于存储选定的上一个键。

答案 5 :(得分:1)

如果MySQL中有事务日志,则可以创建触发器以创建日志实例。一个cronjob可以监视这个日志,并根据你的触发器创建的事件,它可以调用一个PHP脚本。那就是如果你绝对无法控制你的插入。

答案 6 :(得分:1)

为了从数据库获取通知,我使用websocket编写了一个命令行脚本,以检查每秒的最新更新时间戳。这在服务器上作为无限循环运行。如果有更改,则可以向所有连接的客户端发送通知。

答案 7 :(得分:1)

我不知道是否可能,但我总是想象自己可以使用MySQL中的CSV存储引擎来做到这一点。我不知道这个引擎的细节: http://dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html但您可以查看它,并在操作系统中有一个文件监视器,如果文件被修改,则会触发PHP调用。

答案 8 :(得分:0)

cronjob可以监视此日志,并根据您的触发器创建的事件,它可以调用php脚本。也就是说,如果您完全无法控制插入..如果MySQL中有事务日志,则可以创建触发器以创建日志实例。

答案 9 :(得分:-2)

尽可能远离商店程序。它们很难维护并且非常老旧;)