Esto es complicado de explicar (y muy raro), así que tengan paciencia conmigo. Explicaré el problema y la solución, pero me gustaría ver si alguien puede explicar por qué funciona de la manera que funciona :)¿El manejador de la base de datos DBI con AutoCommit establecido en 0 no devuelve los datos correctos con SELECT?
Tengo una aplicación web que usa mod_perl. Utiliza la base de datos MySQL, y estoy escribiendo datos en una base de datos de forma regular. Es modular, por lo que también tiene su propio tipo de módulo de "base de datos", donde manejo conexión, actualizaciones, etc. base de datos :: db_connect() subrutina se usa para conectarse a la base de datos, y AutoCommit
se establece en 0.
Hice otra aplicación Perl (daemon independiente), que periódicamente recupera datos de la base de datos y realiza varias tareas dependiendo de qué datos se devuelven. Incluyo el módulo database.pm, por lo que no tengo que volver a escribir/duplicar todo.
problema que estoy experimentando es:
aplicación se conecta a la base de datos en el arranque, y luego bucles para siempre, ir a buscar los datos de la base de datos cada X segundos. Sin embargo, si se actualizan los datos en la base de datos, mi aplicación sigue recibiendo datos 'viejos', que obtuve en la conexión/consulta inicial a la base de datos.
Por ejemplo, tengo 3 filas y la columna "Nombre" tiene los valores "a", "b" y "c" para cada registro. Si actualizo una de las filas (usando el cliente de mysql desde la línea de comandos, por ejemplo) y cambio el nombre de 'c' a 'x', mi demonio independiente no obtendrá esos datos; aún así obtendrá un/b/c devuelto por MySQL. Capturé el tráfico db con tcpdump, y definitivamente pude ver que MySQL realmente estaba devolviendo esa información. También intenté usar SQL_NO_CACHE con SELECT (ya que no estaba seguro de qué estaba pasando), pero tampoco sirvió de nada.
Luego, he modificado la cadena de conexión de base de datos en mi daemon independiente, y configuré AutoCommit
en 1. De repente, la aplicación comenzó a obtener los datos adecuados.
Estoy desconcertado, porque pensé que AutoCommit solo afecta a los tipos de instrucciones INSERT/UPDATE y no afectó a la instrucción SELECT. Pero parece que sí, y no entiendo por qué.
¿Alguien sabe por qué la instrucción SELECT no devolverá filas 'actualizadas' de la base de datos cuando AutoCommit
se establece en 0, y por qué devolverá las filas actualizadas cuando AutoCommit
está establecido en 1?
Aquí hay un código simplificado (comprobado de errores, etc.) que estoy usando en el daemon independiente, y que no devuelve filas actualizadas.
#!/usr/bin/perl
use strict;
use warnings;
use DBI;
use Data::Dumper;
$|=1;
my $dsn = "dbi:mysql:database=mp;mysql_read_default_file=/etc/mysql/database.cnf";
my $dbh = DBI->connect($dsn, undef, undef, {RaiseError => 0, AutoCommit => 0});
$dbh->{mysql_enable_utf8} = 1;
while(1)
{
my $sql = "SELECT * FROM queue";
my $stb = $dbh->prepare($sql);
my $ret_hashref = $dbh->selectall_hashref($sql, "ID");
print Dumper($ret_hashref);
sleep(30);
}
exit;
Cambio AutoCommit
a 1 permite reparar este problema. ¿Por qué?
Gracias :)
P.S: No estoy seguro si a alguien le interesa, pero la versión de DBI es 1.613, DBD :: mysql es 4.017, Perl es 5.10.1 (en Ubuntu 10.04).
¿La opción 'auto_commit' está activada o desactivada en su cliente mysql de línea de comando (donde realizó la operación' UPDATE')? – Ether
Está activado (está activado por defecto y no lo he cambiado). Puedo ver los 'nuevos' datos actualizados de cliente mysql, o cualquier otra 'sesión' (nueva sesión DBI que se conecta, o cualquier otro cliente que se conecta a DB) - es sólo la sesión con AutoCommit 0 que no se puede acceder a los datos actualizados . – sentinel