我意識到,MongoDB本質上並不會支持這些類型的事務。但是,我發現我確實需要以一種有限的方式使用它們,所以我想出了以下解決方案,我想知道:是這樣做的最好方式,它可以改進當?(之前我去應用它在我的應用程序!)MongoDB中的多文檔'交易'
很顯然,交易是通過應用程序(在我的情況下,一個Python網絡應用程序)控制。對於在本次交易(任何集合)每個文檔,下面的字段添加:
'lock_status': bool (true = locked, false = unlocked),
'data_old': dict (of any old values - current values really - that are being changed),
'data_new': dict (of values replacing the old (current) values - should be an identical list to data_old),
'change_complete': bool (true = the update to this specific document has occurred and was successful),
'transaction_id': ObjectId of the parent transaction
此外,還有一個transaction
集存儲文件,詳細說明進度每一筆交易。他們看起來像:
{
'_id': ObjectId,
'date_added': datetime,
'status': bool (true = all changes successful, false = in progress),
'collections': array of collection names involved in the transaction
}
而這裏是過程的邏輯。希望它能夠以這種方式工作,如果它被中斷或者以其他方式失敗,它可以被正確地回滾。
1:設置一個transaction
文檔
2:對於每個由該事務受影響的文檔:
- 設置
lock_status
到true
(到 '鎖定' 從作爲文件修改) - 將
data_old
和data_new
設置爲其舊值和新值 - 設置
change_complete
到false
- 設置
transaction_id
到的ObjectId的transaction
文件的,我們只是做
3:執行更新。對於每個受影響的文檔:
- 與
data_new
值替換該文件中任何受影響的領域 - 設置
change_complete
到true
4:將transaction
文檔的status
到true
(所有數據已成功修改)
5:對於受交易影響的每個文檔,做一些清理:
- 刪除
data_old
和data_new
,因爲他們不再需要 - 設置
lock_status
到false
(解鎖文件)
6:取出transaction
文件在步驟1中設置(或所建議的,將其標記爲已完成)
我認爲邏輯上是這樣工作的,如果它在任何時候都失敗了,所有的數據都可以回滾或者事務可以繼續(取決於你想要做什麼)。顯然所有的回滾/恢復/等。由應用程序執行,而不是數據庫,通過使用transaction
文檔和其他集合中具有該transaction_id的文檔來執行。
這個邏輯中有沒有明顯的錯誤,我錯過了或忽略了?是否有更有效的方法來處理它(例如,從數據庫中寫入/讀取較少)?
'DBrefs'建議很好。但是,這種兩階段提交方法是否可以與多個文檔一起工作(不會混亂?) - 在我的場景中,我需要同時更新一個集合中的一個文檔和另一個集合中的n個文檔(數量不盡相同)。 – johneth
我想你也可以添加DBrefs的數組。 – jsalonen
我會接受你的建議,而不是刪除交易文件。在文檔到文檔的基礎上,保證事情發生了預期的改變,這是通過使用'change_complete'字段完成的。 – johneth