Mar*_*lli 5 sql-server dbcc pivot sqlcmd xp-cmdshell
我有以下脚本:
-- available space in each of the database files
PRINT @@SERVERNAME
--SQLDWDEV01
USE [BodenStage]
GO
SELECT name
,(CAST(ROUND((size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0),2) AS NUMERIC(18,2))) AS AvailableSpaceInMB
,(CAST(ROUND((size/128.0 - FILEPROPERTY(name, 'SpaceUsed')/128.0)/1024.00,2) AS NUMERIC(18,2))) AS AvailableSpaceInGB
FROM sys.database_files;
GO
Run Code Online (Sandbox Code Playgroud)
尽管我不喜欢既不收缩数据也不收缩日志文件,但有时需要这样做。不是我的错。
有方法,以缩小数据文件,而无须描述累积碎片在这里:
仅截断
将文件末尾的所有可用空间释放给操作系统,但不会在文件内执行任何页面移动。数据文件仅收缩到最后分配的范围。
如何将DBCC SHRINKFILE的结果保存到表中?
请参见下文,这是将DBCC SQLPERF的结果保存到表中的一种方法。
select @@servername as [Server]
,db_name() as [database]
go
SET NOCOUNT ON
begin try
drop table #radhe
end try
begin catch
end catch
create table #radhe (
DatabaseName varchar(100)
, LOGSIZE_MB NUMERIC(18, 9)
, LOGSPACE_USED NUMERIC(18, 9)
, LOGSTATUS NUMERIC(18, 9))
INSERT #Radhe(DatabaseName, LOGSIZE_MB, LOGSPACE_USED, LOGSTATUS)
EXEC('DBCC SQLPERF(LOGSPACE);')
select DatabaseName,
LOGSIZE_GB=CONVERT(NUMERIC(18,2) ,ISNULL( ROUND(LOGSIZE_MB/1024.00,2),0)),
PERC_USED =CONVERT(NUMERIC(4,2) ,ISNULL( ROUND(LOGSPACE_USED,2),0))
from #radhe
order by logsize_mb desc
Run Code Online (Sandbox Code Playgroud)
现在我生成 DBCC SHRINKFILE 命令:
DECLARE @db VARCHAR(108)
DECLARE @dbid INT
DECLARE @amount INT
SELECT @db = 'MY_DATABASSEStage'
SELECT @dbid = DB_ID(@DB)
SELECT @amount = 0
SELECT SHRINKFILE_SCRIPT = 'USE ' + QUOTENAME( DB_NAME(smf.database_id)) + CHAR(10)
+ 'GO' + CHAR(10)
+ 'DBCC SHRINKFILE(''' + smf.name + '''' + ',' + CAST(@amount AS VARCHAR) + ', TRUNCATEONLY) WITH NO_INFOMSGS' + CHAR(10)
+ 'GO' + CHAR(10)
, *
FROM sys.master_files smf
WHERE smf.database_id = @dbid
Run Code Online (Sandbox Code Playgroud)
上面的脚本产生了以下结果:
USE [MY_DATABASSEStage]
GO
DBCC SHRINKFILE('MY_DATABASSEStageStockLedger',0, TRUNCATEONLY) WITH NO_INFOMSGS
GO
USE [MY_DATABASSEStage]
GO
DBCC SHRINKFILE('MY_DATABASSEStageStockLedgerArchive',0, TRUNCATEONLY) WITH NO_INFOMSGS
GO
USE [MY_DATABASSEStage]
GO
DBCC SHRINKFILE('MY_DATABASSEStageProduct',0, TRUNCATEONLY) WITH NO_INFOMSGS
GO
Run Code Online (Sandbox Code Playgroud)
这是其中一个脚本的结果 - 删除 with no_infomsgs
有类似的问题,但他们没有给出适用于我的案例的答案:
结论
我的答案工作正常,但 srutzky 使用的方法要简单得多并且可以完成工作,只需要一个链接服务器。
对于我的测试服务器,我使用以下脚本来创建链接服务器:
USE [master]
GO
IF NOT EXISTS (SELECT srv.name FROM sys.servers srv WHERE srv.server_id != 0 AND srv.name = N'TESTDBCC')
BEGIN
EXEC master.dbo.sp_addlinkedserver
@server = N'TESTDBCC',
@srvproduct=N'',
@provider=N'SQLNCLI11',
@datasrc=N'JPB01275\SQL2014',
@catalog=N'radhe'
EXEC master.dbo.sp_addlinkedsrvlogin
@rmtsrvname=N'TESTDBCC',
@useself=N'True',
@locallogin=NULL,
@rmtuser=NULL,
@rmtpassword=NULL
END
GO
EXEC master.dbo.sp_serveroption
@server=N'TESTDBCC',
@optname=N'collation compatible',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'data access',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'dist',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'pub',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'rpc',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'rpc out',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'sub',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'connect timeout',
@optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'collation name',
@optvalue=null
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'lazy schema validation',
@optvalue=N'false'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'query timeout',
@optvalue=N'0'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'use remote collation',
@optvalue=N'true'
GO
EXEC master.dbo.sp_serveroption @server=N'TESTDBCC',
@optname=N'remote proc transaction promotion',
@optvalue=N'false'
GO
Run Code Online (Sandbox Code Playgroud)
并使用上面的链接服务器,我可以按如下方式收集数据:
--Use the Linked Server via EXEC() AT
CREATE TABLE #ShrinkFileResults
(
[DBID] SMALLINT,
[FileID] INT,
[CurrentSize] INT,
[MinimumSize] INT,
[UsedPages] INT,
[EstimatedPages] INT
);
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [tempdb];
DBCC SHRINKFILE(N''tempdev'', 0, TRUNCATEONLY);
') AT [TestDBCC];
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [radhe];
DBCC SHRINKFILE(N''radhe_log'', 0, TRUNCATEONLY);
') AT [TestDBCC];
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [US16HSMMProduct_AFTER_CHANGES];
DBCC SHRINKFILE(N''US16HSMMProduct_AFTER_CHANGES_log'', 0, TRUNCATEONLY);
') AT [TestDBCC];
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [US16HSMMProduct_AFTER_CHANGES];
DBCC SHRINKFILE(N''US16HSMMProduct_AFTER_CHANGES_log'', 0, TRUNCATEONLY);
') AT [TestDBCC];
SELECT * FROM #ShrinkFileResults;
Run Code Online (Sandbox Code Playgroud)
'remote proc transaction promotion'
这可以通过使用属性设置为 的“环回”链接服务器来轻松完成false
,这可以通过回避操作启动的隐式事务来避免“无法在用户事务内执行收缩文件操作”INSERT...EXEC
错误。否则链接服务器只需要将该'rpc out'
属性设置为true
。和属性不需要启用(至少对我来说不是)'data access'
。'rpc'
创建链接服务器
USE [master];
DECLARE @LinkedServerName sysname;
SET @LinkedServerName = N'TestDBCC';
IF (NOT EXISTS (SELECT srv.name
FROM sys.servers srv
WHERE srv.server_id <> 0
AND srv.name = @LinkedServerName))
BEGIN
EXEC [master].dbo.sp_addlinkedserver
@server = @LinkedServerName, @srvproduct=N'', @provider=N'SQLNCLI11', @datasrc=N'DALI';
EXEC [master].dbo.sp_addlinkedsrvlogin
@rmtsrvname=@LinkedServerName,@useself=N'True',@locallogin=NULL,
@rmtuser=NULL,@rmtpassword=NULL;
END;
--EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
-- @optname=N'data access', @optvalue=N'true';
--EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
-- @optname=N'rpc', @optvalue=N'true'; -- is_remote_login_enabled
EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
@optname=N'rpc out', @optvalue=N'true';
EXEC [master].dbo.sp_serveroption @server=@LinkedServerName,
@optname=N'remote proc transaction promotion', @optvalue=N'false';
GO
Run Code Online (Sandbox Code Playgroud)
通过以下方式使用链接服务器EXEC() AT
CREATE TABLE #ShrinkFileResults
(
[DBID] SMALLINT,
[FileID] INT,
[CurrentSize] INT,
[MinimumSize] INT,
[UsedPages] INT,
[EstimatedPages] INT
);
INSERT INTO #ShrinkFileResults
([DBID], [FileID], [CurrentSize], [MinimumSize], [UsedPages], [EstimatedPages])
EXEC(N'
USE [tempdb];
DBCC SHRINKFILE(N''tempdev'', 0, TRUNCATEONLY);
') AT [TestDBCC];
SELECT * FROM #ShrinkFileResults;
Run Code Online (Sandbox Code Playgroud)
这对我在 SQL Server 2012 SP3 和 SQL Server 2016 RTM 上都有效。
笔记
使用OPENQUERY
不起作用。最初,您会收到“元数据发现”错误,可以通过将调用DBCC
包装在另一个EXEC
使用该WITH RESULT SETS
选项的调用中来解决该错误。但随后您会收到有关“OPENQUERY 无法处理对象,因为它不存在或您没有权限”的错误。但是,如果您更改要收缩的文件的逻辑名称,则会收到一条错误DBCC
,指出它无法找到该名称的文件,并且会出现一个二级错误,OPENQUERY
指出该调用未返回任何结果集,所有这些表示使用正确的文件名会更进一步。
此操作也可以通过 SQLCLR 相当简单地完成。事实上,可以使用外部连接(而不是上下文连接)创建 UDF/标量函数,这将允许在列表中基于集合的操作中进行调用SELECT
。xp_cmdshell
与启用或创建链接服务器相比,这也只需要几行代码,并且可以最大限度地降低安全风险。
归档时间: |
|
查看次数: |
873 次 |
最近记录: |