C'est difficile à expliquer (et très bizarre), alors supportez-moi. Je vais expliquer le problème, et le correctif pour cela, mais je voudrais voir si quelqu'un peut expliquer pourquoi cela fonctionne comme ça fonctionne :)Poignée de la base de données DBI avec AutoCommit définie sur 0 ne renvoyant pas les données correctes avec SELECT?
J'ai une application web qui utilise mod_perl. Il utilise la base de données MySQL et j'écris régulièrement des données dans une base de données. Il est modulaire, donc il a aussi son propre type de base de données, où je gère la connexion, les mises à jour, etc. database :: db_connect() subroutine est utilisé pour se connecter à la base de données, et AutoCommit
est 0.
J'ai créé une autre application Perl (démon autonome), qui extrait périodiquement des données de la base de données et effectue diverses tâches en fonction des données renvoyées. J'y inclus le module database.pm, donc je n'ai pas besoin de réécrire/dupliquer tout.
Problème Je rencontre est:
application se connecte à la base de données au démarrage, puis passe en boucle pour toujours, la récupération des données de base de données toutes les X secondes. Cependant, si les données dans la base de données sont mises à jour, mon application est toujours retournée "anciennes" données, que j'ai obtenu sur la connexion initiale/requête à la base de données. Par exemple - J'ai 3 lignes, et la colonne "Nom" a les valeurs 'a', 'b' et 'c' - pour chaque enregistrement. Si je mets à jour l'une des lignes (en utilisant le client mysql depuis la ligne de commande, par exemple) et que je change de nom de 'c' en 'x', mon démon autonome n'obtiendra pas ces données - il recevra quand même un/b/c MySQL J'ai capturé le trafic db avec tcpdump, et je pouvais vraiment voir que MySQL renvoyait vraiment ces données. J'ai essayé d'utiliser SQL_NO_CACHE avec SELECT (puisque je n'étais pas sûr de ce qui se passait), mais cela n'a pas aidé non plus.
Ensuite, j'ai modifié la chaîne de connexion DB dans mon démon autonome et défini AutoCommit
sur 1. Soudain, l'application a commencé à obtenir des données correctes.
Je suis perplexe, car je pensais que AutoCommit n'affecte que les types d'instructions INSERT/UPDATE et n'a aucun effet sur l'instruction SELECT. Mais apparemment, et je ne comprends pas pourquoi. Est-ce que quelqu'un sait pourquoi l'instruction SELECT ne retournera pas les lignes 'mises à jour' de la base de données lorsque AutoCommit
est définie sur 0 et pourquoi retournera-t-elle les lignes mises à jour lorsque AutoCommit
est défini sur 1?
Voici un code simplifié (vérification des erreurs, etc.) que j'utilise dans un démon autonome, et qui ne renvoie pas les lignes mises à jour.
#!/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;
La modification de AutoCommit
à 1 résout ce problème. Pourquoi?
Merci de
de P.S: Je ne sais pas si quelqu'un se soucie, mais la version DBI est 1,613, DBD :: mysql est 4.017, Perl est 5.10.1 (sur Ubuntu 10.04).
Le paramètre 'auto_commit' est-il activé ou désactivé dans votre client mysql en ligne de commande (où vous avez fait l'opération' UPDATE')? – Ether
Il est activé (il est activé par défaut et je ne l'ai pas modifié). Je peux voir les 'nouvelles' données mises à jour depuis le client mysql, ou toute autre 'session' (nouvelle session DBI connectée, ou tout autre client se connectant à DB) - seule la session avec AutoCommit 0 ne peut pas accéder aux données mises à jour . – sentinel