<?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 SQL Server d&#039;ElSüket &#187; sys.messages</title>
	<atom:link href="https://blog.developpez.com/elsuket/ptag/sys-messages/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/elsuket</link>
	<description>Nicolas Souquet - Expert SQL Server</description>
	<lastBuildDate>Mon, 05 Apr 2021 07:32:41 +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>Vous êtes sûr d&#8217;avoir les BACKUP avec CHECKSUM parce que vous utilisez l&#8217;option COMPRESSION ? Vérifiez une seconde fois !</title>
		<link>https://blog.developpez.com/elsuket/p11990/snippets/backup_checksum_compression</link>
		<comments>https://blog.developpez.com/elsuket/p11990/snippets/backup_checksum_compression#comments</comments>
		<pubDate>Sun, 26 May 2013 13:32:34 +0000</pubDate>
		<dc:creator><![CDATA[elsuket]]></dc:creator>
				<category><![CDATA[Moteur de base de données SQL Server]]></category>
		<category><![CDATA[Snippets]]></category>
		<category><![CDATA[BACKUP]]></category>
		<category><![CDATA[CHECKSUM]]></category>
		<category><![CDATA[COMPRESSION]]></category>
		<category><![CDATA[DBCC]]></category>
		<category><![CDATA[DBCC IND]]></category>
		<category><![CDATA[DBCC PAGE]]></category>
		<category><![CDATA[maintenance plan]]></category>
		<category><![CDATA[plan de maintenance]]></category>
		<category><![CDATA[sauvegarde]]></category>
		<category><![CDATA[sys.dm_db_database_page_allocations]]></category>
		<category><![CDATA[sys.messages]]></category>

		<guid isPermaLink="false">http://blog.developpez.com/elsuket/?p=427</guid>
		<description><![CDATA[Après avoir vu comment compresser toutes les sauvegardes de base de données dès SQL Server 2008, il est intéressant de trouver comment activer l&#8217;option CHECKSUM de l&#8217;instruction BACKUP. A ce sujet, la documentation indique : Indique que l&#8217;opération de sauvegarde &#8230; <a href="https://blog.developpez.com/elsuket/p11990/snippets/backup_checksum_compression">Lire la suite <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Après avoir vu comment <a href="http://blog.developpez.com/elsuket/p9040/moteur-de-base-de-donnees-sql-server/compresser_tous_les_backups_sans_modifie_2008">compresser toutes les sauvegardes de base de données</a> dès SQL Server 2008, il est intéressant de trouver comment activer l&rsquo;option CHECKSUM de l&rsquo;instruction BACKUP.</p>
<p>A ce sujet, la documentation indique :</p>
<blockquote><p> Indique que l&rsquo;opération de sauvegarde vérifie dans chaque page les informations de somme de contrôle et de page endommagée, si elles sont activées et disponibles, et génère une somme de contrôle pour l&rsquo;ensemble de la sauvegarde. <strong>Ceci est le comportement par défaut pour une sauvegarde compressée</strong>.</p></blockquote>
<p>Vérifions donc si cela est vrai : nous allons créer une base de données de test, et nous allons corrompre une de ses pages afin de vérifier le comportement de la sauvegarde. En effet, l&rsquo;option CHECKSUM permet de détecter la corruption de données au moment de la sauvegarde. Cela permet en plus de ne pas se retrouver dans l’inconfortable situation de devoir restaurer une base de données à partir d&rsquo;un fichier de sauvegarde corrompu.<br />
<span id="more-427"></span><br />
<img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>La vérification de l&rsquo;intégrité des pages au niveau de la base de données</strong></p>
<p>Par défaut, lorsqu&rsquo;on crée une nouvelle base de données sous SQL Server 2005 et suivants, la vérification de l&rsquo;intégrité des pages lues à partir du disque se fait à l&rsquo;aide d&rsquo;une somme de contrôle. Celle-ci est calculée à partir du contenu de la page, puis écrite dans l&rsquo;en-tête de celle-ci au moment de l&rsquo;écriture sur disque. Lorsque la page est ensuite lue à partir du disque, la somme de contrôle est recalculée, puis comparée à celle qui est dans l&rsquo;en-tête de la page : si les valeurs sont identiques, alors la page est intègre; à l&rsquo;inverse, on obtient l&rsquo;erreur 824, qui est écrite à la fois dans les journaux de SQL Server et dans le journal d&rsquo;événements de Windows.<br />
Enfin lorsqu&rsquo;on restaure une base de données qui a été créée sous une version antérieure à 2005, il est important de changer cette option de TORN_PAGE_DETECTION à PAGE_VERIFY, car la première est conservée par défaut. L&rsquo;option TORN_PAGE_DETECTION stocke deux bits pour chaque secteur de 512 octets de toute page, dont la taille est 8192 octets. De la même façon, ces 16 * 2 bits sont stockés dans l&rsquo;en-tête de la page, et comparés à la relecture de la page. Comme cette option est moins stricte que CHECKSUM, il est donc recommandé d&rsquo;utiliser cette dernière option.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Le test</strong></p>
<p>Nous créons donc la base de données sous SQL Server 2012, puis nous vérifions l&rsquo;option du contrôle de l&rsquo;intégrité des pages :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM;<br />
GO<br />
<br />
<span style="color: #0000FF;">USE</span> TEST_CHECKSUM<br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; name<br />
&nbsp; &nbsp; &nbsp; &nbsp; , page_verify_option_desc<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">databases</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; name <span style="color: #808080;">=</span> <span style="color: #FF0000;">'TEST_CHECKSUM'</span></div></td></tr></tbody></table></div>
<p><img src="http://img843.imageshack.us/img843/1872/backupchecksum01.png" alt="" /></p>
<p>Nous créons ensuite une table dans cette base de données, à laquelle nous ajoutons une ligne :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">USE</span> TEST_CHECKSUM<br />
GO<br />
<br />
<span style="color: #0000FF;">CREATE</span> <span style="color: #0000FF;">TABLE</span> test_backup_checksum<br />
<span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; id <span style="color: #0000FF;">tinyint</span> <span style="color: #0000FF;">IDENTITY</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , nom <span style="color: #0000FF;">varchar</span><span style="color: #808080;">&#40;</span><span style="color: #000;">16</span><span style="color: #808080;">&#41;</span><br />
<span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #0000FF;">INSERT</span> <span style="color: #0000FF;">INTO</span> dbo.<span style="color: #202020;">test_backup_checksum</span> <span style="color: #808080;">&#40;</span>nom<span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">VALUES</span> <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'test_checksum'</span><span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; dbo.<span style="color: #202020;">test_backup_checksum</span></div></td></tr></tbody></table></div>
<p>Nous forçons ensuite l&rsquo;écriture des pages sur disque, à l&rsquo;aide de l&rsquo;instruction <a href="http://blog.developpez.com/elsuket/p9529/moteur-de-base-de-donnees-sql-server/lazywriter_checkpoint_aamp_ghost_cleanup">CHECKPOINT</a>, puis nous vidons le cache de données, de sorte que la prochaine fois que nous exécuterons une requête sur cette table, ses pages seront lues à partir du disque, à l&rsquo;aide de l&rsquo;instruction DBCC DROPCLEANBUFFERS.</p>
<p><strong>N.B. : </strong>N&rsquo;exécutez <strong>JAMAIS</strong> une instruction non-documentée sur une base de données qui sert une charge de production. Si tel devait être le cas, je ne peux <strong>en aucun cas être tenu pour responsable des conséquences. Vous devez limiter strictement l&rsquo;usage de cette instruction aux environnements de test</strong>.</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">CHECKPOINT</span><br />
GO<br />
<br />
<span style="color: #0000FF;">DBCC</span> DROPCLEANBUFFERS<br />
GO</div></td></tr></tbody></table></div>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>L&rsquo;instruction DBCC IND, ou la DMF sys.dm_db_database_page_allocations</strong></p>
<p>Encore deux options d&rsquo;exploration de la mécanique interne de SQL Server, qui permettent de lister les pages d&rsquo;une table ou d&rsquo;un index, et qui ne sont pas documentées. Voici le prototype d&rsquo;utilisation de ces deux alternatives :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">DBCC</span> <span style="color: #808080;">IN</span>D <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TEST_CHECKSUM'</span>, <span style="color: #FF0000;">'dbo.test_backup_checksum'</span>, <span style="color: #000;">1</span><span style="color: #808080;">&#41;</span> <span style="color: #008080;">-- le dernier argument est l'index id</span><br />
GO<br />
<br />
<span style="color: #0000FF;">SELECT</span>&nbsp; allocated_page_file_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocated_page_page_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocated_page_iam_file_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocated_page_iam_page_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">object_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , index_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , partition_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , allocation_unit_type_desc <span style="color: #0000FF;">AS</span> iam_chain_type<br />
&nbsp; &nbsp; &nbsp; &nbsp; , page_type_desc<br />
&nbsp; &nbsp; &nbsp; &nbsp; , page_level<br />
&nbsp; &nbsp; &nbsp; &nbsp; , rowset_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , next_page_file_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; , next_page_page_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; , previous_page_file_id <br />
&nbsp; &nbsp; &nbsp; &nbsp; , previous_page_page_id<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">dm_db_database_page_allocations</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #FF00FF;">DB_ID</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TEST_CHECKSUM'</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF00FF;">OBJECT_ID</span><span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'dbo.test_backup_checksum'</span><span style="color: #808080;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #000;">0</span> <span style="color: #008080;">-- index id : 0 pour un tas, 1 pour un index cluster, plus grand pour un index non-cluster</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #808080;">NULL</span> <span style="color: #008080;">-- partition id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , <span style="color: #FF0000;">'DETAILED'</span> <span style="color: #008080;">-- niveau de détail</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080;">&#41;</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; is_allocated <span style="color: #808080;">=</span> <span style="color: #000;">1</span>;</div></td></tr></tbody></table></div>
<p>On remarque tout de suite que la DMF produit bien plus d&rsquo;informations que l&rsquo;instruction DBCC (nous ne donnons pas ici toutes les colonnes), et que ses arguments sont similaires à la DMF <em>sys.dm_db_index_physical_stats</em>.</p>
<p><img src="http://img689.imageshack.us/img689/1618/backupchecksum02.png" alt="" /></p>
<p>Voyons donc ce que contient la page 272, puisque c&rsquo;est elle qui contient les données (page_type_desc = DATA_PAGE) :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-- Activation de la sortie de la commande DBCC</span><br />
<span style="color: #0000FF;">DBCC</span> TRACEON <span style="color: #808080;">&#40;</span><span style="color: #000;">3604</span><span style="color: #808080;">&#41;</span><br />
GO<br />
<br />
<span style="color: #008080;">-- DBCC PAGE ([database_name_or_id], [file_id], [page_id], [option])</span><br />
<span style="color: #008080;">-- option = 0 montre seulement l'en-tête de la page</span><br />
<span style="color: #0000FF;">DBCC</span> PAGE <span style="color: #808080;">&#40;</span><span style="color: #FF0000;">'TEST_CHECKSUM'</span>, <span style="color: #000;">1</span>, <span style="color: #000;">272</span>, <span style="color: #000;">0</span><span style="color: #808080;">&#41;</span>;<br />
GO</div></td></tr></tbody></table></div>
<p>Nous obtenons :</p>
<blockquote><p>PAGE: (1:272)</p>
<p>BUFFER:</p>
<p>BUF @0x000000027407BB80</p>
<p>bpage = 0x00000002649F4000          bhash = 0x0000000000000000          bpageno = (1:272)<br />
bdbid = 8                           breferences = 0                     bcputicks = 0<br />
bsampleCount = 0                    bUse1 = 33295                       bstat = 0x9<br />
blog = 0x2121215a                   bnext = 0x0000000000000000          </p>
<p>PAGE HEADER:</p>
<p>Page @0x00000002649F4000</p>
<p>m_pageId = (1:272)                  m_headerVersion = 1                 m_type = 1<br />
m_typeFlagBits = 0x0                m_level = 0                         <strong>m_flagBits = 0x8200</strong><br />
m_objId (AllocUnitId.idObj) = 84    m_indexId (AllocUnitId.idInd) = 256<br />
Metadata: AllocUnitId = 72057594043432960<br />
Metadata: PartitionId = 72057594039042048                                Metadata: IndexId = 0<br />
Metadata: ObjectId = 245575913      m_prevPage = (0:0)                  m_nextPage = (0:0)<br />
pminlen = 5                         m_slotCnt = 1                       m_freeCnt = 8069<br />
m_freeData = 121                    m_reservedCnt = 0                   m_lsn = (30:345:30)<br />
m_xactReserved = 0                  m_xdesId = (0:0)                    m_ghostRecCnt = 0<br />
<strong>m_tornBits = 1209479828</strong>             DB Frag ID = 1</p></blockquote>
<p>Si nous nous en référons à la <a href="http://www.sqlskills.com/blogs/paul/inside-the-storage-engine-anatomy-of-a-page/">documentation donnée par Paul Randal</a>, nous avons bien :</p>
<p>&#8211; <em>m_flagBits = 0x8200</em>, qui indique que l&rsquo;intégrité de la page est vérifiée par somme de contrôle<br />
&#8211; <em>m_tornBits</em> est la somme de contrôle de cette page</p>
<p>Nous allons maintenant mettre la base de données hors-ligne, puis éditer le fichier de données avec un éditeur hexadécimal, de façon à vérifier si SQL Server vérifie bien la somme à la lecture de la page :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">DATABASE</span> <span style="color: #0000FF;">SET</span> OFFL<span style="color: #808080;">IN</span>E<br />
GO</div></td></tr></tbody></table></div>
<p>En ce qui concerne la lecture en hexadécimal, j&rsquo;utilise le logiciel <a href="http://www.chmaas.handshake.de/delphi/freeware/xvi32/xvi32.htm">Hex Editor XVI32</a>. Une fois l&rsquo;outil ouvert en tant qu&rsquo;administrateur, il suffit de chercher la chaîne que nous avons ajouté comme ligne dans la table, en suivant le menu <em>Search</em> / <em>Find</em> :</p>
<p><img src="http://img850.imageshack.us/img850/1565/backupchecksum03.png" alt="" /></p>
<p>Un clic sur le bouton OK nous amène directement à l&rsquo;emplacement, où l&rsquo;on est alors libre de changer la chaîne, où j&rsquo;ai changé le &laquo;&nbsp;k&nbsp;&raquo; en &laquo;&nbsp;d&nbsp;&raquo;, puis sauvé le fichier :</p>
<p><img src="http://img833.imageshack.us/img833/341/backupchecksum04.png" alt="" /></p>
<p>Nous remettons la base de données en ligne :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">ALTER</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">SET</span> ONL<span style="color: #808080;">IN</span>E<br />
GO</div></td></tr></tbody></table></div>
<p>Aucun problème. Exécutons un SELECT * FROM dbo.test_backup_checksum. Nous obtenons le message suivant :</p>
<blockquote><p>
Msg 824, Level 24, State 2, Line 1<br />
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0xf9ec3284; actual: 0xfe6c3284). It occurred during a read of page (1:228) in database ID 7 at offset 0x000000001c8000 in file &lsquo;C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TEST_CHECKSUM.mdf&rsquo;.  Additional messages in the SQL Server error log or system event log may provide more detail. This is a severe error condition that threatens database integrity and must be corrected immediately. Complete a full database consistency check (DBCC CHECKDB). This error can be caused by many factors; for more information, see SQL Server Books Online.</p></blockquote>
<p>Prenons maintenant une sauvegarde de cette base de données, avec COMPRESSION, mais sans spécifier l&rsquo;option CHECKSUM :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM.bak'</span><br />
<span style="color: #0000FF;">WITH</span> COMPRESSION<br />
GO</div></td></tr></tbody></table></div>
<p>Aucun problème : nous obtenons :</p>
<blockquote><p>Processed 280 pages for database &lsquo;TEST_CHECKSUM&rsquo;, file &lsquo;TEST_CHECKSUM&rsquo; on file 1.<br />
Processed 3 pages for database &lsquo;TEST_CHECKSUM&rsquo;, file &lsquo;TEST_CHECKSUM_log&rsquo; on file 1.<br />
BACKUP DATABASE successfully processed 283 pages in 0.468 seconds (4.709 MB/sec).</p></blockquote>
<p>Voyons ce que contient la table d&rsquo;historique des sauvegardes :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #FF00FF;">user_name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , backup_start_date<br />
&nbsp; &nbsp; &nbsp; &nbsp; , recovery_model<br />
&nbsp; &nbsp; &nbsp; &nbsp; , has_backup_checksums<br />
&nbsp; &nbsp; &nbsp; &nbsp; , is_damaged<br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; msdb.<span style="color: #202020;">dbo</span>.<span style="color: #202020;">backupset</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; database_name <span style="color: #808080;">=</span> <span style="color: #FF0000;">'TEST_CHECKSUM'</span></div></td></tr></tbody></table></div>
<p><img src="http://img195.imageshack.us/img195/6295/backupchecksum05.png" alt="" /></p>
<p>On obtient un résultat similaire avec l&rsquo;instruction RESTORE HEADERONLY (colonnes <em>HasBackupChecksums</em> et <em>IsDamaged</em> toutes deux à zéro) :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">RESTORE</span> HEADERONLY<br />
<span style="color: #0000FF;">FROM</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM.bak'</span></div></td></tr></tbody></table></div>
<p>Le fichier de sauvegarde ne dispose pas de la somme de contrôle, et n&rsquo;est pas marqué comme endommagé. Pourtant nous avons bien corrompu le fichier de données, et nous ne pouvons pas lire la table que nous avons peuplé auparavant !</p>
<p>Voyons ce que produit la même instruction, avec l&rsquo;option CHECKSUM :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM_CC.bak'</span><br />
<span style="color: #0000FF;">WITH</span> COMPRESSION, <span style="color: #FF00FF;">CHECKSUM</span><br />
GO</div></td></tr></tbody></table></div>
<blockquote><p>Msg 3043, Level 16, State 1, Line 1<br />
BACKUP &lsquo;TEST_CHECKSUM&rsquo; detected an error on page (1:228) in file &lsquo;C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TEST_CHECKSUM.mdf&rsquo;.<br />
Msg 3013, Level 16, State 1, Line 1<br />
BACKUP DATABASE is terminating abnormally.</p></blockquote>
<p>Voyons maintenant la même instruction, seulement avec l&rsquo;option CHECKSUM :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM_CHK.bak'</span><br />
<span style="color: #0000FF;">WITH</span> <span style="color: #FF00FF;">CHECKSUM</span><br />
GO</div></td></tr></tbody></table></div>
<p>Nous obtenons la même erreur. Si nous interrogeons de nouveau la table d&rsquo;historique des sauvegardes pour cette base de données, nous ne trouvons que le premier backup, dont on sait qu&rsquo;il est corrompu. Pourtant nous n&rsquo;avons (presque) aucun moyen de le savoir, car ni cette table, ni l&rsquo;instruction RESTORE HEADERONLY ne permettent de vérifier que le fichier est bien intègre. On peut cependant vérifier les journaux de SQL Server à l&rsquo;aide de la procédure stockée étendue <a href="http://blog.developpez.com/elsuket/p10279/moteur-de-base-de-donnees-sql-server/gestion_lecture_journaux_sql_server"><em>xp_readerrorlog</em></a>, où l&rsquo;on trouve :</p>
<p><img src="http://img17.imageshack.us/img17/9685/backupchecksum06.png" alt="" /></p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Détecter la corruption le plus tôt possible</strong></p>
<p>Une des premières choses à faire après avoir réalisé une installation fraîche de SQL Server est d&rsquo;ajouter une liste d&rsquo;alertes de l&rsquo;Agent SQL Server, qui enverront un mail dès la détection d&rsquo;un problème de corruption. Ceci nécessite le paramétrage de Database Mail, et la mise en place d&rsquo;un opérateur SQL Agent. Voici le code qui permet d&rsquo;ajouter l&rsquo;alerte :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008080;">-------------------------------</span><br />
<span style="color: #008080;">-- Nicolas Souquet - 26/05/2013</span><br />
<span style="color: #008080;">-------------------------------</span><br />
<span style="color: #0000FF;">DECLARE</span> @i <span style="color: #0000FF;">smallint</span> <span style="color: #808080;">=</span> <span style="color: #000;">823</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; , @alert_name sysname<br />
<br />
<span style="color: #0000FF;">DECLARE</span> @operator_name sysname <span style="color: #808080;">=</span> <span style="color: #FF0000;">'monOperateur'</span><br />
<br />
<span style="color: #0000FF;">WHILE</span> @i <span style="color: #808080;">&amp;</span>lt;<span style="color: #808080;">=</span> <span style="color: #000;">825</span><br />
<span style="color: #0000FF;">BEGIN</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SELECT</span>&nbsp; @alert_name <span style="color: #808080;">=</span> <span style="color: #808080;">&amp;</span>#039;Message <span style="color: #808080;">&amp;</span>#039; <span style="color: #808080;">+</span> <span style="color: #0000FF;">CAST</span><span style="color: #808080;">&#40;</span>@i <span style="color: #0000FF;">AS</span> <span style="color: #0000FF;">char</span><span style="color: #808080;">&#40;</span><span style="color: #000;">3</span><span style="color: #808080;">&#41;</span><span style="color: #808080;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">EXEC</span> msdb.<span style="color: #202020;">dbo</span>.<span style="color: #AF0000;">sp_add_alert</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @name <span style="color: #808080;">=</span> @alert_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @message_id <span style="color: #808080;">=</span> @i<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @severity <span style="color: #808080;">=</span> <span style="color: #000;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @enabled <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @delay_between_responses <span style="color: #808080;">=</span> <span style="color: #000;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @include_event_description_in <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @job_id <span style="color: #808080;">=</span> N<span style="color: #808080;">&amp;</span>#039;00000000<span style="color: #808080;">-</span>0000<span style="color: #808080;">-</span>0000<span style="color: #808080;">-</span>0000<span style="color: #808080;">-</span>000000000000<span style="color: #808080;">&amp;</span>#039;<br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">EXEC</span> msdb.<span style="color: #202020;">dbo</span>.<span style="color: #AF0000;">sp_add_notification</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @alert_name <span style="color: #808080;">=</span> @alert_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @operator_name <span style="color: #808080;">=</span> @operator_name<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; , @notification_method <span style="color: #808080;">=</span> <span style="color: #000;">1</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #0000FF;">SET</span> @i <span style="color: #808080;">=</span> @i <span style="color: #808080;">+</span> <span style="color: #000;">1</span><br />
<span style="color: #0000FF;">END</span></div></td></tr></tbody></table></div>
<p>L&rsquo;erreur qui nous intéresse est la 824, mais les erreurs 823 et 825 sont importantes aussi. Pour trouver leur signification, il suffit d&rsquo;interroger la vue système <em>sys.messages</em> :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">SELECT</span>&nbsp; <span style="color: #808080;">*</span><br />
<span style="color: #0000FF;">FROM</span>&nbsp; &nbsp; sys.<span style="color: #202020;">messages</span><br />
<span style="color: #0000FF;">WHERE</span> &nbsp; message_id <span style="color: #808080;">BETWEEN</span> <span style="color: #000;">823</span> <span style="color: #808080;">AND</span> <span style="color: #000;">825</span><br />
<span style="color: #808080;">AND</span> &nbsp; &nbsp; language_id <span style="color: #808080;">=</span> <span style="color: #000;">1036</span> <span style="color: #008080;">-- Français</span></div></td></tr></tbody></table></div>
<p>On peut faire de même avec l&rsquo;erreur n° 3043, qui est celle que l&rsquo;on obtient lors de la sauvegarde.</p>
<p><img src="http://img12.imageshack.us/img12/5913/iconarrowp.gif" alt="" /> <strong>Activer CHECKSUM pour toutes les sauvegardes</strong></p>
<p>Cela devrait aussi faire partie de la checklist d&rsquo;installation de SQL Server, d&rsquo;autant que c&rsquo;est d&rsquo;une simplicité enfantine : il suffit d&rsquo;activer le drapeau de trace n° 3023 :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">DBCC</span> TRACEON <span style="color: #808080;">&#40;</span><span style="color: #000;">3023</span>, <span style="color: #808080;">-</span><span style="color: #000;">1</span><span style="color: #808080;">&#41;</span></div></td></tr></tbody></table></div>
<p>Après avoir exécuté cette instruction, si nous ré-exécutons maintenant la commande suivante :</p>
<div class="codecolorer-container tsql vibrant" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br /></div></td><td><div class="tsql codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #0000FF;">BACKUP</span> <span style="color: #0000FF;">DATABASE</span> TEST_CHECKSUM<br />
<span style="color: #0000FF;">TO</span> <span style="color: #0000FF;">DISK</span> <span style="color: #808080;">=</span> <span style="color: #FF0000;">'F:\SQLServer2012\TEST_CHECKSUM.bak'</span><br />
<span style="color: #0000FF;">WITH</span> COMPRESSION<br />
GO</div></td></tr></tbody></table></div>
<p>Nous obtenons l&rsquo;erreur que nous avions obtenue lorsque nous avions ajouté l&rsquo;option CHECKSUM :</p>
<blockquote><p>Msg 3043, Level 16, State 1, Line 1<br />
BACKUP &lsquo;TEST_CHECKSUM&rsquo; detected an error on page (1:228) in file &lsquo;C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\DATA\TEST_CHECKSUM.mdf&rsquo;.<br />
Msg 3013, Level 16, State 1, Line 1<br />
BACKUP DATABASE is terminating abnormally.</p></blockquote>
<p>Ceci est très pratique :</p>
<p>&#8211; Si l&rsquo;on prend les sauvegardes de base de données à l&rsquo;aide de <a href="http://blog.developpez.com/elsuket/p11161/agent-sql-server/supporter_plan_de_maintenance">plans de maintenance</a>, il est impossible de spécifier que l&rsquo;on souhaite avoir la somme de contrôle;<br />
&#8211; Si l&rsquo;on code une procédure stockée qui s&rsquo;en charge, cela évite d&rsquo;avoir à l&rsquo;ajouter dans le code.</p>
<p>D&rsquo;autre part si la <a href="http://blog.developpez.com/elsuket/p9040/moteur-de-base-de-donnees-sql-server/compresser_tous_les_backups_sans_modifie_2008">compression des sauvegardes est activée au niveau de l&rsquo;instance</a>, on n&rsquo;a plus qu&rsquo;a se soucier de la sauvegarde elle-même !</p>
<p>Bonnes sauvegardes et intégrité de pages à tous !</p>
<p>ElSüket.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
