quarta-feira, 23 de março de 2016

Hunting down the origins of FETCH API_CURSOR and sp_cursorfetch

Hunting down the origins of FETCH API_CURSOR and sp_cursorfetch

So picture the following scenario on a SQL Server 2008 R2 instance (an amalgam of various DBA situations you've no doubt seen before)… 
You get a call from the application team reporting slow performance on a specific service.  They don’t know why it is slow but they do know the session that is running too slow based on the connection and session properties.  They tell you that the issue is happening right now and that they are seeing the offending session issue the following RPC:Completed events in SQL Profiler:
·        exec sp_cursorfetch 180150003,32,1,1
·        exec sp_cursorfetch 180150003,32,1,1
·        exec sp_cursorfetch 180150003,32,1,1
·        exec sp_cursorfetch 180150003,32,1,1
They ask you to take it over and find out what is happening. You’re not sure what the original query is or why this is showing up, but you see the session id they are pointing to is “53” (and you don’t remember the syntax around pulling SQL text “the new way” – so you execute the following ):
DBCC INPUTBUFFER (53)
This returns:
               FETCH API_CURSOR0000000000000004
You do a few quick searches and it seems to have a relationship with server-side cursors. 
You try activity monitor – just in case – but again, no luck:
clip_image001
You take out the new DMV queries – but your query against sys.dm_exec_requests isn’t turning up anything for session id 53 because the executions of this cursor are erratic and you're not timing it (but SQL Profiler does show it plodding along in fits and starts).
You then run the following query against sys.dm_exec_connections and see if that turns up anything useful based on the most recent SQL handle:
SELECT t.text
FROM sys.dm_exec_connections c
CROSS APPLY sys.dm_exec_sql_text (c.most_recent_sql_handle) t
WHERE session_id = 53
 
This returns:
FETCH API_CURSOR0000000000000004
Didn’t help.  
So what about other DMVs?  You eventually find a reference to the sys.dm_exec_cursors DMV and see it can tell you about open cursors, their properties and associated SQL handle.  But you're not sure the SQL Handle will be any help because it hasn't been helpful with the other DMVs:
SELECT c.session_id, c.properties, c.creation_time, c.is_open, t.text
FROM sys.dm_exec_cursors (53) c
CROSS APPLY sys.dm_exec_sql_text (c.sql_handle) t
What do we get this time? Something a bit more useful:
clip_image003
From the results we see the properties of the cursor (using scroll locks) and we also see when it was created – and we see the original query text (unlike the cryptic FETCH API_CURSOR business or the sp_cursorfetch).  We see it was a SELECT * FROM dbo.FactResellerSales.
Now this isn’t to say that SQL Profiler wouldn’t have helped in this situation – but in this case the cursor was defined before the developers captured the downstream activity.  
If they had been tracing it sooner, you might have seen something like this (and then see it followed by sp_cursorfetch):
declare @p1 int
set @p1=180150003
declare @p3 int
set @p3=2
declare @p4 int
set @p4=2
declare @p5 int
set @p5=-1
exec sp_cursoropen @p1 output,N'SELECT * FROM dbo.FactResellerSales',@p3 output,@p4 output,@p5 output
select @p1, @p3, @p4, @p5
 
But in a situation where you’re reacting to an incident (fox has already left the henhouse, so to speak), chances are you weren’t tracing this activity.  And if that’s the case, you’ve now found one reason to use sys.dm_exec_cursors if you didn’t already have one.

SOURCE: http://www.sqlskills.com 

Nenhum comentário:

Postar um comentário