SQL Server : sp_who2의 필터 출력


191

SQL Server에서 sp_who2의 출력을 필터링하는 쉬운 방법이 있습니까? 예를 들어 특정 데이터베이스의 행만 표시하고 싶다고 가정 해보십시오.


2
@Nick이 암시 한 것처럼 동적 관리 뷰 (DMV)도 살펴볼 가치가 있습니다.
Mitch Wheat

sp_who2
N30

답변:


349

당신은 같은 것을 시도 할 수 있습니다

DECLARE @Table TABLE(
        SPID INT,
        Status VARCHAR(MAX),
        LOGIN VARCHAR(MAX),
        HostName VARCHAR(MAX),
        BlkBy VARCHAR(MAX),
        DBName VARCHAR(MAX),
        Command VARCHAR(MAX),
        CPUTime INT,
        DiskIO INT,
        LastBatch VARCHAR(MAX),
        ProgramName VARCHAR(MAX),
        SPID_1 INT,
        REQUESTID INT
)

INSERT INTO @Table EXEC sp_who2

SELECT  *
FROM    @Table
WHERE ....

그리고 필요한 것을 필터링하십시오.


+1 @ bo-flexson 은이 접근법 의 훌륭한 확장 기능 을 가지고 있습니다.
Lankymart

115

당신은 수있는 임시 테이블에 결과를 저장 하지만,에 소스로 직접 이동하는 더 나은 것입니다 master.dbo.sysprocesses.

다음과 거의 동일한 결과를 반환하는 쿼리가 있습니다 sp_who2.

SELECT  spid,
        sp.[status],
        loginame [Login],
        hostname, 
        blocked BlkBy,
        sd.name DBName, 
        cmd Command,
        cpu CPUTime,
        physical_io DiskIO,
        last_batch LastBatch,
        [program_name] ProgramName   
FROM master.dbo.sysprocesses sp 
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
ORDER BY spid 

지금 당신은 쉽게 추가 할 수 있습니다 ORDER BY또는 WHERE당신이 의미있는 출력을 얻을하고자 절을.


또는 SSMS ( + + ) 에서 활동 모니터 사용을 고려할 수도 있습니다.CtrlAltA


차단은 BlkBy와 다릅니다. 차단은 잠금 해제를 기다리는 피해자입니다. BlkBy는 범죄를 저지른 범죄자입니다. 따라서 BlkBy 별칭을 사용하여 열을 차단하는 것은 절대적으로 잘못되었습니다. sp_who가 1을 SPID로, 2를 BlkBy로 반환하면 1은
doctorgu

25

한 가지 방법은 임시 테이블을 만드는 것입니다.

CREATE TABLE #sp_who2 
(
   SPID INT,  
   Status VARCHAR(1000) NULL,  
   Login SYSNAME NULL,  
   HostName SYSNAME NULL,  
   BlkBy SYSNAME NULL,  
   DBName SYSNAME NULL,  
   Command VARCHAR(1000) NULL,  
   CPUTime INT NULL,  
   DiskIO INT NULL,  
   LastBatch VARCHAR(1000) NULL,  
   ProgramName VARCHAR(1000) NULL,  
   SPID2 INT
) 
GO

INSERT INTO #sp_who2
EXEC sp_who2
GO

SELECT *
FROM #sp_who2
WHERE Login = 'bla'
GO

DROP TABLE #sp_who2
GO

sp * who2에서 *를 선택하십시오. 여기서 login = 'bla'-테이블은 여기에서 # sp_who2로 참조해야합니까?
피터 스코필드

"열 이름 또는 제공된 값 수가 테이블 정의와 일치하지 않습니다." SQL 2008 R2에서 실행
TheLegendaryCopyCoder

11

http://web.archive.org/web/20080218124946/http://sqlserver2005.databases.aspfaq.com/how-do-i-mimic-sp-who2.html 기반으로 찾기를 해결하는

다음 스크립트를 만들었습니다.
DMV를 사용하는 모든 데이터베이스에 대한 활성 연결은 sql 2005, 2008 및 2008R2에서 작동합니다.

다음 스크립트는 sys.dm_exec_sessions , sys.dm_exec_requests , sys.dm_exec_connections , sys.dm_tran_locks를 사용합니다.

Declare @dbName varchar(1000)
set @dbName='abc'

;WITH DBConn(SPID,[Status],[Login],HostName,DBName,Command,LastBatch,ProgramName)
As
(
SELECT 
    SPID = s.session_id,
    Status = UPPER(COALESCE
        (
            r.status,
            ot.task_state,
            s.status, 
        '')),
    [Login] = s.login_name,
    HostName = COALESCE
        (
            s.[host_name],
            '  .'
        ),
    DBName = COALESCE
        (
            DB_NAME(COALESCE
            (
                r.database_id,
                t.database_id
            )),
            ''
        ),
    Command = COALESCE
        (
            r.Command,
            r.wait_type,
            wt.wait_type,
            r.last_wait_type,
            ''
        ),
    LastBatch = COALESCE
        (
            r.start_time,
            s.last_request_start_time
        ),
    ProgramName = COALESCE
        (
            s.program_name, 
            ''
        )
FROM
    sys.dm_exec_sessions s
LEFT OUTER JOIN
    sys.dm_exec_requests r
ON
    s.session_id = r.session_id
LEFT OUTER JOIN
    sys.dm_exec_connections c
ON
    s.session_id = c.session_id
LEFT OUTER JOIN
(
    SELECT 
        request_session_id,
        database_id = MAX(resource_database_id)
    FROM
        sys.dm_tran_locks
    GROUP BY
        request_session_id
) t
ON
    s.session_id = t.request_session_id
LEFT OUTER JOIN
    sys.dm_os_waiting_tasks wt
ON 
    s.session_id = wt.session_id
LEFT OUTER JOIN
    sys.dm_os_tasks ot
ON 
    s.session_id = ot.session_id
LEFT OUTER JOIN
(
    SELECT
        ot.session_id,
        CPU_Time = MAX(usermode_time)
    FROM
        sys.dm_os_tasks ot
    INNER JOIN
        sys.dm_os_workers ow
    ON
        ot.worker_address = ow.worker_address
    INNER JOIN
        sys.dm_os_threads oth
    ON
        ow.thread_address = oth.thread_address
    GROUP BY
        ot.session_id
) tt
ON
    s.session_id = tt.session_id
WHERE
    COALESCE
    (
        r.command,
        r.wait_type,
        wt.wait_type,
        r.last_wait_type,
        'a'
    ) >= COALESCE
    (
        '', 
        'a'
    )
)

Select * from DBConn
where DBName like '%'+@dbName+'%'

다른 답변과 비교할 때 너무 복잡합니다. 그러나 공감대가 필요하다
Doan Cuong

DB가 항상 유용하지는 않지만 @astander@ bo-flexson 접근 방식을 선호하십시오 .
Lankymart

1
이것은 하나의 부모 OS 프로세스에 참여하는 방법을 보여줍니다.
redcalx

sys.dm_tran_locks를 사용하면 많은 트랜잭션 잠금이 열려있는 경우 (예 : 오래 실행되는 트랜잭션)이 스크립트 가이 코드를 크게 느리게한다는 것을 알았습니다.
Mike

6

Astander의 답변에 약간의 개선 . 나는 나의 기준을 정하고 매일 재사용하기 쉽게 만든다 :

DECLARE @Spid INT, @Status VARCHAR(MAX), @Login VARCHAR(MAX), @HostName VARCHAR(MAX), @BlkBy VARCHAR(MAX), @DBName VARCHAR(MAX), @Command VARCHAR(MAX), @CPUTime INT, @DiskIO INT, @LastBatch VARCHAR(MAX), @ProgramName VARCHAR(MAX), @SPID_1 INT, @REQUESTID INT

    --SET @SPID = 10
    --SET @Status = 'BACKGROUND'
    --SET @LOGIN = 'sa'
    --SET @HostName = 'MSSQL-1'
    --SET @BlkBy = 0
    --SET @DBName = 'master'
    --SET @Command = 'SELECT INTO'
    --SET @CPUTime = 1000
    --SET @DiskIO = 1000
    --SET @LastBatch = '10/24 10:00:00'
    --SET @ProgramName = 'Microsoft SQL Server Management Studio - Query'
    --SET @SPID_1 = 10
    --SET @REQUESTID = 0

    SET NOCOUNT ON 
    DECLARE @Table TABLE(
            SPID INT,
            Status VARCHAR(MAX),
            LOGIN VARCHAR(MAX),
            HostName VARCHAR(MAX),
            BlkBy VARCHAR(MAX),
            DBName VARCHAR(MAX),
            Command VARCHAR(MAX),
            CPUTime INT,
            DiskIO INT,
            LastBatch VARCHAR(MAX),
            ProgramName VARCHAR(MAX),
            SPID_1 INT,
            REQUESTID INT
    )
    INSERT INTO @Table EXEC sp_who2
    SET NOCOUNT OFF
    SELECT  *
    FROM    @Table
    WHERE
    (@Spid IS NULL OR SPID = @Spid)
    AND (@Status IS NULL OR Status = @Status)
    AND (@Login IS NULL OR Login = @Login)
    AND (@HostName IS NULL OR HostName = @HostName)
    AND (@BlkBy IS NULL OR BlkBy = @BlkBy)
    AND (@DBName IS NULL OR DBName = @DBName)
    AND (@Command IS NULL OR Command = @Command)
    AND (@CPUTime IS NULL OR CPUTime >= @CPUTime)
    AND (@DiskIO IS NULL OR DiskIO >= @DiskIO)
    AND (@LastBatch IS NULL OR LastBatch >= @LastBatch)
    AND (@ProgramName IS NULL OR ProgramName = @ProgramName)
    AND (@SPID_1 IS NULL OR SPID_1 = @SPID_1)
    AND (@REQUESTID IS NULL OR REQUESTID = @REQUESTID)

4

훌륭한 sp_who3 사용자 저장 프로 시저가 꽤 있습니다. Adam Machanic이 정말 좋은 AFAIK를 수행했다고 확신합니다.

아담은 그것을 활동적인 사람이라고 부른다 : http://whoisactive.com


나는 이것을 시도했지만 쉽지 않았다 ... 나는이 다른 게시물과 비슷한 다른 방법을 게시하고 있습니다 (그러나 테스트되고 정확합니다).
돈 롤링

4

KyleMit answer 와 유사하게 d_.sysprocesses 테이블 만 필요하다고 생각하지만 SP_WHO2에서 사용하는 테이블을 직접 선택할 수 있습니다.

누군가이 SP를 열면 SP가하는 일을 이해할 수 있습니다. 이것은 SP_WHO2와 비슷한 출력을 갖는 최선의 선택입니다

select convert(char(5),sp.spid) as SPID
        ,  CASE lower(sp.status)
                 When 'sleeping' Then lower(sp.status)
                 Else  upper(sp.status)
              END as Status
        , convert(sysname, rtrim(sp.loginame)) as LOGIN
        , CASE sp.hostname
                 When Null  Then '  .'
                 When ' ' Then '  .'
                 Else    rtrim(sp.hostname)
              END as HostName
        , CASE isnull(convert(char(5),sp.blocked),'0')
                 When '0' Then '  .'
                 Else isnull(convert(char(5),sp.blocked),'0')
              END as BlkBy
        , case when sp.dbid = 0 then null when sp.dbid <> 0 then db_name(sp.dbid) end as DBName
        , sp.cmd as Command
        , sp.cpu as CPUTime
        , sp.physical_io as DiskIO
        , sp.last_batch as LastBatch
        , sp.program_name as ProgramName 
        from master.dbo.sysprocesses sp (nolock)
  ;

이 선택을 통해 필요한 필드를 선택하고 원하는 순서를 가질 수 있습니다.


나를 위해 위대한 일
Shai Alon

3

이를 수행하는 가장 쉬운 방법은 EXCEL에서 ODBC 링크를 작성하고 거기서 SP_WHO2를 실행하는 것입니다.

원할 때마다 새로 고칠 수 있으며 EXCEL이기 때문에 모든 것을 쉽게 조작 할 수 있습니다!


7
이것이 가장 쉬운 방법이라고 확신합니까?
geomagas

2

예, sp_who2의 출력을 테이블로 캡처 한 다음 테이블에서 선택하면 좋지 않습니다. 첫째, sp_who2는 인기에도 불구하고 문서화되지 않은 프로 시저이므로 문서화되지 않은 프로 시저에 의존해서는 안됩니다. 둘째, 모든 sp_who2는 sys.dm_exec_requests 및 기타 DMV 에서 얻을 수 있고 훨씬 더 많은 것을 얻을 수 있고 show는 필터링 가능, 정렬, 쿼리 가능 및 쿼리 가능한 행 집합과 함께 제공되는 다른 모든 기능을 제공 할 수 있기 때문입니다.



1

첫 번째 및 최상의 답변의 확장 ... 마스터 데이터베이스에서 저장 프로 시저를 작성하여 데이터베이스 이름과 같은 매개 변수를 ..에 전달할 수 있습니다.

USE master
GO

CREATE PROCEDURE sp_who_db
(
    @sDBName varchar(200)   = null,
    @sStatus varchar(200)   = null,
    @sCommand varchar(200)  = null,
    @nCPUTime int           = null
)
AS
DECLARE @Table TABLE
(
    SPID INT,
    Status VARCHAR(MAX),
    LOGIN VARCHAR(MAX),
    HostName VARCHAR(MAX),
    BlkBy VARCHAR(MAX),
    DBName VARCHAR(MAX),
    Command VARCHAR(MAX),
    CPUTime INT,
    DiskIO INT,
    LastBatch VARCHAR(MAX),
    ProgramName VARCHAR(MAX),
    SPID_1 INT,
    REQUESTID INT
)

INSERT INTO @Table EXEC sp_who2

SELECT  *
    FROM    @Table
    WHERE   (@sDBName IS NULL OR DBName = @sDBName)
    AND     (@sStatus IS NULL OR Status = @sStatus)
    AND     (@sCommand IS NULL OR Command = @sCommand)
    AND     (@nCPUTime IS NULL OR CPUTime > @nCPUTime)
GO 

매개 변수 또는 킬 매개 변수로 주문을 추가하도록 확장하여 특정 데이터에 대한 모든 연결을 끊습니다.


0

나는 내 자신의 미래 사용을 위해 여기에 쓰고 있습니다. 삭제하지 않으면 Temp 테이블을 두 번 사용할 수 없으므로 sp_who2를 사용하고 temp 테이블 대신 테이블 변수에 삽입합니다. 그리고 같은 줄에 차단 및 차단을 표시합니다.

--blocked: waiting becaused blocked by blocker
--blocker: caused blocking
declare @sp_who2 table(
    SPID int,
    Status varchar(max),
    Login varchar(max),
    HostName varchar(max),
    BlkBy varchar(max),
    DBName varchar(max),
    Command varchar(max),
    CPUTime int,
    DiskIO int,
    LastBatch varchar(max),
    ProgramName varchar(max),
    SPID_2 int,
    REQUESTID int
)
insert into @sp_who2 exec sp_who2
select  w.SPID blocked_spid, w.BlkBy blocker_spid, tblocked.text blocked_text, tblocker.text blocker_text
from    @sp_who2 w
        inner join sys.sysprocesses pblocked on w.SPID = pblocked.spid
        cross apply sys.dm_exec_sql_text(pblocked.sql_handle) tblocked
        inner join sys.sysprocesses pblocker on case when w.BlkBy = '  .' then 0 else cast(w.BlkBy as int) end = pblocker.spid
        cross apply sys.dm_exec_sql_text(pblocker.sql_handle) tblocker
where   pblocked.Status = 'SUSPENDED'

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.