2013-04-11 67 views
1

我有一個使用ReadCommitted Isolation的NHibernate MVC應用程序。如何防止NHibernate長時間運行的進程鎖定網站?

在網站上,用戶可以啓動一個特定的過程,根據輸入可能需要幾分鐘的時間。這是因爲會話是按請求進行的,並且整個時間都是打開的。

不過,雖然在運行,其他用戶不能訪問該網站(他們可以嘗試,但除非長時間運行的是完成他們的要求不會通過)

更重要的是,我也有一個需要有一個控制檯應用程序也可以在連接到同一個數據庫時執行這個長時間運行的功能。它造成同樣的問題。

我不確定我的設置有哪部分是錯誤的,任何反饋將不勝感激。

NHibernate設置了流暢的配置和StructureMap。

  • 隔離級別設置爲ReadCommitted。
  • 會話工廠的生命週期是HybridLifeCycle(這在網絡上應該是每個請求的會議,但對勝利的控制檯應用程序將ThreadLocal的)
+0

可以長時間運行的過程中向下削成成代碼工作的小戶型您的系統的要求是什麼? – Rippo 2013-04-12 07:48:52

+0

@Rippo我可以修改可以在較小的塊中工作,但我仍然不知道如何處理或使用會話(單元工作)。無論我的代碼如何分解,它始終是一個巨大會話的一部分。我不能(不知道如何)結束一個會話/在一個進程內啓動一個新的會話 – TheFabledOne 2013-05-13 21:19:43

+0

您是否使用會話請求模式?我傾向於在我的MVC控制器上爲此模式使用actionfilter。然後這讓我可以在單個actionrequest上擁有迷你UOW – Rippo 2013-05-14 08:37:28

回答

5

這聽起來像您的要求是在數據庫鎖等待。您的選項確實是:

  1. 將長時間運行過程分解爲一系列較小的事務。
  2. 大部分時間使用ReadUncommitted隔離級別(這適用於很多用例)。
  3. 明智地使用快照隔離級別(假設您使用的是MS-SQL 2005或更高版本)。

(NB我假設長期運行的功能做了很多的讀/寫的和被封鎖的要求主要是做閱讀。)

+0

我認爲,「將長期運行過程分解爲一系列較小的交易」是更可取的解決方案。 – 2013-09-11 14:14:01

+0

問題是我不知道如何將問題分解爲更小的交易。我能找到的唯一代碼示例是每個HTTP會話或進程都有一個單獨的會話/事務(例如,控制檯應用程序正在運行,直到關閉纔會有一個會話)我不知道如何保持控制檯應用程序打開並創建新的會話。第一個關閉後,我無法打開一個新的。我認爲這與StructureMap設置有關,但我盡力而爲。我嘗試將LifeCycle設置更改爲沒有運氣的一切。 – TheFabledOne 2013-09-11 21:04:08

+1

會話不等於事務。使用如下代碼:'使用(var trx = session.BeginTransaction()){/ *做一些工作*/trx.Commit(); }' – 2013-09-12 15:08:15

1

另一種,但更復雜的解決辦法是:

您建立運行於一臺機器後臺機器人應用

  • 此背景工人機器人可以收到「工人的工作」(一個由用戶發起)
  • 然後,機器人加工的作業在後臺步驟&一步

陷阱是: - 你必須將程序這個機器人非常穩定 - 你需要看機器人莫名其妙

當然,這涉及更多的工作 - 另一方面,您可以選擇集成更多的工作類型,使您的系統能夠在後臺處理不同的事情。

1

我認爲您的應用程序/ SQL語句的設計存在問題,除非您是Facebook我不認爲應該一直採用任何過程,最好是檢查您的設計並檢查瓶頸在哪裏,而不是試圖讓這個漫長的過程繼續下去。

還有些時候ORM對每個場景都不好,您是否嘗試使用SP?

3

如前所述,將您的流程分解爲多個較小的事務可能是解決方案。

我建議看看像Rhino Service Bus或NServiceBus(我的首選是犀牛服務總線 - 我發現它更簡單的個人工作)。允許你做的是將功能分成小塊,但保持交易性質。從本質上說,通過服務總線,您發送消息來啓動一項工作,這項工作將在分佈式事務中進行,並接收消息,因此如果出現問題,消息不會消失,從而讓系統處於潛在的不一致狀態。

根據您需要做的事情,您可以發送初始消息以開始處理,然後在每個步驟後發送新消息以啓動下一步。這確實可以幫助將事務分解成更小的工作(並簡化代碼)。我提到的兩個服務總線(也有Mass Transit)也有類似內置重試和錯誤處理的東西,所以如果出現問題,消息最終會出現在錯誤隊列中,您可以調查出錯的地方,希望修復它並重新處理消息,從而確保您的系統保持一致。

當然,這是否是必要的取決於:)