【发布时间】:2010-11-30 20:13:10
【问题描述】:
当记录插入 MySQL 数据库表时,有什么方法可以调用 PHP 页面/函数?我们无法控制记录插入过程。有没有可以回调PHP脚本的触发机制?
【问题讨论】:
当记录插入 MySQL 数据库表时,有什么方法可以调用 PHP 页面/函数?我们无法控制记录插入过程。有没有可以回调PHP脚本的触发机制?
【问题讨论】:
触发器在 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 可执行文件/脚本。不是那么容易,但似乎有可能。 ;-)
【讨论】:
我和一个朋友想出了如何调用 Bernardo Damele 的 sys_eval UDF,但该解决方案并不像我想要的那样优雅。这是我们所做的:
存储过程代码:
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 代码应该被认为是一种非常糟糕的编程习惯。如果您将使用这种“疯狂”的技巧解释您尝试解决的任务,我们可能会提供一个令人满意的解决方案。
2014 年 3 月 19 日添加:
我应该早点添加一些推理,但现在才找到时间这样做。感谢@cmc 的重要评论。因此,PHP 触发器为您的应用程序添加了以下复杂性:
正如@Johan 所说,为应用程序添加了一定程度的安全问题(外部 PHP 脚本调用、权限设置、可能是 SELinux 设置等)。
为您的应用程序增加了额外的复杂性(要了解数据库的工作原理,您现在需要了解 SQL 和 PHP,而不仅仅是 SQL)并且您还必须调试 PHP,而不仅仅是 SQL。
添加额外的性能分析点。每个 PHP 调用都很昂贵,因为您需要启动解释器、将脚本编译为字节码、执行它等。因此,涉及此触发器的每个查询都会执行得更慢。有时很难隔离查询性能问题,因为 EXPLAIN 没有告诉您任何有关由于触发例程性能而导致查询变慢的信息。而且我不确定触发时间是如何转储到慢查询日志中的。
为应用程序测试添加了一些问题。 SQL 可以很容易地测试。但是要测试 SQL + PHP 触发器,您将不得不运用一些技巧。
【讨论】:
我正在考虑这个确切的问题,因为我不希望 php 脚本必须不断地轮询数据库。轮询需要在某个地方进行,内存可能是最好的。因此,如果触发器可以以某种方式将信息放入 memcache 之类的东西中,那么 php 可以进行轮询,这将整体上不那么密集。只需要一个mysql使用memcache的方法。也许进入具有特定用户 ID 的预定义变量。一旦检索到数据,php 可以重置 var,直到 db 再次设置它。不过不确定时间问题。也许是第二个变量来存储上一个选择的键。
【讨论】:
我发现了这个:
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 ;
【讨论】:
为了从数据库中获取通知,我使用 websocket 编写了一个命令行脚本,以每秒检查最新更新的时间戳。这在服务器上作为无限循环运行。如果发生更改,所有连接的客户端都将收到通知。
【讨论】:
如果您的 MySQL 中有事务日志,则可以创建触发器以创建日志实例。 cronjob 可以监视此日志并根据触发器创建的事件调用 php 脚本。也就是说,如果您绝对无法控制插入。
【讨论】:
我不知道这是否可能,但我总是想象自己能够使用 MySQL 中的 CSV 存储引擎来做到这一点。我不知道这个引擎的细节: http://dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html 但您可以查看它并在您的操作系统中有一个文件观察器,如果文件被修改,它会触发 PHP 调用。
【讨论】:
cronjob 可以监控此日志,并根据触发器创建的事件调用 php 脚本。也就是说,如果您绝对无法控制插入。如果您的 MySQL 中有事务日志,则可以创建触发器以创建日志实例。
【讨论】:
尽可能远离存储过程。它们很难维护,而且是非常古老的东西;)
【讨论】: