2012-06-19 83 views
-1

我想知道在以下假設情況下會發生什麼情況。假設兩個老師給同一個學生完全相同的課程,他們都想更新學生的,bob的成績。鮑勃現在的平均水平是60%,教師1想要通過測試來更新他的平均水平,他得到了70%,而老師2想要通過測試來更新他的平均水平,他得到了40%。2位用戶同時更新記錄

因此,在兩位教師同時打開更新按鈕的1百萬次的機會中,恰恰在同一時間恰好到達分秒,會發生什麼?它會給出一個錯誤消息,PHP或MySQL奇蹟般地排隊更新,只有第一個分數更新鮑勃的平均值,第二個用戶會得到一個錯誤?

編輯:我擔心的是第二個用戶必須在第一個用戶編輯值後獲得值,我正在考慮提取記錄,然後在php中進行計算,然後再次更新記錄,但在這種情況下我可以確保第二位用戶獲取65%而不是60%的值,這可以通過交易完成嗎?

+2

使用交易!在MySQL世界裏,InnoDB支持完整的ACID,在這裏閱讀更多信息http://dev.mysql.com/doc/refman/5.0/en/ansi-diff-transactions.html –

+0

http://en.wikipedia.org/wiki/ACID – mithunsatheesh

+0

交易在提交給它們之前排隊查詢嗎? – grasshopper

回答

2

兩者都將通過,最後一個將被處理將是新的價值。由於數據庫系統的一致性保證,您不會得到損壞的數據,但由於這是一個計算值,因此您可能會得到錯誤的數據。

我懷疑這個平均值是基於其他表中數據的計算值。如果是這種情況,請在一次交易中完成所有工作。將新的測試分數添加到表中,並讓數據庫計算平均值並將結果直接插入到第二個表中。這樣,或者結果將保證是正確的交易將失敗。這需要具有事務支持的存儲引擎(例如InnoDB)。

1

數據庫將按順序更新該行。其中一個查詢將首先運行,鎖定行(或有時表 - 根據查詢),下一個查詢將排隊,直到第一個查詢完成。

3

它們不能運行在同一時間的動作,總是會有一個小的差異,因爲它在物理上是不可能的機器寫在同一時間相同的信息。可能是微秒或更小的問題,但差異將在那裏。

一個通常的解決辦法是添加在您的WHERE條款這樣的數據,並檢查更新是否已經完成:

UPDATE students SET `avg` = '70' WHERE id=<some-id> AND `avg` = '60'; 

然而,像均線東西通常最好不要更新這種方式:有一個單獨的學生成績表,並且自己計算每個學生的這些記錄的平均值(如果你願意,你仍然可以'緩存'它在學生表中)。

1

悲觀鎖定和交易只是這裏故事的一半。數據庫將取出一個行鎖,但這隻能確保任何嘗試修改同一行的人都必須等到當前事務完成。我想要阻止的情況是:

  1. 老師a認爲作業並沒有評分。
  2. 老師b查看作業,沒有評分。
  3. 老師一個分配級70
  4. 教師b分配等級40

這很可能是b並不意味着來覆蓋。你最好的保護是某種形式的樂觀鎖定。當兩個人同時進行編輯時,你會在維基上看到這一點。後面的提交者必須確認編輯,因爲它可能會意外地顛倒較早的提交者的更改。在評分情況下,您可以在where子句中添加顯示給用戶的舊成績,然後聲明更新更改了一行。

UPDATE GRADES SET SCORE=70 WHERE NAME='Jim' AND SCORE=0;