Précédent   Forum des professionnels en informatique > Bases de données > MS SQL-Server > Développement
Développement Forum d'entraide sur le Transact-SQL, le CLR, les procédures stockées, les triggers, les requêtes SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 05/08/2011, 15h43   #1
Membre habitué
 
Avatar de grinder59
 
Inscription : septembre 2005
Messages : 514
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 514
Points : 128
Points : 128
Par défaut accès concurrents entre 2 services distincts sur une même table

Bonjour,

J'ai un petit souci d'accès concurrents avec 2 services windows utilisant la même table.
Le but de ces services est de mettre à jour un montant (mais de 2 façons différentes). Dans le premier service, je procède de la façon suivante :

SERVICE 1
étape 0 :
Begin Transaction

étape 1 - récupération du dernier montant enregistré :
SELECT TOP 1 Montant FROM maTable WITH (tablockx) WHERE ... ORDER ...
cela me renvoie un chiffre que j'appelle Montant1

étape 2 - calcul du nouveau montant
Montant2 = Montant1 + x

étape 3 - enregistrement du nouveau montant via une procédure stockée (c'est historique) :
INSERT INTO [maTable] VALUES(Montant2)

étape 4 - Commit Transaction


SERVICE 2
je procède de la même façon :

étape 0 :
Begin Transaction

étape 1 - récupération du dernier montant enregistré :
SELECT TOP 1 Montant FROM maTable WITH (tablockx) WHERE ... ORDER ...
cela me renvoie un nombre que j'appelle Montant3

étape 2 - calcul du nouveau montant
Montant4 = Montant3 + y

étape 3 - enregistrement du nouveau montant via un requête cette fois ci:
INSERT INTO maTable VALUES(Montant4)

étape 4 - Commit Transaction

A priori, cela fonctionnait, sauf qu'hier, le 2 services se sont exécutés en même temps et que les accès concurrents, que je pensais gérés via le tablelockx, n'a pas fonctionné. Montant2 ET Montant4 ont été calculé à partir de la même valeur initialement récupérée dans ma table. Alors qu'avec une gestion correcte des accès concurrent, le service qui s'exécute en premier termine son exécution et l'insertion du nouveau montant dans la table avant que le second prenne la main et récupère le dernier montant enregistré (par le service 1) pour calculer, à son tour, le nouveau montant...

Est-ce que à tout hasard, là, comme ça, y'a quelque chose qui vous saute aux yeux ? parce que n'étant pas expert en SQL Server, j'ai pensé, suite à mes diverses lectures, qu'un with tablelockx pouvait résoude mes problèmes... Mais je me suis manifestement gourré !

Merci de votre aide !
grinder59 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/08/2011, 12h12   #2
Rédacteur/Modérateur
 
Avatar de fadace
 
Homme Fabien Celaia
Administrateur de base de données
Inscription : octobre 2002
Messages : 3 779
Détails du profil
Informations personnelles :
Nom : Homme Fabien Celaia
Âge : 41
Localisation : Suisse

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : Service public

Informations forums :
Inscription : octobre 2002
Messages : 3 779
Points : 8 124
Points : 8 124
Envoyer un message via ICQ à fadace Envoyer un message via Skype™ à fadace
Le select, même s'il est dans une transaction, génère un verrou partagé... laissant de ce fait l'accès en lecture à un autre select.

Dans votre cas précis, il faut focer le verrouillage exclusif dès le select.

Ceci ce fait via select ... with XLOCK

Source

Ce faisant, vous allez peut-être créer de la contention.... tout à un prix
__________________
Sr DBA Oracle / Sybase / MS-SQL / DB2 / Informix / Postgresql
Administrateur SAP
Mes articles

Attention : pas de réponse technique par MP : pensez aux autres, passez par les forums !
fadace est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/08/2011, 23h30   #3
Modérateur

 
Avatar de elsuket
 
Homme Nicolas Souquet
Administrateur de base de données
Inscription : janvier 2005
Messages : 4 669
Détails du profil
Informations personnelles :
Nom : Homme Nicolas Souquet
Âge : 30
Localisation : Thaïlande

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : janvier 2005
Messages : 4 669
Points : 8 729
Points : 8 729
Bonjour,

Le mieux à mon sens et comme le suggère Fadace est plutôt de mettre SET TRANSACTION ISOLATION LEVEL REPEATABLE READ.
Cela permet de le spécifier une bonne fois pour toutes.
D'autre part on peut le changer en cours de route, et si l'on spécifie un indicateur de table, il prend priorité sur le niveau d'isolation de transaction

@++
__________________
En bases de données relationnelles SQL, il n'y a ni tableaux, ni enregistrements, ni champs: il y a des tables, des lignes et des colonnes.
Blog | Profil| Consulter ou télécharger les fichiers d'aide de SQL Server, des versions 2000 à 2012
elsuket est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 26/08/2011, 12h57   #4
Membre habitué
 
Avatar de grinder59
 
Inscription : septembre 2005
Messages : 514
Détails du profil
Informations forums :
Inscription : septembre 2005
Messages : 514
Points : 128
Points : 128
Je vais regarder tout cela... Merci de vos conseils !!!
grinder59 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 12h39.


 
 
 
 
Partenaires

Hébergement Web