2011-07-20 29 views
2

我有一些(PHP)代碼在InnoDB表上執行關鍵更新。我可以繞過MySQL中的當前事務嗎?

我正在使用(SELECT ... FOR UPDATE),所以我需要在事務中。

當從表單發佈數據時,此代碼正在執行,並且我有一個消息系統,以便將錯誤/成功消息存儲在數據庫中,並在下次頁面呈現時從數據庫中提取。

一些僞代碼: (我ommitting的東西,如try/catch塊和逃避,我在我真正的代碼)

beginTransaction(); 

query("SELECT * FROM `table` WHERE id=1 FOR UPDATE"); 

$x=$_POST[$x]; 
query("UPDATE `table` SET `field` = $X"); 

//add other data in the db related to $X 
query("INSERT INTO `othertable` (x,y,x) VALUES (......)"); 


//check for various errors... 
$erros=0 

if ($error_condition_1) { 
    messageSystem("Error Condition 1!") 
    $errors+=1; 
} 
if ($error_condition_2) { 
    messageSystem("Error Condition 2!") 
    $errors+=1; 
} 

if ($errors) { 
    rollBackTransaction(); 
} else { 
    commitTransaction(); 
} 

的問題應該是顯而易見的:當messageSystem存儲錯誤的數據庫的更改將稍後回滾,並且用戶將永遠不會看到錯誤消息。

有兩個簡單的解決方案,我可以看到:

  1. 修改我的代碼,以便messageSystem被稱爲事務之外。但是,如果我可以像上面那樣內聯,它的可讀性和編寫速度更快。另外,如果這是可能已經在嵌套事務中的庫代碼呢?
  2. 修改messageSystem,以便它使用自己的連接到數據庫。但是,如果我使messageSystem更復雜,並決定在將消息添加到該會話之前需要鎖定session表中的條目,該怎麼辦?這可能會導致死鎖,如果我的主代碼也出於某種原因鎖定了會話。
  3. 在交易前檢查錯誤。但實際上我需要鎖定相關的行,方法是在之前選擇'FOR UPDATE'我可以驗證輸入。

所以我的問題:有沒有辦法在一個(可能是嵌套的)事務中提交X,以至於如果事務回滾了,X仍然會被提交。

另外,是否有避免我所描述的問題的任何好方法。

謝謝!

回答

2

簡單的答案是使用第二個數據庫連接進行錯誤記錄。

+0

是的,這是我目前的解決方案,也許是最好的選擇(+1),但我真的想知道是否有其他方法。 – DaedalusFall

+0

你應該假定每個連接都是爲了自己的特定目的,這樣事務隔離才能正常工作。如果你需要使用數據庫的原因不同(在這種情況下記錄),使用其他連接是正確的方式。 – mikebabcock

+0

明智的分離,我認爲你適合這種情況。但是當它變得更復雜時呢?我已經有一個外鍵約束從我的消息表到我的會話表(所以剩下的消息會在會話消失時被刪除)。在上面的代碼中會話可以被刪除。我可以處理這個問題,但是分離已經不是100%乾淨了。我對備選答案感興趣,所以我可以在更復雜的情況下處理它,但情況可能不會那麼好。對不起,這麼長的評論。 – DaedalusFall

相關問題