有没有办法 运行 sys.dm_db_log_space_usage 用于所有数据库?

Is there a way to run sys.dm_db_log_space_usage for all databases?

我想创建一个监控工具来跟踪我们维护的生产服务器上事务日志使用情况的变化。

之前,我使用了 DBCC SQLPERF(LOGSPACE);,它提供了所有数据库的列表及其当前事务日志内存状态。然而,微软似乎建议从 2012 年开始,应该从 sys.dm_db_log_space_usage 查看日志详细信息,它提供了类似的详细信息,但似乎是特定于数据库的,而不是提供服务器整体视图(即您必须连接到您希望使用的数据库)。

https://docs.microsoft.com/en-us/sql/t-sql/database-console-commands/dbcc-sqlperf-transact-sql?view=sql-server-ver15

我想我的问题有两个:

  1. 有没有办法对所有数据库使用sys.dm_db_log_space_usage
  2. 有什么理由不应该使用 DBCC SQLPERF(LOGSPACE); 吗?

我无法让它在我的机器上运行,但我发现了很多关于 sp_MSForEachDB 的信息。你可以试试看:

declare @findKeySQL varchar(1000)
SET @findKeySQL = 'IF ''[?]'' NOT IN (''[master]'', ''[model]'',''[msdb]'', ''[tempdb]'')
        USE [?] select * from sys.dm_db_log_space_usage'
EXEC sp_MSForEachDB @findKeySQL

希望这对你有用!

DBCC SQLPERF(LOGSPACE); 有什么原因吗?不应该使用?

Starting with SQL Server 2012 (11.x), use the sys.dm_db_log_space_usage DMV instead of DBCC SQLPERF(LOGSPACE), to return space usage information for the transaction log per database

有没有办法对所有数据库使用sys.dm_db_log_space_usage?

您可以使用以下光标。也许它需要更多的发展;

CREATE TABLE [dbo].[Tbl_DbSizes](
    [database_id] [int] NULL,
    [total_log_size_in_bytes] [bigint] NULL,
    [used_log_space_in_bytes] [bigint] NULL,
    [used_log_space_in_percent] [real] NULL,
    [log_space_in_bytes_since_last_backup] [bigint] NULL
) ON [PRIMARY]

GO
DECLARE 
    @queryAsList VARCHAR(MAX) ,@DbName AS VARCHAR(100)

DECLARE Db_List CURSOR
FOR
SELECT name  FROM sys.databases 

OPEN Db_List;

FETCH NEXT FROM Db_List INTO 
   @DbName 

WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @queryAsList = 'INSERT INTO Tbl_DbSizes select * from '+ @DbName + '.' + 'sys.dm_db_log_space_usage'
        EXEC(@queryAsList)

        FETCH NEXT FROM Db_List INTO 
           @DbName
    END;

CLOSE Db_List;

DEALLOCATE Db_List;
SELECT name as databasename , total_log_size_in_bytes  ,
used_log_space_in_bytes,used_log_space_in_percent,log_space_in_bytes_since_last_backup 
FROM Tbl_DbSizes INNER JOIN sys.databases databaseinfo 
ON databaseinfo.database_id= Tbl_DbSizes.database_id

TRUNCATE TABLE [Tbl_DbSizes]


+--------------------+-------------------------+-------------------------+---------------------------+--------------------------------------+
|    databasename    | total_log_size_in_bytes | used_log_space_in_bytes | used_log_space_in_percent | log_space_in_bytes_since_last_backup |
+--------------------+-------------------------+-------------------------+---------------------------+--------------------------------------+
| master             |                 2088960 |                  729088 |                  34.90196 |                               270336 |
| tempdb             |                 8380416 |                  675840 |                  8.064516 |                               299008 |
| model              |                 8380416 |                 1617920 |                  19.30596 |                                73728 |
| msdb               |                 9428992 |                 1208320 |                  12.81494 |                                86016 |
| DWDiagnostics      |                75489280 |                 6467584 |                  8.567553 |                               253952 |
| DWConfiguration    |                 8380416 |                  626688 |                  7.478006 |                               253952 |
| DWQueue            |                 8380416 |                 1404928 |                  16.76442 |                               253952 |
| DemoDb             |                 8380416 |                 1732608 |                  20.67449 |                               266240 |
| ReportServer       |                75489280 |                13873152 |                  18.37765 |                               274432 |
| ReportServerTempDB |                75489280 |                 1925120 |                   2.55019 |                               245760 |
+--------------------+-------------------------+-------------------------+---------------------------+--------------------------------------+

结合 Newman and dylenv 前两条评论中的方法,我编写了一个基本脚本,将结果放入临时 table,以便可以根据需要对其进行过滤或操作。

declare
    -- Table already multiplies percent by 100
    -- Use the whole number percent
    -- (e.g. 25 instead of 0.25)
    @Percent_Used_threshold real = 25

drop table if exists ##log_space;

create table ##log_space (
    database_id int primary key
    , [db_name] sysname not null
    , total_space_gb float not null
    , used_space_gb float not null
    , remaining_space_gb float not null
    , used_log_space_in_percent real not null
);

declare
    @sql varchar(max) = '

declare
    @decimal_places int = 4
;

insert into
    ##log_space
select
    db.database_id
    , db.[name] as [db_name]
    , round(
        cast(log_space.total_log_size_in_bytes as float) / power(1024, 3)
        , @decimal_places
    ) as total_space_gb
    , round(
        cast(log_space.used_log_space_in_bytes as float) / power(1024, 3) 
        , @decimal_places
    ) as used_space_gb
    , round(
        cast(log_space.total_log_size_in_bytes - log_space.used_log_space_in_bytes as float) / power(1024, 3)
        , @decimal_places) as remaining_space_gb
    , round(log_space.used_log_space_in_percent, @decimal_places) as used_log_space_in_percent
from
    ?.sys.dm_db_log_space_usage as log_space
inner join
    ?.sys.databases as db
    on log_space.database_id = db.database_id
;'

exec sys.sp_MSforeachdb @sql

select
    *
from
    ##log_space
where
    used_log_space_in_percent >= @Percent_Used_threshold
order by
    used_log_space_in_percent desc

许多数据库中 运行ning 查询的最佳选择是@AaronBertrand sp_InEachDb,因此首先 运行 master(或其他数据库)中的脚本创建 sp_InEachDb 然后你可以 运行 这样的事情:

-- Make a temp table to store results from each db
drop table if exists #results
create table #results ( Db nvarchar(128), database_id int, total_log_size_in_bytes bigint, used_log_space_in_bytes bigint, used_log_space_in_percent real, log_space_in_bytes_since_last_backup bigint) 

-- run the query in each db, putting results into our temp table
exec sp_ineachdb  @command = '
insert into #results
select db_name(), * from sys.dm_db_log_space_usage
', @name_pattern = 'tenant_%' -- whatever you like here, if anything

-- let's see what it gave us
select * from #results 
order by Db

查看 these articles 了解 sp_ineachdb 的更多解释。不要费心自己写一个proc,这样会好很多。 sp_MSForEachDB 在很多情况下都可以,但有很多问题,所以使用 sp_ineachdb 会更好,这样可以避免以后的麻烦。