Checkliste SQL Server Datenbankmigration

cover image of blog article 'Checkliste SQL Server Datenbankmigration'

Immer wieder kommt das Szenario auf, dass eine oder mehrere Benutzerdatenbanken von einem auf den anderen Server migriert werden sollen. Dieser Prozess birgt die ein oder andere Falle, in die unerfahrene Datenbankentwickler:innen tappen können. Wir möchten Ihnen mit diesem Artikel eine Art Checkliste an die Hand geben, in der die wichtigsten Schritte, Maßnahmen und Eigenschaften festgehalten sind. Denn wie Sie vermutlich wissen, können kleinste Fehler schwerwiegende Leistungseinbrüche nach sich ziehen und Ausfallzeiten verursachen. Folgen Sie unseren Schritten und halten sich an die Checkliste, können Sie zumindest das Gröbste vermeiden.

Was ist vor der Migration zu beachten?

  • Analysieren Sie den verfügbaren Speicherplatz des Zielservers, auf den die neue Datenbank migriert werden soll. Reicht der Speicherplatz nicht aus, müssen Sie entsprechend weiteren Speicherplatz hinzufügen.
  • Wählen Sie den Speicherort der Daten und der Protokolldatei auf dem Zielserver.
  • Analysieren und sammeln Sie Infos zu den Datenbankeigenschaften. Dazu zählen z.B. Eigenschaften wie Auto Stats, DB Owner, Recovery Model, Compatibility Level, Trustworthy Option…
  • Berücksichtigen Sie Informationen zu abhängigen Anwendungen. Sie sollten dafür sorgen, dass entsprechende Anwendungen im worst case auch gestoppt werden können.
  • Stellen Sie Informationen zu Datenbankanmeldungen, Usern und deren Berechtigungen zusammen.
  • Überprüfen Sie die Datenbank auf Karteileichen und verwaiste Nutzer.
  • Überprüfen Sie den SQL Server auf abhängige Objekte, wie SQL Agent Jobs oder Verbindungsserver.
  • Checken Sie, ob die Datenbank Teil eines Wartungsplans ist.

Folgend stellen wir Ihnen die Skripts zusammen, die Sie zum Überprüfen der obenstehenden Fakten verwenden können:

Überprüfen der Festplatten- & Datenbankgröße

exec master..xp_fixeddrives
-- To Check database size
exec sp_helpdb [dbName]
--or
use [dbName]
select str(sum(convert(dec(17,2),size)) / 128,10,2)  + 'MB'
from dbo.sysfiles
GO

Überprüfen der Datenbankeigenschaften

Use [dbName]
select
 sysDB.database_id, 
 sysDB.Name AS "Database Name", 
 syslogin.Name AS "DB Owner", 
 sysDB.state_desc, 
 sysDB.recovery_model_desc, 
 sysDB.collation_name, 
 sysDB.user_access_desc, 
 sysDB.compatibility_level, 
 sysDB.is_read_only, 
 sysDB.is_auto_close_on , 
 sysDB.is_auto_shrink_on, 
 sysDB.is_auto_create_stats_on, 
 sysDB.is_auto_update_stats_on, 
 sysDB.is_fulltext_enabled, 
 sysDB.is_trustworthy_on 
from sys.databases sysDB 
INNER JOIN sys.syslogins syslogin ON sysDB.owner_sid = syslogin.sid

oder alternativ:

declare @dbdesc varchar(max)
declare @name varchar(10)
set @name='Master'
SELECT @dbdesc = 'Status=' + convert(sysname,DatabasePropertyEx(@name,'Status'))  
SELECT @dbdesc = @dbdesc + ', Updateability=' + convert(sysname,DatabasePropertyEx(@name,'Updateability'))  
SELECT @dbdesc = @dbdesc + ', UserAccess=' + convert(sysname,DatabasePropertyEx(@name,'UserAccess'))  
SELECT @dbdesc = @dbdesc + ', Recovery=' + convert(sysname,DatabasePropertyEx(@name,'Recovery'))  
SELECT @dbdesc = @dbdesc + ', Version=' + convert(sysname,DatabasePropertyEx(@name,'Version'))  
  
 -- These props only available if db not shutdown  
 IF DatabaseProperty(@name, 'IsShutdown') = 0  
 BEGIN  
  SELECT @dbdesc = @dbdesc + ', Collation=' + convert(sysname,DatabasePropertyEx(@name,'Collation'))  
  SELECT @dbdesc = @dbdesc + ', SQLSortOrder=' + convert(sysname,DatabasePropertyEx(@name,'SQLSortOrder'))  
 END  
  
 -- These are the boolean properties  
 IF DatabasePropertyEx(@name,'IsAutoClose') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAutoClose'  
 IF DatabasePropertyEx(@name,'IsAutoShrink') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAutoShrink'  
 IF DatabasePropertyEx(@name,'IsInStandby') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsInStandby'  
 IF DatabasePropertyEx(@name,'IsTornPageDetectionEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsTornPageDetectionEnabled'  
 IF DatabasePropertyEx(@name,'IsAnsiNullDefault') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAnsiNullDefault'  
 IF DatabasePropertyEx(@name,'IsAnsiNullsEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAnsiNullsEnabled'  
 IF DatabasePropertyEx(@name,'IsAnsiPaddingEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAnsiPaddingEnabled'  
 IF DatabasePropertyEx(@name,'IsAnsiWarningsEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAnsiWarningsEnabled'  
 IF DatabasePropertyEx(@name,'IsArithmeticAbortEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsArithmeticAbortEnabled'  
 IF DatabasePropertyEx(@name,'IsAutoCreateStatistics') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAutoCreateStatistics'  
 IF DatabasePropertyEx(@name,'IsAutoUpdateStatistics') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsAutoUpdateStatistics'  
 IF DatabasePropertyEx(@name,'IsCloseCursorsOnCommitEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsCloseCursorsOnCommitEnabled'  
 IF DatabasePropertyEx(@name,'IsFullTextEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsFullTextEnabled'  
 IF DatabasePropertyEx(@name,'IsLocalCursorsDefault') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsLocalCursorsDefault'  
 IF DatabasePropertyEx(@name,'IsNullConcat') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsNullConcat'  
 IF DatabasePropertyEx(@name,'IsNumericRoundAbortEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsNumericRoundAbortEnabled'  
 IF DatabasePropertyEx(@name,'IsQuotedIdentifiersEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsQuotedIdentifiersEnabled'  
 IF DatabasePropertyEx(@name,'IsRecursiveTriggersEnabled') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsRecursiveTriggersEnabled'  
 IF DatabasePropertyEx(@name,'IsMergePublished') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsMergePublished'  
 IF DatabasePropertyEx(@name,'IsPublished') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsPublished'  
 IF DatabasePropertyEx(@name,'IsSubscribed') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsSubscribed'  
 IF DatabasePropertyEx(@name,'IsSyncWithBackup') = 1  
  SELECT @dbdesc = @dbdesc + ', ' + 'IsSyncWithBackup'  
SELECT @dbdesc

Suche nach verwaisten Benutzern:

sp_change_users_login 'report'
GO

Suche nach Verbindungsservern:

select  *
from sys.sysservers

Auflistung der datenbankabhängigen Jobs:

USE [msdb]
select 
 distinct 
 name,
 database_name
from sysjobs sj
INNER JOIN sysjobsteps sjt on sj.job_id = sjt.job_id

Durchführung der Datenbankmigration

  1. Stoppen Sie laufende Anwendungsdienste
  2. Änderung der Datenbank in einen schreibgeschützten Modus mit folgendem Skript:
USE [master] 
GO 
ALTER DATABASE [DBName] SET READ_ONLY WITH NO_WAIT 
GO 
ALTER DATABASE [DBName] SET READ_ONLY 
GO
  1. Erstellen Sie eine Sicherung aller an der Migration beteiligten Datenbanken
  2. Stellen Sie die besagten Datenbanken auf dem Zielserver in den entsprechenden Laufwerken wieder her
  3. Vergleichen Sie die Datenbankeigenschaften mit den Ergebnissen der zuvor ausgeführten Skripte und passen sie, falls notwendig, die Eigenschaften an.

Ändern des Datenbankbesitzers

Durch folgendes Skript ändern sie den Datenbank-Eigentümer in sa. Mit dem Skript können Sie auch andere User zum Eigentümer ernennen.

USE [DBName] 
EXEC sp_changedbowner 'sa'

Aktivieren der vertrauenswürdigen Option

Mit der Datenbankeigenschaft TRUSTWORTHY wird angegeben, ob die SQL Server-Instanz die Datenbank und ihre Inhalte als vertrauenswürdig einstuft. War diese Option zuvor gesetzt, können Sie sie mit diesem Statement wieder aktivieren.

ALTER DATABASE DBName SET TRUSTWORTHY ON

Ändern des Kompatibilitätsgrads

Dies ist vor allem notwendig bei einem Upgrade auf eine neuere Version. Es wird standardmäßig der vorhandene Kompatibilitätsgrad übernommen.

ALTER DATABASE DBName 
SET SINGLE_USER 
GO 
EXEC sp_dbcmptlevel DBName, 150; 
GO 
ALTER DATABASE DBName
SET MULTI_USER 
GO

Verwaiste User identifizieren

Führen Sie folgende Skripts auf dem Zielserver aus um nach verwaisten Benutzern zu suchen und dieses Problem auch direkt zu beheben.

EXEC sp_change_users_login 'Report'
--Use below code to fix the Orphan User issue
DECLARE @username varchar(25)
DECLARE fixusers CURSOR 
FOR
SELECT UserName = name FROM sysusers
WHERE issqluser = 1 and (sid is not null and sid <> 0x0)
and suser_sname(sid) is null
ORDER BY name
OPEN fixusers
FETCH NEXT FROM fixusers
INTO @username
WHILE @@FETCH_STATUS = 0
BEGIN
EXEC sp_change_users_login 'update_one', @username, @username
FETCH NEXT FROM fixusers
INTO @username
END
CLOSE fixusers
DEALLOCATE fixusers

DBCC CHECKDB bei SQL Server Versionsupdate

Wenn Sie auf eine neuere SQL Server Version wechseln, führen Sie danach DBCC UPDATEUSAGE für die wiederhergestellte Datenbank aus. Nutzen Sie dafür den folgenden Code:

DBCC UPDATEUSAGE('database_name') WITH COUNT_ROWS 
DBCC CHECKDB 
ODER 
DBCC CHECKDB('database_name') WITH ALL_ERRORMSGS

Index-Neuaufbau oder Reorganisation

Je nach Bedarf wird ein Neuaufbau oder reine Reorganisation vorhandener Indizes benötigt. Der Neuaufbau löscht den vorhandenen Index und erstellt einen neuen.

GO 
ALTER INDEX ALL ON [ObjectName] REBUILD 
GO

Die Reorganisation organisiert den Blattknoten des Index physikalisch.

USE AdventureWorks; 
GO 
ALTER INDEX ALL ON [Objektname] REORGANIZE 
GO

Aktualisieren Sie im Nachgang ihre Indexstatistik mit folgendem Code:

sp_updatestats

Prozeduren kompilieren

Kompilieren Sie die gespeicherten Prozeduren neu.

sp_recompile 'procedureName'

Applikationsdienste & Windows Event Log

Testen Sie im Nachgang die Anwendungsfunktionalität durch einen Neustart der Anwendungsdienste. Checken Sie unbedingt die Windows-Ereignisprotokolle auf Auffälligkeiten.

Fehlerprotokoll überprüfen

Überprüfen Sie das SQL Server Fehlerprotokoll auf Auffälligkeiten und Fehler jeglicher Art wie z.B. Login-Fehler.

EXEC xp_readerrorlog 0,1,"Error",Null

Quellsystem offline nehmen

Laufen alle Anwendungen einwandfrei und so, wie Sie es sich vorgestellt haben, können Sie die Datenbanken auf dem Quellserver offline schalten. Alternativ können Sie die Datenbanken auch einfach schreibgeschützt machen.

USE [master] 
GO 
ALTER DATABASE [DBName] SET READ_ONLY WITH NO_WAIT 
GO 
ALTER DATABASE [DBName] SET READ_ONLY 
GO

oder alternativ:

EXEC sp_dboption N'DBName', N'offline', N'true'
OR
ALTER DATABASE [DBName] SET OFFLINE WITH
ROLLBACK IMMEDIATE

Nächste Schritte

Mit den obigen Checklisten für die Vorbereitung und Durchführung der Migration, sollten Sie auf die allermeisten Fallen vorbereitet sein. Weiterhin sollten Sie den Prozess testen und im Auge behalten. Es gibt vielerlei Optimierungen, die Sie individuell vornehmen können und sollten. Dazu gehört beispielsweise die Überwachung wie viel Zeit und Speicherplatz benötigt werden. Hierbei ist ein Sicherungs- & Wiederherstellungsprozess hilfreich. Auch ist es hilfreich, einen Rollback-Plan zu erstellen, sollte die Anwendung nicht Ihren Anforderungen nach optimal laufen. Fügen Sie der Checkliste weitere Migrationsfälle und Auffälligkeiten hinzu, die Ihnen auffallen und in Zukunft helfen können.

Gerne helfen wir Ihnen bei Ihrer Datenbankmigration weiter. Als zertifizierte Experten auf diesem Gebiet können wir Ihnen individuelle Pläne und Skripte zusammenstellen, die Ihnen die Migration deutlich erleichtern werden. Kontaktieren Sie uns gerne für ein unverbindliches Beratungsgespräch und lassen Sie uns gemeinsam Ihren Bedarf ermitteln. Über unser Kontaktformular erreichen Sie uns am Besten!