2016-06-01 11 views
3

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 

を持っていることを期待しています。

私はここで何が欠けていますか?

ありがとうございます

答えて

0

問題を別の見方から見ると、私は見つからなかったものを見つけました。

もう1つの投稿a multithread transactionに記載されているように、MySQLでは使用できません。同期化されたアクセス(mutexとして)を扱うコードの一部は必須です。

私は他のプログラマーには便利だと思うので、ここに質問を残しておきます。

乾杯

+0

このリンクは実際に発生した問題とは関係ありません。 Beanの問題は、データがデータベースから抽出され、次に値を更新し、最後に新しい値をデータベースに戻すことです。より古典的なRDBMS操作では、単に "UPDATEテストSET alivesince = alivesince + 1 WHERE ..."を実行します。 RedBeansのアプローチは、データを取得する前にトランザクションを開始する場合を除いて、並行処理の制御を行いません。非効率的であるだけでなく、コードに煩わしい(保守が困難です)。 –

関連する問題