J'ai un souci dans une application qui fait des imports en masse. Dans
certains cas, j'obtiens le message suivant :
[Microsoft][ODBC SQL Server Driver][SQL Server]La transaction (ID du
processus 61) a été bloquée sur les ressources lock par un autre processus
et a été choisie comme victime. Relancez la transaction
Cela semble complètement aléatoire. Cependant, cela n'arrive que sur des
volumes assez important, jamais unitairement. La particularité de cet import
est de faire un DELETE des données qu'il va insérer par la suite (la raison
étant qu'on n'importe pas forcément exactement les mêmes choses, donc on
nettoie d'abord). Mais la table comporte plusieurs centaines de milliers
d'enregistrements (voire millions). Je me demande si le problème ne
viendrait pas de là, SQL Server me rendrait la main alors que son DELETE
n'est pas totalement achevé en acceptant l'INSERT sur la même table.
Qu'en pensez-vous ? Est-ce que cela peut venir de là ?.Y-a-t-il un moyen de
contrôler ça ou faut-il faire des insert/update et purger le reste en fin de
traitement ?
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Laurent Marzouk [MS]
Bonjour,
En général, les instructions exécutées par un même client sont exécutées de manière sérialisée, donc il est peut probable que le problème vienne de là, à moins que l'application n'ait ouvert plusieurs connexions, auquel cas l'exécution simultannée de ces 2 instructions peut effectivement générer un deadlock si elles travaillent sur des pages de données communes.
Il faut donc tout d'abord identifier le processus qui provoque un deadlock avec votre traitement : s'agit-il de votre propre traitement (self-deadlock) ou d'un autre procesus ?
Pour le savoir, vous pouvez positionner les flag 1204 et 1205 (option -T <N° flag>) dans les paramètres de démarrage de SQL Server), qui inscriront plusieurs informations intéressantes lorsqu'un prochain deadlock se produira. Vous aurez notamment les N° des processus entrant en conflit et surtout les instructions SQL correspondantes, ce qui vous permttra de vérifier votre assertion.
Si vous avez besoin de supprimer toutes les données de la table avant d'insérer les nouvelles, il vaut mieux cependant utiliser l'instruction TRUNCATE TABLE, qui supprime toutes les lignes de la table presque instantanément car l'opération n'est par journalisée.
Si vous ne devez supprimer qu'une partie des lignes, vous pouvez essayer de sortir les instructions DELETE / INSERT de la transaction si elle en faisaient partie. Autre voie à explorer, si l'application accède à la base par le biais de composants COM+ dans MTS, le mode d'isolation des transactions est de facto positionné à SERIALIZABLE (i.e. le plus au niveau d'isolation), ce qui peut parfois poser ce genre de problème. Il suffit dans ce cas de créer une procédure stockée qui réalisera le traitement de suppression / insertion et dans laquelle vous pourrez forcer le mode d'isolation par défaut de SQL Server (READ COMMITTED) afin de limiter la contention liée aux verrous:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
Vous pouvez également vérifiez que l'instruction DELETE ne pose pas de verrous exclusif de type table (TABLOCKX ) en raison d'un nombre important de lignes à supprimer. Si tel est le cas, vous pouvez soit essayer de limiter la pose des verrous au niveau page (DELETE FROM <table> WITH (PAGLOCK) WHERE ..., soit supprimer les lignes par lot de 10000 pour limiter les verrsou posés et accélérer les traitement de suppression (plus petites transactions). Il est également possible par ce biais de définir le niveau d'isolation de l'instruction (ex. DELETE FROM <table> WITH (READCOMMITTED)).
Pour finir, je vous engage à parrcourir la section intitulée "Troubleshooting Deadlocks" de l'aide en ligne SQL Server qui fournit des instructions pour déterminer l'origine d'un deadlock.
Cordialement,
---------------------------------------------------------------- Laurent Marzouk Microsoft Services France ---------------------------------------------------------------- SQL Server 2005 Rocks !! :-)
"Fabrice Fauconnier" wrote in message news:433cf0cc$0$17061$ Bonjour,
J'ai un souci dans une application qui fait des imports en masse. Dans certains cas, j'obtiens le message suivant :
[Microsoft][ODBC SQL Server Driver][SQL Server]La transaction (ID du processus 61) a été bloquée sur les ressources lock par un autre processus et a été choisie comme victime. Relancez la transaction
Cela semble complètement aléatoire. Cependant, cela n'arrive que sur des volumes assez important, jamais unitairement. La particularité de cet import est de faire un DELETE des données qu'il va insérer par la suite (la raison étant qu'on n'importe pas forcément exactement les mêmes choses, donc on nettoie d'abord). Mais la table comporte plusieurs centaines de milliers d'enregistrements (voire millions). Je me demande si le problème ne viendrait pas de là, SQL Server me rendrait la main alors que son DELETE n'est pas totalement achevé en acceptant l'INSERT sur la même table.
Qu'en pensez-vous ? Est-ce que cela peut venir de là ?.Y-a-t-il un moyen de contrôler ça ou faut-il faire des insert/update et purger le reste en fin de traitement ?
Merci
Fabrice
Bonjour,
En général, les instructions exécutées par un même client sont exécutées de
manière sérialisée, donc il est peut probable que le problème vienne de là,
à moins que l'application n'ait ouvert plusieurs connexions, auquel cas
l'exécution simultannée de ces 2 instructions peut effectivement générer un
deadlock si elles travaillent sur des pages de données communes.
Il faut donc tout d'abord identifier le processus qui provoque un deadlock
avec votre traitement : s'agit-il de votre propre traitement (self-deadlock)
ou d'un autre procesus ?
Pour le savoir, vous pouvez positionner les flag 1204 et 1205 (option -T <N°
flag>) dans les paramètres de démarrage de SQL Server), qui inscriront
plusieurs informations intéressantes lorsqu'un prochain deadlock se
produira. Vous aurez notamment les N° des processus entrant en conflit et
surtout les instructions SQL correspondantes, ce qui vous permttra de
vérifier votre assertion.
Si vous avez besoin de supprimer toutes les données de la table avant
d'insérer les nouvelles, il vaut mieux cependant utiliser l'instruction
TRUNCATE TABLE, qui supprime toutes les lignes de la table presque
instantanément car l'opération n'est par journalisée.
Si vous ne devez supprimer qu'une partie des lignes, vous pouvez essayer de
sortir les instructions DELETE / INSERT de la transaction si elle en
faisaient partie. Autre voie à explorer, si l'application accède à la base
par le biais de composants COM+ dans MTS, le mode d'isolation des
transactions est de facto positionné à SERIALIZABLE (i.e. le plus au niveau
d'isolation), ce qui peut parfois poser ce genre de problème. Il suffit dans
ce cas de créer une procédure stockée qui réalisera le traitement de
suppression / insertion et dans laquelle vous pourrez forcer le mode
d'isolation par défaut de SQL Server (READ COMMITTED) afin de limiter la
contention liée aux verrous:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
Vous pouvez également vérifiez que l'instruction DELETE ne pose pas de
verrous exclusif de type table (TABLOCKX ) en raison d'un nombre important
de lignes à supprimer. Si tel est le cas, vous pouvez soit essayer de
limiter la pose des verrous au niveau page (DELETE FROM <table> WITH
(PAGLOCK) WHERE ..., soit supprimer les lignes par lot de 10000 pour limiter
les verrsou posés et accélérer les traitement de suppression (plus petites
transactions). Il est également possible par ce biais de définir le niveau
d'isolation de l'instruction (ex. DELETE FROM <table> WITH (READCOMMITTED)).
Pour finir, je vous engage à parrcourir la section intitulée
"Troubleshooting Deadlocks" de l'aide en ligne SQL Server qui fournit des
instructions pour déterminer l'origine d'un deadlock.
Cordialement,
----------------------------------------------------------------
Laurent Marzouk
Microsoft Services France
----------------------------------------------------------------
SQL Server 2005 Rocks !! :-)
"Fabrice Fauconnier" <fauconnier@noosfere.com> wrote in message
news:433cf0cc$0$17061$8fcfb975@news.wanadoo.fr...
Bonjour,
J'ai un souci dans une application qui fait des imports en masse. Dans
certains cas, j'obtiens le message suivant :
[Microsoft][ODBC SQL Server Driver][SQL Server]La transaction (ID du
processus 61) a été bloquée sur les ressources lock par un autre processus
et a été choisie comme victime. Relancez la transaction
Cela semble complètement aléatoire. Cependant, cela n'arrive que sur des
volumes assez important, jamais unitairement. La particularité de cet import
est de faire un DELETE des données qu'il va insérer par la suite (la raison
étant qu'on n'importe pas forcément exactement les mêmes choses, donc on
nettoie d'abord). Mais la table comporte plusieurs centaines de milliers
d'enregistrements (voire millions). Je me demande si le problème ne
viendrait pas de là, SQL Server me rendrait la main alors que son DELETE
n'est pas totalement achevé en acceptant l'INSERT sur la même table.
Qu'en pensez-vous ? Est-ce que cela peut venir de là ?.Y-a-t-il un moyen de
contrôler ça ou faut-il faire des insert/update et purger le reste en fin de
traitement ?
En général, les instructions exécutées par un même client sont exécutées de manière sérialisée, donc il est peut probable que le problème vienne de là, à moins que l'application n'ait ouvert plusieurs connexions, auquel cas l'exécution simultannée de ces 2 instructions peut effectivement générer un deadlock si elles travaillent sur des pages de données communes.
Il faut donc tout d'abord identifier le processus qui provoque un deadlock avec votre traitement : s'agit-il de votre propre traitement (self-deadlock) ou d'un autre procesus ?
Pour le savoir, vous pouvez positionner les flag 1204 et 1205 (option -T <N° flag>) dans les paramètres de démarrage de SQL Server), qui inscriront plusieurs informations intéressantes lorsqu'un prochain deadlock se produira. Vous aurez notamment les N° des processus entrant en conflit et surtout les instructions SQL correspondantes, ce qui vous permttra de vérifier votre assertion.
Si vous avez besoin de supprimer toutes les données de la table avant d'insérer les nouvelles, il vaut mieux cependant utiliser l'instruction TRUNCATE TABLE, qui supprime toutes les lignes de la table presque instantanément car l'opération n'est par journalisée.
Si vous ne devez supprimer qu'une partie des lignes, vous pouvez essayer de sortir les instructions DELETE / INSERT de la transaction si elle en faisaient partie. Autre voie à explorer, si l'application accède à la base par le biais de composants COM+ dans MTS, le mode d'isolation des transactions est de facto positionné à SERIALIZABLE (i.e. le plus au niveau d'isolation), ce qui peut parfois poser ce genre de problème. Il suffit dans ce cas de créer une procédure stockée qui réalisera le traitement de suppression / insertion et dans laquelle vous pourrez forcer le mode d'isolation par défaut de SQL Server (READ COMMITTED) afin de limiter la contention liée aux verrous:
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
Vous pouvez également vérifiez que l'instruction DELETE ne pose pas de verrous exclusif de type table (TABLOCKX ) en raison d'un nombre important de lignes à supprimer. Si tel est le cas, vous pouvez soit essayer de limiter la pose des verrous au niveau page (DELETE FROM <table> WITH (PAGLOCK) WHERE ..., soit supprimer les lignes par lot de 10000 pour limiter les verrsou posés et accélérer les traitement de suppression (plus petites transactions). Il est également possible par ce biais de définir le niveau d'isolation de l'instruction (ex. DELETE FROM <table> WITH (READCOMMITTED)).
Pour finir, je vous engage à parrcourir la section intitulée "Troubleshooting Deadlocks" de l'aide en ligne SQL Server qui fournit des instructions pour déterminer l'origine d'un deadlock.
Cordialement,
---------------------------------------------------------------- Laurent Marzouk Microsoft Services France ---------------------------------------------------------------- SQL Server 2005 Rocks !! :-)
"Fabrice Fauconnier" wrote in message news:433cf0cc$0$17061$ Bonjour,
J'ai un souci dans une application qui fait des imports en masse. Dans certains cas, j'obtiens le message suivant :
[Microsoft][ODBC SQL Server Driver][SQL Server]La transaction (ID du processus 61) a été bloquée sur les ressources lock par un autre processus et a été choisie comme victime. Relancez la transaction
Cela semble complètement aléatoire. Cependant, cela n'arrive que sur des volumes assez important, jamais unitairement. La particularité de cet import est de faire un DELETE des données qu'il va insérer par la suite (la raison étant qu'on n'importe pas forcément exactement les mêmes choses, donc on nettoie d'abord). Mais la table comporte plusieurs centaines de milliers d'enregistrements (voire millions). Je me demande si le problème ne viendrait pas de là, SQL Server me rendrait la main alors que son DELETE n'est pas totalement achevé en acceptant l'INSERT sur la même table.
Qu'en pensez-vous ? Est-ce que cela peut venir de là ?.Y-a-t-il un moyen de contrôler ça ou faut-il faire des insert/update et purger le reste en fin de traitement ?
Merci
Fabrice
Fabrice Fauconnier
Bonjour
Merci pour toutes ces pistes qui nous ont beaucoup écaliré ! Du coup, nous avons approfondi l'analyse concernant la parallélisation ou serialisation des requêtes. Le problème est donc devenu un tout petit plus complexe mais bien plus clair.
En fait, l'import de données a bien été fait sur une seule et unique connexion. Nous avons bien vérifié tout ça, corrigé certaines bricoles mais le problème persistait, certes moins fréquemment. Il s'avère qu'en fin d'import, un traitement de recalcul ré-utilise ces données qui peuvent évoluer au gré du recalcul et sont donc ré-injectées de la même manière par ce deuxième thread de recalcul. Le problème vient donc bien d'une parallélisation des requêtes. Le seul truc qui m'embête est qu'au moment du deadlock, ce sont bien les mêmes tables qui sont attéquées mais sur des plages de données complètement différentes. (en gros on importe les données sur un dossier client particulier et le recalcul se fait sur un autre dossier, les SELECT sont donc différents) Après lecture de l'aide, il semblerait que dans certains cas, SQL Server pose un verrou exlusif pour étendre ses pages d'index (IX) ce qui bloquerait les autres processus. Partant de ce principe, nous avons essayé d'effectuer des DELETE unitaires (enregistrement par enregistrement) pour limiter les concurrences. Effectivement plus d'erreur mais j'ai peur que ce soit que reculer pour mieux s'écraser plus tard sans compter des temps de traiement qui risque fort de grimper.
Ce comportement est-il normal et existe-t-il un moyen de le contourner ? J'ai bien pensé à faire des DELETE NOLOCK mais j'ai là aussi un peu peur des effets de bord. Nous allons revoir toutes les procédures de façon à plutôt faire de l'UPDATE/INSERT mais j'aimerai bien coprendre et éviter de retomber dans ce genre de problème.
En tout cas, merci pour votre aide préciesue !
Fabrice
Bonjour
Merci pour toutes ces pistes qui nous ont beaucoup écaliré ! Du coup, nous
avons approfondi l'analyse concernant la parallélisation ou serialisation
des requêtes. Le problème est donc devenu un tout petit plus complexe mais
bien plus clair.
En fait, l'import de données a bien été fait sur une seule et unique
connexion. Nous avons bien vérifié tout ça, corrigé certaines bricoles mais
le problème persistait, certes moins fréquemment. Il s'avère qu'en fin
d'import, un traitement de recalcul ré-utilise ces données qui peuvent
évoluer au gré du recalcul et sont donc ré-injectées de la même manière par
ce deuxième thread de recalcul. Le problème vient donc bien d'une
parallélisation des requêtes. Le seul truc qui m'embête est qu'au moment du
deadlock, ce sont bien les mêmes tables qui sont attéquées mais sur des
plages de données complètement différentes. (en gros on importe les données
sur un dossier client particulier et le recalcul se fait sur un autre
dossier, les SELECT sont donc différents) Après lecture de l'aide, il
semblerait que dans certains cas, SQL Server pose un verrou exlusif pour
étendre ses pages d'index (IX) ce qui bloquerait les autres processus.
Partant de ce principe, nous avons essayé d'effectuer des DELETE unitaires
(enregistrement par enregistrement) pour limiter les concurrences.
Effectivement plus d'erreur mais j'ai peur que ce soit que reculer pour
mieux s'écraser plus tard sans compter des temps de traiement qui risque
fort de grimper.
Ce comportement est-il normal et existe-t-il un moyen de le contourner ?
J'ai bien pensé à faire des DELETE NOLOCK mais j'ai là aussi un peu peur des
effets de bord. Nous allons revoir toutes les procédures de façon à plutôt
faire de l'UPDATE/INSERT mais j'aimerai bien coprendre et éviter de retomber
dans ce genre de problème.
Merci pour toutes ces pistes qui nous ont beaucoup écaliré ! Du coup, nous avons approfondi l'analyse concernant la parallélisation ou serialisation des requêtes. Le problème est donc devenu un tout petit plus complexe mais bien plus clair.
En fait, l'import de données a bien été fait sur une seule et unique connexion. Nous avons bien vérifié tout ça, corrigé certaines bricoles mais le problème persistait, certes moins fréquemment. Il s'avère qu'en fin d'import, un traitement de recalcul ré-utilise ces données qui peuvent évoluer au gré du recalcul et sont donc ré-injectées de la même manière par ce deuxième thread de recalcul. Le problème vient donc bien d'une parallélisation des requêtes. Le seul truc qui m'embête est qu'au moment du deadlock, ce sont bien les mêmes tables qui sont attéquées mais sur des plages de données complètement différentes. (en gros on importe les données sur un dossier client particulier et le recalcul se fait sur un autre dossier, les SELECT sont donc différents) Après lecture de l'aide, il semblerait que dans certains cas, SQL Server pose un verrou exlusif pour étendre ses pages d'index (IX) ce qui bloquerait les autres processus. Partant de ce principe, nous avons essayé d'effectuer des DELETE unitaires (enregistrement par enregistrement) pour limiter les concurrences. Effectivement plus d'erreur mais j'ai peur que ce soit que reculer pour mieux s'écraser plus tard sans compter des temps de traiement qui risque fort de grimper.
Ce comportement est-il normal et existe-t-il un moyen de le contourner ? J'ai bien pensé à faire des DELETE NOLOCK mais j'ai là aussi un peu peur des effets de bord. Nous allons revoir toutes les procédures de façon à plutôt faire de l'UPDATE/INSERT mais j'aimerai bien coprendre et éviter de retomber dans ce genre de problème.
En tout cas, merci pour votre aide préciesue !
Fabrice
Fred BROUARD
Bonjour,
Fabrice Fauconnier a écrit:
Bonjour
Merci pour toutes ces pistes qui nous ont beaucoup écaliré ! Du coup, nous avons approfondi l'analyse concernant la parallélisation ou serialisation des requêtes. Le problème est donc devenu un tout petit plus complexe mais bien plus clair.
En fait, l'import de données a bien été fait sur une seule et unique connexion. Nous avons bien vérifié tout ça, corrigé certaines bricoles mais le problème persistait, certes moins fréquemment. Il s'avère qu'en fin d'import, un traitement de recalcul ré-utilise ces données qui peuvent évoluer au gré du recalcul et sont donc ré-injectées de la même manière par ce deuxième thread de recalcul. Le problème vient donc bien d'une parallélisation des requêtes. Le seul truc qui m'embête est qu'au moment du deadlock, ce sont bien les mêmes tables qui sont attéquées mais sur des plages de données complètement différentes. (en gros on importe les données sur un dossier client particulier et le recalcul se fait sur un autre dossier, les SELECT sont donc différents) Après lecture de l'aide, il semblerait que dans certains cas, SQL Server pose un verrou exlusif pour étendre ses pages d'index (IX) ce qui bloquerait les autres processus. Partant de ce principe, nous avons essayé d'effectuer des DELETE unitaires (enregistrement par enregistrement) pour limiter les concurrences. Effectivement plus d'erreur mais j'ai peur que ce soit que reculer pour mieux s'écraser plus tard sans compter des temps de traiement qui risque fort de grimper.
Ce comportement est-il normal et existe-t-il un moyen de le contourner ? J'ai bien pensé à faire des DELETE NOLOCK mais j'ai là aussi un peu peur des effets de bord. Nous allons revoir toutes les procédures de façon à plutôt faire de l'UPDATE/INSERT mais j'aimerai bien coprendre et éviter de retomber dans ce genre de problème.
Non, n'utilisez pas de DELETE en NOLOCK. Pensez plutôt à baisser le niveau d'isolation de vos transactions ou bien de faire des delete par block représentant une page du cluster. Pour ma part dans ce cas je ferais de multiples transactions en calculant que le volume des MAJ ne touche pas plus d'une à 8 pages de données (a mesurer). Vous pouvez aussi obliger certains index à vérouiller plutôt en row ou page à l'aide de sp_indexoption. Enfin si le batch est en dehors des heures de prod, pensez à supprimer tous les index et les recréer en fin de traitement. Dans tous les cas faîtes des tests !!!
A +
En tout cas, merci pour votre aide préciesue !
Fabrice
-- Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com Audit, conseil, expertise, formation, modélisation, tuning, optimisation ********************* http://www.datasapiens.com ***********************
Bonjour,
Fabrice Fauconnier a écrit:
Bonjour
Merci pour toutes ces pistes qui nous ont beaucoup écaliré ! Du coup, nous
avons approfondi l'analyse concernant la parallélisation ou serialisation
des requêtes. Le problème est donc devenu un tout petit plus complexe mais
bien plus clair.
En fait, l'import de données a bien été fait sur une seule et unique
connexion. Nous avons bien vérifié tout ça, corrigé certaines bricoles mais
le problème persistait, certes moins fréquemment. Il s'avère qu'en fin
d'import, un traitement de recalcul ré-utilise ces données qui peuvent
évoluer au gré du recalcul et sont donc ré-injectées de la même manière par
ce deuxième thread de recalcul. Le problème vient donc bien d'une
parallélisation des requêtes. Le seul truc qui m'embête est qu'au moment du
deadlock, ce sont bien les mêmes tables qui sont attéquées mais sur des
plages de données complètement différentes. (en gros on importe les données
sur un dossier client particulier et le recalcul se fait sur un autre
dossier, les SELECT sont donc différents) Après lecture de l'aide, il
semblerait que dans certains cas, SQL Server pose un verrou exlusif pour
étendre ses pages d'index (IX) ce qui bloquerait les autres processus.
Partant de ce principe, nous avons essayé d'effectuer des DELETE unitaires
(enregistrement par enregistrement) pour limiter les concurrences.
Effectivement plus d'erreur mais j'ai peur que ce soit que reculer pour
mieux s'écraser plus tard sans compter des temps de traiement qui risque
fort de grimper.
Ce comportement est-il normal et existe-t-il un moyen de le contourner ?
J'ai bien pensé à faire des DELETE NOLOCK mais j'ai là aussi un peu peur des
effets de bord. Nous allons revoir toutes les procédures de façon à plutôt
faire de l'UPDATE/INSERT mais j'aimerai bien coprendre et éviter de retomber
dans ce genre de problème.
Non, n'utilisez pas de DELETE en NOLOCK. Pensez plutôt à baisser le niveau
d'isolation de vos transactions ou bien de faire des delete par block
représentant une page du cluster.
Pour ma part dans ce cas je ferais de multiples transactions en calculant que le
volume des MAJ ne touche pas plus d'une à 8 pages de données (a mesurer).
Vous pouvez aussi obliger certains index à vérouiller plutôt en row ou page à
l'aide de sp_indexoption.
Enfin si le batch est en dehors des heures de prod, pensez à supprimer tous les
index et les recréer en fin de traitement.
Dans tous les cas faîtes des tests !!!
A +
En tout cas, merci pour votre aide préciesue !
Fabrice
--
Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL
Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com
Audit, conseil, expertise, formation, modélisation, tuning, optimisation
********************* http://www.datasapiens.com ***********************
Merci pour toutes ces pistes qui nous ont beaucoup écaliré ! Du coup, nous avons approfondi l'analyse concernant la parallélisation ou serialisation des requêtes. Le problème est donc devenu un tout petit plus complexe mais bien plus clair.
En fait, l'import de données a bien été fait sur une seule et unique connexion. Nous avons bien vérifié tout ça, corrigé certaines bricoles mais le problème persistait, certes moins fréquemment. Il s'avère qu'en fin d'import, un traitement de recalcul ré-utilise ces données qui peuvent évoluer au gré du recalcul et sont donc ré-injectées de la même manière par ce deuxième thread de recalcul. Le problème vient donc bien d'une parallélisation des requêtes. Le seul truc qui m'embête est qu'au moment du deadlock, ce sont bien les mêmes tables qui sont attéquées mais sur des plages de données complètement différentes. (en gros on importe les données sur un dossier client particulier et le recalcul se fait sur un autre dossier, les SELECT sont donc différents) Après lecture de l'aide, il semblerait que dans certains cas, SQL Server pose un verrou exlusif pour étendre ses pages d'index (IX) ce qui bloquerait les autres processus. Partant de ce principe, nous avons essayé d'effectuer des DELETE unitaires (enregistrement par enregistrement) pour limiter les concurrences. Effectivement plus d'erreur mais j'ai peur que ce soit que reculer pour mieux s'écraser plus tard sans compter des temps de traiement qui risque fort de grimper.
Ce comportement est-il normal et existe-t-il un moyen de le contourner ? J'ai bien pensé à faire des DELETE NOLOCK mais j'ai là aussi un peu peur des effets de bord. Nous allons revoir toutes les procédures de façon à plutôt faire de l'UPDATE/INSERT mais j'aimerai bien coprendre et éviter de retomber dans ce genre de problème.
Non, n'utilisez pas de DELETE en NOLOCK. Pensez plutôt à baisser le niveau d'isolation de vos transactions ou bien de faire des delete par block représentant une page du cluster. Pour ma part dans ce cas je ferais de multiples transactions en calculant que le volume des MAJ ne touche pas plus d'une à 8 pages de données (a mesurer). Vous pouvez aussi obliger certains index à vérouiller plutôt en row ou page à l'aide de sp_indexoption. Enfin si le batch est en dehors des heures de prod, pensez à supprimer tous les index et les recréer en fin de traitement. Dans tous les cas faîtes des tests !!!
A +
En tout cas, merci pour votre aide préciesue !
Fabrice
-- Frédéric BROUARD, MVP SQL Server, expert bases de données et langage SQL Le site sur le langage SQL et les SGBDR : http://sqlpro.developpez.com Audit, conseil, expertise, formation, modélisation, tuning, optimisation ********************* http://www.datasapiens.com ***********************