2016-09-02 26 views
1

問題:mysqli_begin_transactionとMySQLのストアドプロシージャでデータを保存するためにmysqli_commitは、select文が追加されたときに失敗し

できません。

詳細:

次のコードは、mysqlのストアドプロシージャを使用して簡単なinsertselectを行います。コードはで、select文なしで正常に実行されます。しかし、selectステートメントが追加されると、クエリーがPHP側で成功を返しても、データをコミットしません。

スニペット(PHP):

$DB_DRRM_SQLI = mysqli_connect("localhost","root","", "sandbox_db"); 
mysqli_begin_transaction($DB_DRRM_SQLI); 

$SQL_QUERY_CODE = "CALL SANDBOX_TEST()"; 
$DB_QUERY = mysqli_query($DB_DRRM_SQLI, $SQL_QUERY_CODE); 


// ERROR REPORTING 
if($DB_QUERY === false) 
{ 
    echo mysqli_error($DB_DRRM_SQLI); 
    mysqli_rollback($DB_DRRM_SQLI); 
} 
else 
{ 
    echo 'success'; 
    mysqli_commit($DB_DRRM_SQLI); 
} 
exit; 

スニペット(MySQLのストアドプロシージャ):

BEGIN 
    INSERT INTO 
    `sandbox_table` 
    (
     `SOME_STRING` 
    ) 
    VALUES 
    (
     'ABCDEFGHIJKL...' 
    ); 

    SELECT 
     LAST_INSERT_ID() AS INSERTED_ID, 
     'ABCDE...' AS OTHER_PARAMS; 
END 

データベース(表sandbox_table):

  1. RECORD_PRIMARY_ID(のInt - オートインクリメント
  2. SOME_STRING(varchar型 - 500長

仕様:

  • PHPバージョン:5.6.14
  • 10.1.8- MariaDB
  • ストレージエンジン:InnoDB

注:

  • トランザクションは、ストアドプロシージャで行われている場合は正常に動作しますが、私は、クエリの結果に応じて、複数のクエリ要求と応答を処理するためにPHP管理のトランザクションを必要としています。
  • (私は、ストアドプロシージャに全体のPHPコードを変換する必要があり、パラメータのトンを渡す必要がある他の解決策は、ありませんならばそれは可能最後することができます)動作確認済み

方法:

  • 他のPHPバージョン7.0.9と同じ結果(10.1.16-MariaDB)を試しました
  • sandbox_table以上のストアドプロシージャを除く他のデータがない新しいデータベースでテストされています。
  • 追加のインクルードライブラリなしでテストされています(純粋に上のスニペットでテスト済み)。
+0

はどのようにmysqliのが失敗したコミットことを知っていますか? –

+0

ストアドプロシージャ自体でトランザクション処理をしないのはなぜですか? – Shadow

+0

@あなたの常識 'sandbox_table'ではレコードを保存しません。このサンプルでは、​​' SOME_STRING'フィールドに文字列 "ABCDEFGHIJKL ..."を1つ追加する必要があります。 – FrozenFire

答えて

0

ソリューション:

それはmysqli_commitで同期エラーのうち、コマンドによって引き起こされました。 mysqliは、上記のストアドプロシージャにselectステートメントを追加すると、クエリが開いている間にトランザクションをコミットすることを許可しません。

これを処理するには、最初にクエリを閉じるか、クエリをバッファに入れる必要があります。

スニペット(PHP):

// SQL Database 
$DB_DRRM_SQLI = mysqli_connect("localhost","root","", "sandbox_db"); 
mysqli_begin_transaction($DB_DRRM_SQLI); 

$SQL_QUERY_CODE = "CALL SANDBOX_TEST()"; 
$DB_QUERY = mysqli_query($DB_DRRM_SQLI, $SQL_QUERY_CODE); 

// ERROR REPORTING 
if($DB_QUERY === false) 
{ 
    echo mysqli_error($DB_DRRM_SQLI); 
    mysqli_rollback($DB_DRRM_SQLI); 
} 
else 
{ 
    // Must free current query result before committing transaction 
    @mysqli_free_result($DB_QUERY); 
    @mysqli_next_result($DB_DRRM_SQLI); 

    if(mysqli_commit($DB_DRRM_SQLI) === false) 
    { 
     echo mysqli_error($DB_DRRM_SQLI); 
    } 
    else 
    { 
     echo 'success'; 
    } 
} 
exit; 
関連する問題