2009-09-30 11 views
0

Je suis confronté à un problème étrange avec du code TSQL sur SQL2005.Mise à jour simultanée sur le même enregistrement

La pièce que nous soupçonnons génère la question est:

INSERT INTO SGVdProcessInfo 
    ([StartTs]) 
    VALUES 
    (GETDATE()) 

SELECT @IdProcessInfo = SCOPE_IDENTITY() 

UPDATE TOP(@quantity) 
    [SGVdTLogDetail] WITH (ROWLOCK) 
SET 
    [IdSGVdProcessInfo] = @IdProcessInfo 
WHERE 
    [IdSGVdProcessInfo] IS NULL 
    and IdTLogDetailStatus != 9 

@Quantity prend habituellement 500.

Il y a un index non cluster sur IdSGVdProcessInfo et IdTLogDetailStatus sur SGVdTLogDetail

Qu'est-ce qui se passe est que certains enregistrements de SGVdTLogDetail sont d'abord mis à jour avec un identifiant de la table processinfo et plus tard ils sont mis à jour à nouveau par un autre processus avec un nouvel identifiant processinfo.

Je me demande si le soupçon de tolet soulève cette question ou peut-être il y a quelque chose d'autre ...

Je suppose alors que la mise à jour est appliquée sur les 500 premières lignes sélectionnées, un autre processus consiste à sélectionner la prochaine groupe, et en prenant quelques enregistrements du premier groupe qui ne sont pas encore mis à jour (à cause du rowlock). Est-ce possible?

Toute aide sera grandement appréciée!

Répondre

1

Oui, cela semble correct. Vous pouvez le réparer (au prix d'une concurrence perdue) en mettant toute l'opération dans une transaction sérialisable. Cela garantira que toutes les lignes sont verrouillées pendant la durée de la transaction, et non seulement pendant les lectures et les mises à jour au niveau de la ligne atomique.

0

Je crois que cela se produit parce que SQL Server escalade les verrous au niveau des lignes pour les verrous de page. Vous pensez qu'une MISE À JOUR dans laquelle vous spécifiez la clé primaire entraînerait toujours un verrouillage de ligne, mais lorsque SQL Server obtient un lot avec un groupe de ceux-ci, et que certains d'entre eux se trouvent sur la même page (en fonction de cette situation , cela peut être très probable, par exemple, la mise à jour de tous les fichiers d'un dossier, les fichiers qui ont été créés à peu près en même temps), vous verrez des verrous de page, et de mauvaises choses arriveront. Et si vous ne spécifiez pas de clé primaire pour un UPDATE ou un DELETE, il n'y a aucune raison que la base de données ne présume pas qu'un lot ne sera pas affecté, donc cela va probablement directement aux verrous de page, et de mauvaises choses se produisent. En demandant spécifiquement des verrous au niveau des lignes, ces problèmes sont évités comme vous le faites, cependant, dans votre cas, beaucoup de lignes sont affectées, et la base de données prend l'initiative et l'escalade vers les verrous de page.

Questions connexes