J'ai trébuché à la situation qui change mes connaissances sur les transactions et de verrouiller fondamentalement (je ne sais pas grand chose si) et j'ai besoin d'aide pour le comprendre.
Disons que j'ai une table comme ceci:
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]
et j'exécute cette "insérer 1000 lignes dans une transaction" requête:
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
Bien que cette transaction fonctionne, j'exécute une sélection simple:
SELECT Id, Moment, SomeData, SomeInt FROM [SomeTable]
Il n'est pas toujours possible de le reproduire (apparemment dépend des horaires), mais parfois de sélectionner une requête, une fois les finitions de transaction insérées, renvoie moins de 1000 rangées. Dans mon ignorance, j'ai cru que Select retournera toujours 1000 rangées (étant donné que le niveau d'isolement est lu engagé), mais j'ai évidemment mal compris la manière dont les transactions et les travaux de verrouillage.
Cependant, si je mettais une clé principale sur la colonne ID (qui génère un indice en cluster), sélectionnez la requête, aussi longtemps que j'ai essayé, retournez toutes les 1000 lignes. Mettre des index Quelques autres voies, avec une index en cluster sur la clé composite et un indice non clusterné sur certaines autres colonnes, peut à nouveau entraîner une rédaction de nombre moins de lignes que prévu.
Donc, j'ai ces questions:
Merci d'avance.
Je n'ai pas réussi à reproduire cela après avoir exécuté votre code plusieurs fois.
Je présume que cela doit arriver quand une ligne ultérieure est insérée sur une page antérieure dans le fichier.
Donc l'ordre des opérations est (par exemple)
Le tableau comprenait 10 pages. Par défaut, les 8 premières pages seront attribuées à partir d'extensions mixtes, puis il sera attribué une étendue uniforme. Peut-être que dans votre espace de cas était disponible dans le dossier d'une étendue uniforme gratuit avant les extensions mixtes utilisées.
Vous pouvez tester cette théorie en exécutant ce qui suit dans une fenêtre différente après avoir reproduit le problème et en voyant si les lignes manquantes de l'original SELECT
apparaissent tous au début de ces Resultset.
SELECT [SomeData],
Moment,
SomeInt,
file_id,
page_id,
slot_id
FROM [SomeTable]
/*Undocumented - Use at own risk*/
CROSS APPLY sys.fn_PhysLocCracker(%% physloc %%)
ORDER BY page_id, SomeInt
L'opération contre une table indexée sera dans l'ordre des essences d'index plutôt que dans l'ordre d'attribution afin que ce scénario ne soit pas affecté par ce scénario.
Un scan commandé d'une allocation peut être effectué contre un index, mais il est seulement pris en compte si la table est suffisamment grande et que le niveau d'isolement est lu non engagé ou une serrure de table est maintenue.
Parce que la lecture commune libère généralement des verrômes dès que les données sont lues, il est possible pour une analyse par rapport à l'index de lecture de lignes deux fois ou non du tout (si la clé d'index est mise à jour par une transaction simultanée provoquant l'avant ou l'arrière. ) Voir LE NIVEAU D'ISOLATION EN LIRE Pour plus de discussion sur ce type de problème.
En passant, j'avais initialement envisagé l'affaire indexée que l'indice était sur l'une des colonnes qui augmente par rapport à l'ordre d'insertion (n'importe lequel de l'ID, du moment, de la peinture). Cependant, même si l'indice en cluster est sur le hasard SomeData
, le problème ne survient toujours pas.
J'ai essayé
DBCC TRACEON(3604, 1200, -1) /*Caution. Global trace flag. Outputs lock info
on every connection*/
SELECT TOP 2 *,
%%LOCKRES%%
FROM [SomeTable] WITH(nolock)
ORDER BY [SomeData];
SELECT *,
%%LOCKRES%%
FROM [SomeTable]
ORDER BY [SomeData];
/*Turn off trace flags. Doesn't check whether or not they were on already
before we started, with TRACEOFF*/
DBCC TRACEOFF(3604, 1200, -1)
Les résultats étaient comme ci-dessous
Le deuxième Resultins comprend les 1 000 lignes. Les informations de verrouillage montrent que même s'il a été bloqué en attente de la ressource de verrouillage 24c910701749
Lorsque le verrou a été publié ne le fait pas continuez simplement le scan de ce point. Au lieu de cela, il libère immédiatement cette serrure et acquiert une serrure de ligne sur la nouvelle première rangée.