Вызов скрипта PHP из триггера MySQL

Есть ли способ вызвать страницу / функцию PHP, когда запись вставлена ​​в таблицу базы данных MySQL? У нас нет контроля над процедурой ввода записей. Есть триггерный механизм, который может вызвать PHP-скрипт?

Solutions Collecting From Web of "Вызов скрипта PHP из триггера MySQL"

Триггер выполняется на сервере MySQL, а не на PHP (даже если они оба находятся на одной машине).

Поэтому я бы сказал, что это не совсем возможно – по крайней мере, не просто.

Тем не менее, учитывая эту запись из MySQL FAQ о триггерах :

23.5.11: Может ли триггер вызвать внешнее приложение через UDF?

Да. Например, триггер может ссылаться на sys_exec() UDF, доступный здесь: https://github.com/mysqludf/lib_mysqludf_sys#readme

Таким образом, может существовать способ через функцию UDF, которая запускает исполняемый файл / скрипт php. Не так просто, но кажется возможным. 😉

Мы с другом выяснили, как назвать Sys_eval UDF Бернардо Дамела, но решение не так элегантно, как хотелось бы. Вот что мы сделали:

  1. Поскольку мы используем Windows, нам пришлось скомпилировать библиотеку UDF для Windows с помощью инструкций Roland Bouman и установить их на нашем сервере 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); 

Я не в восторге от наличия хранимой процедуры, и я не знаю, создает ли она дополнительные накладные расходы, но это действительно работает. Каждый раз, когда строка добавляется в sometable, срабатывает триггер.

Это следует считать очень плохой практикой программирования, чтобы вызвать PHP-код из триггера базы данных. Если вы объясните задачу, которую вы пытаетесь решить, используя такие «безумные» трюки, мы можем предложить удовлетворительное решение.

ДОБАВЛЕНО 19.03.2014:

Я должен был добавить некоторые рассуждения раньше, но только нашел время, чтобы сделать это сейчас. Спасибо @cmc за важное замечание. Таким образом, триггеры PHP добавляют к вашему приложению следующие сложности:

  • Добавляет определенные проблемы безопасности к приложению (внешние вызовы PHP-скриптов, настройка прав доступа, возможно, установка SELinux и т. Д.), Как говорит @Johan.

  • Добавляет дополнительный уровень сложности вашему приложению (чтобы понять, как работает база данных, вам теперь нужно знать как 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-скрипт должен постоянно опробовать db. Опрос нужно было бы сделать где-то, память, вероятно, была бы лучше. Поэтому, если какой-то триггер может помещать информацию в нечто вроде memcache, то php мог бы опросить, что было бы намного менее интенсивным в целом. Просто нужен метод mysql для использования memcache. Возможно, в предопределенную переменную с определенным идентификатором пользователя. Как только данные будут восстановлены, php может сбросить значение var до тех пор, пока db не установит его снова. Однако не уверены в сроках. Возможно, вторая переменная для сохранения предыдущего выбранного ключа.

Если в вашем MySQL есть журналы транзакций, вы можете создать триггер для создания экземпляра журнала. Cronjob может контролировать этот журнал и на основе событий, созданных вашим триггером, может вызвать скрипт php. То есть, если вы абсолютно не имеете контроля над вставкой.

Чтобы получить уведомление из базы данных, я написал сценарий командной строки, используя websocket, чтобы проверять последнюю обновленную временную метку каждую секунду. Это выполнялось как бесконечный цикл на сервере. Если есть изменение, все подключенные клиенты могут отправить уведомление.

Я не знаю, возможно ли это, но я всегда представлял себе возможность сделать это с помощью механизма хранения CSV в MySQL. Я не знаю подробностей этого движка: http://dev.mysql.com/doc/refman/5.7/en/csv-storage-engine.html, но вы можете изучить его и иметь наблюдателя файлов в своей операционной система, которая запускает вызов PHP, если файл изменен.

Cronjob может контролировать этот журнал и на основе событий, созданных вашим триггером, может вызвать скрипт php. То есть, если вы абсолютно не имеете контроля над вставкой. Если у вас есть журналы транзакций в вашем MySQL, вы можете создать триггер для создания экземпляра журнала.

Как можно больше убежать от процедур магазина. Их довольно сложно поддерживать и ОЧЕНЬ СТАРЫЙ СТУФ;)