Sql Server數據庫備份腳本以及如何在阿里雲雲數據庫RDS還原數據庫(代碼源自阿里雲)


 今天研究阿里雲服務數據庫的遷移,備份和還原的時候,在阿里雲web后台發現了一個很好用的sql腳本,就默默地偷了過來,它可以支持全量備份,差異備份和日志備份,代碼解釋也都很清楚,我也嘗試着跑了一下,性能也還是蠻不錯的,本地電腦運行壓縮后1個多G的數據備份用了二十多秒

我們可以將下面代碼放到SQL作業里面,然后定期的去做全量和差異的備份,這不免也算是一種不錯的數據庫備份方案了,當然這種備份功能完全可以用SqlServer自帶的數據庫維護計划功能代替,而且阿里雲等類似的雲數據庫都是會提供數據備份服務的,不需要開發人員自己做數據備份。

代碼如下,如果有用阿里雲服務器的碼友可以直接到用戶后台下載最新源碼

USE master
GO

/**
* author: 
*    jianming.wjm@alibaba-inc.com of Alibaba Cloud Team.
*
* @purpose:
*    Backup your databases to local directory (no matter destination folder exist or not).
*    You can personal your backup type, support three backup types include(FULL, DIFF, LOG).
*    This script also support just check to see details or run directly.
*
*    if you find something happen unhappy, please kindly tell us via the author email. thanks.
* 
* @usage:
*    Copy all the script (ctrl + a) into SSMS, fill out the public variables and then F5 or Execute it.
*
* @parameters:
*    @backup_databases_list: databases list needed to backup
*    @backup_type: which backup type needed, choice one of ['FULL', 'DIFF', 'LOG']
*    @backup_folder: where backup files located
*    @is_run: I want to run or just check, 1: run; 0: just check.
* 
* @version:
*    1.0.0, 2018/03/02 15:20: Create script.
*
* @Tips:
*    We'd like to advice you to change your databases to FULL recovery model to improve migrate to RDS.
*    example: ALTER DATABASE [db_simple] SET RECOVERY FULL WITH NO_WAIT
*    pay attention to the SSMS output messages, and correct the error if have any.
**/

SET NOCOUNT ON

-- declare public variables
DECLARE
    @backup_databases_list NVARCHAR(max),
    @backup_type SYSNAME,
    @backup_folder SYSNAME,
    @is_run TINYINT
;

-- YOU HAVE TO INIT PUBLIC VARIABLES HERE!!!!
SELECT
    /**
    * Databases list needed to backup, delimiter is ; or ,
    * empty('') or null: means all databases excluding system database
    * example: '[testdb];TestDR,Test,readonly'
    **/
    @backup_databases_list = N'[TestA];[TestB],readonly,Test',
    @backup_type = N'FULL',                                -- Backup Type? FULL: FULL backup; DIFF: Differential backup; LOG: Log backup
    @backup_folder = N'C:\BACKUP',                        -- Backup folder to store backup files.
    @is_run = 1                                            -- Check or run? 1, run directly; 0, just check
;

-- variables checking
IF @backup_type NOT IN(N'FULL', N'DIFF', N'LOG')
BEGIN
    RAISERROR('Backup type %s is not supported!', 16, 1, @backup_type)
    RETURN
END
;

IF ISNULL(@backup_folder, N'') = N''
BEGIN
    RAISERROR('backup_folder is not allow empty!', 16, 1)
    RETURN
END

IF @is_run NOT IN(0, 1)
BEGIN
    RAISERROR('is_run parameter should be 0 or 1 !', 16, 1)
    RETURN
END

-- declare private variables
DECLARE
    @database_name SYSNAME,
    @database_state TINYINT,
    @database_state_desc NVARCHAR(60),
    @database_count INT,
    @database_do INT,
    @flag_edition BIT,
    @exec_sql NVARCHAR(MAX),
    @timestamp VARCHAR(20),
    @context_info VARCHAR(20),
    @backup_databases_list_XML XML
;

-- private variables init.
SELECT
    @database_name = N'',
    @database_state = 11,
    @database_state_desc = N'',
    @database_count = 0,
    @database_do = 1,
    @flag_edition = CASE
                            WHEN CONVERT(sysname, SERVERPROPERTY(N'Edition')) LIKE N'Enterprise%' THEN 1
                            ELSE 0
                        END,
    @exec_sql = N'',
    @timestamp = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(19), GETDATE(),120), N'-', N''), N':', N''), CHAR(32), N''),
    @backup_folder = CASE 
                        WHEN RIGHT(@backup_folder, 1) = N'\' THEN @backup_folder 
                        ELSE @backup_folder + N'\' 
                    END,
    @context_info = N'0x1256698449',
    @backup_databases_list_XML = 
            N'<V><![CDATA[' + 
                REPLACE(
                    REPLACE(
                        REPLACE(
                                REPLACE(
                                        REPLACE(
                                                REPLACE(
                                                        @backup_databases_list, '[', ''
                                                    ), ']', ''
                                            ), ';', ','
                                    ),CHAR(10),']]></V><V><![CDATA['
                                ),',',']]></V><V><![CDATA['
                            ),CHAR(13),']]></V><V><![CDATA['
                    ) 
                + ']]></V>'
;

-- temp table declare to save databases splitted
IF OBJECT_ID('tempdb..#tmp_databases', 'U') IS NOT NULL
    DROP TABLE #tmp_databases
CREATE TABLE #tmp_databases(
    RowId INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Database_name SYSNAME
)
;

-- get databases name
IF ISNULL(@backup_databases_list, N'') > N''
BEGIN
    INSERT INTO #tmp_databases
    SELECT DISTINCT
        [Database_name] = T.C.value('(./text())[1]','sysname')
    FROM @backup_databases_list_XML.nodes('./V') AS T(C)
    WHERE T.C.value('(./text())[1]','sysname') IS NOT NULL
    ;
END
ELSE
BEGIN
    INSERT INTO #tmp_databases
    SELECT DISTINCT name
    FROM sys.databases WITH (NOLOCK)
    WHERE name NOT IN (N'master', N'tempdb', N'model', N'msdb', N'distribution')
END

-- decalre cursor to loop each database.
DECLARE CUR_DatabaseList CURSOR LOCAL STATIC FORWARD_ONLY READ_ONLY
FOR
SELECT DISTINCT name, state, state_desc
FROM sys.databases WITH (NOLOCK)
WHERE name IN(SELECT [Database_name] FROM #tmp_databases)

-- Open cursor and get the rowcount
OPEN CUR_DatabaseList
FETCH NEXT FROM CUR_DatabaseList INTO @database_name, @database_state, @database_state_desc
SET @database_count = @@CURSOR_ROWS;

-- prepare folder on local host.
IF @database_count > 0
BEGIN
    EXEC sys.xp_create_subdir @backup_folder
END

WHILE @@FETCH_STATUS = 0
BEGIN
    -- contact the backup script for each backup type.
    SET
        @exec_sql = 
                    CASE 
                        WHEN @backup_type = N'FULL' 
                        THEN  N'BACKUP DATABASE ' + QUOTENAME(@database_name) 
                            + N' TO DISK = N' + QUOTENAME(@backup_folder + @database_name + N'_' + @backup_type + N'_' + @timestamp + N'.bak', '''') 
                            + N' WITH STATS = 1' + CASE 
                                                        WHEN @flag_edition = 1 THEN N', COMPRESSION;'
                                                        ELSE N';'
                                                    END
                        WHEN @backup_type = N'DIFF'
                        THEN N'BACKUP DATABASE ' + QUOTENAME(@database_name) 
                            + N' TO DISK = N' + QUOTENAME(@backup_folder + @database_name + N'_' + @backup_type + N'_' + @timestamp + N'.bak', '''')
                            + N' WITH DIFFERENTIAL, STATS = 1' + CASE 
                                                        WHEN @flag_edition = 1 THEN N', COMPRESSION;'
                                                        ELSE N';'
                                                    END
                        WHEN @backup_type = N'LOG'
                        THEN N'BACKUP LOG ' + QUOTENAME(@database_name) 
                            + N' TO DISK = N' + QUOTENAME(@backup_folder + @database_name + N'_' + @backup_type + N'_' + @timestamp + N'.bak', '''')
                            + N' WITH STATS = 1' + CASE 
                                                        WHEN @flag_edition = 1 THEN N', COMPRESSION;'
                                                        ELSE N';'
                                                    END
                        ELSE N''
                    END
    ;

    RAISERROR('--==============%d/%d: Working on database: %s', 10, 1, @database_do , @database_count, @database_name) WITH NOWAIT;

    --Only online database can be Backup.
    IF @database_state = 0
    BEGIN
        RAISERROR('-- %s', 10, 1, @exec_sql) WITH NOWAIT;

        IF @is_run = 1
        BEGIN
            SET
                @exec_sql = N'SET CONTEXT_INFO ' + @context_info + N';' + @exec_sql
            ;
            EXEC sys.sp_executesql @exec_sql
        END
    END
    ELSE
    BEGIN
        RAISERROR('-- database %s state: %s can''t be backup, skipped.', 10, 1, @database_name, @database_state_desc) WITH NOWAIT;
    END
    
    SET @database_do = @database_do + 1;
    FETCH NEXT FROM CUR_DatabaseList INTO @database_name, @database_state, @database_state_desc
END

-- close and release cursor.
CLOSE CUR_DatabaseList
DEALLOCATE CUR_DatabaseList
GO

還有一點需要注意的是阿里雲雲數據庫RDS是不支持數據庫直接操作還原的,在雲數據庫上操作還原數據庫會報如下錯誤

那么我們如何在阿里雲數據庫還原數據呢?人家阿里雲爸爸也提供了相應的解決方案——OSS備份數據恢復,它可以將指定數據庫文件還原到雲數據庫

相關功能可以參考鏈接 https://help.aliyun.com/document_detail/68310.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM