2011-11-16 77 views
0

快速問題/澄清需要在這裏。我有一個很可能同時更新記錄的數據庫表。我爲應用程序使用了Zend Framework,並且我已經閱讀了兩個避免這種情況的方向,第一個是鎖定表(LOCK TABLES test WRITE)或類似的東西,將返回並重新讀取如何完全執行它這是最好的解決方案。第二個事務是:$ db-> beginTransaction(); ... $ db-> commit();MySQL事務與鎖定

現在假設我正在使用諸如InnoDB之類的事務性存儲引擎,事務似乎是更常見的解決方案。然而這是否避免以下情形:

用戶A在網頁上 - >數據提交 - >開始交易 - >逐行讀取 - >計算新價值 - > update行 - >保存 - >提交

用戶B同時在同一個網頁上並同時提交數據,現在我們只是說它幾乎是同時發生的(用戶B在開始事務和提交用戶A事務之間的點處調用更新函數)用戶B依賴於來自用戶A的交易的承諾數據才能實現更新記錄的準確計算。

IE:在數據庫行

開啓值:5用戶A提交的5的值(開始 交易 - >讀值(5) - >添加提交的值(5 + 5 = 10) - >寫 的更新值 - >保存 - >提交)

用戶B提交的值爲7.我需要確保 用戶B的事務讀取值爲10,而不是5(如果更新在閱讀之前沒有完成 )。

我知道這是一個冗長的解釋,我很抱歉,我不完全確定正確的術語來簡化問題。

謝謝

+1

你可以通過像'UPDATE table SET value = value + 5'這樣的事情逃脫嗎?然後交易不是必需的。 –

+0

這可以工作,會讓我的生活變得容易。只有一個問題可能會遇到。我進行更新,然後第二個會話在讀取值之前進行更新,並且我需要將正確的值發送回原始用戶。所以這將是一個更新,然後選擇檢索當前的'價值'。在閱讀發生之前會厭惡第二次更新,那麼返回的結果將是無效的(或者我是不正確的)。我擔心的原因是數據必須在更新並返回給用戶時100%保證正確。 –

+0

我不認爲你可以100%正確。即使您確保讀取了正確的值,但您發送給用戶並釋放鎖定的時刻即可過期。除非您有一個接收實時數據庫更新的事件驅動系統,否則您不能保證具有當前值。 (即使那樣,可能會有明顯的延遲。) –

回答

0

事務不確保鎖定。事務中的整個塊被視爲對db的原子更新(如果在此塊的所有先前更改之間有任何失敗,則爲回滾)。所以,並行運行的兩個事務可以更新同一行。

您需要同時使用兩者。

Transaction do 
row.lock 
update row 
end 

看到,如果行級鎖定可以使它更容易爲你。

+0

我打算接受這個答案純粹是基於它回答我的原始(快速版)的問題是「交易是否能防止競爭條件」,答案是否定的。我認爲@MichaelMior的評論幫助我從不同的角度看待了我的問題,並提供了更可行的解決方案。所以,謝謝你們倆/和平! –