Archives mensuelles : juin 2008

Restauration : Présentation générale.

La plupart des opérations de restauration débutent par la re-création de la base de données à un instant précis, puis appliquent des sauvegardes ulterieures pour ramener la base de données à un point précis dans le temps.

exemple :

RESTORE DATABASE PUBS FROM DISK 'C:\DEMOPUBS.BAK' WITH REPLACE

WITH RECOVERY : la base de données est mise en ligne.
WITH NORECOVERY : la base de données reste fixée à RESTORING, on peux appliquer une nouvelle restauration sur la base.

Sauvegarde différentielle.

exemple :
RESTORE DATABASE PUBS FROM DISK ‘C:\DEMOPUBS_FULL.BAK‘ WITH NORECOVERY
RESTORE DATABASE PUBS FROM DISK ‘C:\DEMOPUBS_DIFF.BAK‘ WITH RECOVERY

Restauration d’une sauvegarde de journal de transaction.

Récupérer une base de données sans aucune perte de données serait plus facile si les problèmes arrivait juste apres une sauvegarde, avant meme que l’application n’est effectue une quelconque transaction. Malheureusement, nous n’avons pas cette chance. Aussi dans tout scénario catastrophe, le journal contient toujours des transactions qui n’ont pas ete sauvegarde.
c’est pour cette raison que la premiere etape de toute operation de recuperation doit toujours consister à emettre une derniere commande backup log. Ce processus capture toute transaction validée non encore sauvegarde et est sauvent nomme sauvegarde de queue de journal. comme vous pouvez executer une commande back up log sur une base de donnée meme en l’indisponibilite de tout fichier de donnees. La sauvegarde de la queue de journal est le dernier journal que vous restaurez dans un processus de restauration. Ainsi, vous ne perdez aucune données.

exemple :

RESTORE DATABASE AdventureWorks FROM DISK ‘c: estawf.bak’ WITH NORECOVERY
RESTORE LOG AdventureWorks FROM DISK ‘c: estaw1.trn’ WITH NORECOVERY
RESTORE LOG AdventureWorks FROM DISK ‘c: estaw2.trn’ WITH RECOVERY

sauvegarde.

Merci à serge934 de la communauté developpez.com (http://www.developpez.net/forums/showthread.php?t=372323)

je te joins un script que j’utilise pour mes backups que j’ai mis dans une PSlancée par un travail

USE Master go
–drop table #BckDatabases
CREATE TABLE #BckDatabases ( databasename sysname)
SET nocount ON
declare @BckPath varchar(255)
declare @Prefix varchar(50)
declare @Extension varchar(10)
/****************************/
/* Paramétrage */
/****************************/
SET @BckPath = ‘chemin_backup’
SET @Prefix = cast(year(getdate()) AS varchar)+cast(month(getdate()) AS varchar)+cast(day(getdate()) AS varchar)
SET @Extension = ‘.bak’
INSERT INTO #BckDatabases values(‘base1′)
INSERT INTO #BckDatabases values(‘base2′) etc…
/****************************/
PRINT  »
PRINT ‘Liste des bases à Backuper :’
SELECT * FROM #BckDatabases
declare @CurrentDB sysname
declare @sql varchar(2000)
declare @fileName varchar(255)
SET nocount off
Declare curDB Cursor FOR
SELECT databasename FROM #BckDatabases
open curDBFetch
next FROM CurDB INTO @CurrentDB
while @@fetch_status = 0
begin SET @FileName = @bckPath +@Prefix +@CurrentDB + @Extension
PRINT ‘====================================================================’ PRINT ‘** ‘+@CurrentDB + ‘ Backup Started on ‘+Cast(GetDate() AS Varchar)
SET @sql = ‘BACKUP DATABASE ‘+@CurrentDB + ‘ TO DISK=N »’ + @filename +  » »
print @sql
exec (@sql)
PRINT ‘** ‘+@CurrentDB + ‘ Backup Ended on ‘+Cast(GetDate() AS Varchar)
PRINT ‘====================================================================’ PRINT  »
Fetch next FROM CurDB INTO @CurrentDB
end
deallocate CurDB
DROP TABLE #BckDatabases

tes sauvegardes s’appelleront
20070704_base1.bak
20070704_base2.bak
20070705_base1.bak
20070705_base2.bak
etc..
ensuite j’ai un travail qui supprime les fichiers dont la date est inférieure a 8 jours de la date du jour.

pour s’assurer que la base est bien sauvegarde, il faut :

tu peux le faire en faisant un « restore verifyonly » après ta sauvegarde. En fait ce n’est pas une restauration mais juste une verif.regardes
http://technet.microsoft.com/fr-fr/library/ms188902.aspx

quelques conseils:

le plan doit contenir:
-reindexations des tables les plus usitées => DBCC DBREINDEX …
-sauvegarde du journal de transaction ( et que lui !) après-test place dispo sur tes devices
-test des jobs qui pourraient se lancer pendant ta sauvegarde
-compactage SANS replacement en tête de fichier
-sauvegarde de tes bases COMPLETES (les differentielles plantent toujours a la restauration sauf chez oracle )
-test avec VERIFYONLY
-zip des .bak
-archivages des bak d’un coté et des zip d’un autre (sur un disque DIFFERENT)
PS: attention si tu es sous RAID5, ne garde que le dernier journal de transaction, supprime (del) les anciens.

verifier qu’une sauvegarde est bonne.

Le seul moyen de s’assurer qu’une sauvegarde est bonne est d’appliquer la restauration sur une nouvelle base.

nom base initial : test
nom base finale : test2

USE master
GO
SELECT ‘kill’,spid
FROM sysprocesses
WHERE dbid=db_id(‘test2′)
GO
/* Exécution de l’output de la commande ci-dessus afin de libérer la base */
GO
RESTORE DATABASE test2 FROM DISK=N'C:\BACKUP\2007711TEST.bak' WITH
MOVE N’TEST’ TO N’C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\test2.mdf‘,
MOVE N’TEST_log’ TO N’C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\Test2_Log.ldf‘, REPLACE
ALTER DATABASE test2 MODIFY FILE (NAME=N’TEST’, NEWNAME=N’test2′)
ALTER DATABASE test2 MODIFY FILE (NAME=N’TEST_log’, NEWNAME=N’test2_log’)
GO

cette technique de restauration en ligne de commande n’est pas tres utilise. Dans l’article suivant, Romelard Fabrice nous explique comment restaurer une base sur une autre à l’aide de sql serveur manager : http://www.technos-sources.com/tutorial.aspx?ID=37

Pour connaitre les processus sur le serveur :
EXEC SP_WHO

choix des tables et colonnes à indexer.

Indexer…
les tables qui ont de nombreuses lignes ( au moins 100 000 ).
les colonnes souvent utilisées dans les requetes.
les colonnes utilisées dans les fonctions d’agregation
les colonnes utilisées dans les requetes group by
les colonnes utilisées dans les requetes order by
les colonnes utilisées dans les jointures, nottament les clef étrangères!

Ne pas indexer…
Les tables qui ont peu de lignes ( moins de 10 000 )
Les colonnes utilisées rarement dans les requêtes
Les colonnes de taille importante
Les colonnes souvent modifiées mais peu interrogées.

FONCTION DE FENETRAGE ET DE RANKING.

Syntaxe :
ROW_NUMBER() OVER([PARTITION BY value_expression ] ORDER BY value_expression)
Définition :
ROW_NUMBER()
Retourne le numéro séquentiel d’une ligne d’une partition d’un jeu de résultats, en commençant à 1 pour la première ligne de chaque partition
PARTITION BY
Divise l’ensemble de résultats en partitions. La fonction de fenêtre est appliquée à chaque partition séparément et le calcul redémarre pour chaque partition.
toute l’information à l’adresse :
http://sqljunkies.com/Article/4E65FA2D-F1FE-4C29-BF4F-543AB384AFBB.scuk

Un exemple d’utilisation :
Fournir les 3 premiers traffic d’un identificateur de cellule par semaine.

CREATE TABLE TRAFFIC_CELLULES(identificateur_de_cellule CHAR(3),traffic INT,date DATETIME);  <br />
 <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('A',100,'01/01/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('A',200,'01/01/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('A',225,'01/01/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('A',400,'01/01/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('A',150,'01/02/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('A',175,'01/02/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('A',200,'01/02/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('B',100,'01/01/2008') <br />
INSERT INTO TRAFFIC_CELLULES(identificateur_de_cellule,traffic,date) VALUES ('B',100,'01/03/2008')  <br />
 <br />
WITH selection <br />
AS <br />
( <br />
SELECT identificateur_de_cellule,traffic,datepart(ww,date) as sem,ROW_NUMBER() OVER (PARTITION BY identificateur_de_cellule,datepart(ww,date) ORDER BY traffic) as OrderRank FROM TRAFFIC_CELLULES <br />
) <br />
SELECT * FROM selection where OrderRank <= 3 <br />
 <br />
Resultat: <br />
 <br />
A      100    1    1 <br />
A      200    1    2 <br />
A      225    1    3 <br />
A      150    5    1 <br />
A      175    5    2 <br />
A      200    5    3 <br />
B      100    1    1 <br />
B      100    9    1