stored - procedimientos almacenados en mysql y utilizarlos en php
PHP Apache se bloquea al ejecutar un PROCEDIMIENTO ALMACENADO (5)
Aparentemente hay un poco de dinero pasando, es decir, scaricabarile , entre PHP PHP y MySQLi.
Lo que parece estar sucediendo es que MySQLi reacciona de manera "impropia", y devuelve un valor inesperado (apostaría una pequeña suma a que es un NULO) a PHP, que debidamente cede. Este comportamiento está documentado y el veredicto de PHPland es: "No es un error [PHP]". Por su parte, los chicos de MySQLi sostienen que es PHP que no está verificando correctamente el resultado devuelto. Y esos resultados ''impropios'' dependían de tu consulta de todos modos.
Así que me arriesgo y supongo que el suyo es el mismo problema de "dificultades de comunicación", por lo que el problema se convierte en: "Su consulta obliga a MySQLi a abandonar / reconectarse". ¿Por qué es así? Aparentemente (algunos) los procedimientos almacenados requieren mysqli_multi_query
para comportarse correctamente .
Y mysqli_multi_query
no es compatible con mysqli_prepare
.
Así que sugeriría intentar sin preparar la consulta y ejecutarla con mysqli_multi_query
.
$conn->query("SET @res = ''''");
$conn->multi_query("CALL retrieve_matches(5,3, 16, 2, false, @res)");
do {
if ($result = $conn->store_result()) {
while ($row = $result->fetch_row()) {
var_dump($row);
}
$result->free();
}
} while ($conn->more_results() && $conn->next_result());
Con este código, su caso de prueba me pone, como se esperaba,
array(1) {
[0] =>
string(4) "test"
}
Problema
Cuando ejecuto el siguiente código (estoy llamando a un procedimiento almacenado con 5 parámetros IN y 1 parámetro OUT)
$conn->query("SET @res = ''''");
$mysqli=$conn;
if (!($stmt = $mysqli->prepare("CALL retrieve_matches(5,3, 16, 2, false, @res)"))) {
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
do {
if ($res = $stmt->get_result()) { //Apache crash on this call
printf("---/n");
var_dump(mysqli_fetch_all($res));
mysqli_free_result($res);
} else {
if ($stmt->errno) {
echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
} while ($stmt->more_results() && $stmt->next_result());
apache se está estrellando con el error:
AH00428: Padre: el proceso hijo 9628 salió con el estado 255 - Reiniciando.
Lo que intenté
- Este código funciona bien y está devolviendo correctamente los resultados:
$conn->query("SET @res = ''''");
$res=$conn->query("CALL retrieve_matches(5,3, 16, 2, false, @res)");
var_dump($res->fetch_assoc());
NOTA : El mismo código anterior que hace que Apache se cuelgue está funcionando correctamente si simplemente cambio el número en la entrada del procedimiento almacenado como:
if (!($stmt = $mysqli->prepare("CALL retrieve_matches(5,6, 16, 2, false, @res)"))) {
- Intentado desde la mesa de trabajo MySQl y ambas llamadas funcionan bien.
- Estoy usando WAMP 64b en un WIN7 Enterprise 64b, probé con WAMP 32b pero tuve el mismo problema.
- Revisé el evento de Windows y encontré que httpd.exe se bloquea debido a php5ts.dll
- Si busca "httpd.exe php5ts.dll" en google, puede encontrar un montón de personas que tienen este problema. Pero no encontré una solución para WAMP ...
- Trató con AMPPS, exactamente el mismo problema
Registro de errores de PHP
[10-Jul-2015 15:30:03 UTC] PHP Warning: PHP Startup: Unable to load dynamic library ''C:/Program Files/wamp/bin/php/php5.5.12/ext/php_ldap.dll'' - Impossibile trovare il modulo specificato.
in Unknown on line 0
[10-Jul-2015 15:30:04 UTC] PHP Warning: PHP Startup: Unable to load dynamic library ''C:/Program Files/wamp/bin/php/php5.5.12/ext/php_intl.dll'' - Impossibile trovare il modulo specificato.
Registro de errores APACHE:
[Tue Jul 14 15:02:13.038276 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00428: Parent: child process 9448 exited with status 255 -- Restarting.
[Tue Jul 14 15:02:13.324305 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00455: Apache/2.4.9 (Win32) PHP/5.5.12 configured -- resuming normal operations
[Tue Jul 14 15:02:13.329306 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00456: Apache Lounge VC11 Server built: Mar 16 2014 12:13:13
[Tue Jul 14 15:02:13.329306 2015] [core:notice] [pid 7044:tid 404] AH00094: Command line: ''C://Program Files//wamp//bin//apache//apache2.4.9//bin//httpd.exe -d C:/Program Files/wamp/bin/apache/apache2.4.9''
[Tue Jul 14 15:02:13.352308 2015] [mpm_winnt:notice] [pid 7044:tid 404] AH00418: Parent: Created child process 3140
[Tue Jul 14 15:02:14.528388 2015] [mpm_winnt:notice] [pid 3140:tid 332] AH00354: Child: Starting 64 worker threads.
Estoy realmente perdido aquí, ¿dónde debería buscar el problema? Muchas gracias por su ayuda
EDITAR
Me di cuenta de que el procedimiento almacenado "retrieve_matches" está llamando a un procedimiento almacenado diferente en función del valor modificado. Depuré el procedimiento almacenado "retrieve_standalone" que es el que hace que Apache se bloquee. Este procedimiento está haciendo selección / inserción, lo verifiqué y la inserción se realizó correctamente. PERO dentro de "retrieve_standalone" estoy usando un cursor de una manera extraña:
declare bNoMoreRows bool default false;
declare tmp_cursor cursor for
select comp_id from to_match; -- to_match is a temporary table
declare continue handler for not found set bNoMoreRows := true;
si no abro el cursor
open tmp_cursor;
todo esta funcionando bien !! Así que supongo que encontré el problema ahora: ¿cómo puedo resolverlo?
Creo que estás confundiendo $conn
y $stmt
. Esto es lo que tengo. (Reúne el resultado en $ out.)
if ($conn->multi_query($call)) {
$raa = array();
do {
/* store first result set */
if ($result = $conn->use_result()) {
while ($row = $result->fetch_row()) {
$raa[] = $row;
printf("+/n");
}
$result->close();
}
$out[] = $raa;
/* print divider */
if ($conn->more_results()) {
printf("-----------------/n");
}
} while ($conn->next_result());
}
else
echo "err";
Descubrí cómo reproducirlo, creo que es un error php / apache
Código PHP:
if (!($stmt = $mysqli->prepare("CALL test()"))) {
echo "Prepare failed: (" . $mysqli->errno . ") " . $mysqli->error;
}
if (!$stmt->execute()) {
echo "Execute failed: (" . $stmt->errno . ") " . $stmt->error;
}
do {
if ($res = $stmt->get_result()) {
printf("---/n");
//var_dump(mysqli_fetch_all($res));
var_dump($res->fetch_assoc());
mysqli_free_result($res);
} else {
if ($stmt->errno) {
echo "Store failed: (" . $stmt->errno . ") " . $stmt->error;
}
}
} while ($stmt->more_results() && $stmt->next_result());
Código de procedimiento de la tienda:
CREATE DEFINER=`root`@`localhost` PROCEDURE `test`()
BEGIN
declare test_var varchar(100) default "ciao";
declare bNoMoreRows bool default false;
declare test_cursor cursor for
select id from tmp_folder;
declare continue handler for not found set bNoMoreRows := true;
create temporary table tmp_folder select "test" as id;
open test_cursor;
fetch test_cursor into test_var;
close test_cursor;
select test_var;
drop temporary table if exists tmp_folder;
END
Error abierto: Apache: https://bz.apache.org/bugzilla/show_bug.cgi?id=58136
Intenta cambiar la pila de tu servidor. Actualice WAMP o ejecute su código en un entorno diferente. Esta pregunta sugiere que hay un error en WAMP que hará que Apache arroje el error 255
php -> mysql_connect -> proceso hijo finalizado con el estado 255 - Reiniciando
Si php5ts.dll, o cualquier otra parte de apache se bloquea de forma reproducible cada vez que ejecuta un script corto, lo más probable es que haya detectado un error en php. Especialmente si ejecuta un apache actualizado con una versión reciente de php descargada de php.net, tiene muchas posibilidades de obtener soporte del equipo de PHP. Así que lea https://bugs.php.net/how-to-report.php , vea si puede reproducir el bloqueo al ejecutar el script sin apache (en un script separado en el cli usando php.exe) y genere un Backtrace que luego puede enviar como un error.
Errores como estos a veces se pueden solucionar, pero rara vez se pueden solucionar desde el contexto de su script. PHP nunca debe bloquear el servidor web y, si lo hace de manera reproducible, se debe presentar un error para que se pueda corregir.