用于启动xp_cmdshell作业的T SQL多线程

时间:2013-04-09 06:19:51

标签: sql multithreading xp-cmdshell

我有一个工作,它使用七个zips命令行实用程序获取数据库备份文件并将它们压缩为.7z文件,目前需要大约8个小时来运行所有.bak文件,因为它一次只执行一个。这个运行大约有16个内核,7z进程似乎只使用1个内核,所以我希望能够运行xp_cmdshell命令的多个实例,让它一次压缩几个文件。有没有办法在MSSQL Server 2005上的T SQL中执行命令列表?

我在下面发布了我的脚本。

这是我用来压缩文件的程序的链接。 [http://downloads.sourceforge.net/sevenzip/7za920.zip] [1]

-- YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
-- II       zip all files in a folder                       II
-- VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV

-- Zip and then Delete all files from the backup folder
-- List all files in a directory - T-SQL parse string for date and filename 
DECLARE  @PathName       VARCHAR(256) , 
         @CMD            VARCHAR(512) 

CREATE TABLE #CommandShell ( Line VARCHAR(512)) 

    -- To use the xp_cmdshell option it has to be enabled. you can use the script bellow to enable it.
    --
    -- -- run exec sp_configure to see if the option exists in this list and you can check if it is enabled.
    -- EXEC sp_configure
    -- go
    -- -- if you don't see xp_cmdshell in the list then you will have to enable advanced options first 
    -- -- before you can enable the xp_cmdshell option.
    -- EXEC sp_configure 'show advanced options', 1;
    -- go
    -- reconfigure
    -- go
    -- -- if xp_cmdshell is in the list then you should just need to run this script.
    -- exec sp_configure 'xp_cmdshell', 1
    -- go
    -- reconfigure

SET @PathName = 'D:\FILES\Backups\' 

SET @CMD = 'DIR ' + @PathName + ' /TC' 

INSERT INTO #CommandShell 
EXEC MASTER..xp_cmdshell   @CMD 

-- Delete lines not containing filename
DELETE 
FROM   #CommandShell 
WHERE  Line NOT LIKE '[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] %' 
OR Line LIKE '%<DIR>%'
OR Line is null

-- SQL reverse string function - charindex string function 
SELECT ROW_NUMBER() OVER (ORDER BY REVERSE( LEFT(REVERSE(Line),CHARINDEX(' ',REVERSE(line))-1 ) )) AS ROW_NUM,
  FileName = REVERSE( LEFT(REVERSE(Line),CHARINDEX(' ',REVERSE(line))-1 ) ),
  CreateDate = LEFT(Line,10)
INTO #tempFileList 
FROM #CommandShell
WHERE REVERSE( LEFT(REVERSE(Line),CHARINDEX(' ',REVERSE(line))-1 ) ) LIKE '%.bak'
ORDER BY FileName

DROP TABLE #CommandShell

DECLARE @FileMaxRownum INT
SET @FileMaxRownum = (SELECT MAX(ROW_NUM) FROM #tempFileList)

DECLARE @FileIter INT
SET @FileIter = (SELECT MIN(ROW_NUM) FROM #tempFileList)

WHILE @FileIter <= @FileMaxRownum
BEGIN
    DECLARE @DelFile varchar(200)
    --@@
    DECLARE @cmd2 VARCHAR(1000)
    SET @cmd2 = null
    DECLARE @db_bkp_files_dir varchar(100)
    SET @db_bkp_files_dir = null
    DECLARE @archive_destination_dir varchar(100)
    SET @archive_destination_dir = null
    DECLARE @archive_name varchar(100)
    SET @archive_name = null
    DECLARE @7z_path varchar(100)
    SET @7z_path = null
    set @archive_destination_dir = @PathName --destination dir
    set @7z_path = 'D:\FILES'
    set @db_bkp_files_dir = right(@PathName,1) --db backup files origin 
    SELECT TOP(1) @archive_name = FileName FROM #tempFileList WHERE ROW_NUM = @FileIter
    SET @cmd2 = @7z_path + '\7za a -t7z -mx5 -ms=off ' + @archive_destination_dir + @archive_name + '.7z ' +  @archive_destination_dir + @archive_name
    print @cmd2
    EXEC xp_cmdshell @cmd2
    --@@
    SELECT TOP(1) @DelFile = 'del ' + @PathName + FileName FROM #tempFileList WHERE ROW_NUM = @FileIter
    EXEC xp_cmdshell @DelFile
    SET @FileIter = @FileIter + 1
END
DROP TABLE #tempFileList

3 个答案:

答案 0 :(得分:1)

我不认为问题出在SQL Server上。如果你想同时运行多个执行线程,你可以使用SQL Server代理中的预定作业...但是,这只是你正在使用的7-Zip压缩算法的一种解决方法

The default compression won't use more than two cores, but an alternate compression algorithm, such as b-zip, will make better use of your server's available cores.

请尝试使用-t7z,而不是使用-tbzip2切换,这是上述博客文章中详述的算法。

SET @cmd2 = @7z_path + '\7za a -tbzip2 -mx5 -ms=off ' 
  + @archive_destination_dir 
  + @archive_name + '.7z ' 
  + @archive_destination_dir 
  + @archive_name

答案 1 :(得分:0)

这是我最终用来测试加速进程的脚本。它在完成后将作业留在msdb数据库中,所以我必须返回并删除它们在完成运行后添加的所有作业,所以它有点乱,如果我还没有为服务器代理设置权限服务和我访问的文件夹我认为它会给我错误。 我可能会重写这个,只是为每个数据库创建单独的备份和压缩作业,所以我不是一直在下降和创建服务器代理作业,但这可以用于测试。

-- YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY
-- II       zip all files in a folder                       II
-- VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV

-- Zip and then Delete all files from the backup folder
-- List all files in a directory - T-SQL parse string for date and filename 
DECLARE  @PathName       VARCHAR(256) , 
         @CMD            VARCHAR(512) 

CREATE TABLE #CommandShell ( Line VARCHAR(512)) 

SET @PathName = 'D:\FILES\Backups\' 

SET @CMD = 'DIR ' + @PathName + ' /TC' 

INSERT INTO #CommandShell 
EXEC MASTER..xp_cmdshell   @CMD 

-- Delete lines not containing filename
DELETE 
FROM   #CommandShell 
WHERE  Line NOT LIKE '[0-9][0-9]/[0-9][0-9]/[0-9][0-9][0-9][0-9] %' 
OR Line LIKE '%<DIR>%'
OR Line is null

-- SQL reverse string function - charindex string function 
SELECT ROW_NUMBER() OVER (ORDER BY REVERSE( LEFT(REVERSE(Line),CHARINDEX(' ',REVERSE(line))-1 ) )) AS ROW_NUM,
  FileName = REVERSE( LEFT(REVERSE(Line),CHARINDEX(' ',REVERSE(line))-1 ) ),
  CreateDate = LEFT(Line,10)
INTO #tempFileList 
FROM #CommandShell
WHERE REVERSE( LEFT(REVERSE(Line),CHARINDEX(' ',REVERSE(line))-1 ) ) LIKE '%.bak'
ORDER BY FileName

DROP TABLE #CommandShell

DECLARE @FileMaxRownum INT
SET @FileMaxRownum = (SELECT MAX(ROW_NUM) FROM #tempFileList)

DECLARE @FileIter INT
SET @FileIter = (SELECT MIN(ROW_NUM) FROM #tempFileList)

WHILE @FileIter <= @FileMaxRownum
BEGIN
    DECLARE @DelFile varchar(200)
    --@@
    DECLARE @cmd2 VARCHAR(1000)
    SET @cmd2 = null
    DECLARE @db_bkp_files_dir varchar(100)
    SET @db_bkp_files_dir = null
    DECLARE @archive_destination_dir varchar(100)
    SET @archive_destination_dir = null
    DECLARE @archive_name varchar(100)
    SET @archive_name = null
    DECLARE @7z_path varchar(100)
    SET @7z_path = null
    set @archive_destination_dir = @PathName --destination dir
    set @7z_path = 'D:\FILES'
    set @db_bkp_files_dir = right(@PathName,1) --db backup files origin 
    SELECT TOP(1) @archive_name = FileName FROM #tempFileList WHERE ROW_NUM = @FileIter
    --   7za switches: 
    --   -mx0 (Don't compress)
    --   -mx1 (Low)
    --   -mx3 (Fast)
    --   -mx5 (Normal)
    --   -mx7 (Maximum)
    --   -mx9 (Ultra)
    --
    --   -mmt (enable multithreading)
    --   
    --   -t7z
    --   -tbzip2
    SET @cmd2 = @7z_path + '\7za a -t7z -mx5 -ms=off ' + @archive_destination_dir + @archive_name + '.7z ' +  @archive_destination_dir + @archive_name
    --SET @cmd2 = @7z_path + '\7za a -tbzip2 -mx5 ' + @archive_destination_dir + @archive_name + '.7z ' +  @archive_destination_dir + @archive_name

    DECLARE @cmd3 nvarchar(max)
    SET @cmd3 = 'USE msdb; EXEC sp_add_job @job_name = N''' + @archive_name + ' Zip job' + ''''

    DECLARE @cmd4 nvarchar(max)
    SET @cmd4 = 'USE msdb; EXEC sp_add_jobstep @job_name = N''' + @archive_name + ' Zip job' +''', @step_name = N''' + @archive_name + ' Zip job Step 1'  + ''', ' +
                '@subsystem = N''TSQL'', @command = N''' + 'DECLARE @cmd VARCHAR(1000) SET @cmd = ''''' + @7z_path + '\7za a -t7z -mx5 -ms=off ' + @archive_destination_dir + @archive_name + '.7z ' +  @archive_destination_dir + @archive_name + ''''' EXEC xp_cmdshell @cmd '  + ''', @retry_attempts = 5, @retry_interval = 1'

    DECLARE @cmd5 nvarchar(max)
    SET @cmd5 = 'USE msdb; EXEC dbo.sp_add_jobserver @job_name = N''' + @archive_name + ' Zip job' + ''', @server_name = N''ServerName'';'

    DECLARE @cmd6 nvarchar(max)
    SET @cmd6 = 'USE msdb; EXEC dbo.sp_start_job N''' + @archive_name + ' Zip job' + ''';'

    DECLARE @cmd7 nvarchar(max)
    SET @cmd7 = 'EXEC sp_delete_job @job_name = N''' + @archive_name + ' Zip job' + ''';'

    PRINT @cmd3
    EXEC sp_executesql @statement = @cmd3
    PRINT @cmd4
    EXEC sp_executesql @statement = @cmd4
    PRINT @cmd5
    EXEC sp_executesql @statement = @cmd5
    PRINT @cmd6
    EXEC sp_executesql @statement = @cmd6

    PRINT @cmd7

    --print @cmd2
    --EXEC xp_cmdshell @cmd2
    --@@
    SELECT TOP(1) @DelFile = 'del ' + @PathName + FileName FROM #tempFileList WHERE ROW_NUM = @FileIter
    --EXEC xp_cmdshell @DelFile
    SET @FileIter = @FileIter + 1
END
DROP TABLE #tempFileList

答案 2 :(得分:0)

sp_add_job有一个@delete_level参数,它允许在成功完成后自动删除作业。

http://technet.microsoft.com/en-us/library/aa259577(v=sql.80).aspx