从MySQL触发器调用PHP脚本
有什么办法当一个logging被插入到MySQL数据库表时如何调用一个PHP页面/函数? 我们无法控制logging插入过程。 有没有可以调用PHP脚本的触发机制?
触发器在MySQL服务器上执行,而不是在PHP上执行(即使这些都在同一台机器上)。
所以,我会说这是不可能的 – 至less不是简单的。
尽pipe如此, 从“MySQL触发器常见问题解答”
23.5.11:触发器是否可以通过UDF调用外部应用程序?
是。 例如,触发器可以调用此处提供的
sys_exec()
UDF: https : //github.com/mysqludf/lib_mysqludf_sys#readme
所以,可能会有一种方法通过UDF函数来启动php可执行文件/脚本。 不是那么容易,但似乎是可能的。 😉
我和一个朋友已经想出了如何调用Bernardo Damele的sys_eval UDF,但是这个解决scheme并不像我想的那么优雅。 以下是我们所做的:
- 由于我们使用的是Windows,所以我们必须使用Roland Bouman的指令编译Windows的UDF库,并将它们安装在我们的MySQL服务器上。
- 我们创build了一个调用sys_eval的存储过程。
- 我们创build了一个调用存储过程的触发器。
存储过程代码:
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代码。 如果你要用这样的“疯狂”技巧来解释你正在尝试解决的任务,我们可能会提供一个令人满意的解决scheme。
已添加19.03.2014:
我应该早些时候join一些推理,但现在只有时间才能做到这一点。 感谢@cmc的重要评论。 所以,PHP触发器将以下复杂性添加到您的应用程序中:
-
@Johan说,为应用程序添加了一定程度的安全问题(外部PHP脚本调用,权限设置,可能是SELinux安装等)。
-
为您的应用程序增加了额外的复杂性(要了解数据库如何工作,您现在需要知道SQL和PHP,而不仅仅是SQL),而且还必须debuggingPHP,而不仅仅是SQL。
-
为你的应用程序添加额外的故障点(例如PHP错误configuration),这也需要进行诊断(我认为触发器需要保存一些debugging代码,这些代码会logging所有不成功的PHP解释器调用及其原因)。
-
增加额外的性能分析点。 每个PHP调用都很昂贵,因为您需要启动解释器,将脚本编译为字节码,执行等。因此,涉及此触发器的每个查询都会执行得更慢。 有时候,查询性能问题很难隔离,因为EXPLAIN没有告诉你任何有关由于触发例程性能而导致查询速度较慢的问题。 而且我不确定如何将触发时间转储到慢查询日志中。
-
给应用程序testing增加了一些问题。 SQL可以很容易地testing。 但是为了testingSQL + PHP触发器,你将不得不应用一些技巧。
我find了这个:
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的预定义variables。 一旦数据被检索,PHP可以重置该variables,直到数据库再次设置。 不确定时间问题,但。 也许第二个variables存储先前select的键。
如果您在MySQL中有事务日志,则可以创build用于创build日志实例的触发器。 一个cronjob可以监视这个日志,并根据触发器创build的事件调用一个php脚本。 那就是如果你完全无法控制你的插入。
为了从数据库中获得通知,我使用websocket编写了一个命令行脚本,以便每秒钟检查最新的更新时间戳。 这在服务器上作为无限循环运行。 如果有变化,所有连接的客户端都可以发送通知。
我不知道是否有可能,但我总是想象自己能够用MySQL中的CSV存储引擎来做到这一点。 我不知道这个引擎的细节: http : //dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html,但你可以看看它,并在您的操作有一个文件观察器如果文件被修改,则触发PHP调用。
一个cronjob可以监视这个日志,并根据触发器创build的事件调用一个php脚本。 这就是说,如果你完全无法控制你的插入。如果你在MySQL中有事务日志,你可以创build一个触发器来创build日志实例。
尽可能远离商店手续。 他们很难维护,是非常老的东西;)