Robimy znaczne wykorzystanie Entity Framework w bazie danych pierwszego modelu z Entity Framework 6 i SqlSever 2012.Entity Framework Blokady i współbieżność
Mamy szereg dość długich procesów biegania (10-tych sekund), którą każdy Utwórz obiekt tego samego typu z różnymi danymi, które te obiekty w trakcie tworzenia zapisują i usuwają dane w bazie danych za pomocą struktury encji. Jak na razie dobrze. W celu poprawy wydajności aplikacji Szukamy uruchamia te operacje równolegle i jako taki jest używany Task
konstrukt do achive to w następujący sposób:
Private Async Function LongRunningProcessAsync(data As SomeData) As Task(Of LongRunningProcessResult)
Return Await Task.Factory.StartNew(Of LongRunningProcessResult)(Function()
Return Processor.DoWork(data)
End Function)
End Function
prowadzimy 10 z nich i czekać na nich wszystkich do wypełnić drukowanymi Task.WaitAll
Class Processor
Public Function DoWork(data As SomeData) As LongRunningProcessResult
Using context as new dbContext()
' lots of database calls
context.saveChanges()
end Using
' call to sub which creates a new db context and does some stuff
doOtherWork()
' final call to delete temporary database data
using yetAnotherContext as new dbContext()
Dim entity = yetAnotherContext.temporaryData.single(Function(t) t.id = me.Id)
yetAnotherContext.temporaryDataA.removeAll(entity.temporaryDataA)
yetAnotherContext.temporaryDataB.removeAll(entity.temporaryDataB)
yetAnotherContext.temporaryData.remove(entity)
' dbUpdateExecption Thrown here
yetAnotherContext.SaveChanges()
end using
End Function
End Class
to działa dobrze ~ 90% czasu pozostałe 10% to zakleszczenia serwer bazy danych z wewnętrzną wyjątkiem dodatkowego blokowania
wszystkie procesory wykorzystują te same tabele ale nie udostępniaj absolutnie żadnych danych między procesami (i nie zależą one od tych samych wierszy FK) i twórz wszystkie własne struktury ramek encji bez interakcji współdzielonej między nimi.
Przeglądanie zachowania profilowania instancji Sql Server
Widzimy dużą liczbę bardzo krótkich przejęć i uwolnień blokady między każdym pomyślnym zapytaniem. Prowadzące do ewentualnego łańcucha impasu:
Lock:Deadlock Chain Deadlock Chain SPID = 80 (e413fffd02c3)
Lock:Deadlock Chain Deadlock Chain SPID = 73 (e413fffd02c3)
Lock:Deadlock Chain Deadlock Chain SPID = 60 (6cb508d3484c)
The zamki sami są typu KEY
i zapytania deadlocking są w tej samej tabeli, ale z różnych kluczy postaci:
exec sp_executesql N'DELETE [dbo].[temporaryData]
WHERE ([Id] = @0)',N'@0 int',@0=123
Mamy stosunkowo nowy do struktury encji i nie są w stanie zidentyfikować głównej przyczyny tego, co wydaje się zbyt dużym blokadom (nie jestem w stanie zidentyfikować za pomocą narzędzia profilowania sql wierszy, które są blokowane).
EDIT: deadlock.xdl
EDIT2: Wywoływanie saveChanges
po każdym oświadczenie remove usuwa impasu nadal nie bardzo rozumiem dlaczego został deadlocking
Czy masz dostępny plik xdl? Jeśli tak, sprawdź poziom izolacji transakcji dla każdego z zaangażowanych procesów. Stawiałbym pieniądze na pączki, że przynajmniej jeden z nich jest ustawiony na "serializowalny". –
isolationlevel = "przeczytaj zatwierdzone (2)" dla wszystkich – user2732663
Wygląda na to, że przegrałem ten zakład. :) Czy umieścisz plik XDL gdzieś do analizy? –