<?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>Cap Data Team SGBD Blog : Oracle, SQL Server, MySQL, Sybase... &#187; mode de récupération</title>
	<atom:link href="http://blog.capdata.fr/index.php/tag/mode-de-recuperation/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.capdata.fr</link>
	<description>Le blog technique sur les bases de données de CAP DATA Consulting</description>
	<lastBuildDate>Wed, 01 Feb 2012 17:21:53 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Modes de récupération et journal de transactions, épisode 1</title>
		<link>http://blog.capdata.fr/index.php/modes-de-recuperation-et-journal-de-transactions-episode-1/</link>
		<comments>http://blog.capdata.fr/index.php/modes-de-recuperation-et-journal-de-transactions-episode-1/#comments</comments>
		<pubDate>Fri, 13 Jun 2008 12:16:18 +0000</pubDate>
		<dc:creator>David BAFFALEUF</dc:creator>
				<category><![CDATA[SQL Server]]></category>
		<category><![CDATA[journal de transactions]]></category>
		<category><![CDATA[mode de récupération]]></category>
		<category><![CDATA[Sauvegarde & Restauration]]></category>

		<guid isPermaLink="false">http://192.168.1.220:8080/blogs/sqlserver/?p=4</guid>
		<description><![CDATA[Une petite série de posts sur les différents modes de récupération des bases sous SQL Server 2005/2008, et leur impact sur le journal de transactions.
Dans ce premier épisode:

Qu&#8217;implique le passage de SIMPLE à COMPLET.
Que devient mon journal en mode COMPLET si je ne le sauvegarde pas régulièrement.

Le mode de récupération (recovery model en anglais) est [...]]]></description>
			<content:encoded><![CDATA[<p>Une petite série de posts sur les différents modes de récupération des bases sous SQL Server 2005/2008, et leur impact sur le journal de transactions.</p>
<p><strong>Dans ce premier épisode:</strong></p>
<ol>
<li>Qu&#8217;implique le passage de SIMPLE à COMPLET.</li>
<li>Que devient mon journal en mode COMPLET si je ne le sauvegarde pas régulièrement.</li>
</ol>
<p>Le mode de récupération (<em>recovery model</em> en anglais) est une propriété de base de données qui va préciser pour celle-ci deux choses essentielles:</p>
<ol>
<li>Le recyclage de l&#8217;espace consommé par les transactions validées dans son journal  de transactions.</li>
<li>La possibilité ou non de pouvoir sauvegarder ces transactions validées.</li>
</ol>
<p>Il existe trois modes de récupération: <strong>FULL</strong>,<strong> SIMPLE </strong>et <strong>BULK-LOGGED</strong>.</p>
<p><strong>FULL: </strong>c&#8217;est le mode par défaut. Dans ce mode, toutes les transactions sont journalisées, même les  opérations de modifications de masse (CREATE INDEX, BULK INSERT ou bcp.exe, SELECT INTO, et les opérations sur les champs TEXT). Dès l&#8217;instant où il y a eu au moins une sauvegarde complète sur la base, les transactions validées restent dans le journal. La seule façon de recycler l&#8217;espace occupé par ces transactions est de lancer régulièrement une sauvegarde du journal. Les transactions validées sont sauvegardées dans un fichier et sont alors supprimées du journal * .</p>
<p><strong>SIMPLE: </strong>dans ce mode, le recyclage des transactions validées est la responsabilité du checkpoint. En plus de flusher sur disque les pages de données modifiées dans le cache de données, le checkpoint supprime les transactions validées du journal sans les sauvegarder. Conséquence de celà, je n&#8217;ai pas la possibilité de sauvegarder mes transactions en mode SIMPLE. Je ne pourrai exécuter que des sauvegardes complètes ou différentielles (ou de fichier en lecture seule).</p>
<p><strong>BULK-LOGGED: </strong>c&#8217;est un mode à combiner avec le mode FULL. Dans ce mode, les opérations de modification de masse (citées plus haut) ne sont pas complètement journalisées, et l&#8217;impact de telles opérations sur le journal est limité. Le fait de changer de FULL à BULK-LOGGED ne modifie en rien ma façon de sauvegarder mes bases. En mode BULK-LOGGED, mes sauvegardes transactionnelles horaires continuent de s&#8217;exécuter sans problème. Très utile lorsqu&#8217;on lance notre réorganisation des indexes hebdomadaire car on gagne un temps fou.</p>
<table border="0">
<tbody>
<tr>
<td bgcolor="#dddddd"><em><strong>*: </strong>il existe au moins deux exceptions à cette règle: si la base est principale dans une session de miroir synchrone et que le site miroir est injoignable, où si la base est publiée dans le cadre d&#8217;une réplication transactionnelle et que la distribution ou l&#8217;agent de lecture du journal sont injoignables / inactifs. Dans ces deux cas, les transactions en attente (non envoyées au miroir, non écrites dans la base distribution) restent dans le journal et ne sont pas vidées par les sauvegardes de transactions.</em></td>
</tr>
</tbody>
</table>
<p><strong>Note: </strong>Attention à ne pas confondre mode de récupération FULL et sauvegarde FULL.</p>
<p><strong>Pour retrouver le mode de récupération d&#8217;une base:</strong></p>
<pre><span>SELECT</span><span> DATABASEPROPERTYEX(<span>'maBase'</span>,<span>'RECOVERY'</span>) <span>as</span> RECOVERYMODE</span></pre>
<p class="MsoNormal"><strong>Pour changer le mode d&#8217;une base:</strong></p>
<p class="MsoNormal">
<pre><span>ALTER</span><span> <span>DATABASE</span> maBase <span>SET</span> RECOVERY [ FULL | SIMPLE | BULK_LOGGED ]</span></pre>
<p class="MsoNormal">
<p><strong>1) Première remarque: il faudra obligatoirement (re)lancer une sauvegarde complète avant de sauvegarder le journal:</strong><br />
- Quand je créé ma base.<br />
- Quand je passe de SIMPLE à FULL.</p>
<p>La sauvegarde de transaction a besoin d&#8217;un numéro de transaction (LSN pour Log Sequence Number) de référence pour savoir à partir de quelle transaction commencer sa sauvegarde. Lorsqu&#8217;il n&#8217;y a pas eu d&#8217;autre sauvegarde de transactions avant elle, comme c&#8217;est le cas quand je passe de SIMPLE à FULL ou quand je viens de créer ma base, elle se base sur le LSN de fin de la dernière sauvegarde complète dans le même mode. Le fonctionnement précis de la sauvegarde à chaud fera l&#8217;objet d&#8217;un autre article prochainement.</p>
<p>Pour le mettre en évidence, créons-nous une petite base CRASHTEST:<br />
<span><br />
</span></p>
<pre><span>CREATE</span><span> <span>DATABASE</span> CRASHTEST</span></pre>
<pre><span>on</span><span> <span>PRIMARY</span></span></pre>
<pre><span>(NAME=<span>'CRASHTEST_data'</span>,</span></pre>
<pre><span>FILENAME=<span>'F:\KATMAI\MSSQL10.KATMAI\MSSQL\DATA\CRASHTEST_data.mdf'</span>,</span></pre>
<pre><span>SIZE=100MB, MAXSIZE=500MB)</span></pre>
<pre><span>LOG <span>ON</span></span></pre>
<pre><span>(NAME=<span>'CRASHTEST_log'</span>,</span></pre>
<pre><span>FILENAME=<span>'F:\KATMAI\MSSQL10.KATMAI\MSSQL\DATA\CRASHTEST_log.ldf'</span>,</span></pre>
<pre><span>SIZE=50MB,
MAXSIZE=500MB)</span></pre>
<p>Vérifions son mode de récupération:</p>
<pre><span>SELECT</span><span> DATABASEPROPERTYEX(<span>'CRASHTEST'</span>,<span>'RECOVERY'</span>) <span>as</span> RECOVERYMODE</span></pre>
<pre>RECOVERYMODE
---------------------------------------------------------
FULL</pre>
<p>Créons une petite transaction et essayons de la sauvegarder:</p>
<pre><span>use</span><span> CRASHTEST</span></pre>
<pre><span>create</span><span> <span>table</span> TABLE1 (A numeric <span>identity</span>, B varchar(5000))</span></pre>
<pre><span>insert</span><span> <span>into</span> TABLE1 <span>values</span> (replicate(<span>'b'</span>,5000))</span></pre>
<pre><span>backup</span><span> log CRASHTEST <span>to</span> disk=<span>'C:\CRASHTEST.log1.trn'</span> <span>with</span><span> </span>init, stats</span></pre>
<pre><span><em>Msg 4214, Level 16, State 1, Line 1</em></span></pre>
<pre><span><em>
BACKUP LOG cannot be performed because there is no current database backup.</em></span></pre>
<p><span><em> </em></span><br />
J&#8217;ai donc effectivement besoin d&#8217;avoir une sauvegarde complète pour initialiser ma chaîne:</p>
<pre><span>backup</span><span> <span>database</span> CRASHTEST <span>to</span> disk=<span>'C:\CRASHTEST.1.bak'</span> <span>with</span> init, stats</span></pre>
<pre><span><em>Processed 152 pages for database 'CRASHTEST', file 'CRASHTEST_data' on file 1.
100 percent processed.
Processed 1 pages for database 'CRASHTEST', file 'CRASHTEST_log' on file 1.
BACKUP DATABASE successfully processed 153 pages in 0.266 seconds (4.711 MB/sec).
</em></span></pre>
<p>OK, je retente de sauvegarder mon log:</p>
<pre><span>backup</span><span> log CRASHTEST <span>to</span> disk=<span>'C:\CRASHTEST.log1.trn'</span> <span>with</span><span> </span>init, stats</span></pre>
<pre><span><em>100 percent processed.</em></span></pre>
<pre><span><em>
Processed 6 pages for database 'CRASHTEST', file 'CRASHTEST_log' on file 1.</em></span></pre>
<pre><span><em>
BACKUP LOG successfully processed 6 pages in 0.161 seconds (0.283 MB/sec).</em></span></pre>
<p><span><em> </em></span><br />
Même problème lorsque je passe de SIMPLE à FULL:</p>
<pre><span>ALTER</span><span> <span>DATABASE</span> CRASHTEST <span>set</span> RECOVERY SIMPLE</span></pre>
<pre><span>ALTER</span><span> <span>DATABASE</span> CRASHTEST <span>set</span> RECOVERY <span>FULL</span></span></pre>
<pre><span>backup</span><span> log CRASHTEST <span>to</span> disk=<span>'C:\CRASHTEST.log2.trn'</span> <span>with</span> init, stats</span></pre>
<pre><span><em>Msg 4214, Level 16, State 1, Line 1
BACKUP LOG cannot be performed because there is no current database backup.</em></span></pre>
<p><strong>2) SAUVEGARDEZ VOS TRANSACTIONS !</strong></p>
<p>C&#8217;est un problème que l&#8217;on retrouve chez beaucoup de clients: grands comptes, PME&#8230; Il y a toujours chez eux au moins une base de données en mode de récupération FULL dont le journal n&#8217;a JAMAIS été sauvegardé. Ce n&#8217;est pas étonnant en un sens puisque FULL est le mode par défaut pour toutes les bases créées par l&#8217;utilisateur. Le résultat est un fichier LDF qui fait 80 Gb parce qu&#8217;il contient une année ou deux de transactions validées, sauvegardées dans des backup FULL depuis belle lurette, mais on le répète, en mode FULL, il n&#8217;y a qu&#8217;une sauvegarde de journal qui permet de recycler l&#8217;espace occupé par des transactions validées.</p>
<p>Reprenons notre base CRASHTEST, et créons un peu de volumétrie&#8230;</p>
<pre><span>USE</span><span> CRASHTEST</span></pre>
<pre><span>declare</span><span> @cpt int</span></pre>
<pre><span>set</span><span> @cpt=1</span></pre>
<pre><span>while</span><span>(@cpt&lt;=50000)</span></pre>
<pre><span>begin</span></pre>
<pre><span>insert</span><span> <span>into</span> TABLE1 <span>values</span> (replicate(<span>'b'</span>,5000))</span></pre>
<pre><span>set</span><span><span> </span>@cpt=@cpt+1</span></pre>
<pre><span>end</span></pre>
<pre><span>go</span></pre>
<p>&#8230;et vérifions quelle est la situation du journal à l&#8217;issue:</p>
<pre><span>DBCC</span><span> SQLPERF(LOGSPACE)</span></pre>
<pre>Database Name       Log Size (Mb)    Log Space Used (%)      Status
------------------  ---------------  ----------------------  --------
(...)               (...)            (...)                   (...)
CRASHTEST           253,3047         97,07731                0</pre>
<p>Il a plus que quadruplé de volume et il est plein.</p>
<p>Pour récupérer l&#8217;espace sur le disque, il faudra faire un DBCC SHRINKFILE en mode TRUNCATEONLY.<br />
Si je lance le DBCC SHRINKFILE tout de suite:</p>
<p><span><br />
</span></p>
<pre><span>DBCC</span><span> SHRINKFILE(’CRASHTEST_log’,<span>'TRUNCATEONLY’)</span></span></pre>
<pre>Dbid        Fileid        CurrentSize        MinimumSize    UsedPages         EstimatedPages
---------   ----------- ----------------  ---------------- ---------------   ------------------
8           2            31680            6400             31680             6400</pre>
<p>31680*8192Kb = 247,5 Mb, autant dire que presque rien n&#8217;a été fait. Celà vient du fait que le TRUNCATEONLY tronque la taille du fichier jusqu&#8217;au dernier extent alloué.<br />
Comme mon journal est plein, le dernier extent alloué est précisément à la fin du fichier.</p>
<p>Donc il faut commencer par vider ce journal: je sauvegarde ma transaction :</p>
<pre><span>backup</span><span> log CRASHTEST <span>to</span> disk=<span>'C:\CRASHTEST.log3.trn'</span> <span>with</span> init, stats, compression</span></pre>
<pre><span>go</span></pre>
<pre><span>
100 percent processed.</span></pre>
<pre><span>
Processed 31461 pages for database 'CRASHTEST', file 'CRASHTEST_log' on file 3.</span></pre>
<pre><span>
BACKUP LOG successfully processed 31461 pages in 16.391 seconds (15.723 MB/sec).</span></pre>
<p><span> </span><br />
Dans mon journal&#8230;</p>
<pre><span>DBCC</span><span> SQLPERF(LOGSPACE)</span></pre>
<pre>Database Name        Log Size (Mb)    Log Space Used (%)      Status
------------------   ---------------  ----------------------  --------
(...)                (...)            (...)                   (...)
CRASHTEST            247,4922         4,201521                 0</pre>
<p>Je retrouve mon enveloppe à 247,5Mb, et cette fois elle est bien vide. Je vais pouvoir ramener mon log à sa taille d&#8217;origine:</p>
<pre><span>DBCC</span><span> SHRINKFILE(’CRASHTEST_log’,<span>'TRUNCATEONLY’)</span></span></pre>
<p><span><br />
</span></p>
<pre>Dbid        Fileid        CurrentSize        MinimumSize    UsedPages         EstimatedPages
---------   ----------- ----------------  ---------------- ---------------   ------------------
8           2            6400               6400            6400              6400</pre>
<p>Attention, si je choisis de rester en mode FULL, je devrai programmer des sauvegardes de transactions (à travers le SQL Agent par exemple).</p>
<p>Dans le cas où ce journal fait plusieurs dizaines de Gb, je choisis de le vider en passant la base en mode SIMPLE:</p>
<pre><span lang="EN-GB">ALTER</span><span lang="EN-GB"> <span>DATABASE</span> CRASHTEST <span>SET</span> RECOVERY SIMPLE</span></pre>
<p>Un checkpoint initié dès la fin de l&#8217;ALTER se chargera de vider le contenu du journal, et il ne restera plus qu&#8217;à faire le SHRINKFILE.</p>
<p>A suivre l&#8217;effet du BULK-LOGGED sur la taille du journal&#8230;</p>
<p>[ David B. ]</p>
<p> <script type="text/javascript" src="http://tcr.tynt.com/javascripts/Tracer.js?user=d4FlbGI04r35lZadbi-bpO"></script><strong>Continuez votre lecture sur le blog :</strong>
<ul class="similar-posts">
<li><a href="http://blog.capdata.fr/index.php/sqldiag-episode-1/" rel="bookmark" title="5 février 2010">SQLDIAG (épisode 1)</a> (David BAFFALEUF) [SQL Server]</li>
<li><a href="http://blog.capdata.fr/index.php/journees-sql-server-a-paris-les-12-et-13-decembre-2011/" rel="bookmark" title="25 octobre 2011">Journées SQL Server à Paris les 12 et 13 décembre 2011 !</a> (David BAFFALEUF) [SQL Server]</li>
<li><a href="http://blog.capdata.fr/index.php/abonnez-vous-au-blog-de-la-capdata-team/" rel="bookmark" title="23 juin 2010">Abonnez-vous au blog de la CapData team !</a> (Cédric PEINTRE) [GénéralMySQLOracleSQL ServerSybase]</li>
<li><a href="http://blog.capdata.fr/index.php/regenerer-le-ddl-des-indexes-full-text/" rel="bookmark" title="12 octobre 2011">Regénérer le DDL des indexes FULL TEXT</a> (David BAFFALEUF) [SQL Server]</li>
<li><a href="http://blog.capdata.fr/index.php/consistence-des-ecritures-avec-sata/" rel="bookmark" title="13 mars 2011">Consistence des écritures avec SATA</a> (David BAFFALEUF) [Operating SystemSQL Server]</li>
</ul>
<p><!-- Similar Posts took 3.106 ms -->
<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fmodes-de-recuperation-et-journal-de-transactions-episode-1%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fblog.capdata.fr%2Findex.php%2Fmodes-de-recuperation-et-journal-de-transactions-episode-1%2F&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
]]></content:encoded>
			<wfw:commentRss>http://blog.capdata.fr/index.php/modes-de-recuperation-et-journal-de-transactions-episode-1/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

