2011-07-13 130 views
1

我有事務性應用程序,像這樣工作的:死鎖和超時打破ACID事務

try { 
    $db->begin(); 
    increaseNumber(); 
    $db->commit(); 
} catch(Exception $e) { 
    $db->rollback(); 
} 

然後是increaseNumber()內我會像這樣的查詢,這是唯一可行的功能與此表:

// I use FOR UPDATE so that nobody else can read this table until its been updated 
$result = $db->select("SELECT item1 
FROM units 
WHERE id = '{$id}' 
FOR UPDATE"); 

$result = $db->update("UPDATE units SET item1 = item1 + 1 
WHERE id = '{$id}'"); 

一切都包裹在一個交易,但最近我一直在處理一些相當緩慢查詢,並有大量的併發在我的應用怎麼回事,所以我真的不能確保查詢將按特定順序運行。

死鎖是否會導致ACID事務中斷?我有一個函數添加了一些東西,然後另一個刪除它,但是當我有死鎖時,我發現數據完全不同步,就像事務被忽略了一樣。

這是否會發生或者是其他的錯誤?

感謝,多米尼克

回答

1

ACID中的A表示Atomic,所以沒有死鎖不能導致ACID事務中斷 - 相反它會使它不會像全部或全部沒有發生一樣。如果您的數據不一致,那麼您的應用程序在邏輯單一事務中執行多個「事務」,比如:user created and account(transaction-begin ..- commit),用戶設置一個密碼(事務-begin ...-死鎖..-回滾)你的應用程序忽略了錯誤並繼續,現在你的數據庫留下了一個用戶創建的密碼。

在應用程序中查看應用程序除了回滾之外還在做什麼以及邏輯上是否有多個部分用於構建一致性數據。

+0

嘿,我已經添加了一個正在使用的查詢的例子(它只在這個地方使用,並且只是在事務中包裝)。 我認爲死鎖可能會導致事務中斷的原因是,當我發生大量死鎖時,數據在該單元表中不一致。我很困惑,因爲它只用在這一個地方......也許它是FOR UPDATE的一個問題,它允許2個人在死鎖釋放鎖時編輯數據? –

+0

當你懷疑死鎖造成不一致時,你究竟發現了哪些錯誤?據我可以從上面的代碼中知道,你只更新一條記錄,所以在ACID事務結束時,它會被更新或不更新 - 「是否」是回滾的結果。 不一致需要兩次更新才能在同一個事務中發生,其中您看到一個更新發生但沒有發生另一個更新 - 我的代碼中沒有看到類似的更新。 – Soren

+0

我有一個需要執行的任務表。如果兩個人查詢任務表,我使用FOR UPDATE來確保只有一個人執行任務。一個人可以將item1設置爲1,然後另一個人可能希望將其設置爲0.當存在死鎖時,item1的值有時可以是2,3,4,5,6,但它應該只有0或1我感覺到,當發生死鎖時,將事務設置爲0並不成功,它變爲1 + 1 = 2. –

2

好吧,如果一個事務中運行到一個鎖(從另一個事務)不會釋放,它會超時後失敗。我相信默認值是30秒。如果有人在數據庫上使用任何第三方應用程序,則應該記下這些信息。我知道一個事實,例如,SQL Manager 2007不會在InnoDB上釋放鎖,除非你從數據庫斷開連接(有時它只需要一個提交事務......以及所有事情),這會導致很多查詢在超時後失敗。當然,如果您的交易符合ACID標準,它應該全部或全部執行。只有在事務之間破壞數據時它纔會中斷。

您可以嘗試延長超時時間,但30秒鎖可能意味着一些更深層次的問題。當然,這取決於您使用的是什麼存儲引擎(通過MySQL標籤和交易,我假設InnoDB)。

您還可以嘗試打開query profiling以查看是否有任何查詢運行的時間很可笑。請注意,它確實會降低性能,因此它可能不是一個生產解決方案。

+0

嗯我沒有想到這一點。因此,如果我使用MySQL Workbench並使用行,並且我沒有在生產中提交事務,那麼我將持有一個鎖。將看看這個我猜 –

+0

你可以用'SHOW FULL PROCESSLIST'來檢查它,看看有沒有什麼可疑的。 – Naltharial