Suchen...
Generic filters
Exact matches only
Search in title
Search in excerpt
Search in content

Automatisierte Datenbankvervielfältigung

Steuerung+C und Steuerung+V sind zwei Windows-Tastenkombinationen, die wir täglich vielfach verwenden, um eine Kopie einer bestehenden Datei zu erstellen. Doch was im Dateisystem so leicht von der Tastatur geht, scheint im Rahmen eines nächtlichen Lade- und Aufbereitungsprozesses ein wenig komplexer. So möchten wir am Beispiel einer als Blaupause dienenden Datenbank eine Möglichkeit erläutern, diese mittels eines Skriptes in beliebiger Anzahl zu vervielfältigen.

So ist beispielsweise ein sehr restriktives Szenario denkbar, bei dem die Entwicklung in einer Hauptdatenbank geschieht und deren Inhalte dann nachts in verschiedene Kinderdatenbanken für jede Region (Nord, Süd, Ost, West) transportiert werden. Die Einschränkung der Inhalte steuern wir per Prozedur oder im Verfahren des Abzugs aus den Vorsystemen. Und wie werden die strukturellen Änderungen an der Hauptdatenbank in die einzelnen Satelliten publiziert? Dies kann mit folgender Logik umgesetzt werden.

Das Ziel der Automatisierung ist die nächtliche Kopie einer Hauptdatenbank in vier verschiedene Satelliten für die Regionen Nord, Süd, West und Ost. Hierfür werden die *.mdf Datei der Blaupause, sowie beliebig viele zugehörige Log Dateien (*.log) im Dateisystem kopiert, mit einem neuen Namen versehen und als Unterbau für den neu erstellten Klon zur Verfügung gestellt. Soweit die Theorie. In der Praxis kann dies am Beispiel unserer Chair wie folgt aussehen.

Für den Zugriff auf die SQL Server Dateien der zu kopierenden Datenbank, muss zunächst deren Speicherort im Dateisystem ermittelt werden. Dies geschieht in der Prozedur per Auslesen der SQL Server Registry Inhalte:

Speicherort der Datenbank:

EXEC master.dbo.xp_instance_regread N'H-
KEY_LOCAL_MACHINE',N'Software\Microsoft\MSSQLServer\MSSQLServer',N'DefaultData',
@DirData  output, 'no_output'

Speicherort der Logfiles:

EXEC master.dbo.xp_instance_regread N'H-
KEY_LOCAL_MACHINE',N'Software\Microsoft\MSSQLServer\MSSQLServer',N'DefaultLog', @DirLog output, 'no_output'

Hierbei werden jeweils in die beiden nvarchar Variablen @DirData und @DirLog die in der Registry hinterlegten Speicherorte für Datendatei und Logfile der Hauptdatenbank ausgelesen.

Da nun die Pfade zu den Dateien bekannt sind, muss vor dem eigentlichen Kopierprozess die Quelldatenbank offline gesetzt werden. Wäre sie noch aktiv, kann im Dateisystem nicht auf die Dateien zugegriffen werden. Daher müssen wir in unserem Kopierskript an das Offlinesetzen der Datenbank denken. Sie wird nach erfolgreichem Abschluss der Prozedur wieder automatisch online gesetzt.

select @vSourceDBStatus = state_desc from sys.databases where name =
@vSourceDB
    begin
        if @vSourceDBStatus <> 'OFFLINE'
            set @vSQL = N'alter database ' + @vSourceDB + ' set offline with rollback immediate';
            exec (@vSQL)
    end

Nun soll für jede Region der Chair eine Kopie der Quelldatenbank erstellt werden.
Hierfür benötigen wir Zugriff auf die ‚xp_cmdshell‘ – Funktionalität des SQL Servers. Ist diese deaktiviert, kann sie mit Hilfe des Kommandos

EXEC sp_configure'xp_cmdshell', 1
RECONFIGURE

aktiviert werden. Zunächst lesen wir in einen Cursor ‘cur_region’ alle vorhanden Regionen der Dimensionstabelle.

declare cur_region cursor for (select distinct region_de from T_DIM_05_02_Region)

Da nun die vier geographischen Separatoren in der Cursorvariable enthalten sind, können wir diese in einer Schleife abrufen und pro Ausprägung eine Kopie von Daten und Logfile(s) erstellen.

OPEN cur_region
    FETCH NEXT FROM cur_region INTO @vRegionID
    WHILE @@FETCH_STATUS = 0
    BEGIN

        -- Zusammenfügen des neuen Datenbanknamens
        SET @vNewDB = replace(@vSourceDB, '_Master', '') + '_' + @vRegionID

        -- Prüfen, ob dieser neue Name derzeit schon existiert.
        -- Falls ja, löschen der existenten Datenbank
        IF EXISTS(SELECT * FROM sys.databases WHERE name = @vNewDB)
        BEGIN
            SET @vSQL = 'DROP DATABASE ' + @vNewDB
            EXEC (@vSQL)
        END

        -- Auslesen des existenten Dateinamens
        DECLARE cur_dbfile CURSOR FOR
            (
                SELECT
                    physical_name
                FROM
                    sys.master_files
                WHERE
                    database_id = DB_ID(N'' + @vSourceDB + '') AND type_desc = 'ROWS'
            )


        OPEN cur_dbfile
            FETCH NEXT FROM cur_dbfile INTO @vSourceDBFileName
            WHILE @@FETCH_STATUS = 0
                BEGIN
                    -- Zusammenfügen des neuen Dateinamens
                    SET @vNewDBFileName = REPLACE(@vSourceDBFileName, '.mdf', '_' +
                    @vRegionID + '.mdf')
                    SET @vDBFileName = @vNewDBFileName
                    -- Kopieren der Datei
                    SET @XPcommand = 'copy ' + @vSourceDBFileName + ' ' + @vNewDBFileName
                    exec master..xp_cmdshell @XPcommand
                    FETCH NEXT FROM dbfile_cursor INTO @vSourceDBFileName
                END

        CLOSE cur_dbfile
        DEALLOCATE cur_dbfile
        FETCH NEXT FROM cur_region INTO @vRegionID
    END
CLOSE cur_region
DEALLOCATE cur_region

Analog hierzu kann der Name und Speicherot von einem oder mehreren Logfiles der Quelldatenbank kopiert und mit dem Kürzel der Region versehen werden.
Nach der erfolgten Kopie der gewünschten Dateien, können die neuen Datenbanken im SQL Server hinzugefügt werden.

set @vSQL = 'Create Database ' + @vNewDB + ' on (Filename = ''' + @vDBFileName + '''), (Filename = ''' + @vLogFileName + ''') for attach'

Je nachdem, ob in der Quelldatenbank mehrere Logfiles existierten, können diese über eine Schleife ebenfalls in die Satelliten publiziert werden.

WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @vAddLogfileSQL = 'ALTER DATABASE ' + @vNewDB + ' ADD FILE ( NAME = N' + @vLogName + ',
        FILENAME = N' + @vLogFileName + ' , SIZE = 3072KB , FILEGROWTH = 1024KB )
        TO FILEGROUP [PRIMARY]'
        EXEC (@vAddLogfileSQL)
        FETCH NEXT FROM ...
    END

Da es sich bei der zu kopierenden Hauptdatenbank ganz bestimmt um eine mit DeltMaster Modeler konfigurierte Datenbank handelt, prüfen wir am Ende noch unter T_Model_Parameters den eingestellten Namen der zugehörigen OLAP Datenbank und ändern diesen ebenfalls auf den jeweiligen Klon der Masterinhalte.

Am Schluss wird die Quelldatenbank dann wieder online gestellt und unsere eine Masterdatenbank hat erfolgreich vier Kinder bekommen.

set @vSQL = N'alter database ' + @vSourceDB + ' set online';
exec (@vSQL)

In größeren Datenbanken macht es sicherlich Sinn, vor dem Kopieren noch die Fakten- und Dimensionstabellen zu leeren und diese erst im Anschluß mit den jeweilig korrekten Inhalten zu befüllen.
Auf Nachfrage kann gerne das komplette Skript zur Verfügung gestellt werden, worin auch dieses vorige „Abspecken“ der Quelldatenbank berücksichtigt ist.