2014-01-17 106 views
3

我有一些使用PHP和MySQL的經驗,我知道交易但使用它們的經驗相當少。MySQL的交易時機

我正在開發一個Web應用程序,用戶將在這個Web應用程序中對單個數據庫進行各種CRUD操作。 (是的,它是InnoDB)。我很好奇,交易將如何表現,我給你一個相當簡單的例子:

1)用戶1開始事務在我的數據庫更新的John Smith名稱Johnathon Smith

2)用戶2開始一個事務右後用戶1的事務已經開始閱讀的John Smith的名字,但在提交之前。

用戶2將看到的結果是什麼? JohnJohnathon

在用戶1的交易過程中,John Smith的記錄被鎖定,還是可以在交易過程中讀取?

此外,這兩項交易的時間安排如何?用戶2的交易是否在某個隊列中等待,直到用戶1的交易完成? MySQL DB如何對多個事務嘗試訪問同一個表/記錄進行分類?

另外,假設用戶1的事務平均需要500毫秒才能完成,而用戶2的事務操作平均需要750毫秒才能完成。用戶2的響應時間有多長? 1250毫秒?

任何鏈接到相關文章或其他SO問題,非常感謝!

回答

2

它的工作原理默認方式是,用戶2看到John Smith直到用戶1提交用戶2點開始一個新交易

換句話說,默認事務隔離稱爲REPEATABLE-READ。也就是說,InnoDB假定用戶2想要查看數據庫,就像用戶2開始當前事務時那樣。即使其他人更新數據並提交更新,用戶2仍然希望看到原始數據,直到他明確刷新其對數據庫的「查看」爲止。

MySQL解決這個問題的方式是保持更新的行的兩個版本。 Johnathon Smith的「當前」版本有一個指向該行以前版本的內部指針。 InnoDB將檢查這些版本,確定用戶2是否應該能夠看到當前版本,如果沒有,請按照指向先前版本的指針。這是按行自動完成的。

用戶2的交易根本沒有理由等待,這就是「讀者不會阻止作者,反之亦然」的含義。這是多版本併發控制(MVCC)功能的好處,它在Oracle,PostgreSQL和Firebird等多種RDBMS產品中具有類似的實現。

一旦用戶1提交了他的更改,並且沒有任何事務仍在運行,需要查看以前版本的行,InnoDB有一個後臺線程逐漸清理舊版本。

這對於報告希望運行多個查詢並希望所有小計匹配的應用程序非常重要。如果後者在報告中查詢時看到數據庫的更新視圖,則可能會得到與先前查詢不同的結果。

您可以選擇更改事務隔離級別讀取已提交的,所以用戶2將自動獲得他不斷刷新數據庫的「視圖」,以查看更新的名稱Johnathon Smith(原文如此),但只有用戶1提交。如果用戶1尚未提交,則用戶2不能看到更改。

甚至可以將事務隔離級別更改爲READ-UNCOMMITTED,因此用戶2甚至可以在用戶1提交之前看到更新。但是這很少是你想要做的 - 用戶1可能會回滾,因爲Johnathon顯然是拼寫錯誤Jonathan

您可以嘗試通過打開兩個運行mysql客戶端的shell窗口來測試所有這些,並在它們之間來回跳轉,查看從一個會話到另一個會話如何顯示更改。

您將需要了解如何使用SET TRANSACTION語句更改每個會話的事務隔離級別。

參見:

+0

哇,謝謝你的詳細,非常易懂的響應!現在你提到它了,我記得有關MVCC的知識,*讀者不會阻止作者,反之亦然*規則......感謝鏈接,我不知道爲什麼我沒有想到多個shell窗戶,這將使我很容易找出自己的!請原諒我沒有正確拼寫'Jonathan'!哈哈 –

+1

我的榮幸,很高興幫助。我只是在逗你玩喬納森問題。感謝你們奉上的精神。 :-) –