2017-01-15 20 views
1

我有一個使用LMDB的應用程序。如果多個進程需要寫入數據庫,則一次只允許一個進程運行,其餘的進程將被阻止。正因爲如此,我想重寫應用程序以使用客戶機 - 服務器模型。LMDB:回滾事務而不回滾所有內容

如果應用程序編寫爲使用客戶端 - 服務器模型,則服務器可以管理寫入,而其他進程不會阻止。但是,如果客戶端遇到錯誤並且必須回滾事務,那麼它如何回滾其數據而無需回滾其他客戶端寫入的內容?

我看過嵌套事務,但寫入事務可能只有一個嵌套事務。因此,儘管客戶端可以將其數據寫入嵌套事務並在發生錯誤時將其回滾,但一次只能運行一個客戶端。因此,儘管解決了回滾問題,但我們又回到了一次只有一個客戶端可以寫入的問題。

我也看了一下MDB_NOLOCK選項,這會導致LMDB不會阻止您創建多個寫入事務。當您嘗試提交除第一個事務之外的任何事務時,它將返回一個錯誤。也許客戶可以把他們的寫入彙集到他們自己的事務中,當他們準備提交時,服務器將把這些條目轉儲到第一次寫入事務中,但這很冒險,我確信這不是開發人員想要的被用於。

我能想到的唯一的另一個解決方案是將客戶端保存在一個單獨的數據庫中,這就解除了切換到客戶端 - 服務器模型的全部目的。

有沒有其他方法可以讓不同的進程寫入數據庫,同時能夠回滾一個客戶端的數據而不需要回滾一切?

回答

0

對您提出的挑戰沒有簡單的解決方案。

可以任意深度嵌套寫入事務,但正如您所說,不能幫助您實現更好的吞吐量,因爲您仍然僅限於該寫入事務的一個線程。因此,對於大多數意圖和目的,如果您將LMDB設計爲使用LMDB,則只會有一個線程在數據庫上執行寫操作。

您問過如何在不回滾其他人的txn的情況下中止某人的交易。這在很大程度上不是問題,因爲如上所述,您將只有一個寫事務處於活動狀態。如果您在請求結束時提交併在下一個請求開始時啓動新的事務,則您的寫入事務不會重疊。一旦你提交了第一個事務,你將無法中止它,但是如果你的客戶端通知服務器在提交之前中止請求,你的服務器可以中止它。並且當它中止時,數據庫狀態將採取它在該事務開始時的狀態。它不會丟失任何其他交易,也不會丟失其他請求創建的更改。

正如您所指出的,您可以將一些寫入請求批量寫入單個寫入txn。您可以在其他線程中處理其中一些寫入請求,但全部 LMDB API調用仍必須在原始線程中完成。如果您嘗試將線程專用於每個請求以實現某種並行性,您仍然需要確保請求是相互兼容的並且不會相互干擾。如果其中一個請求遇到麻煩,則必須中止事務並可能重新啓動事務。當您重新啓動事務時,您可能只包含沒有遇到麻煩的請求。 - 這一切都是可能的,但只有您對您的應用程序有足夠的瞭解才能知道這是否會提高性能並值得您付出努力。