IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

La transaction d'isolement d'instantanée a été abandonnée


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Formateur en informatique
    Inscrit en
    Octobre 2002
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Formateur en informatique

    Informations forums :
    Inscription : Octobre 2002
    Messages : 16
    Par défaut La transaction d'isolement d'instantanée a été abandonnée
    Bonjour,

    j'ai fait une SP pour mettre à jour des champs d'une table. L'application montant en charge, j'ai parfois cette sp qui est exécutée à 1 seconde d'intervalle à partir d'un autre PC mais sous le même login SQL.

    j'ai le message suivant
    Error : System.Exception: System.Data.SqlClient.SqlException (0x80131904): La transaction d'isolement d'instantané a été abandonnée en raison d'un conflit de mise à jour. Vous ne pouvez pas utiliser l'isolement d'instantané pour accéder à la table 'dbo.Journee' directement ou indirectement dans la base de données '' afin de mettre à jour, de supprimer ou d'insérer la ligne modifiée ou supprimée par une autre transaction.
    je suppose que c'est parce que la première est en cours de mise à jour et qu'il ne veut pas laisser la seconde s'exécuter pour ne pas avoir de mauvais chiffre.

    existe-t-il un moyen de dire à SQL d'attendre que la première est finie avant de faire la seconde plutôt que planter ? comme un FIFO. ou alors une autre approche.
    ma SP met à jour des infos grâce à une requête imbriquées. Peut être que c'est préférable de faire la requête de comptage , puis l'update ?

    Merci
    morceau de contenu de la SP.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    update Journee set UVGlobalJournee = ( SELECT
    													CASE WHEN max(E.UVGlobale) IS NULL THEN 0 
    													ELSE max(E.UVGlobale) 
    													END 
                                                   FROM Examen E inner join 
    												    IT_Journee_Examen IT on E.IdExamen = IT.IDEXAMEN 
                                                   WHERE Journee.IdJournee = IT.IDJOURNEE
    											  ) 
            WHERE Test = '1'  and Journee.IdPlanning = @IdPlanning

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 009
    Billets dans le blog
    6
    Par défaut
    Vous utilisez un verrouillage optimiste (READ COMITTED SNAPSHOT) par défaut au niveau de la base... les transactions sont donc lancées concurremment, chacune travaillant sur sa copie (SNAPSHOT). Si la copie de l'une est mise à jour avant la copie de l'autre il en résulte une anomalie de perte de mise à jour. C'est le message qui vous est adressé.

    Repassez à une verrouillage pessimiste rendra vos transactions sérielles...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre averti
    Profil pro
    Formateur en informatique
    Inscrit en
    Octobre 2002
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Formateur en informatique

    Informations forums :
    Inscription : Octobre 2002
    Messages : 16
    Par défaut
    Merci beacoup pour votre réponse. par contre je ne sais pas comment faire ce que vous m'indiquez.

    La conf de la base sur SQL Server 2014 standard est comme suit
    - Autoriser l'isolement d'instantanée = true
    - Durabilité retardée = false
    - Est un instantanée Read cOmmited = false

    J'ai essayé tous les modes et a chaque fois j'ai une erreur dans mon appli. Ne peut on pas dire au systeme d'attendre que la premiere transaction soit temriné pour exécuter la suivante ?
    Je suis completement perdu sur cette notion que je ne maitrise pas. Mon souhait serait que le système bufferise dans une file d'attente et qu'il exécute des qu'il le peut.
    J'ai essayé read commited, read uncommited et il semble que ce soit pire.... Peut etre que ma base est mal configurée

    Merci pour vos conseils

    ma SP

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    ALTER PROCEDURE [dbo].[MajDispoJournees] @DateJourneeDeb nchar(6),
    @DateJourneeFin nchar(6),@MajPlanning int,@IdJournee int,@IdPlanning int,@IdEnt int
     
    AS
    BEGIN
    --SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
    SET TRANSACTION ISOLATION LEVEL SNAPSHOT
    BEGIN TRANSACTION
    --Verif si on doit mettre a jour toutes la session ou que la journée
    IF (@MajPlanning = 1)
    	BEGIN
    --Mise a jour des UV global des journées Test pour la session spécifiée
    		update Journee set UVGlobalJournee = ( SELECT
    													CASE WHEN max(E.UVGlobale) IS NULL THEN 0 
    													ELSE max(E.UVGlobale) 
    													END 
                                                   FROM Examen E inner join 
    												    IT_Journee_Examen IT on E.IdExamen = IT.IDEXAMEN 
                                                   WHERE Journee.IdJournee = IT.IDJOURNEE
    											  ) 
            WHERE Test = '1'  and Journee.IdPlanning = @IdPlanning
     
    --Mise a jour des UV unitaires des journées Test pour la session spécifiée
    		update Journee set UVUnitaireJournee = ( SELECT
    													CASE WHEN SUM(E.UVUnitaire) IS NULL THEN 0 
    													ELSE SUM(E.UVUnitaire) 
    													END 
    												 FROM Examen E inner join IT_Journee_Examen IT on E.IdExamen = IT.IDEXAMEN 
    												WHERE Journee.IdJournee = IT.IDJOURNEE) 
            WHERE Test = '1'  and Journee.IdPlanning =@IdPlanning
     
    --Mise a jour des dipos formateur pour le non A définir on en prend toutes journées du formateur dont le format est yyMMdd
    		update Journee set UVDispoFormateur = ( select 6 - sum(UVUnitaireJournee) from Journee J where CONVERT(varchar, Journee.DateDebut, 12) = CONVERT(varchar, J.DateDebut, 12) and Journee.Test = '1' and Journee.IdFormateur = J.IdFormateur)   WHERE Test = '1' AND IdEntreprise=@IdEnt and IdFormateur <> -1  AND CONVERT(varchar, DateDebut, 12) >= @DateJourneeDeb  AND CONVERT(varchar, DateDebut, 12) <= @DateJourneeFin
     
    --Mise a jour des dipos formateur pour le A définir on en prend que la journée
    		update Journee set UVDispoFormateur = ( select 6 - sum(UVUnitaireJournee) from Journee J where Journee.IdJournee = J.IdJournee)    WHERE Test = '1'  AND IdEntreprise=@IdEnt and IdFormateur = -1 AND CONVERT(varchar, DateDebut, 12) >= @DateJourneeDeb  AND CONVERT(varchar, DateDebut, 12) <= @DateJourneeFin
     
     
     
    	END
    ELSE
    	BEGIN
    --Mise a jour des UV global des journées Test pour la journée spécifiée
    		update Journee set UVGlobalJournee = ( select 
                                                       case
                                                       WHEN max(E.UVGlobale) IS NULL THEN 0 
                                                       ELSE 
                                                       max(E.UVGlobale) 
                                                       END 
                                                       from Examen E inner join IT_Journee_Examen IT on E.IdExamen = IT.IDEXAMEN 
                                                       WHERE Journee.IdJournee = IT.IDJOURNEE) 
                                                      WHERE Test = '1'  and Journee.IdJournee = @IdJournee
    --Mise a jour des UV unitaires des journées Test pour la journée spécifiée
    		update Journee set UVUnitaireJournee = ( select 
                                                case  
                                                WHEN SUM(E.UVUnitaire) IS NULL THEN 0 
                                                ELSE 
                                                SUM(E.UVUnitaire) 
                                                END 
                                                from Examen E inner join IT_Journee_Examen IT on E.IdExamen = IT.IDEXAMEN 
                                                WHERE Journee.IdJournee = IT.IDJOURNEE) 
                                                WHERE Test = '1'  and Journee.IdJournee =@IdJournee
    --Mise a jour des dipos formateur pour le non A définir on en prend toutes journées du formateur dont le format est yyMMdd
    		update Journee set UVDispoFormateur = ( select 6 - sum(UVUnitaireJournee) from Journee J where Journee.DateDebut = J.DateDebut and Journee.Test = '1' and Journee.IdFormateur = J.IdFormateur)   WHERE Test = '1'  AND IdEntreprise=@IdEnt and IdFormateur <> -1 AND CONVERT(varchar, DateDebut, 12) = @DateJourneeDeb
    --Mise a jour des dipos formateur pour le A définir on en prend que la journée
    		update Journee set UVDispoFormateur = ( select 6 - sum(UVUnitaireJournee) from Journee J where Journee.DateDebut = J.DateDebut and Journee.Test = '1' and Journee.IdJournee = J.IdJournee)    WHERE Test = '1'  AND IdEntreprise=@IdEnt and IdFormateur = -1 AND CONVERT(varchar, DateDebut, 12) = @DateJourneeDeb
    	END
    COMMIT TRANSACTION
    END

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 009
    Billets dans le blog
    6
    Par défaut
    Pour sérialiser les transactions il faut :
    1) placer la base en mode de verrouillage pessimiste
    2) entamer une transaction explicite au niveau d'isolation SERIALIZABLE

    ATTENTION : placer la base en mode de verrouillage pessimiste aura des conséquences sur TOUTES les autres transactions en cours (sachant que n'importe quelle commande manipulant les données ou modifiant la structure de la base est une transaction...).

    À mon sens ce que vous tentez de faire est une ineptie... En effet les SGBD Relationnel sont là pour faire des transactions avec une forte concurrence. Si vous voulez être seul à exécuter des traitement, il fallait plutôt utiliser de l'Excel !

    Essayez de nous dire quel est le sens de votre traitement sur le plan sémantique, autrement dit expliquez nous ce que fait votre code et termes fonctionnels. Je soupçonne une incompréhension des mécanismes de concurrence et probablement une mauvaise structure de votre base de données.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Membre averti
    Profil pro
    Formateur en informatique
    Inscrit en
    Octobre 2002
    Messages
    16
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Formateur en informatique

    Informations forums :
    Inscription : Octobre 2002
    Messages : 16
    Par défaut
    Bonjour,
    je ne suis pas le seul à utiliser la base. Il y a aujourdhui environ 20 personnes qui l'utilise toute la journée et un vingtaine ponctuellement.

    cette SP permet de définir les disponibilités d'une personne sur une journée en unité UV. Sachant qu'il peu en faire 6 par jour.
    A chaque modification du un nombre d'UV faite sur une journée (table de liaison entre journée et stagiaire) cette sp recalculer les disponibiltiés soit de la journée en allant récupérer le nombre d'UV pour cette personne sachant qu'il peut etre sur plusieurs sessions.

    L'application connectée dessus est développée en C#. Il y a une connexion commune vers la base pour tous les utilisateurs. Je ne sais pas si en faire une par utilisateur serait mieux.

    je pensais que le mode SNAPSHOT était adapté en me disant que le systeme vérouille les aute requetes tant que celle en court n'est pas terminée.
    Or j'ai de plus en plus de message d'erreur comme celui mis dans mon premier message ou comme : La transaction a été bloquée sur les ressources verrous par un autre processus et a été choisie comme victime......
    C'est du à la montée en puissance de l'application.

    Aujourdhui je n'arrive pas à reproduire le cas qui est aléatoire. Donc très complexe de modifié le code côté applicatif.

    Bref cela comme a etre très pénalisant et je ne sais aps trop par ou chercher...

    Merci

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 009
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 22 009
    Billets dans le blog
    6
    Par défaut
    Citation Envoyé par PatricePatrice Voir le message
    ...
    cette SP permet de définir les disponibilités d'une personne sur une journée en unité UV. Sachant qu'il peu en faire 6 par jour.
    A chaque modification du un nombre d'UV faite sur une journée (table de liaison entre journée et stagiaire) cette sp recalculer les disponibiltiés soit de la journée en allant récupérer le nombre d'UV pour cette personne sachant qu'il peut etre sur plusieurs sessions....
    Apparemment, si je comprends bien, votre calcul est ensuite stocké dans une autre table...

    Si tel est bien le cas, vous constituez une redondance par calcul... Ce qui prose deux problèmes !
    1) dans un SGBD Relationnel il ne doit jamais y avoir de redondance
    2) pour stocker cette redondance vous devez utiliser une transaction explicite qui bloque les accès concurrent susceptible de générer des verrous mortels

    Solution... Revoyez votre code. En aucun cas vous ne devriez redonder ce calcul, mais simplement l'afficher en faisant lecture des informations.
    Ceci peut sans doute être fait en une seule requête et par conséquent être traduit en vue SQL...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

Discussions similaires

  1. Gestion des transactions et isolation
    Par SQLpro dans le forum Accès aux données
    Réponses: 3
    Dernier message: 04/01/2011, 12h46
  2. transaction et isolation serialized
    Par BaronSamdi dans le forum Développement
    Réponses: 8
    Dernier message: 16/12/2009, 13h03
  3. Réponses: 5
    Dernier message: 19/09/2007, 15h23
  4. [TOUS] Isolation des transactions : Optimisation
    Par dymezac dans le forum MS SQL Server
    Réponses: 17
    Dernier message: 03/09/2007, 19h03
  5. Niveau isolement des transactions
    Par lio33 dans le forum Débuter
    Réponses: 4
    Dernier message: 23/11/2005, 16h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo