RedbeanPHPを使用しているトランザクションで何が問題になっているのか分かりません。私は、問題はMySQLの 'autocommit'値が常にONになっているためだと思います。Redbeanのトランザクションが動作しない
かいつまん:
1)R::freeze(true);
発行された、両方のR::begin()
... R::commit()
とR::transaction($callback)
構文ここ
にしようとしました
2)は、テストコードを持つ単純なクラスです:
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();
}
}
さらに多くのPHPスクリプトを使用してtest()関数を同時に実行すると(12回試してみました)、データベースの項目が正しくありません:
私は
batchclass: 'instance', alivesince: 11
batchclass: 'instance2', alivesince: 11
ではなく、私は、スクリプトを実行した瞬間に応じて
batchclass: 'instance', alivesince: 7
batchclass: 'instance2', alivesince: 7
あるいは
batchclass: 'instance', alivesince: 5
batchclass: 'instance2', alivesince: 5
を持っていることを期待しています。
私はここで何が欠けていますか?
ありがとうございます
このリンクは実際に発生した問題とは関係ありません。 Beanの問題は、データがデータベースから抽出され、次に値を更新し、最後に新しい値をデータベースに戻すことです。より古典的なRDBMS操作では、単に "UPDATEテストSET alivesince = alivesince + 1 WHERE ..."を実行します。 RedBeansのアプローチは、データを取得する前にトランザクションを開始する場合を除いて、並行処理の制御を行いません。非効率的であるだけでなく、コードに煩わしい(保守が困難です)。 –