X-Coder
Aktiver NGBler
- Registriert
- 14 Juli 2013
- Beiträge
- 149
Ich bin gerade mit meinem Latein am Ende und könnte etwas Hilfe gebrauchen.
Hat vielleicht jemand eine Idee warum es beim Commit in Zeile 50 nur gelegentlich zu dem PDO-Fehler: "There is no active transaction" kommt?
Ich starte diese Transaktion doch zuvor in Zeile 7, und beende diese dazwischen nicht mehr. Ich kann darin keinen Fehler entdecken.
Eingesetzt wird PHP 7.
Dieser Fehler tritt nur gelegentlich auf, ich konnte bis jetzt noch nicht nachstellen wann und warum. Er zeigt sich auch nur im Produktiv-System, nicht bei der Entwicklung.
Grundlegend versuche ich mehrere CSV-Dateien einzulesen, nehme vor dem Import in die Datenbank noch diverse Prüfungen vor, und importiere diese dann in eine MySQL-Datenbank.
Jede CSV-Datei wird als ein Auftragsjob behandelt, bei dem Datensätze mit Fehlern aber einfach übersprungen werden sollen und nur solche importiert werden sollen, welche auch allen Kriterien erfüllen und importierbar sind.
Ein Rollback soll nur durchgeführt werden, wenn gar keine Datensätze in die job_detail-Tablle importiert worden sind, damit der zuerst angelegt Job aus der job-Tabelle auch wieder gelöscht wird.
Könnte es sein, dass die Transaktion nicht durch mein Skript unterbrochen wird, sondern durch ein datenbankseitigen Timeout oder so etwas?
In dieser Zeit finden auch keine externen ALTER-Table Anweisungen statt, welche Transaktionen abbrechen lassen würden.
Der Code ist sehr gekürzt, ich habe weitgehendst nur die Kontrollstrukturen darin gelassen.
[src=php]<?php
try {
#$cfg->db // = Wrapper für PDO
$cntRowsInserted = 0; // Zähler für erfolgreiche Inserts
$autocommit = $cfg->db->get_autocommit(); // aktuellen Transaktionsmodus sichern (für verschachtelte Transaktionen)
$cfg->db->autocommit(false); // Autocommit deaktivieren und Transaktion starten
if ($hasError) {
throw new Exception('Fehlermeldung');
}
// Job anlegen
$stmt = $LEVEO->db->prepare('INSERT INTO jobs ...');
$stmt->execute();
// Zeilen einlesen und in Datenbank abspeichern
while ($row = ...) {
try {
if ($hasError) {
throw new Exception('Fehlermeldung');
}
// Query ausführen
try {
$stmt = $cfg->db->query('INSERT INTO job_details ...'); //löst Exception aus bei Fehlern
$cntRowsInserted++; //Wenn OK, dann erhöhen
}
catch (Exception $e) {
throw $e;
}
}
catch (Exception $ex) {
// - alle Exception abfangen, fehlerhaften Datensatz überspringen
// - mit anderen Datensätzen fortfahren
// - Fehlermeldung protokollieren
#fputcsv(...);
}
}
//Alles Datensätze des Jobs verarbeitet? - dann Job speichern
if ($cntRowsInserted > 0) { // Es wurde mindestens ein Datensatz erfolgreich verarbeitet
// ganzen Job zur Weiterverarbeitung freigeben
if ($autoFreigabe) {
$stmtJobFreigabe->bindValue(':job_id', $job_id);
$stmtJobFreigabe->execute();
}
// Auftragsjob speichern
$cfg->db->commit(); //<------------------ There is no active transaction!
$cfg->db->autocommit($autocommit); // Transaktionsmodus wiederherstellen
} else {
// Sollten keine Datensätze importiert worden sein, dann Job durch Rollback löschen
$cfg->db->rollback();
}
}
//Fehler?
catch (Exception $ex) {
// Sonstige unbehandelte Fehler speichern
$error = $ex->getMessage();
if (empty($DEBUG)) {
// Fehler-Details mailen
}
try {
// alle Änderungen an der Datenbank zurücknehmen
$cfg->db->rollback();
$cfg->db->autocommit($autocommit); // Transaktionsmodus wiederherstellen
}
catch (Exception $ex2) {
if (!empty($DEBUG)) {
// Fehlermeldung an Debugoutput anhängen
$error .= "\r\n" . $ex2->getMessage();
}
}
}
?>
[/src]
Hat vielleicht jemand eine Idee warum es beim Commit in Zeile 50 nur gelegentlich zu dem PDO-Fehler: "There is no active transaction" kommt?
Ich starte diese Transaktion doch zuvor in Zeile 7, und beende diese dazwischen nicht mehr. Ich kann darin keinen Fehler entdecken.
Eingesetzt wird PHP 7.
Dieser Fehler tritt nur gelegentlich auf, ich konnte bis jetzt noch nicht nachstellen wann und warum. Er zeigt sich auch nur im Produktiv-System, nicht bei der Entwicklung.
Grundlegend versuche ich mehrere CSV-Dateien einzulesen, nehme vor dem Import in die Datenbank noch diverse Prüfungen vor, und importiere diese dann in eine MySQL-Datenbank.
Jede CSV-Datei wird als ein Auftragsjob behandelt, bei dem Datensätze mit Fehlern aber einfach übersprungen werden sollen und nur solche importiert werden sollen, welche auch allen Kriterien erfüllen und importierbar sind.
Ein Rollback soll nur durchgeführt werden, wenn gar keine Datensätze in die job_detail-Tablle importiert worden sind, damit der zuerst angelegt Job aus der job-Tabelle auch wieder gelöscht wird.
Könnte es sein, dass die Transaktion nicht durch mein Skript unterbrochen wird, sondern durch ein datenbankseitigen Timeout oder so etwas?
In dieser Zeit finden auch keine externen ALTER-Table Anweisungen statt, welche Transaktionen abbrechen lassen würden.
Der Code ist sehr gekürzt, ich habe weitgehendst nur die Kontrollstrukturen darin gelassen.
[src=php]<?php
try {
#$cfg->db // = Wrapper für PDO
$cntRowsInserted = 0; // Zähler für erfolgreiche Inserts
$autocommit = $cfg->db->get_autocommit(); // aktuellen Transaktionsmodus sichern (für verschachtelte Transaktionen)
$cfg->db->autocommit(false); // Autocommit deaktivieren und Transaktion starten
if ($hasError) {
throw new Exception('Fehlermeldung');
}
// Job anlegen
$stmt = $LEVEO->db->prepare('INSERT INTO jobs ...');
$stmt->execute();
// Zeilen einlesen und in Datenbank abspeichern
while ($row = ...) {
try {
if ($hasError) {
throw new Exception('Fehlermeldung');
}
// Query ausführen
try {
$stmt = $cfg->db->query('INSERT INTO job_details ...'); //löst Exception aus bei Fehlern
$cntRowsInserted++; //Wenn OK, dann erhöhen
}
catch (Exception $e) {
throw $e;
}
}
catch (Exception $ex) {
// - alle Exception abfangen, fehlerhaften Datensatz überspringen
// - mit anderen Datensätzen fortfahren
// - Fehlermeldung protokollieren
#fputcsv(...);
}
}
//Alles Datensätze des Jobs verarbeitet? - dann Job speichern
if ($cntRowsInserted > 0) { // Es wurde mindestens ein Datensatz erfolgreich verarbeitet
// ganzen Job zur Weiterverarbeitung freigeben
if ($autoFreigabe) {
$stmtJobFreigabe->bindValue(':job_id', $job_id);
$stmtJobFreigabe->execute();
}
// Auftragsjob speichern
$cfg->db->commit(); //<------------------ There is no active transaction!
$cfg->db->autocommit($autocommit); // Transaktionsmodus wiederherstellen
} else {
// Sollten keine Datensätze importiert worden sein, dann Job durch Rollback löschen
$cfg->db->rollback();
}
}
//Fehler?
catch (Exception $ex) {
// Sonstige unbehandelte Fehler speichern
$error = $ex->getMessage();
if (empty($DEBUG)) {
// Fehler-Details mailen
}
try {
// alle Änderungen an der Datenbank zurücknehmen
$cfg->db->rollback();
$cfg->db->autocommit($autocommit); // Transaktionsmodus wiederherstellen
}
catch (Exception $ex2) {
if (!empty($DEBUG)) {
// Fehlermeldung an Debugoutput anhängen
$error .= "\r\n" . $ex2->getMessage();
}
}
}
?>
[/src]
Zuletzt bearbeitet: