Триггеры MySQL - триггер ПОСЛЕ ВСТАВКИ + UDF sys_exec () проблема - PullRequest
8 голосов
/ 06 сентября 2010

Проблема: у меня есть таблица, которая содержит определенные записи. После того, как вставка сделана, я хочу вызвать внешнюю программу (скрипт php) через sys_ * UDF MySQL. Теперь проблема - триггер, который у меня есть, передает идентификатор записи в скрипт. Когда я пытаюсь извлечь данные через скрипт, я получаю 0 строк. Во время моего собственного тестирования я пришел к выводу, что триггер вызывает скрипт php и передает параметры ДО фактической вставки, поэтому я не получаю записей для данного идентификатора. Я тестировал это на MySQL 5.0.75 и 5.1.41 (ОС Ubuntu). Я могу подтвердить, что параметры передаются в скрипт до фактической вставки, потому что я добавил sleep (2); на мой PHP-скрипт, и я получил данные правильно. Без сна(); Заявление, я получаю 0 записей для данного идентификатора.

Мой вопрос - как решить эту проблему без необходимости жестко задавать какую-то задержку в скрипте php? У меня нет свободы предполагать, что 2 секунды (или 10 секунд) будут достаточной задержкой, поэтому я хочу, чтобы все происходило «естественно», когда одна команда завершается - другая выполняется.

Я предполагал, что если триггер имеет тип AFTER INSERT, все в теле триггера будет выполнено после того, как MySQL фактически вставит данные.

Таблица раскладки:

CREATE TABLE test (
id int not null auto_increment PRIMARY KEY,
random_data varchar(255) not null
);

Схема запуска:

DELIMITER $$

CREATE TRIGGER `test_after_insert` AFTER INSERT ON `test` 
FOR EACH ROW BEGIN

SET @exec_var = sys_exec(CONCAT('php /var/www/xyz/servers/dispatcher.php ', NEW.id));
END;
$$

DELIMITER ;

Отказ от ответственности: я знаю проблемы безопасности при использовании функции sys_exec, моя проблема в том, что MySQL не вставляет FIRST, а затем вызывает скрипт с необходимыми параметрами. Если кто-то может пролить некоторый свет на то, как это исправить, или использует другой подход, который не включает SELECT INTO OUTFILE и использование FAM - я был бы очень признателен. Заранее спасибо.

Ответы [ 2 ]

4 голосов
/ 27 июля 2013

Даже если вы используете триггер AFTER, строка еще не зафиксирована. Но sys_exec () не возвращается, пока не завершится php-скрипт, поэтому триггер AFTER не может завершиться, поэтому вы также не можете зафиксировать INSERT.

Это по замыслу. В конце концов, вы можете выполнять больше операций в рамках одной транзакции или откатить транзакцию. В этом проблема вызова внешних процессов из триггера: внешние процессы не могут видеть данные в рамках транзакции в базе данных.

Вы не должны выполнять эту задачу с триггером. В лучшем случае вы должны использовать триггер, чтобы установить столбец «флаг», а затем написать внешний процесс для поиска строк с установленным флагом, а затем вызвать этот сценарий PHP. Таким образом будут обрабатываться только строки, которые были успешно вставлены и зафиксированы.

3 голосов
/ 27 июня 2013

Если я правильно понимаю, вы вставляете строку в свою БД. Это вызывает триггер, который запускает внешнюю команду, написанную на PHP. Эта команда в свою очередь запрашивает одну и ту же БД, используя id вставленной строки?

Я не думаю это проблема "задержки".

Настоящая «проблема» - это ваша первоначальная вставка, и ваша внешняя команда подключается к одной и той же БД в двух разных сеансах - возможно, в двух разных транзакциях (в зависимости от механизма базы данных и уровень изоляции вашей транзакции).

I Предположим , когда триггер в вызванной вставке строки еще не зафиксирован в БД. Таким образом, внешняя команда по-прежнему видит базу данных, как это было раньше.


Кстати, если приведенное выше объяснение весьма умозрительно - для меня более очевидно, что вам, вероятно, следует подумать о другом дизайне, чем пытаться заставить работать эту работу такой, какая она есть.

...