Ich bin heute hier, weil ich nicht herausfinden kann, was das Problem mit meinen Transaktionen mit RedbeanPHP ist. Ich vermute, dass das Problem mit dem "Autocommit" -Wert von MySQL lag, da dieser immer eingeschaltet ist.Redbeans Transaktion funktioniert nicht
Lange Rede kurzer Sinn:
1) R::freeze(true);
erteilt wurde,
2) versucht, beide R::begin()
.. R::commit()
und R::transaction($callback)
Syntax
Hier ist eine einfache Klasse mit einem Testcode:
class TestTransactions{
public function testme($args){
$tstname = $args;
$src = R::findOne('batchscripts', 'batchclass = :tstname',
array(':tstname' => $tstname));
sleep(2);
if($src){
$src->alivesince = intval($src->alivesince) + 1;
R::store($src);
} else {
$bean = R::dispense('batchscripts');
$bean->batchclass = $tstname;
$bean->alivesince = 0;
$bean->start = R::$f->now();
R::store($bean);
}
}
public function testCallback(){
$that = &$this;
R::freeze(true);
try{
$ret2 = R::transaction(function() use ($that){
//uncomment me to see autocommit value
//$g = R::getAll("show global variables like 'autocommit'");
//$g = array_pop($g);
//var_dump($g);
$that->testme('instance');
});
} catch (Exception $e){
throw $e;
}
}
public function testProcedural(){
R::freeze(true);
try{
R::begin();
$this->testme('instance2');
R::commit();
} catch (Exception $e) {
R::rollback();
throw $e;
}
}
public function test(){
$this->testCallback();
$this->testProcedural();
}
}
Ausführung der test() - Funktion mit mehreren PHP-Skripten gleichzeitig (ich habe mit 12 versucht), Datenbankeinträge sind nicht korrekt:
Ich erwarte, dass ich
bekam ichbatchclass: 'instance', alivesince: 11
batchclass: 'instance2', alivesince: 11
statt haben
batchclass: 'instance', alivesince: 7
batchclass: 'instance2', alivesince: 7
Oder sogar
batchclass: 'instance', alivesince: 5
batchclass: 'instance2', alivesince: 5
abhängig von dem Moment die Skripte ausgeführt werden.
Was fehlt mir hier?
Danke
Dieser Link ist eigentlich irrelevant für das Problem, das Sie aufgetreten sind. Das Problem mit Beans besteht darin, dass die Daten aus der Datenbank extrahiert werden. Anschließend aktualisieren Sie den Wert, und Sie fügen den neuen Wert schließlich wieder in die Datenbank ein. In klassischeren RDBMS-Operationen würden Sie einfach "UPDATE test SET alivesince = alivesin + 1 WHERE ..." ausführen. Der RedBeans-Ansatz verhindert die Steuerung des gemeinsamen Zugriffs, außer wenn Sie vor dem Abrufen der Daten eine Transaktion starten, die nicht nur ineffizient, sondern auch lästig ist (und schwer zu warten ist). –