SQL Server 2008 Running Procs: How to get the xp_cmdshell items? - sql-server

I'm using this query to find some queries that have been running for a long time:
SELECT sqltext.TEXT,
req.session_id,
req.status,
req.command,
req.cpu_time,
req.total_elapsed_time
FROM sys.dm_exec_requests req
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext
order by req.total_elapsed_time des
Currently, we have some xp_cmdshell things that seem to be stuck (we use it to call bcp.exe for bulk exporting in jobs). However, the output of sys.dm_exec_sql_text() only outputs "xp_cmdshell" and not the parameters -- I really would like to see exactly what commands xp_cmdshell is running so I can track down the issues.
Is there any way to do that in SQL server?
EDIT: The active sessions are calling xp_cmdshell from a stored procedure. E.g.:
EXEC usp_xxx -> calls EXEC usp_yyy -> calls xp_cmdshell.
So, the output of DBCC InputBuffer is the call to usp_xxx which is not what I want.

I'm not sure if the details are available in any of the dynamic management views, but you could take your session_id and use it with DBCC INPUTBUFFER to get the details you seek.
DBCC INPUTBUFFER(83)
would return something like this as an example
EventType Parameters EventInfo
-------------- ---------- ------------------------
Language Event 0 EXEC xp_cmdshell 'sc /h'

Related

Query multiple SQL Servers in One query

I am trying to set up a query that will grab the Windows version of each SQL Server I have and throw it into a table. I have the query that grabs the version but I think there is a better way to get the information needed than connecting to each indiviual server one by one to run the query. I am not opposed to using XP_cmdshell I am just wondering if there is a way to run one query that will grab the version of each Windows OS I have on the sql servers. Also I do have a list of servers to use.
EDIT: I know I wil have to in some way touch each server. I would just like a way to get around having the RDP to each server and open SQL server and query it or haveing to connect to each server within sql server and running the query one by one.
All I have right now code wise is a simple INSERT STATEMENT I get here and I draw a blank on where to go next of even hoe to tackle the problem. The table below has two columns ServerName and Win_Ver ServerName is already populated with all the servers I have.
INSERT INTO mtTable
(Win_Ver)
SELECT ##Version
Given that:
there are "roughly 112 servers"
the servers being a "mixture between 2008 - 2012"
"There is table we are keeping with all of our DB server Statistics."
and "We periodically get asked to produce these statistics"
one option is to cycle through that table of servers using a cursor, and for each one, execute xp_cmdshell to call SQLCMD to run the query. You would use a table variable to capture the result set from SQLCMD as returned by xp_cmdshell. Something like:
DECLARE #ServerName sysname,
#Command NVARCHAR(4000),
#CommandTemplate NVARCHAR(4000);
DECLARE #Results TABLE ([ResultID] INT IDENTITY(1, 1) NOT NULL, [Result] NVARCHAR(4000));
SET #CommandTemplate = N'SQLCMD -S {{SERVER_NAME}} -E -h-1 -Q "PRINT ##VERSION;"';
DECLARE srvrs CURSOR LOCAL READ_ONLY FAST_FORWARD
FOR SELECT [ServerName]
FROM ServerStats;
OPEN srvrs;
FETCH NEXT
FROM srvrs
INTO #ServerName;
WHILE (##FETCH_STATUS = 0)
BEGIN
SET #Command = REPLACE(#CommandTemplate, N'{{SERVER_NAME}}', #ServerName);
INSERT INTO #Results ([Result])
EXEC xp_cmdshell #Command;
-- Get results via SELECT [Result] FROM #Results ORDER BY [ResultID];
-- Do something with the data in #Results
DELETE FROM #Results;
FETCH NEXT
FROM srvrs
INTO #ServerName;
END;
CLOSE srvrs;
DEALLOCATE srvrs;
And it wouldn't hurt to throw in a TRY / CATCH in there :-).
Even if not the most ideal of solutions, it is at least doesn't require adding 112 Linked Servers, and is dynamic and will adjust to servers being added and removed.
In SQL Server you are able to create a Linked Server that you can query from another server.
On the server you wish to write the query in:
Open the Object Explorer
Go to Server Objects
Right Click Linked Servers and add a New Linked Server
Add the Name of your networked server, select SQL server and make sure to define security roles.

Check background process from SQL Server

I have a background process running, it can be seen in task Manager while its running. I need to check from my database, whether the process is running or not
I have tried the following query
select * from sys.dm_os_threads
select * FROM sys.dm_os_tasks
But it doesnt show me all process running on the system
I have a background process running, it can be seen in task Manager while its running. I need to check from my database, whether the process is running or not
I hope you are talking about background SQL Server process. Below queries only show information related to SQL Server
All processes running on SQL server can be seen by querying DMV
select * from sys.dm_exec_requests
select * from sys.dm_exec_sessions
select * from sys.dm_exec_connections
You can read books online about the documentation about these DMV's
use this query
select
tblSysProcess.cmd
, tblSysProcess.physical_io IOUsage
, tblSysProcess.cpu as CPUusage
, tblSysProcess.waittype as waitType
, tblSysProcess.waittime as waitTime
, tblSysProcess.lastwaittype as lastWaitType
, tblSysProcess.waitResource as waitResource
, tblSysProcess.dbid as databaseID
, case
when (dbid > 0) then db_name(dbid)
else ''
end as dbName
, memusage as memUsage
, status
from master.dbo.sysprocesses tblSysProcess
where
(
--background process
(tblSysProcess.spid < 50)
)
select db_name(dbid),cmd,spid,status
from
sys.sysprocesses
where
db_name(dbid) = 'dbname' and status = 'background'
So it looks like you're not trying to see a SQL server process but another process on the machine for another application, none of the built in DMVs or functions will be able to show you this information natively. You have a couple of options, one is to write a CLR stored proc or function to check for the process, the other is to use xp_cmdshell to get the tasklist, you can do that like this:
EXEC sp_configure 'show advanced options', 1
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
GO
EXEC xp_cmdshell 'tasklist.exe'
GO
EXEC sp_configure 'xp_cmdshell', 0
RECONFIGURE
That will list out all the running processes on the machine, you could shove that data into a table if you like for further analysis if required, or you can play with the tasklist.exe parameters to just look for the process that you are interested in. Just remember to turn off xp_cmdshell whenever you don't need it as it can be a security risk.
Try This;
EXEC sp_who1
EXEC sp_who2
SELECT *
FROM MASTER..sysprocesses
SELECT *
FROM sys.dm_exec_sessions
WHERE is_user_process = 1

Why SQL Server doesn't allow to remove a Distributor exactly after Configuration?

I Configured a distribution in SQL Server 2008 using both Wizard and T-SQL but after it when I want to remove it Using Wizard (right clicking on Replication and choosing 'Disable Publishing and Distribution...') or executing following command with and without its parameters:
exec sp_dropdistributor #no_checks = 1 -- no new results with #ignore_distributor = 1
this Error would be presented:
Msq 21122, Level 16, State 1, Procedure sp_dropdistributiondb Line 124
Cannot drop the distribution database 'lobloblob' because it is
currently in use.
I didn't publish any thing, didn't configure any subscription but gave this error
what should I do ?
Try this:
SELECT spid FROM sys.sysprocesses WHERE dbid = db_id('distribution')
Kill the spid and try again. Now it should work.
I used the following scripts:
SELECT spid FROM sys.sysprocesses WHERE dbid = db_id('distribution')
and found that the session_id of current session (which contains the distribution configuration script) doesn't allow to disable distribution so i suggest this script to kill running spid to drop distribution:
use [master]
declare #spid varchar(10)
select #spid=spid from sys.sysprocesses where dbid = DB_ID('distribution')
while ##ROWCOUNTS <> 0
exec ('KILL ' + #spid)
exec sp_dropdistributor #no_checks = 1
My guess would be that the distribution cleanup job is causing the problem. But, to check, prepare to execute the sp_dropdistributor in one window in SSMS and note the session_id of the window. In a second, prepare to run select session_id from sys.dm_os_waiting_tasks where blocked_session_id = <spid from window 1>. Back in window 1, run the proc and then switch back to window 2 and run the select. it'll tell you the session_ids of the sessions blocking the drop of the database.

How do you access the Context_Info() variable in SQL2005 Profiler?

I am using the Context_Info() variable to keep track of the user that is executing a stored procedure and free-form sql. When troubleshooting issues on this server everyone session comes through. I would like to be able to bring in the value of the context_info() variable and filter based on it.
You can use the UserConfigurable Events along with sp_trace_generateevent (EventId's 82-91) when setting the context_info() to output the values to the trace. Your option is to either do that, or trace the statements setting the context_info(). You won't be able to get the value any other way unless you write a process to dump the output of sys.dm_exec_sessions in a loop while the trace is running:
select session_id, cast(context_info as varchar(128)) as context_info
from sys.dm_exec_sessions
where session_id > 50 -- user sessions
for SQL 2000 you can use sysprocesses:
select spid, cast(context_info as varchar(128)) as context_info
from sysprocesses
where sid > 50 -- user sessions

How can I display the execution plan for a stored procedure?

I am able to view the Estimated Execution Plan (Management Studio 9.0) for a query without a problem but when it comes to stored procedures I do not see an easy way to do this without copying the code from the ALTER screen and pasting it into a query window, otherwise it will show the plan for the ALTER and not the procedure. Even after doing this, any inputs are missing and I would need to DECLARE them as such.
Is there an easier way to do this on stored procedures?
Edit:
I just thought of something that might work but I am not sure.
Could I do the estimated execution plan on
exec myStoredProc 234
SET SHOWPLAN_ALL ON
GO
-- FMTONLY will not exec stored proc
SET FMTONLY ON
GO
exec yourproc
GO
SET FMTONLY OFF
GO
SET SHOWPLAN_ALL OFF
GO
Select the storedprocedure name (just type it in a query window), right click, and choose the 'Display Estimated Execution Plan' button in the toolbar of SQl Server Mgmt Studio.
Note that you don't have to have the stored procedure code open. Just the procedure name has to be selected.
The plan for the stored procedure from with in the called procedures will also be displayed in graphical form.
When executing a stored procedure in SQL Management Studio 2008 you can click Query -> Include Actual Execution Plan from the menu...its also on the tool bar
After reading through the comments executing seems to be an issue and to solve this issue i would recommend wrapping the execution of the stored procedure in a transaction rolling it back at the end
Use
SET SHOWPLAN_ALL ON
Go
exec myStoredProc 234
GO
SET SHOWPLAN_ALL OFF
GO
See http://msdn.microsoft.com/en-us/library/aa259203.aspx
As long as you aren't using tmp tables i think this will work
I know answer was submitted a while ago but I find query below useful
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT [ProcedureName] = OBJECT_NAME([ps].[object_id], [ps].[database_id])
,[ProcedureExecutes] = [ps].[execution_count]
,[VersionOfPlan] = [qs].[plan_generation_num]
,[ExecutionsOfCurrentPlan] = [qs].[execution_count]
,[Query Plan XML] = [qp].[query_plan]
FROM [sys].[dm_exec_procedure_stats] AS [ps]
JOIN [sys].[dm_exec_query_stats] AS [qs] ON [ps].[plan_handle] = [qs].[plan_handle]
CROSS APPLY [sys].[dm_exec_query_plan]([qs].[plan_handle]) AS [qp]
WHERE [ps].[database_id] = DB_ID()
AND OBJECT_NAME([ps].[object_id], [ps].[database_id]) = 'TEST'
There are quite a few ways to get the actual execution plan of a stored procedure.
SELECT
qp.query_plan,
SQLText.text
FROM sys.dm_exec_cached_plans AS CP
CROSS APPLY sys.dm_exec_sql_text( plan_handle)AS SQLText
CROSS APPLY sys.dm_exec_query_plan( plan_handle)AS QP
WHERE objtype = 'Proc' and cp.cacheobjtype = 'Compiled Plan'
looking at the plans on a production server with the statistics of the data in the production server may show a different plan then of a dev box with a smaller dataset.
There is a lot more data to look at, like how often is a procedure executed according to query cache
SELECT
qp.query_plan,
CP.usecounts as [Executed],
DB_name(QP.dbid) as [Database],
OBJECT_NAME(QP.objectid) as [Procedure],
SQLText.text as [TSQL],
so.create_date as [Procedure Created],
so.modify_date as [Procedure Modified]
FROM sys.dm_exec_cached_plans AS CP
CROSS APPLY sys.dm_exec_sql_text( plan_handle)AS SQLText
CROSS APPLY sys.dm_exec_query_plan( plan_handle)AS QP
join sys.objects as so on so.[object_id]=QP.objectid
WHERE objtype = 'Proc' and cp.cacheobjtype = 'Compiled Plan'
The XML query plan (the first column in both queries), contains the XML of the execution plan allowing you, in SSMS to click on it and view the actual plans but also allows you to scan for things you do not like to have like index scan or "god forbid" table scans.
SELECT
qp.query_plan,
CP.usecounts as [Executed],
DB_name(QP.dbid) as [Database],
OBJECT_NAME(QP.objectid) as [Procedure],
SQLText.text as [TSQL],
so.create_date as [Procedure Created],
so.modify_date as [Procedure Modified]
FROM sys.dm_exec_cached_plans AS CP
CROSS APPLY sys.dm_exec_sql_text( plan_handle)AS SQLText
CROSS APPLY sys.dm_exec_query_plan( plan_handle)AS QP
join sys.objects as so on so.[object_id]=QP.objectid
WHERE objtype = 'Proc' and cp.cacheobjtype = 'Compiled Plan'
and cast(qp.query_plan as nvarchar(max)) like '%loop%'
I sample this using a really bad way by casting the XML to string and then doing a wildcard search however XML queries are not things most do every day and string wildcards are easy for everyone.
Running the stored procedure in management studio (or query analyser) with show actual execution plan (from the query menu) enabled will show you the plan for the stored procedure after you have run it. If you cant run it there is show estimated execution plan (though in my experience that is often less accurate.)
You can also use Profiler to see the execution plan. You'll want to include the Performance : Show Plan Statistics Profile option and be sure to inlcude Binary Data in your columns.
You can then run any query or procedure and see the execution plan.
Edit
If you can't use profiler, and you don't want to open another window I suggest that you include a comment block at the begining of your stored procs. For example imagine the following:
/*
Description: This procedure does XYZ etc...
DevelopedBy: Josh
Created On: 4/27/09
Execution: exec my_procName N'sampleparam', N'sampleparam'
*/
ALTER PROCEDURE my_procName
#p1 nvarchar(20),
#p2 nvarchar(20)
AS
What this allows is that you can highlight just the execution purpose and turn on show execution plan. And run it.
Here's a screenshot.Took me a while to figure out where to look for.

Resources