2017-05-02 2 views
1

準備されたMySQLストアドプロシージャコールがトランザクションで正常に実行され、ストアドプロシージャの予想される結果が表示されますが、実際のデータベースに保存します。Prepared PDO MySQL文はコミットされますが、変更はスティックではありません

物事のPHP側は次のようになります。

$options = array(); 
$db = new PDO("mysql:host=localhost;dbname=mydb", "myuser", "mypass", $options); 
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 

// ..... .... ... .. . 

$response["error"] = true; 
if ($db->beginTransaction() == true) 
{ 
    try 
    { 
     $stmt = $db->prepare("call Layout_Row_Add(:pageid, :position);"); 
     // $jason->page_id 
     $stmt->bindValue(':pageid', (int)$jason->page_id, PDO::PARAM_INT); 
     // $jason->position 
     $stmt->bindValue(':position', (int)$jason->position, PDO::PARAM_INT); 
     $stmt->execute(); 
     $response["dbg1"] = $jason->page_id; 
     $response["dbg2"] = $jason->position; 
     $response["intrans1"] = $db->inTransaction(); 
     $row = $stmt->fetch(); 
     $db->commit(); 
     $response["intrans2"] = $db->inTransaction();   
     $response["new_row_id"] = $row["NewRowId"]; 
     $response["error"] = false; 
    } 
    catch (PDOException $e) 
    { 
     $db->rollBack(); 
     $response["errortext"] = "PDO exception: " . $e->getMessage(); 
    } 
    catch (Exception $exc) 
    { 
     $db->rollBack(); 
     $response["errortext"] = "Exception: " . $e->getMessage(); 
    }  
} 
else    
{ 
    $response["errortext"] = "Couldn't start transaction"; 
} 

$response変数をJSONにエンコードし、これを取得し、ブラウザに返送されます:

error  false 
dbg1  1 
dbg2  3 
intrans1 true 
intrans2 false 
new_row_id 21 

すべてがまさにそれのように見えますnew_row_idが期待値になっていれば、自動インクリメントフィールドがティックアップされ、デバッグフィールドとトランザクション情報が期待どおりになることを意味します。

しかし、MySQL Workbenchでselect *を実行しても、プロシージャによって追加された行は返されません。 MySQL Workbenchでプロシージャ自体を動かすことはうまくいきます。コミットが実際に固執します。手順は次のとおりです。

CREATE DEFINER=`myuser`@`myhost` PROCEDURE `Layout_Row_Add`(PageId int, Position int) 
BEGIN 
    declare NewRowId int unsigned default 0; 
    update pages_layout_rows set ordinal = ordinal + 1 where page_id = PageId and ordinal >= Position; 
    insert into pages_layout_rows (page_id, ordinal) values (PageId, Position); 
    set NewRowId = last_insert_id(); 
    select NewRowId; 
END 

テーブルがInnoDBに設定されているため、トランザクションサポートが利用可能になっているはずです。私は次に何を試すべきか分からない。

+0

なぜストアドプロシージャを使用するのですか?最悪のシナリオでは、代わりにPHPにクエリを置くことができますか? – NobleUplift

+0

また、 '$ db-> commit();'の後に '$ row = $ stmt-> fetch();'を移動して、トランザクションの外に出ているものを見てください。 – NobleUplift

+0

フェッチを移動しても効果はありませんでした。ステートメントのハードコーディングは更新を行いますが、主にカプセル化のためにストアドプロシージャを使用することをお勧めします。 – varius

答えて

0

見つかった - すべての結果セットを消費しないと、トランザクションは最後にロールバックされているように見えます。ストアドプロシージャコールは、最後の結果セットとして空の結果セットを追加するので、そのようなことが起こります。

// ... 
$row = $stmt->fetch(); 
// let's consume all resultsets 
while($stmt->nextRowset() && $stmt->columnCount()); 
$sol->db->commit(); 
// ... 
関連する問題