Laden...

Zugriff auf die durch eine Transaction gesperrten Daten

Erstellt von alexander_ vor 14 Jahren Letzter Beitrag vor 14 Jahren 2.886 Views
A
alexander_ Themenstarter:in
15 Beiträge seit 2009
vor 14 Jahren
Zugriff auf die durch eine Transaction gesperrten Daten

verwendetes Datenbanksystem: <SQL Express 2008>
VS 2008 C# mit LINQ to SQL

Hallo,
ich habe folgendes Problem.

Mein Programm besteht aus einem UI und einem Background Thread.

Der Background schreibt kontinuierlich Messdaten in die Datenbank (Messdaten Tabelle) (Dies habe ich über eine Transaction gelößt).

Auf der UI hat der User die Möglichkeit sich die Messdaten anzeigen zu lassen.

Allerdings kann er die Daten nicht anzeigen während die Transaction offen ist.

Ich hätte gerne, dass aus der MessdatenTabelle alle Daten angezeigt werden, die nicht von der Transaction betroffen sind.
Wenn ich aber die Tabelle abfrage laufe ich nur in ein Timeout...

Gibts eine Möglichkeit in der LINQ Abfrage zu sagen, er soll nur nicht gesperrte Daten ausgeben?

Dank für alle Hilfe
Alexander

Brot kann schimmeln - ich kann nichts!

1.564 Beiträge seit 2007
vor 14 Jahren

Hallo Alexander

Standardmäßig werden nur die Zeilen gelockt die neu geschrieben oder aktualisiert werden. Wenn deine Abfrage diese Daten nicht beinhaltet sollte normalerweise ein Ergebnis zurückgeliefert werden. Ausnahme ist hierbei jedoch Lock Escalation. Hier ein Artikel von Adam Machanic zu dem Thema:
SQL Server 2008: Lock Escalation, INSERTs, and a Potential Bug

Ansonsten gäbe es theoretisch(!!!) die Möglichkeit mit SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED zu arbeiten. Davon rate ich aber dringendst ab!

Der einfache korrekte Ansatz wäre hier einfach den Background Thread nicht die ganze Zeit mit der gleichen Transaktion arbeiten zu lassen sondern diese alle paar Sekunden zu comitten. Damit kann das parallel abgesetzte SELECT zurückgeliefert werden und alles ist valide.

Ein anderer Weg wäre den Background Thread in eine Staging-Tabelle statt in die eigentliche Zieltabelle schreiben zu lassen und die Daten erst am Ende über eine Bulk-Operation in die Zieltabelle zu übertragen.

Frage:
Welche Datenmengen importiert der Background Thread denn, dass der so lange braucht?

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

A
alexander_ Themenstarter:in
15 Beiträge seit 2009
vor 14 Jahren

...die Daten kommen von einer Messmaschine, wobei an dieser nicht exakt die Dauer einer Messfahrt definiert ist.

Eigentlich wollte ich die Transaction nutzen, damit nicht vor dem Ende der Messung auf die zugehöirgen Daten zugegriffen werden kann.

Wonach könnte ich die Abfrage filtern, damit nicht die Daten, die momentan geschrieben werden (gesperrt sind), Teil der Abfrage sind.
Ich weiss ja nicht auf welche Datensätze geschrieben wird...

Grüsse
Alexander

Brot kann schimmeln - ich kann nichts!

1.564 Beiträge seit 2007
vor 14 Jahren

Hallo Alexander

Kommt drauf an. Wie schon gesagt, vielleicht einfach mit einer Staging-Tabelle arbeiten.

Je nach Menge der Daten kannst du die in dem Worker-Thread puffern und über eine Bulk-Operation auf einmal in die Tabellen schreiben. Die Performance bei Bulk-Operationen ist dabei so hoch dass es den Client nicht stören sollte. Hierzu kannst du die Daten entweder die SqlBulkCopy Klasse verwenden welche auf BCP aufsetzt, oder Table-Valued Parameter (TVPs) verwenden. Zu TVPs habe ich vor ein paar Monaten einige Tests gemacht und komme dabei mit 400.000 Datensätzen auf eine Laufzeit von 7 Sekunden. Siehe:
Table-Valued Parameters - A Performance Comparison

Zuletzt kannst du noch mit TRANSACTION LEVEL SNAPSHOT arbeiten. Das erfordert in deiner aktuellen Implementierung keine Anpassungen, ist aber teuer für den SQL Server da er alle Requests kopieren muss. Dazu muss über ALTER DATABASE Sandbox SET ALLOW_SNAPSHOT_ISOLATION OFF erstmal Snapshot auf der Datenbank erlaubt werden und danach über SET TRANSACTION ISOLATION LEVEL SNAPSHOT; die entsprechende Transaktion in den Snapshot-Modus versetzt werden. Allerdings kann ich dir hier jetzt nicht sagen wie du das in deinem O/R-Mapper aktivieren kannst.

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.

A
alexander_ Themenstarter:in
15 Beiträge seit 2009
vor 14 Jahren

Hallo,

hab die TVPs mal überflogen, klingt echt vielversprechend (leider keine Linq 2 SQL Unterstützung).

Gibt es eine Möglichkeit, dass mir beim Lesen nur aller Daten der Tabelle nur die angezeigt werden, welche "commited" sind und die anderen weggelassen werden?

so siehts im Moment aus


li_messungen = (from m in rohdatendc.Messungen
                                where (m.FKTypNummerPK == iPK)
                                select
                                    new T_Messungen(m.PK, m.UNI, m.Timestamp, ....).ToList();

...
ich möchte, dass mir nur die angezeigt werden, die commited sind
(die halbfertigen soll er nicht anzeigen)

Gruß alex

Brot kann schimmeln - ich kann nichts!

1.564 Beiträge seit 2007
vor 14 Jahren

Nur weil's LINQ2SQL nicht kann heißt das ja nicht dass man's nicht machen kann...

Anyway...
Wie schon gesagt, du musst das Transaction-Level auf Snapshot stellen oder stagen.

Grüße
Flo

Blog: Things about Software Architecture, .NET development and SQL Server
Twitter
Google+

Je mehr ich weiß, desto mehr weiß ich was ich noch nicht weiß.