2008-12-25 87 views
1

我使用MySql 5.x並在我的環境中,我有一個名爲CALLS的表。鎖定查詢的選擇更新

表CALLS具有一個列狀態,該狀態需要一個枚舉{inprogress,completed}。

我想讀/表的更新是行鎖定,所以:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
SET AUTOCOMMIT = 0; 
SELECT amount from CALLS where callId=1213 FOR UPDATE; 
COMMIT 

基本上我即使在情況做了FOR UPDATE,由此我只需要閱讀量,並返回。我發現這允許我確保讀取/更新不會相互干擾。不過,我被告知這會降低應用程序的併發性。

有沒有辦法實現相同的事務一致性而不會產生鎖定開銷?謝謝。

回答

1

免責聲明:MySQL通常充滿了驚喜,所以以下可能是不真實的。

你在做什麼對我來說沒有任何意義:你在SELECT之後提交,應該打破鎖定。所以在我看來,你的代碼不應該帶來任何重大的開銷;但它也沒有給你任何一致性改進。

通常,SELECT FOR UPDATE可以是一種非常合理而且合理的方式,可以確保一致性,而不會佔用比真正需要的鎖更多的鎖。但是,當然,它只能在需要時才使用。也許你應該有不同的代碼路徑:一個(使用FOR UPDATE)當在後續的更改操作中使用檢索的值時使用。另一個(不使用FOR UPDATE)時,不需要保護值不受更改。

+1

我想我終於明白什麼時候需要FOR UPDATE。如果我在修改之前查詢某些列並對檢索的值做出一些決定;那麼FOR UPDATE是適當的。例如保留我自己的自動增量表。 – ashitaka 2009-01-02 09:07:55

0

您在那裏實施的內容 - 如果您不熟悉它 - 稱爲pessimistic locking。你爲了一致性而犧牲性能,這有時是一個有效的選擇。在我的職業經歷中,我發現悲觀鎖定遠不止於幫助。

首先,它可能導致deadlock

(更好的imho)替代方案是optimistic locking,其中您假設碰撞不經常發生,而您只需在發生碰撞時處理它們即可。你在交易中做你的owrk,所以碰撞不應該讓你的數據處於不一致的狀態。

這是關於optimistic locking在Java意義上的更多信息,但這些想法適用於任何事情。

+0

對錶格的修改是財務事務,不得以不一致爲結果。否則我的公司將會從中虧損。這是我使用悲觀鎖定的動機。 – ashitaka 2008-12-25 09:46:53