<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Le blog de SQLpro &#187; verrou</title>
	<atom:link href="https://blog.developpez.com/sqlpro/ptag/verrou/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/sqlpro</link>
	<description>Le SQL pour SQL Server, PostGreSQL et tous les autres SGBDR</description>
	<lastBuildDate>Thu, 15 Oct 2020 12:59:17 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Une peste nommée NOLOCK&#8230; et comment l&#8217;éviter</title>
		<link>https://blog.developpez.com/sqlpro/p13181/langage-sql-norme/une-peste-nommee-nolock-et-comment-leviter</link>
		<comments>https://blog.developpez.com/sqlpro/p13181/langage-sql-norme/une-peste-nommee-nolock-et-comment-leviter#comments</comments>
		<pubDate>Sun, 08 Jul 2018 14:55:07 +0000</pubDate>
		<dc:creator><![CDATA[SQLpro]]></dc:creator>
				<category><![CDATA[Langage SQL (norme)]]></category>
		<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[SQL Server 2017]]></category>
		<category><![CDATA[ISOLATION]]></category>
		<category><![CDATA[NOLOCK]]></category>
		<category><![CDATA[SNAPSHOT]]></category>
		<category><![CDATA[transaction]]></category>
		<category><![CDATA[verrou]]></category>
		<category><![CDATA[verrouilage]]></category>
		<category><![CDATA[verrous]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/sqlpro/?p=818</guid>
		<description><![CDATA[L&#8217;utilisation du tag de table NOLOCK, hélas largement prisé par de nombreux développeurs, est, la plupart du temps, une absurdité conduisant à des résultats potentiellement faux. Est-il possible de faire autrement pour minimiser les blocages induit par les verrouillages dans SQL Server ? Réponse OUI ! À la suite de cette remarque : &#171;&#160;&#8230;je passe [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>L&rsquo;utilisation du tag de table NOLOCK, hélas largement prisé par de nombreux développeurs, est, la plupart du temps, une absurdité conduisant à des résultats potentiellement faux. Est-il possible de faire autrement pour minimiser les blocages induit par les verrouillages dans SQL Server ? Réponse OUI !<br />
<span id="more-818"></span><br />
À la suite de cette remarque :<br />
<em>&laquo;&nbsp;&#8230;je passe aussi sur le NOLOCK qui est une véritable connerie en production et donne des valeurs fausses !&nbsp;&raquo;</em><br />
Publiée ici :<br />
<a href="https://www.developpez.net/forums/d1870299/bases-donnees/ms-sql-server/developpement/utilisation-excessive-structure-conditionnelle-choix-multiples/#post10343427" rel="noopener" target="_blank"></a><br />
Mon interlocuteur me répondais :<br />
<em>&laquo;&nbsp;Merci pour cette précision. Comme vous abordez le sujet du NOLOCK effectivement j&rsquo;ai constaté certaines fois en production on avait des valeurs totalement erronées, mais je n&rsquo;arrivais pas à me l&rsquo;expliquer. J&rsquo;ai maintenant une piste et je vais creuser du côté du NOLOCK que nous utilisons beaucoup en production sur une base de données CRM 2013. Aussi par quoi pouvons nous remplacer le NOLOCK ??&nbsp;&raquo;</em></p>
<p>Je lui donnais donc l&rsquo;explication suivante&#8230;<br />
<strong><br />
Le &laquo;&nbsp;NOLOCK&nbsp;&raquo; peut parfaitement se remplacer par le niveau d&rsquo;isolation SNAPSHOT</strong> par exemple&#8230;</p>
<p>NOLOCK ne signifie pas &laquo;&nbsp;<em>je ne pose pas de verrou</em>&laquo;&nbsp;, mais plus précisément : &laquo;&nbsp;<em>j&rsquo;ignore qu&rsquo;il y a des verrous et je lit ce que je peut</em>&nbsp;&raquo; (ceci est plus connu dans la littérature professionnelle sous le nom de <em><strong>lecture dans le chaos</strong></em>&#8230;). Vous pouvez donc lire plusieurs fois les mêmes données ou encore ne pas lire certaines.</p>
<p><strong>Quid du mode SNAPSHOT ?</strong></p>
<p>SNAPSHOT fait du verrouillage optimiste pour les lectures. Par défaut SQL Server fait du verrouillage pessimiste, c&rsquo;est à dire que les lectures posent des verrous qui permettent d&rsquo;autres lectures concurrentes (verrous partagés, mode &laquo;&nbsp;SHARE&nbsp;&raquo;), mais empêchent les écritures des autres utilisateurs. Conceptuellement, le verrouillage optimiste (donc via le mode d’isolation SNAPSHOT) fait une copie (si besoin) des données avant de permettre leurs lectures. Comme vous travaillez sur une copie, les utilisateurs concurrent peuvent modifier les vraies ligne sans que cela vous concerne. Bien entendu il peut toujours y avoir des conflits, mais cela réduit considérablement le nombre de verrous bloquants tout en gardant l&rsquo;intégrité et la consistante de la base, ce qui n&rsquo;est pas du tout le cas du NOLOCK.</p>
<p><strong>Alors, à quoi sert le NOLOCK ? </strong></p>
<p>Cela peut servir pour certains cas ou l&rsquo;on désire des résultats dont on se fout de l&rsquo;intégrité ou de la précision. Souvent dans le domaine de la statistique.<br />
par exemple si vous voulez savoir combien les français ont d&rsquo;enfant par foyer et scrutez donc, pour ce faire, une table de 60 millions de lignes (population française), je ne suis pas sûr que dans un camembert représentant la chose, on fasse la distinction des quelques pixels de l&rsquo;imprécision de la 6e décimale du résultat liées à quelques mauvaises lectures de lignes !<br />
On utilise d&rsquo;ailleurs très souvent le NOLOCK pour des tâches d&rsquo;administration systèmes dans SQL Server afin d&rsquo;éviter tout blocage au risque de perdre quelques lignes, ce qui n&rsquo;a pas toujours une importance capitale lorsque l&rsquo;on veut remonter quelques informations concernant les 20% de requêtes les moins performantes !</p>
<p><strong>Mais alors, le SNAPSHOT fait la même chose en mieux ? </strong></p>
<p>Oui et non&#8230; Certes il permet de garantir l&rsquo;intégrité, la consistance, etc&#8230; mais son mécanisme est plus lourd (un peu moins rapide) et consomme des ressources pour générer les copies (SNAPSHOT). Rassurez-vous il est assez malin pour ne faire ces copies qui s&rsquo;il a besoin de les faire&#8230; En d&rsquo;autres termes si aucun utilisateur concurrent veut faire des modif sur le jeu de lignes que vous manipulez en mode SNAPSHOT, aucune copie ne sera générée. Mais si, lorsque vous avez démarré une lecture en mode SNAPSHOT, un utilisateur concurrent veut modifier des lignes, et bien la copie sera réalisée au cours de votre lecture sans que vous vous en aperceviez&#8230; En quelque sorte le système fonctionne à l&rsquo;envers&#8230; Bien évidemment il faut un espace de stockage pour ces copies et c&rsquo;est la base tempdb qui s&rsquo;y colle. Il faut donc, la dimensionner correctement&#8230;<br />
Tiens, à nouveau un travail de DBA !</p>
<p><strong>Des conflits ! Quels conflits ?</strong></p>
<p>J&rsquo;ai précédemment parlé de conflits possible avec l&rsquo;utilisation du mode SNAPSHOT. En effet, si vous voulez modifier des données lors d&rsquo;une transaction en mode d’isolation SNAPSHOT, c&rsquo;est possible, mais ces modifications seront faites sur la copie, et non sur la base originale, et seront reportées sur la base originale au moment du COMMIT. Deux hypothèses se font alors jour :<br />
■ soit aucune ligne visée par vos modifications faites en mode SNAPSHOT n&rsquo;a été modifié dans une autre session directement sur la base, alors la mise à jour est appliquée.<br />
Ou alors :<br />
■ s&rsquo;il existe au moins une ligne qui a été modifiée par une autre session entre temps sur la base originale, alors vos modifications ne pourront être appliquées aux données originales et vont êtres abandonnées.<br />
Dans ce dernier cas vous obtiendrez une message d&rsquo;erreur (3960) assez abscons, qui indique :<br />
<em>&laquo;&nbsp;La transaction d&rsquo;isolement d&rsquo;instantané a été abandonnée en raison d&rsquo;un conflit de mise à jour. &#8230;&nbsp;&raquo;</em></p>
<p>Notez qu&rsquo;il existe un autre tag plus intéressant que le NOLOCK&#8230;. Le <strong>READPAST</strong> !&#8230;  Qui fait presque la même chose, mais ignore tout ce qui est verrouillé !</p>
<p><strong>Les modes d&rsquo;isolation selon la norme SQL</strong></p>
<p>Sachez que le mode d’isolation SNAPSHOT ne fait pas partie de la norme SQL qui n&rsquo;autorise que les modes d&rsquo;isolation suivants :<br />
0 &#8211; READ UNCOMMITTED : lecture des données invalides (non &laquo;&nbsp;committées&nbsp;&raquo;)<br />
1 &#8211; READ COMMITTED : lecture de données valides (ce qui n&rsquo;empêche pas certaines anomalies transactionnelles comme la lecture non répétable, ou l&rsquo;apparition de lignes fantômes)<br />
2 &#8211; REPEATABLE READ : lecture répétable de données (ce qui n&rsquo;empêche pas certaines anomalies transactionnelles comme l&rsquo;apparition de lignes fantômes)<br />
3 &#8211; SERIALIZABLE : lecture en mode série (aucun accès concurrent aux tables lors des mises à jour, ce qui empêche toute anomalies)<br />
Évidemment plus on monte le niveau d’isolation, plus le verrouillage est important et moins les accès concurrents peuvent travailler.<br />
La norme SQL considère que les manipulation des données doivent porter sur des valeurs &laquo;&nbsp;vivantes&nbsp;&raquo;. Hors, en utilisant le mode SNAPSHOT et son versionnement des lignes, ont est appelé à lire potentiellement des valeurs antérieurs des données, ce n&rsquo;est donc pas une lecture de l&rsquo;état actuel des valeurs dans la base&#8230;</p>
<p>Pour informations, des SGBRD comme Oracle, ou PostGreSQL fonctionnent nativement en mode d&rsquo;isolation SNAPSHOT, autrement dit utilisent systématiquement le verrouillage optimiste et ne savent pas faire autres choses (verrouillage pessimiste en particulier) voir ne savent même pas utiliser certains autres niveau d&rsquo;isolation. Par exemple PostGreSQL ne permet pas de faires des transaction en mode READ UNCOMMITTED et Oracle ne permettent pas d&rsquo;utiliser le niveau d&rsquo;isolation REPEATABLE READ&#8230;</p>
<p><strong>Activer le mode s&rsquo;isolation SNAPSHOT</strong></p>
<p>Pour permettre ce mode d&rsquo;isolation, vous devez d&rsquo;abord autoriser la base à utiliser le mode SNAPSHOT. Ce paramétrage est à deux niveaux :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER DATABASE { CURRENT | nom_base } SET ALLOW_SNAPSHOT_ISOLATION ON;</div></div>
<p>permet d&rsquo;utiliser à tout moment le mode d’isolation SNAPSHOT qui doit être introduit préalablement par la commande SET TRANSACTION ISOLATION SNAPSHOT ou par un tag de table (SNAPSHOT)<br />
&#8230; et :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">ALTER DATABASE { CURRENT | nom_base } SET READ_COMMITTED_SNAPSHOT ON;</div></div>
<p>qui place d&rsquo;office toutes les lectures en mode SNAPSHOT (comme le fait Oracle ou PostGreSQL);<br />
<strong>ATTENTION</strong> : pour assurer le versionnement des lignes, SQL Server rajoute à toutes les lignes de toutes les tables une information de version qui est codé sur 14 octets. Ceci peut prendre du temps à mettre en œuvre, en particulier sur de grosses bases.<br />
<strong></p>
<p>Appendice :</strong></p>
<p>Pour une démonstration des effets du NOLOCK : <a href="http://mssqlserver.fr/les-dangers-du-nolock/" rel="noopener" target="_blank">http://mssqlserver.fr/les-dangers-du-nolock/</a></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Frédéric Brouard, alias SQLpro, ARCHITECTE DE DONNÉES<br />
Expert &nbsp;S.G.B.D &nbsp;relationnelles &nbsp; et &nbsp; langage &nbsp;S.Q.L<br />
Moste &nbsp;Valuable &nbsp;Professionnal &nbsp;Microsoft &nbsp;SQL Server<br />
Société SQLspot &nbsp;: &nbsp;modélisation, conseil, formation,<br />
optimisation, &nbsp;audit, &nbsp;tuning, &nbsp;administration &nbsp;SGBDR<br />
Enseignant: CNAM PACA, ISEN Toulon, CESI Aix en Prov.</div></div>
<p>L&rsquo;entreprise <a href="http://www.sqlspot.com">SQL Spot</a><br />
<strong>Le site web sur le </strong><a href="http://sqlpro.developpez.com/">SQL et les SGBDR</a></p>
<p><img src="http://blog.developpez.com/media/Microsoft_MVP_logo_vertical Brouard 400.jpg" width="400" height="135" alt="MVP Microsoft SQL
Server" /></p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Déblocage d&#8217;une instance SQL Server bloquée</title>
		<link>https://blog.developpez.com/sqlpro/p13127/ms-sql-server/sql-server-2005/deblocage-dune-instance-bloquee</link>
		<comments>https://blog.developpez.com/sqlpro/p13127/ms-sql-server/sql-server-2005/deblocage-dune-instance-bloquee#comments</comments>
		<pubDate>Thu, 12 Jan 2017 14:12:46 +0000</pubDate>
		<dc:creator><![CDATA[SQLpro]]></dc:creator>
				<category><![CDATA[SQL Server 2005]]></category>
		<category><![CDATA[SQL Server 2008]]></category>
		<category><![CDATA[SQL Server 2012]]></category>
		<category><![CDATA[SQL Server 2014]]></category>
		<category><![CDATA[SQL Server 2016]]></category>
		<category><![CDATA[attente]]></category>
		<category><![CDATA[blocage]]></category>
		<category><![CDATA[SQL server]]></category>
		<category><![CDATA[verrou]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/sqlpro/?p=727</guid>
		<description><![CDATA[Il arrive, souvent à cause d&#8217;un mauvais développement (voir en gras italique plus loin), qu&#8217;un serveur SQL se bloque du fait des verrous. Une session en bloque autre qui en bloque plusieurs autres&#8230; et c&#8217;est l&#8217;effet boule de neige. La plupart du temps, les développeurs ou pseudo DBA réagissent mal en relaçant le service SQL [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Il arrive, souvent à cause d&rsquo;un mauvais développement (voir en <em><strong>gras italique</strong></em> plus loin), qu&rsquo;un serveur SQL se bloque du fait des verrous. Une session en bloque autre qui en bloque plusieurs autres&#8230; et c&rsquo;est l&rsquo;effet boule de neige. La plupart du temps, les développeurs ou pseudo DBA réagissent mal en relaçant le service SQL Server ce qui fait perdre une grande partie des mises à jour demandées, empêchent les utilisateurs de travailler et pour peu qu&rsquo;une longue transaction n&rsquo;ai pas encore enregistrées les données, rend indisponible la base après le redémarrage du serveur, souvent pendant de longues minutes&#8230; Tout cela pouvant être évité avec un peu d&rsquo;analyse et surtout la bonne requête que je vous présente, destinées à débloquer sans frustrer !<br />
<span id="more-727"></span><br />
Un blocage est une situation normale dans une base de données, comme dans la vie courante. Les feux rouges, l&rsquo;accès à des toilettes, les portiques de sécurité des aéroports, sont autant de points ou vous pouvez vous retrouvé bloqué pendant un certain temps, et cela est normal et fait partie de la vie. Les bases de données devant assurer la cohérence entre ceux qui lisent les données et ceux qui les écrivent, doivent poser des verrous afin de bloquer les utilisateurs concurrents dans certaines situations. Le principe est le suivant :</p>
<ul>
<li>un utilisateur qui <strong>lit</strong> des données, doit bloquer l&rsquo;accès aux utilisateurs qui veulent modifier les mêmes données, mais n&rsquo;empêchent pas d&rsquo;autres utilisateurs de lire en même temps les mêmes données. Dans ce cas la base pose un <strong>verrou partagé</strong> (shared), qui peut être pessimiste (posé préventivement) ou optimiste (actionné après coup).</li>
<li>un utilisateur qui <strong>écrit</strong> des données doit empêcher toute lecture et toute écriture concurrente. On parle alors de <strong>verrou exclusif</strong>.</li>
</ul>
<p>Si une session doit faire différentes modification au sein d&rsquo;une même transaction, les verrous vont être maintenus jusqu&rsquo;à ce qu&rsquo;intervienne la finalisation de la transaction, par un COMMIT (validation) ou un ROLLBACK (annulation). Pendant ce temps, si d&rsquo;autres utilisateurs doivent accéder à ces données, il faut qu&rsquo;ils patientent. C&rsquo;est la notion de blocage. Un blocage est donc une situation normale dans une base de données, comme c&rsquo;est le cas de madame Michu qui patiente dans sa 4L au feu rouge pour laisser passer les automobiliste de la voie latérale.<br />
Ce qui n&rsquo;est pas toujours normal, c&rsquo;est un blocage qui dure, longtemps, voire, très, très longtemps&#8230; mais jamais de manière éternelle, car la situation doit se débouquer à la fin du traitement bloquant, c&rsquo;est une certitude !<br />
Dans ce cas, il est possible que d&rsquo;autres utilisateurs se retrouvent bloqués, alors que même, ils ont déjà entamé des modification de données, susceptible d&rsquo;entrainer d&rsquo;autres blocages ! D’où l&rsquo;effet boule de neige&#8230; Là encore cette situation peut être normale, si le bloqueur de tête met à jour une très importante quantité de données alors que beaucoup d&rsquo;utilisateurs sont en train de parcourir ces mêmes données ! Mais dans bien des cas, c&rsquo;est une situation anormale, généralement due à des mauvaises pratiques de développement, tel que <em><strong>des transaction démarré côté client, des transactions avec interactions de l&rsquo;utilisateur, le forçage de verrous (les SGBDR se débrouillent généralement mieux tous seuls), des transactions non finalisées, l&rsquo;usage d&rsquo;un niveau d&rsquo;isolation inappropriée, l&rsquo;utilisation de code itératif eu lieu de code ensembliste, l&rsquo;oubli de poser les index adéquats, l&rsquo;utilisation de tables obèses, le recours systématique aux curseur, l’usage immodéré des déclencheurs</strong></em>, etc !<br />
Bref, la question est, en présence d&rsquo;un tel blocage, comment faire ?</p>
<p>LA SOLUTION</p>
<p>Elle consiste tout simplement à recherche qui bloque qui, et remonter jusqu&rsquo;à bloqueur de tête pour le forcer à abandonner son traitement. Problème, cela nécessite de parcourir récursivement l&rsquo;arbre de blocage de blocage&#8230; Second problème, il peut y avoir plusieurs chaines de blocage !<br />
La DMV sys.dm_exec_requests permet de savoir qui bloque qui dans l&rsquo;état actuel de l&rsquo;instance. Les deux colonnes qui nous intéressent pour ce faire sont :</p>
<ul>
<li>session_id : l&rsquo;identifiant de la session en cours</li>
<li>blocking_session_id : l&rsquo;identifiant de la session qui bloque</li>
</ul>
<p><div id="attachment_737" style="width: 688px" class="wp-caption aligncenter"><a href="http://blog.developpez.com/sqlpro/files/2017/01/blocage_session_chaine_arbre_sql_server1.jpg"><img src="http://blog.developpez.com/sqlpro/files/2017/01/blocage_session_chaine_arbre_sql_server1.jpg" alt="Différentes chaines de blocage de sessions dans SQL Server (en fait des arbres)" width="678" height="403" class="size-full wp-image-737" /></a><p class="wp-caption-text">Différentes chaines de blocage de sessions dans SQL Server (en fait des arbres)</p></div><br />
Dans la figure ci avant, les sessions 53 et 57 sont les leaders et bloquent respectivement :</p>
<ul>
<li>pour le 53, 11 session avec une profondeur maximale de 5</li>
<li>pour le 57, 3 sessions avec une profondeur maximale de 3</li>
</ul>
<p>Il faudrait débloquer en priorité le 53, attendre quelques instants pour voir si cela ne débloque pas le 57.</p>
<p>À partir de ces seules deux informations (session_id et blocking_session_id), nous pouvons remonter jusqu’aux bloqueurs de tête. L&rsquo;écriture de cette requête doit procéder en deux temps :<br />
rechercher les bloquers de tête, c&rsquo;est à dire ceux qui ne sont pas bloqués par d&rsquo;autres, mais qui en bloque d&rsquo;autres. Une fois ces &laquo;&nbsp;leaders&nbsp;&raquo; trouvés, il suffit de descendre dans l&rsquo;arbre de blocage pour comptabiliser le nombre de sessions bloquées et la profondeur du blocage.<br />
Il suffit alors de tuer les &laquo;&nbsp;lead blockers&nbsp;&raquo; les plus prégnants, c&rsquo;est à dire en général ceux qui bloquent le plus de session, ceux qui ont la plus grande profondeur de blocage, ceux dont le temps de traitement a été le plus long, ceux ayant consommé le plus d&rsquo;IO, ceux ayant la requête la moins critique&#8230;. À vous de choisir !</p>
<p>La requête !</p>
<div class="codecolorer-container sql default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="sql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #993333; font-weight: bold;">WITH</span><br />
T_SESSION <span style="color: #993333; font-weight: bold;">AS</span><br />
<span style="color: #66cc66;">&#40;</span><br />
<span style="color: #808080; font-style: italic;">-- on récupère les sessions en cours des utilisateurs</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> session_id<span style="color: #66cc66;">,</span> blocking_session_id<br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; sys<span style="color: #66cc66;">.</span>dm_exec_requests <span style="color: #993333; font-weight: bold;">AS</span> tout<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp;session_id <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">50</span><br />
<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
T_LEAD <span style="color: #993333; font-weight: bold;">AS</span><br />
<span style="color: #66cc66;">&#40;</span><br />
<span style="color: #808080; font-style: italic;">-- on recherche les bloqueurs de tête</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> session_id<span style="color: #66cc66;">,</span> blocking_session_id<br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; T_SESSION <span style="color: #993333; font-weight: bold;">AS</span> tout<br />
<span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp;session_id <span style="color: #66cc66;">&gt;</span> <span style="color: #cc66cc;">50</span><br />
&nbsp; <span style="color: #993333; font-weight: bold;">AND</span> &nbsp;blocking_session_id <span style="color: #66cc66;">=</span> <span style="color: #cc66cc;">0</span><br />
&nbsp; <span style="color: #993333; font-weight: bold;">AND</span> &nbsp;<span style="color: #993333; font-weight: bold;">EXISTS</span><span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; T_SESSION <span style="color: #993333; font-weight: bold;">AS</span> tin<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">WHERE</span> &nbsp;tin<span style="color: #66cc66;">.</span>blocking_session_id <span style="color: #66cc66;">=</span> tout<span style="color: #66cc66;">.</span>session_id<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
T_CHAIN <span style="color: #993333; font-weight: bold;">AS</span><br />
<span style="color: #66cc66;">&#40;</span><br />
<span style="color: #808080; font-style: italic;">-- requête récursive pour trouver les chaines de blocage</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> session_id <span style="color: #993333; font-weight: bold;">AS</span> lead_session_id<span style="color: #66cc66;">,</span> session_id<span style="color: #66cc66;">,</span> blocking_session_id<span style="color: #66cc66;">,</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> p<br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; T_LEAD<br />
<span style="color: #993333; font-weight: bold;">UNION</span> &nbsp;<span style="color: #993333; font-weight: bold;">ALL</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> C<span style="color: #66cc66;">.</span>lead_session_id<span style="color: #66cc66;">,</span> S<span style="color: #66cc66;">.</span>session_id<span style="color: #66cc66;">,</span> S<span style="color: #66cc66;">.</span>blocking_session_id<span style="color: #66cc66;">,</span> p<span style="color: #66cc66;">+</span><span style="color: #cc66cc;">1</span> <br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; T_CHAIN <span style="color: #993333; font-weight: bold;">AS</span> C<br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">JOIN</span> T_SESSION <span style="color: #993333; font-weight: bold;">AS</span> S<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> C<span style="color: #66cc66;">.</span>session_id <span style="color: #66cc66;">=</span> S<span style="color: #66cc66;">.</span>blocking_session_id<br />
<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><br />
T_WEIGHT <span style="color: #993333; font-weight: bold;">AS</span><br />
<span style="color: #66cc66;">&#40;</span><br />
<span style="color: #808080; font-style: italic;">-- calculs finaux</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> lead_session_id <span style="color: #993333; font-weight: bold;">AS</span> LEAD_BLOCKER<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">COUNT</span><span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">*</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span><span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> BLOCKED_SESSION_COUNT<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">MAX</span><span style="color: #66cc66;">&#40;</span>p<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> <span style="color: #cc66cc;">1</span> <span style="color: #993333; font-weight: bold;">AS</span> BLOCKED_DEEP<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #ff0000;">'KILL '</span> <span style="color: #66cc66;">+</span> <span style="color: #993333; font-weight: bold;">CAST</span><span style="color: #66cc66;">&#40;</span>lead_session_id <span style="color: #993333; font-weight: bold;">AS</span> <span style="color: #993333; font-weight: bold;">VARCHAR</span><span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">16</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">+</span> <span style="color: #ff0000;">';'</span> <span style="color: #993333; font-weight: bold;">AS</span> SQL_CMD<br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; T_CHAIN<br />
<span style="color: #993333; font-weight: bold;">GROUP</span> &nbsp;<span style="color: #993333; font-weight: bold;">BY</span> lead_session_id<br />
<span style="color: #66cc66;">&#41;</span><br />
<span style="color: #993333; font-weight: bold;">SELECT</span> T<span style="color: #66cc66;">.*,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;DB_NAME<span style="color: #66cc66;">&#40;</span>r<span style="color: #66cc66;">.</span>database_id<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> database_name<span style="color: #66cc66;">,</span> host_name<span style="color: #66cc66;">,</span> program_name<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;nt_user_name<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;q<span style="color: #66cc66;">.</span>text <span style="color: #993333; font-weight: bold;">AS</span> sql_command<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp;DATEDIFF<span style="color: #66cc66;">&#40;</span>ms<span style="color: #66cc66;">,</span> last_request_start_time<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">COALESCE</span><span style="color: #66cc66;">&#40;</span>last_request_end_time<span style="color: #66cc66;">,</span> GETDATE<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> duration_ms<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;s<span style="color: #66cc66;">.</span>open_transaction_count<span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp;r<span style="color: #66cc66;">.</span>cpu_time<span style="color: #66cc66;">,</span> r<span style="color: #66cc66;">.</span>reads<span style="color: #66cc66;">,</span> r<span style="color: #66cc66;">.</span>writes<span style="color: #66cc66;">,</span> r<span style="color: #66cc66;">.</span>logical_reads<span style="color: #66cc66;">,</span> r<span style="color: #66cc66;">.</span>total_elapsed_time <br />
<span style="color: #993333; font-weight: bold;">FROM</span> &nbsp; T_WEIGHT <span style="color: #993333; font-weight: bold;">AS</span> T<br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">JOIN</span> sys<span style="color: #66cc66;">.</span>dm_exec_sessions <span style="color: #993333; font-weight: bold;">AS</span> s <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> T<span style="color: #66cc66;">.</span>LEAD_BLOCKER <span style="color: #66cc66;">=</span> s<span style="color: #66cc66;">.</span>session_id<br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">JOIN</span> sys<span style="color: #66cc66;">.</span>dm_exec_requests <span style="color: #993333; font-weight: bold;">AS</span> r <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #993333; font-weight: bold;">ON</span> s<span style="color: #66cc66;">.</span>session_id <span style="color: #66cc66;">=</span> r<span style="color: #66cc66;">.</span>session_id<br />
&nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #993333; font-weight: bold;">OUTER</span> APPLY sys<span style="color: #66cc66;">.</span>dm_exec_sql_text<span style="color: #66cc66;">&#40;</span>sql_handle<span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> q<br />
<span style="color: #993333; font-weight: bold;">ORDER</span> &nbsp;<span style="color: #993333; font-weight: bold;">BY</span> BLOCKED_SESSION_COUNT <span style="color: #993333; font-weight: bold;">DESC</span><span style="color: #66cc66;">,</span> BLOCKED_DEEP <span style="color: #993333; font-weight: bold;">DESC</span>;</div></div>
<p>Cette requête présente les sessions bloquant les autres sessions, en déterminant la session à la tête d&rsquo;une chaine de blocage (LEAD_BLOCKER), avec le nombre de sessions bloquées (BLOCKED_SESSION_COUNT) et la longueur maximale de la chaîne de blocage (BLOCKED_DEEP). Ceci permet de déterminer quelle session est à annuler en priorité en cas de blocage intempestif et d&rsquo;utiliser la commande KILL (SQL_CMD) qui termine la session fautive en forçant un ROLLBACK. Les autres colonnes donnent des informations sur la requête qui a bloqué (texte SQL, base, origine du code, métriques diverses&#8230;) </p>
<p><strong>ATTENTION </strong><br />
Ne pas confondre blocage et interblocage (ou étreinte fatale, ou encore verrou mortel&#8230;). Dans un interblocage, une session bloque des ressources qu&rsquo;une autre session veut obtenir, tandis que cette même session demandeuse a bloqué des objets que la première a besoin. Dans ce cas, nous pouvons atteindre éternellement, car le blocage ne peut être résolu par l&rsquo;attente. Le seul moyen consiste donc à sacrifier une des victimes de ce blocage et lui forçant une annulation de la transaction. Ceci est détecté automatiquement dans les bons SGBDR, qui procèdent automatiquement à l&rsquo;achèvement d&rsquo;une des victimes. Dans SQL Server, le message est intentionnellement significatif : <em>&laquo;&nbsp;La transaction (ID de processus %1!) a été bloquée sur les ressources &#8230; par un autre processus et a été choisie comme victime. Réexécutez la transaction.&nbsp;&raquo;</em></p>
<p><strong>LE CODE * LE CODE * LE CODE * LE CODE * LE CODE * LE CODE * LE CODE * LE CODE * LE CODE</strong><br />
<a href="http://sqlpro.developpez.com/_fichierSQL/LeadBlocker.txt" title="Fichier du code" target="_blank">Le code !</a></p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Frédéric Brouard, alias SQLpro, ARCHITECTE DE DONNÉES<br />
Expert &nbsp;S.G.B.D &nbsp;relationnelles &nbsp; et &nbsp; langage &nbsp;S.Q.L<br />
Moste &nbsp;Valuable &nbsp;Professionnal &nbsp;Microsoft &nbsp;SQL Server<br />
Société SQLspot &nbsp;: &nbsp;modélisation, conseil, formation,<br />
optimisation, &nbsp;audit, &nbsp;tuning, &nbsp;administration &nbsp;SGBDR<br />
Enseignant: CNAM PACA, ISEN Toulon, CESI Aix en Prov.</div></div>
<p>L&rsquo;entreprise <a href="http://www.sqlspot.com">SQL Spot</a><br />
<strong>Le site web sur le </strong><a href="http://sqlpro.developpez.com/">SQL et les SGBDR</a></p>
<p><img src="http://blog.developpez.com/media/Microsoft_MVP_logo_vertical Brouard 400.jpg" width="400" height="135" alt="MVP Microsoft SQL
Server" /></p>
<div id="attachment_590" style="width: 548px" class="wp-caption alignnone"><a href="http://blog.developpez.com/sqlpro/files/2015/09/Couverture-livre-SQL-server-Eyrolles.jpg"><img src="http://blog.developpez.com/sqlpro/files/2015/09/Couverture-livre-SQL-server-Eyrolles.jpg" alt="Développez et administrez pour la performance avec SQL Server 2014" width="538" height="652" class="size-full wp-image-590" /></a><p class="wp-caption-text">Développez et administrez pour la performance avec SQL Server 2014</p></div>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
