2014-09-25 57 views
1

我有一個系統每秒處理很多查詢。我使用mysqlPHP編碼我的系統。記錄在交易過程中被刪除

我的問題是mysqli交易仍然提交交易甚至記錄被其他用戶同時刪除,我所有的表都使用InnoDB

這是我如何與mysqli的代碼我的交易:

mysqli_autocommit($dbc,FALSE); 
$all_query_ok=true; 

$q="INSERT INTO Transaction() VALUES()"; 
mysqli_query ($dbc,$q)?null:$all_query_ok=false; 

$q="INSERT INTO Statement() VALUES()"; 
mysqli_query ($dbc,$q)?null:$all_query_ok=false; 

if($all_query_ok==true){ 
    //all success 
    mysqli_commit($dbc); 
}else{ 
    //one of it failed , rollback everything. 
    mysqli_rollback($dbc); 
} 

下面是由其他用戶在其他腳本的同時執行,然後最終搞亂預期的系統行爲的查詢,

$q="DELETE FROM Transaction..."; 
mysqli_query ($dbc,$q)?null:$all_query_ok=false; 

請指教,我是否錯誤地執行了交易?我已閱讀關於行級鎖定,並相信innoDB在交易過程中鎖定記錄

+0

您可以使用['的mysqli :: begin_transaction'(http://php.net/manual/de/mysqli.begin-transaction.php) – TiMESPLiNTER 2014-09-25 08:46:42

+0

@TiMESPLiNTER做到這一點具有mysqli_autocommit任何區別()? – 2014-09-25 08:48:50

+0

'mysqli_autocommit()'只是定義了您執行的查詢是否在執行後立即提交。所以你必須關閉它(就像你已經在上面的代碼中那樣)來使用事務。 – TiMESPLiNTER 2014-09-25 08:52:07

回答

1

我做了行級鎖的一些研究,可以從刪除的後鎖定記錄或更新

FOR UPDATE

Official Documentation

權開始交易我必須選擇那些我想鎖定的記錄如下

SELECT * FROM Transaction WHERE id=1 FOR UPDATE 

這樣記錄將被鎖定,直到transaction end

這種方法不上的MyISAM類型表

2

我不知道你在談論哪種交易,但是使用mysqli擴展我使用以下方法來處理交易:

那麼這個過程是這樣的:

  1. 開始與mysqli::begin_transaction
  2. 一個新的事務執行SQL查詢
  3. 在成功使用mysqli::commit確認在步驟2 OR上的錯誤執行過程中您的疑問所作的更改您在第2步中的查詢使用mysqli::rollback來恢復他們所做的更改。

您可以將事務視爲您的查詢的臨時緩存。它與PHP的輸出緩存類似,具有ob_*函數。只要你沒有刷新緩存的數據,屏幕上就沒有任何反應。與交易相同:只要您沒有提交任何內容(並且自動提交被關閉),數據庫中就不會發生任何事情。

0

工作看起來像的race condition一個典型的例子。您執行兩個並行腳本並行修改數據。您的第一個腳本可能成功插入記錄並提交事務,第二個腳本可能會成功刪除記錄。但我不確定你的意思是「其他用戶在其他腳本中同時執行的查詢」。

0

你將不得不這樣這樣做:

mysqli_autocommit($dbc,FALSE); 

$dbc->begin_transaction(); 

$all_query_ok=true; 

$q="INSERT INTO Transaction() VALUES()"; 
mysqli_query ($dbc,$q)?null:$all_query_ok=false; 

$q="INSERT INTO Statement() VALUES()"; 
mysqli_query ($dbc,$q)?null:$all_query_ok=false; 

if($all_query_ok==true){ 
    //all success 
    mysqli_commit($dbc); 
}else{ 
    //one of it failed , rollback everything. 
    mysqli_rollback($dbc); 
} 

您可以使用或面向對象的調用begin_transaction當程序風格(我更喜歡面向對象的)。