У нас есть устаревшее приложение ASP, которое где-то пропускает соединения SQL. В Activity Monitor я вижу кучу незанятых процессов, время последней партии которых превышает час.
Когда я смотрю на пакет команд T-SQL, это всегда FETCH API_CURSOR [XXX] ([XXX] - это случайно кажущееся шестнадцатеричное число, например FETCH API_CURSOR0000000002CE0BEC), что, насколько я понимаю, вызвано неправильно закрытыми наборами записей ASP ADO.
Пока мы пытаемся определить проблемный код, могу ли я отслеживать, какие запросы открывают какие курсоры? Я предполагаю, что профилировщик, но я не уверен, что именно нужно отслеживать. Я вижу несколько вызовов sp_cursoropen, но нигде не вижу имени API_CUSROR [XXX].
Во-вторых, сможет ли кто-нибудь предложить сценарий, который мы могли бы запустить, чтобы убить эти процессы, на основе времени последней партии> 10 минут и команды последней партии, являющейся FETCH API_CURSOR [XXX]?
К сожалению, по разным причинам у нас нет администраторов баз данных SQL Server.
ОБНОВИТЬ
На основе предоставленного jl сценария и некоторой информации, которую я нашел на SQLAuthority.com, Я придумал этот сценарий, который прекрасно справляется со своей задачей.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
CREATE PROCEDURE [dbo].[sp_KillHungADORecordsets] @dbname varchar(50)
AS
CREATE table #oldSpids
(
spid int,
)
DECLARE @Now DATETIME
SET @Now = GETDATE()
INSERT INTO #oldSpids
select spid
from master.dbo.sysprocesses (nolock)
where dbid = db_id(@dbname)
and spid > 50
and DATEDIFF(minute,last_batch,@Now) > 10
DECLARE hungSpids CURSOR FAST_FORWARD
FOR SELECT spid FROM #oldSpids
DECLARE @spid int
OPEN hungSpids
DECLARE @strSQL varchar(255)
DECLARE @sqlHandle VARBINARY(128)
DECLARE @sqlText VARCHAR(MAX)
FETCH NEXT FROM hungSpids INTO @spid
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
SELECT @sqlHandle = sql_handle
FROM sys.sysprocesses
WHERE spid = @spid
SELECT @sqlText = TEXT
FROM sys.dm_exec_sql_text(@sqlHandle)
IF (@sqlText LIKE 'FETCH API_CURSOR%')
BEGIN
PRINT 'Killing ' + convert(varchar(10),@spid)
SET @strSQL = 'KILL ' + convert(varchar(10),@spid)
EXEC (@strSQL)
END
END
FETCH NEXT FROM hungSpids INTO @spid
END
CLOSE hungSpids
DEALLOCATE hungSpids
DROP table #oldSpids
Однако я до сих пор не знаю, как сопоставить команды sp_opencusror с соответствующим API_CURSOR [XXX] с помощью профилировщика.
Не оригинальный сценарий, но доработанный, который может оказаться там, где вам нужно, или, по крайней мере, для начала:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[uspKillUsersFETCH] @dbname varchar(50)
as
DECLARE @strSQL varchar(255)
PRINT 'Killing Users '
PRINT '-------------------------------------------------------------------------------------------'
CREATE table #tmpUsers(
spid int,
dbname varchar(128),
cmd varchar(128))
INSERT INTO #tmpUsers
select spid, convert(varchar(128),db_name(dbid)), cmd
from master.dbo.sysprocesses (nolock)
DECLARE LoginCursor CURSOR
READ_ONLY
FOR SELECT spid, program_name FROM #tmpUsers WHERE dbname = 'database name here'
and spid > 50
and cmd like '%FETCH API_CURSORXXX%'
DECLARE @spid int
DECLARE @dbname2 varchar(128)
OPEN LoginCursor
FETCH NEXT FROM LoginCursor INTO @spid, @dbname2
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
PRINT 'Killing ' + convert(varchar(10),@spid)
SET @strSQL = 'KILL ' + convert(varchar(10),@spid)
EXEC (@strSQL)
END
FETCH NEXT FROM LoginCursor INTO @spid, @dbname2
END
CLOSE LoginCursor
DEALLOCATE LoginCursor
DROP table #tmpUsers
**** Опять же, не оригинал, так что следует отдать должное неизвестному сценаристу ****
Я использую эту версию для уничтожения spid-пакетов SQL 2005, которые подключаются к резервной базе данных с доставкой журналов с помощью Mgt Studion.