2016-06-22 19 views
2

Ich kam in einem seltsamen Verhalten einer Abfrage, die ich für eine SQL Server renne jetzt 2014.SELECT gibt datarow zweimal

SELECT * 
FROM ExampleTable 
WHERE ExampleTimestamp < '22.06.2016 15:35:00' 

Das Merkwürdige ist, dass es eine Reihe zweimal zurückgibt, was ich habe nicht erwartet zu passieren.

Aus den Daten kann ich sehen, dass zwei Spalten der doppelten Zeilen in jedem Vorkommen unterschiedlich sind (eine davon ist die ExampleTimestamp Spalte).

Es ist wahrscheinlich, dass die Datenzeile durch einen anderen Thread geändert wurde, aber ist es normal, dass die Datenzeile dann zweimal in einem DataTable zurückgegeben wird?

Wie kann ich verhindern, dass eine Zeile zweimal angezeigt wird, wenn sie während der Abfrage geändert wurde?

+0

Sie können versuchen, 'DISTINCT' –

+0

zu verwenden Ich glaube nicht, dass' DISTINCT' hier die Arbeit erledigen wird, da ich alle Spalten zurückgeben muss. Da es Unterschiede zwischen den zwei Zeilen gibt, wird es immer noch beide zurückgeben. Zusätzlich, wenn ich distinct auf der PK dieser Spalte verwende, welcher Datenteil sollte der SQL-Server dann zurückgeben? –

+0

Sie machen nicht viel Sinn. Der Grund, warum es die 2 Zeilen zurückgibt, ist, dass sie anders sind, du hast gerade gesagt, dass sie anders sind.DISTINCT hat auch nichts mit Entfernen von Spalten zu tun –

Antwort

1

Sie müssen transaction isolation level korrekt einzurichten. Z.B .:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; 

Nur sehr vorsichtig mit ihm sein, weil diese Ebenen einen wesentlichen Einfluss auf die Leistung haben. In diesen Fällen ist Geschwindigkeit wichtiger als Konsistenz, manchmal umgekehrt.

Wahrscheinlich müssen Sie Ihre Abfrage in einem transaction laufen:

BEGIN TRANSACTION 'tran'; 
    SELECT * 
    FROM ExampleTable 
    WHERE ExampleTimestamp < '22.06.2016 15:35:00' 
COMMIT TRANSACTION 'tran'; 
GO 

Update: REPEATABLE READ geht dieses Problem an, tut READ COMMITTED nicht.

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; 

Nach der Isolationsstufe Definitionen ist die REPEATABLE READ l east restrictive isolation level, die das Non Repeatable Read Phänomen verhindert.

+0

Ich habe gelesen, wie die Einstellung für meine aktuelle Sitzung mit dieser Abfrage ist: http://stackoverflow.com/questions/1038113/how-to-find-current-transaction-level. Es ist bereits auf ReadCommitted gesetzt. Zumindest für meine MSSMS-Sitzung ist es so eingestellt. Da ich die Sitzung nicht von meinem Programm verändere, kann ich erwarten, dass die Einstellung ähnlich ist? –

+0

In der Tat, wenn ich die Where-Klausel aus dieser Abfrage herausnehmen, haben alle Sitzungen gesetzt ReadCommitted –

+0

Ich würde das erwarten. Denken Sie daran, dass READ COMMITTED immer noch überlappende Threads erlaubt. Es erlaubt immer noch die wiederholbaren Lese- und Phantomleseprobleme. Für Ihren Fall müssen Sie "nicht wiederholbare Lesevorgänge" verhindern. 'REPEATABLE READ' würde Ihnen also besser passen. Weitere Informationen finden Sie in der [MSDN-Dokumentation] (https://msdn.microsoft.com/en-us/library/ms378149 (v = sql.110) .aspx) oder in der zugehörigen [Wikipedia-Seite] (https: //en.wikipedia. org/wiki/Isolation_ (database_systems) #Repeatable_reads) –

2

Ich könnte mich nicht falsch, aber nach meinem letzten WISSEN einem Update auf eine Datenreihe wird eine neue Zeile und Löschen der alten einlegen. Sie haben wahrscheinlich Ihre Anfrage genau zu der Zeit dazwischen platziert.

Es ist möglich, dieses Verhalten zu umgehen, wenn Sie in einer Transaktion Schreibzugriff auf Ihre Datenbank umbrechen. Auf diese Weise erhalten Sie entweder den Status vor oder nach dem Festschreiben der Transaktion, aber niemals einen undefinierten Zustand dazwischen.

Ich hoffe, das wird helfen.

Saxxon