简体   繁体   English

从MySQL触发器调用PHP脚本

[英]Invoking a PHP script from a MySQL trigger

Is there any way how to invoke a PHP page / function when a record is inserted to a MySQL database table? 将记录插入MySQL数据库表时,有没有办法调用PHP页面/函数? We don't have control over the record insertion procedure. 我们无法控制记录插入过程。 Is there a trigger mechanism which can call a PHP script back? 是否有可以调用PHP脚本的触发器机制?

The trigger is executed on the MySQL server, not on the PHP one (even if those are both on the same machine). 触发器在MySQL服务器上执行,而不是在PHP服务器上执行(即使它们都在同一台机器上)。

So, I would say this is not quite possible -- at least not simply. 所以,我想说这不太可能 - 至少不是简单的。


Still, considering this entry from the MySQL FAQ on Triggers : 考虑到MySQL触发器常见问题解答中的这一条目

23.5.11: Can triggers call an external application through a UDF? 23.5.11:触发器可以通过UDF调用外部应用程序吗?

Yes. 是。 For example, a trigger could invoke the sys_exec() UDF available here: https://github.com/mysqludf/lib_mysqludf_sys#readme 例如,触发器可以调用此处提供的sys_exec() UDF: https//github.com/mysqludf/lib_mysqludf_sys#readme

So, there might be a way via an UDF function that would launch the php executable/script. 因此,可能有一种方法可以通过UDF函数启动php可执行文件/脚本。 Not that easy, but seems possible. 不是那么容易,但似乎有可能。 ;-) ;-)

A friend and I have figured out how to call Bernardo Damele's sys_eval UDF, but the solution isn't as elegant as I'd like. 我和朋友已经想出如何调用Bernardo Damele的sys_eval UDF,但解决方案并不像我想的那样优雅。 Here's what we did: 这是我们做的:

  1. Since we're using Windows, we had to compile the UDF library for Windows using Roland Bouman's instructions and install them on our MySQL server. 由于我们使用的是Windows,因此我们必须使用Roland Bouman的说明为Windows编译UDF库,并将它们安装在我们的MySQL服务器上。
  2. We created a stored procedure that calls sys_eval. 我们创建了一个调用sys_eval的存储过程。
  3. We created a trigger that calls the stored procedure. 我们创建了一个调用存储过程的触发器。

Stored Procedure code: 存储过程代码:

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

Trigger code: 触发代码:

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

I'm not thrilled about having the stored procedure, and I don't know if it creates extra overhead, but it does work. 我对使用存储过程并不感到兴奋,我不知道它是否会产生额外的开销,但它确实有效。 Each time a row is added to sometable, the trigger fires. 每次向某个表添加一行时,触发器都会触发。

That should be considered a very bad programming practice to call PHP code from a database trigger. 从数据库触发器调用PHP代码应该被认为是一种非常糟糕的编程习惯 If you will explain the task you are trying to solve using such "mad" tricks, we might provide a satisfying solution. 如果您将使用这种“疯狂”技巧解释您尝试解决的任务,我们可能会提供令人满意的解决方案。

ADDED 19.03.2014: 新增19.03.2014:

I should have added some reasoning earlier, but only found time to do this now. 我本来应该先加一些推理,但现在才有时间做这件事。 Thanks to @cmc for an important remark. 感谢@cmc的重要评论。 So, PHP triggers add the following complexities to your application: 因此,PHP触发器为您的应用程序添加了以下复杂性:

  • Adds a certain degree of security problems to the application (external PHP script calls, permission setup, probably SELinux setup etc) as @Johan says. 正如@Johan所说,向应用程序添加了一定程度的安全问题(外部PHP脚本调用,权限设置,可能是SELinux设置等)。

  • Adds additional level of complexity to your application (to understand how database works you now need to know both SQL and PHP, not only SQL) and you will have to debug PHP also, not only SQL. 为您的应用程序增加了额外的复杂程度(了解数据库如何工作,您现在需要知道SQL和PHP,而不仅仅是SQL),您还必须调试PHP,而不仅仅是SQL。

  • Adds additional point of failure to your application (PHP misconfiguration for example), which needs to be diagnosied also ( I think trigger needs to hold some debug code which will log somwewhere all insuccessful PHP interpreter calls and their reasons). 为您的应用程序添加额外的故障点(例如PHP配置错误),这也需要进行诊断(我认为触发器需要保存一些调试代码,这些代码将记录所有不成功的PHP解释器调用及其原因)。

  • Adds additional point of performance analysis. 添加额外的性能分析点。 Each PHP call is expensive, since you need to start interpreter, compile script to bytecode, execute it etc. So each query involving this trigger will execute slower. 每个PHP调用都很昂贵,因为你需要启动解释器,将脚本编译为字节码,执行它等等。因此涉及此触发器的每个查询执行速度都会变慢。 And sometimes it will be difficult to isolate query performance problems since EXPLAIN doesn't tell you anything about query being slower because of trigger routine performance. 有时候很难分离查询性能问题,因为EXPLAIN没有告诉你任何关于查询由于触发器例程性能而变慢的事情。 And I'm not sure how trigger time is dumped into slow query log. 而且我不确定如何将触发时间转储到慢速查询日志中。

  • Adds some problems to application testing. 在应用程序测试中添加了一些问题。 SQL can be tested pretty easily. SQL可以很容易地测试。 But to test SQL + PHP triggers, you will have to apply some skill. 但是要测试SQL + PHP触发器,您将不得不应用一些技巧。

I found this: 我找到了这个:

http://forums.mysql.com/read.php?99,170973,257815#msg-257815 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 ;

I was thinking about this exact issue for a case with long polling where I didn't want the php script to have to continually poll the db. 我正在考虑一个长轮询案例的确切问题,我不希望php脚本不得不继续轮询数据库。 Polling would need to be done somewhere, memory would probably be best. 轮询需要在某个地方完成,内存可能是最好的。 So if somehow the trigger could put the info into something like memcache, then php could poll that would would be much less intensive overall. 因此,如果某种程度上触发器可以将信息放入像memcache这样的东西,那么php可以进行轮询,这将会大大减少整体密集度。 Just need a method for mysql to use memcache. 只需要一个mysql的方法来使用memcache。 Perhaps into a predefined variable with a specific user id. 也许进入具有特定用户ID的预定义变量。 Once the data is retrieved php could reset the var until the db sets it again. 一旦数据被检索,php就可以重置var,直到db再次设置它为止。 Not sure about timing issues though. 虽然不确定时间问题。 Perhaps a second variable to store the previous key selected. 也许第二个变量用于存储选定的上一个键。

If you have transaction logs in you MySQL, you can create a trigger for purpose of a log instance creation. 如果MySQL中有事务日志,则可以创建触发器以创建日志实例。 A cronjob could monitor this log and based on events created by your trigger it could invoke a php script. 一个cronjob可以监视这个日志,并根据你的触发器创建的事件,它可以调用一个PHP脚本。 That is if you absolutely have no control over you insertion. 那就是如果你绝对无法控制你的插入。

In order to get a notification from the database I wrote a command line script using websocket to check for the latest updated timestamp every second. 为了从数据库获取通知,我使用websocket编写了一个命令行脚本,以检查每秒的最新更新时间戳。 This ran as an infinite loop on the server. 这在服务器上作为无限循环运行。 If there is a change all connected clients will can be sent a notification. 如果有更改,则可以向所有连接的客户端发送通知。

I don't know if it's possible but I always pictured myself being able to do this with the CSV storage engine in MySQL. 我不知道是否可能,但我总是想象自己能够使用MySQL中的CSV存储引擎来做到这一点。 I don't know the details of this engine: http://dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html but you can look into it and have a file watcher in your operating system that triggers a PHP call if the file is modified. 我不知道这个引擎的细节: http//dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html但你可以查看它并在你的操作中有一个文件监视器如果文件被修改则触发PHP调用的系统。

A cronjob could monitor this log and based on events created by your trigger it could invoke a php script. 一个cronjob可以监视这个日志,并根据你的触发器创建的事件,它可以调用一个PHP脚本。 That is if you absolutely have no control over you insertion.. If you have transaction logs in you MySQL, you can create a trigger for purpose of a log instance creation. 也就是说,如果您完全无法控制插入..如果MySQL中有事务日志,则可以创建触发器以创建日志实例。

Run away from store procedures as much as possible. 尽可能远离商店程序。 They are pretty hard to maintain and are VERY OLD STUFF ;) 他们很难维护,非常老了;)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM