2016-03-23 66 views
0

當我們在上個星期五發布時,我收到了一個我沒有接受的錯誤。該錯誤信息是:NHibernate IStatelessSession CreateQuery失敗

could not execute update query[SQL: delete from dbo.MyTable where col1=? and col2=? and col3=? and col4=? and col5=?]

我的C#代碼如下:

var hqlDelete = "DELETE MyTable m WHERE m.Col1 = :var_1 AND m.Col2 = :var_2 AND m.Col3= :var_3 AND m.Col4 = :var_4 AND m.Col5= :var_5"; 
var deletedEntities = session.CreateQuery(hqlDelete) 
          .SetString("var_1", variable1) 
          .SetString("var_2", variable2) 
          .SetString("var_3", variable3) 
          .SetString("var_4", variable4) 
          .SetString("var_5", variable5) 
          .ExecuteUpdate(); 
transaction.Commit(); 
session.Close(); 

現在,正如我所說,在接受測試時錯誤沒有觸發。另外,當我使用生產數據庫(來自我的開發人員座位的代碼)進行測試時,它的工作也沒有問題。

當我調用Web服務並向其發佈「測量」時,會觸發該代碼。唯一的區別是我在測試時調用服務,在生產時另一家公司將測量結果發送到Web服務。

我認爲這可能與會話/事務的數量有關,但這並不能解釋爲什麼變量在錯誤消息中顯示爲?

任何想法?有更多的信息可以提供,所以你可以幫助我解決這個問題嗎?

編輯:InnerExeption是

{"Transaction (Process ID 68) was deadlocked on lock | communication buffer resources with another process and has been chosen as the deadlock victim. Rerun the transaction."}

+2

首先,顯示完整的異常堆棧..上面的那部分將只是一個開始...真實和有趣的信息將遵循... –

+1

正如Radim所指出的,您的錯誤信息不足。它只是告訴它不能做什麼。通常它有一些原因。記錄異常的詳細信息,包括其「InnerException」。如果您沒有更多,請添加log4net,將其配置爲至少記錄警告和更高級別,然後NHibernate應該發佈關於失敗的詳細日誌。 –

+0

好的謝謝。我希望這是一些典型的錯誤或什麼。調試很難,因爲我必須遵循一個發佈計劃(我可以每個月發佈一次),因此只能接受測試。所以即使添加log4net,我也要等一個月才能看到錯誤。 – Tjab

回答

1

解決死鎖可以使用ORM尤其是很難的事,。通常會發生死鎖,因爲不同的進程(或線程)以相同的順序獲取數據庫對象的鎖,導致它們相互等待。

ORM不會給你很大的控制鎖定順序。您可以重新安排您的查詢排序,但這可能很乏味。特別是當緩存導致其中一些不擊中DB時。此外,應該使用相同的數據庫在任何其他應用程序上進行相同的排序。

您可能會檢測到死鎖錯誤並執行消息所說的內容:重試整個過程。使用NHibernate,這意味着放棄當前會話並重試整個工作單元。

如果您的數據庫是SQL Server,則會有一個默認設置,極大地增加了死鎖風險:禁用read committed snapshot mode。如果它在數據庫上被禁用,則可以通過啓用它來大大減少死鎖風險。此模式允許在讀取提交隔離級別下的讀取停止發出讀取鎖定。

您可以檢查此設置

select snapshot_isolation_state_desc, is_read_committed_snapshot_on 
    from sys.databases 
    where name = 'YourDbName' 

您可以啓用此設置與

alter database YourDbName 
    set allow_snapshot_isolation on 

alter database YourDbName 
    set read_committed_snapshot on 

這需要在目標數據庫有沒有運行的事務。當然,這需要DB上的管理員權限。

在我沒有選擇更改此設置的應用程序中,我不得不採取更古怪的方式:將NHibernate默認隔離模式(connection.isolation configuration parameter)設置爲ReadUncommitted。我的應用程序大部分是隻讀的,並且我在幾個必須讀取然後寫入數據的事務上(例如使用session.BeginTransaction(System.Data.IsolationLevel.ReadCommitted))明確提升隔離模式。

您還應該檢查所有使用數據庫的應用程序當前使用的隔離模式:其中一些使用的隔離級別高於實際需要的隔離級別嗎? (如果可能,應避免使用RepeatableReadSerializable)。這是一個耗時的過程,因爲它需要很好地理解隔離級別,同時研究每個用例以確定什麼是適當的最小隔離級別。

+0

謝謝你非常詳細的答案!提交的快照隔離/讀取確實設置爲false/0,並且我不知道這個設置。 – Tjab

+1

我忘記了關於讀取提交快照模式的一點:它會導致更多的tempdb空間使用。你的DBA應該知道它。 –

+0

嗯,那我也需要注意這一點。數據庫本身非常龐大,目前在1個表中談論將近4億條記錄...不知道它是'表/ db越大,tempdb空間使用得越多',但如果是這樣的話。 :) – Tjab

相關問題