2010-09-06 18 views
7

Problema: Tengo una tabla que contiene ciertos registros. Una vez realizada la inserción, deseo llamar a un programa externo (script php) a través de las UDS de Sys_ * de MySQL. Ahora, el problema: el desencadenador que tengo pasa la identificación del registro a la secuencia de comandos. Cuando intento extraer los datos mediante el script, obtengo 0 filas. Durante mi propia prueba, llegué a la conclusión de que el desencadenador invoca la secuencia de comandos php y pasa los parámetros ANTES de que se produzca la inserción real, por lo que no obtengo ningún registro para la identificación dada. He probado esto en MySQL 5.0.75 y 5.1.41 (SO Ubuntu). Puedo confirmar que los parámetros se pasan al script antes de que ocurra la inserción real porque he agregado sleep (2); a mi script php y obtuve los datos correctamente. Sin dormir(); declaración, estoy recibiendo 0 registros para la identificación dada.Desencadenadores MySQL - DESPUÉS DE INSERTAR disparador + UDF sys_exec() problema

Mi pregunta es - ¿cómo solucionar este problema sin tener que hardcode algún tipo de retraso dentro del script php? No tengo la libertad de suponer que 2 segundos (o 10 segundos) serán suficiente retraso, por lo que quiero que todo fluya "naturalmente", cuando un comando finaliza, el otro se ejecuta.

Supuse que si el activador es de tipo DESPUÉS DE INSERTAR, todo dentro del cuerpo del desencadenador se ejecutará después de que MySQL realmente inserte los datos.

diseño

Tabla:

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

diseño de disparo:

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 ; 

responsabilidad: Sé que los problemas de seguridad cuando se utiliza la función sys_exec, mi problema es que el MySQL no inserta primero y luego llamar la secuencia de comandos con los parámetros necesarios. Si alguien puede arrojar algo de luz sobre cómo solucionar esto o si tiene un enfoque diferente que no involucre SELECT INTO OUTFILE y usar FAM, estaría muy agradecido. Gracias por adelantado.

+0

Aclare: El script DHCP dispatcher.php se activa, establece una conexión de cliente con su base de datos y luego realiza una consulta. ¿Está bien? –

+0

Se insertan datos. El desencadenador se invoca y pasa la ID a dispatcher.php. Dispatcher.php recupera la fila y la envía al navegador. La razón por la que no envío todos los datos en el inserto es porque los insertaré en una sola tabla, pero extraeré los datos de la vista, por lo que no sé todas las columnas que usaré en un momento dado. – Mihael

+0

Entonces, dispatcher.php tiene su propia conexión de cliente a mySQL? Esto no va a funcionar de manera confiable, porque la transacción de inserción/actualización en la que se ejecuta su desencadenador no está completa hasta que finaliza el desencadenador. Entonces, dispatcher.php ve datos inconsistentes o previos a la transacción. En cualquier caso, es como comer una rebanada de pastel mientras el pastel todavía está en el horno. los desencadenantes deben permanecer dentro del servidor de la base de datos. –

Respuesta

3

Si lo entiendo claramente, inserta una fila en su base de datos. Que invoque un disparador que ejecute un comando externo escrito en PHP. Ese comando consulta a su vez el mismo DB utilizando el id de la fila insertada?

Yo no piensa este es un problema de "retraso".

El verdadero "problema" es su inserción inicial y comandos externos se conectan a la misma base de datos en dos diferentes sessions - probablemente en dos diferentes transactions (dependiendo de su motor de base de datos y el nivel de aislamiento).

I suponga, cuando el desencadenador en el que se invoca el inserto de fila aún no se ha confirmado en la base de datos. Entonces el comando externo aún ve el DB como estaba antes.


Por cierto, si la explicación anterior es bastante especulativa - lo que es más evidente para mí es que probablemente debe pensar en un diseño diferente que tratar de que el trabajo realizado como es.

2

Incluso si usa un disparador DESPUÉS, la fila aún no está confirmada. Pero sys_exec() no regresa hasta que se cierra el script php, por lo que el desencadenador AFTER no puede completarse, por lo tanto, tampoco puede confirmar el INSERT.

Esto es por diseño.Después de todo, puede hacer más operaciones dentro de la misma transacción, o puede revertir la transacción. Ese es el problema de invocar procesos externos desde un desencadenante: los procesos externos no pueden ver los datos dentro del alcance de la transacción en la base de datos.

No debe hacer esta tarea con un disparador. En el mejor de los casos, debe usar el desencadenador para establecer una columna de "marca" y luego escribir un proceso externo para buscar filas con el indicador establecido y luego invocar ese script PHP. De esta forma solo se procesarán las filas que se hayan insertado Y confirmado con éxito.

+0

¿Pasa los datos que necesita a través de los argumentos de línea de comando? – JDPeckham

+0

@JDPeckham, seguro que podría pasar toda la fila al guión. Pero, ¿qué ocurre si el INSERT es parte de una transacción que finalmente se retrotrae? Entonces el script acaba de actuar sobre datos que nunca serán visibles en la base de datos. –

+0

Gracias Bill! Eso tiene sentido. Creo que uno debería llamar a un procedimiento extra o algo así. – JDPeckham

Cuestiones relacionadas