Frage

Ich habe ein Problem, wenn ich Apache :: DBI in Kinderprozessen verwende. Das Problem ist, dass Apache :: DBI einen einzelnen Griff für alle Prozesse bietet, die es verwenden, also bekomme ich

Dbd :: mysql :: db selectall_arrayref fehlgeschlagen: Befehle außerhalb der Synchronisierung; Sie können diesen Befehl jetzt nicht unter /usr/local/www/apache22/data/test-fork.cgi Zeile 20 ausführen.

Die Wiederverbindung hilft nicht, da Apache :: DBI in allen Prozessen wieder verbunden ist, wie ich den folgenden Fehler verstanden habe

Der Server stieß auf einen internen Fehler und konnte Ihre Anfrage nicht abschließen.

Fehlermeldung: Der DBD -Treiber hat das AutoCommit -Attribut nicht implementiert unter /usr/local/lib/perl5/site_perl/5.8.9/apache/dbi.pm Zeile 283.,,

Hier ist der Ursprungscode:

use Data::Dumper 'Dumper';
use DBI ();

my $dbh = DBI->connect($dsn, $username, $password, {
        RaiseError => 1,
        PrintError => 0,
    });
my $file = "/tmp/test-fork.tmp";

my $pid = fork;
defined $pid or die "fork: $!";

if ($pid) {
    my $rows = eval { $dbh->selectall_arrayref('SELECT SLEEP(1)') };

    print "Content-Type: text/plain\n\n";
    print $rows ? "parent: " . Dumper($rows) : $@;
}
else {
    my $rows = eval { $dbh->selectall_arrayref('SELECT SLEEP(1)') };

    open FH, '>', $file or die "$file: $!";
    print FH $rows ? "child: " . Dumper($rows) : $@;
    close FH;
}

Der Code, den ich zur Wiederverbindung verwendet habe:

...
else {
    $dbh->disconnect;
    $dbh = DBI->connect($dsn, $username, $password, $attrs);
    my $rows = eval { $dbh->selectall_arrayref('SELECT SLEEP(1)') };

    open FH, '>', $file or die "$file: $!";
    print FH $rows ? "child: " . Dumper($rows) : $@;
    close FH;
}

Gibt es eine sichere Möglichkeit, Apache :: DBI mit Gabeln zu verwenden? Gibt es eine Möglichkeit, dass es vielleicht eine neue Verbindung herstellt?

War es hilfreich?

Lösung 2

Gabel nicht unter mod_perl2. Verwenden Apache2 :: Subprozess. Siehe auch Ist es eine schlechte Idee, unter mod_perl2 zu gabeln?

Andere Tipps

Ich sehe ein paar Optionen:

  • Schließen Sie Ihre DB -Griffe explizit, wenn Sie gabeln, und öffnen Sie sie nach Bedarf wieder.

z.B:

my $dbh = DBI->connect(...);

my $pid = fork;
defined $pid or die "fork: $!";

if ($pid) {
    # parent...
}
else {
    # child...
    undef $dbh;

Dies könnte durch die Speicherung der Speichern erleichtert werden $dbh In einem Objekt und das Übergeben dieses Objekts nach Bedarf an Teile Ihres Systems. Das Objekt wäre für die Wiedereröffnung des $ dBH nach Bedarf verantwortlich, sodass sich der Rest der Anwendung nicht mit den Details befassen muss. Halten Sie den Code aus anderen Teilen des Systems eingekapselt und gut getrennt.

Ich verwende DBIX :: Connector in meinem System in einem Moose -Objekt, das eine Methodendelegation verwendet, um die DBH bereitzustellen. Die Anwendung macht einfach:

my $dbh = $db_dbj->dbh;
my $sth = $dbh->prepare(...);
# more boring DBI code here

... und der DBH wird unsichtbar wieder verbunden/regeneriert.


Abgesehen davon sollten Sie sehr darauf achten, dass Sie bloße Dateihandles in einer Multiprozessumgebung verwenden. Sie könnten sehr leicht Ihre Daten überschreiten. open (my $fh, $file) or die "Cannot open $file: $!" ist viel sicherer.

Ich bin auch ein wenig nervös, wenn ich dich benutzt sehe eval {} Blöcke ohne den Inhalt von zu überprüfen $@. Sie maskieren nur Fehler, anstatt sich mit ihnen zu beschäftigen, sodass möglicherweise mehr Dinge vor sich gehen, als Sie wissen. Überprüfen Sie Ihre Ergebniswerte (oder besser, verwenden Sie ein explizit Versuchen Sie :: winzig. verwenden use strict; use warnings;.

Ps. Mir ist gerade aufgefallen, dass Sie explizit einbeziehen DBI in Ihrem Code. Tu das nicht. Wenn Sie Apache :: DBI in Ihrem startup_modperl.pl (oder wie auch immer Sie Ihre Bootstrap -Datei nennen) verwenden, sollten Sie niemals DBI selbst einbeziehen müssen. Ich kann nicht sicher sagen, aber ich wäre nicht zuversichtlich, dass das richtige Paket angerufen wird (es ist schon eine Weile her, seit ich mich Apache :: DBIs Eingeweide angesehen habe; es könnte sich aber für Sie darum kümmern).

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top