Hallo Stefan,
wir haben uns jetzt mal den Aufwand gemacht und sind in den Kaninchenbau hinabgestiegen und haben folgendes vorgefunden:
Das Problem findet seinen Ursprung wenn die TSE aktiv ist und Buchungen signiert.
Also fangen wir an in der Methode
addProductListToQueueCore
Um dem Problem auf die Spur zu kommen ist es wichtig, das wir verstehen das in der Methode
addProductListToQueueCore die Datenbank Transaction gestartet wird:
Code: Alles auswählen
public function addProductListToQueueCore($pdo,$ordertime,$theTableid,$prods,$doPrint,$payprinttype,$userid,$quickcash, $order = null,$orderOption="") {
if (intval($theTableid) == 0) {
$theTableid = null; // togo room
}
if (!is_null($order)) {
$order->setCreatorid($userid);
}
$printAndQueueJobs = CommonUtils::getConfigValue($pdo, "printandqueuejobs", 0);
if ($printAndQueueJobs == 1) {
$doPrint = 1;
}
$pdo->beginTransaction();
Siehe hier
$pdo->beginnTransaction. Nun finden im Code eine Reihe vorbereitender Maßnahmen statt. Ist die TSE aktiv, so wird dann innerhalb der Methode die Methode
signAtTSE gecalled. Der Methode wird dann das PDO-Objekt mit der gestarteten Transaktion übergeben. Die Methode
signAtTSE reicht ihrerseits dann die Daten nach erfolgreicher Signierung weiter an die Methode
createOperations der Klasse Operations.
Und hier wird es dann interessant:
Wir haben hier in der Klasse das PDO-Objekt mit der laufenden Transaktion rein bekommen. Um die Daten in die Table
os_operations schreiben zu können werden vorher zwei neue IDs selbst kreiert. Das das schief gehen kann findet sich auch im Code.
Code: Alles auswählen
// In parallel transactions and with transaction isolatoon level REPEATABLE READ it may be possible that the max id is already set by another transaction.
// Therefore run this in a try catch block just in case of a deadlock and increment the maxid in catch
// In a very very unikely case of race condition still the bonid can be created multiple times, but the unique primary key id is evidence that there is no
// intention in creating an invalid operation. Therefore also this comment is left in this source code!
Und beim Versuch die Daten zu schreiben wird dann eine Exception gefangen, wenn es die ID schon geben sollte.
Code: Alles auswählen
try {
if ($maxtries == 4) {
$signtxt = $signtxt_ascii;
error_log("Using from now on the ascii version of the signtxt to store in operations table");
}
CommonUtils::execSql($pdo, $sql, array($maxid+1,$range,$maxbonid+1,$opType,$table,$logtime,$trans, $sigcounter, $tseSignature, $pubkeyRef, $sigalgRef, $serialNoRef,$certificateRef, $signtxt, $tseerror, $terminalEntryId));
$ok = true;
} catch (Exception $ex) {
$maxid++;
$attempt++;
$maxtries--;
sleep(1);
}
Aber diese Exception wird niemals fliegen, da wir uns in einer Transaktion befinden und die IDs selbst erstellt haben. Die Datenbank Transaktion hat keine Kenntnis von den IDs und glaubt und. Also werden hier bei einer zeitgleichen Transaktion eine die gleiche maxid und maxbonid.
Das fällt aber erst beim finalen commit auf und die Daten werden nicht in die Datenbank geschrieben.
--------------------
Lieber Stefan,
konnten wir Dir damit helfen? Sollen wir versuchen das selbst zu lösen und Dir das dann in die Hand drücken?