Ich bin über eine Situation gestolpert, die mein Wissen über Transaktionen und Sperren grundlegend verändert (ich weiß allerdings nicht viel), und ich brauche Hilfe, um es zu verstehen.
Nehmen wir an, ich habe einen Tisch wie diesen:
CREATE TABLE [dbo].[SomeTable](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[SomeData] [varchar](200) NOT NULL,
[Moment] [datetime] NOT NULL,
[SomeInt] [bigint] NOT NULL
) ON [PRIMARY]
und ich führe diese Abfrage "1000 Zeilen in eine Transaktion einfügen" aus:
BEGIN TRAN t1
DECLARE @i INT = 0
WHILE @i < 1000
BEGIN
SET @i = @i + 1
INSERT INTO [SomeTable] ([SomeData] ,Moment, SomeInt)
VALUES (CONVERT(VARCHAR(255), NEWID()), getdate(), @i)
WAITFOR DELAY '00:00:00:010'
END
COMMIT TRAN t1
Während diese Transaktion ausgeführt wird, führe ich eine einfache Auswahl aus:
SELECT Id, Moment, SomeData, SomeInt FROM [SomeTable]
Es ist nicht immer möglich, es zu reproduzieren (anscheinend hängt es vom Zeitpunkt ab), aber manchmal gibt die ausgewählte Abfrage nach Abschluss der Einfügungstransaktion weniger als 1000 Zeilen zurück. In meiner Unwissenheit habe ich geglaubt, dass select immer 1000 Zeilen zurückgibt (vorausgesetzt, die Isolationsstufe ist Read Committed), aber offensichtlich habe ich falsch verstanden, wie Transaktionen und Sperren funktionieren.
Wenn ich jedoch einen Primärschlüssel in die ID-Spalte einfüge (die einen Clustered-Index generiert), gibt die Auswahlabfrage, solange ich es versucht habe, alle 1000 Zeilen zurück. Wenn Sie Indizes auf andere Weise platzieren, mit einem Clustered-Index für den zusammengesetzten Schlüssel und einem Nicht-Clustered-Index für einige andere Spalten, kann dies wiederum dazu führen, dass weniger Zeilen zurückgegeben werden, als ich erwartet habe.
Ich habe also folgende Fragen:
- Warum gibt select nicht immer alle von der Transaktion festgeschriebenen Zeilen zurück?
- Wenn dies erwartetes Verhalten ist, wie kann es am besten funktionieren, wie ich es erwartet habe? Grundsätzlich möchte ich auswählen, dass der Status der Tabelle nach (oder vor) der Transaktion zurückgegeben wird, nicht einige halbfertige Daten. Die Snapshot-Isolierung ist derzeit keine Option. Das Setzen von TABLOCK scheint die Arbeit zu erledigen, aber gibt es eine bessere Lösung? Im wirklichen Leben habe ich Tabellen, die ich auf dieser Ebene nicht sperren möchte, wenn es nicht unbedingt notwendig ist.
- Warum ändert das Setzen eines Index dieses Verhalten?
Danke im Voraus.