How to find the number of concurrent SQL Server connections - sql

I have a SQL Server that is reaching the max limit of concurrent connections. I have many different servers & services connecting to one SQL Server at the same time.
I did find another query that seems to work:
SELECT DB_NAME(dbid) AS DBName,
COUNT(dbid) AS NumberOfConnections,
loginame AS LoginName,
nt_domain AS NT_Domain,
nt_username AS NT_UserName,
hostname AS HostName
FROM sys.sysprocesses
WHERE dbid > 0
GROUP BY dbid,
hostname,
loginame,
nt_domain,
nt_username
ORDER BY NumberOfConnections DESC;
However, this gives me the number of connections which is good. How do i further dig down this to find to see the each connection and what action they are doing?

the sql command "sp_who" which provides information about current users, sessions, and processes in an instance of the Microsoft SQL Server Database Engine (MSDN) From here, you should be able to send the results into a temp table and group them by servername.
such as the following...
CREATE TABLE #tbl (
spid int
, ecid int
, status varchar(50)
, loginame varchar(255)
, hostname varchar(255)
, blk varchar(50)
, dbname varchar(255)
, cmd varchar(255)
, request_id varchar(255)
)
GO
INSERT INTO #tbl EXEC sp_who
SELECT COUNT(0), hostname FROM #tbl group by hostname
DROP TABLE #tbl
GO

Are you talking about how to check the connections that are reaching your SQL Server instance? How about some DOS commands? try to search for the port 1433 or for the PID of your SQL Server process.
netstat -nao | find "1433"
To find the PID (process identifier) that you are looking for, just go to your task manager and customize the processes view, mode details here:
http://www.mydigitallife.info/how-to-get-and-view-process-identifier-process-id-or-pid-on-windows/

Related

Identifying a User and a Machine [duplicate]

My work company has a MSSQL server 2005. I have two questions about finding out current log user and any way to send out a warning message:
First question is if there is any T-SQL or SP available to find out current login user name and machine name. If the user is using SQL server sa name to remotely access to SQL server, is there any way to find out that user's windows name (the name to log to the windows)?
My next question is that if I can get the user name or id, is there any way to send out a warning message such as "currently SQL server is clean up or backup, please do not log in at this time". I guess it may be difficult. I may have to send an email out to the user.
The SQL server is only accessible in the company. The SQL server has a list of users as login users: windows users, SQL users and sa.
SELECT SUSER_SNAME(), HOST_NAME()
If the connection is "sa" (or any other SQL login) then you can't find the domain/windows user name. SQL Server only knows it's "sa" or that SQL login.
HOST_NAME may not be reliable either, it can be set in the connection string ("Application Name"). Or it could be vague eg "Microsoft Office" for by default for Access, Excel etc
You could backtrack via client_net_address in sys.dm_exec_connections and match MAC address to IP and find out who is logged on...
An easy way to find out both host and user is
EXEC sp_who2;
where you get some other information that can be good to know, as if the user is active and so on...
It does not resolve the issues that gbn announced.
Thanks for all your suggestions first. I tried all the methods and I think Joakim Backman's method meet my need. Here is summary of what I find out.
Query of sys.syslogins only list login information. The accdate does not give the current login user timestamp. I tried to login from another application to my SQL and this query does not list the login.
SELECT SUSER_SNAME(), HOST_NAME() only list one user on SQL server. For example, I log in in as my name to SQL server. The result of this query only lists my name and machine name. This query does not list current users on the SQL server.
exec sp_who2 lists information I need. It lists current user name machine name, active status, db name user's access, and command used.
In order to get the information I use in SP, I have to filter and join the information with other tables, such as emails. Here is the codes I use:
DECLARE #retTable TABLE (
SPID int not null
, Status varchar (255) not null
, Login varchar (255) not null
, HostName varchar (255) not null
, BlkBy varchar(10) not null
, DBName varchar (255) null
, Command varchar (255) not null
, CPUTime int not null
, DiskIO int not null
, LastBatch varchar (255) not null
, ProgramName varchar (255) null
, SPID2 int not null
, REQUESTID INT
)
INSERT INTO #retTable EXEC sp_who2
SELECT Status, Login, HostName, DBName, Command, CPUTime, ProgramName -- *
FROM #retTable
--WHERE Login not like 'sa%' -- if not interested in sa
ORDER BY Login, HostName

List the User mapped to a Login on one particular database

I'm back here with a SQL User/Login problem.
First off all i'm working on SQL server 2008 and i'm not the master on that server.
On that SQL server i have different Login and these Login are mapped to a USER to my database 'DB_MyDataBase'.
Indeed, i have 10 different Login mapped to 10 different User on my database 'DB_MyDataBase'.
For i.e., when i'm connecting to the SQL server with a Login 'Laurent', That SQL Login 'Laurent' is the USER 'Laurel' on my database 'DB_MyDataBase'. For the moment, no problem.
But now for that 10 different Login and want to know their respective USER for my database 'DB_MyDataBase'.
After some research i've found a request that can do "the job"
sp_msloginmappings 'Laurent', 1
Normally, that show mapping user account info in current databases context for login account 'Laurent'
But when i tried it, i had a error message.
Nom d'objet 'dbo.syslogins' non valide.
Error message is : Object name 'dbo.syslogins' is not valid for non French users.
I've found another request which is working "a bit".
SET NOCOUNT ON
CREATE TABLE #temp
(
SERVER_name SYSNAME NULL ,
Database_name SYSNAME NULL ,
UserName SYSNAME ,
GroupName SYSNAME ,
LoginName SYSNAME NULL ,
DefDBName SYSNAME NULL ,
DefSchemaName SYSNAME NULL ,
UserID INT ,
[SID] VARBINARY(85)
)
DECLARE #command VARCHAR(MAX)
--this will contain all the databases (and their sizes!)
--on a server
DECLARE #databases TABLE
(
Database_name VARCHAR(128) ,
Database_size INT ,
remarks VARCHAR(255)
)
INSERT INTO #databases--stock the table with the list of databases
EXEC sp_databases
SELECT #command = COALESCE(#command, '') + '
USE ' + database_name + '
insert into #temp (UserName,GroupName, LoginName,
DefDBName, DefSchemaName,UserID,[SID])
Execute sp_helpuser
UPDATE #TEMP SET database_name=DB_NAME(),
server_name=##ServerName
where database_name is null
'
FROM #databases
EXECUTE ( #command )
SELECT loginname ,
UserName ,
Database_name
FROM #temp
WHERE LoginName = 'Laurent'
So that one is working it's listing all User mapped to that Login on every database BUT (there is always a "but"...) it's only working with the Login i use to connect.
For i.e. When i connect to the SQL server with Login 'Laurent' the previous request is working because i request for the same Login that i used to connect to the SQL server but when i connect with Login 'Laurent' and do the previous request with a different Login (so not 'Laurent' but another one which have a user mapped to my database 'DB_MyDataBase'.) I don't see anything, it returns me blank column....
Maybe it's because i'm not master on that SQL server.
So how i can list User mapped to a Login different from the one i'm connected?
I hope my question is clear enough (sorry for long text) and thanks for your future answer. Don't hesitate to ask me if you need further info to answer me.
What you can see will depend on the permissions of the user you are logged in as. This query against two of the security catalog views should give you what you want provided you have the necessary permission.
select
dp.name as UserName,
sp.name as LoginName
from
sys.database_principals dp
left join sys.server_principals sp on sp.sid = dp.sid
where
dp.type in ('S', 'U')

How to find out what is locking my tables?

I have a SQL table that all of a sudden cannot return data unless I include with (nolock) on the end, which indicates some kind of lock left on my table.
I've experimented a bit with sys.dm_tran_locks to identify that there are in fact a number of locks on the table, but how do I identify what is locking them (ie the request element of the sys.dm_tran_locks)?
EDIT: I know about sp_lock for pre SQL 2005, but now that that sp is deprecated, AFAIK the right way to do this is with sys.dm_tran_locks. I'm using SQL Server 2008 R2.
Take a look at the following system stored procedures, which you can run in SQLServer Management Studio (SSMS):
sp_who
sp_lock
Also, in SSMS, you can view locks and processes in different ways:
Different versions of SSMS put the activity monitor in different places. For example, SSMS 2008 and 2012 have it in the context menu when you right-click on a server node.
For getting straight to "who is blocked/blocking" I combined/abbreviated sp_who and sp_lock into a single query which gives a nice overview of who has what object locked to what level.
--Create Procedure WhoLock
--AS
set nocount on
if object_id('tempdb..#locksummary') is not null Drop table #locksummary
if object_id('tempdb..#lock') is not null Drop table #lock
create table #lock ( spid int, dbid int, objId int, indId int, Type char(4), resource nchar(32), Mode char(8), status char(6))
Insert into #lock exec sp_lock
if object_id('tempdb..#who') is not null Drop table #who
create table #who ( spid int, ecid int, status char(30),
loginame char(128), hostname char(128),
blk char(5), dbname char(128), cmd char(16)
--
, request_id INT --Needed for SQL 2008 onwards
--
)
Insert into #who exec sp_who
Print '-----------------------------------------'
Print 'Lock Summary for ' + ##servername + ' (excluding tempdb):'
Print '-----------------------------------------' + Char(10)
Select left(loginame, 28) as loginame,
left(db_name(dbid),128) as DB,
left(object_name(objID),30) as object,
max(mode) as [ToLevel],
Count(*) as [How Many],
Max(Case When mode= 'X' Then cmd Else null End) as [Xclusive lock for command],
l.spid, hostname
into #LockSummary
from #lock l join #who w on l.spid= w.spid
where dbID != db_id('tempdb') and l.status='GRANT'
group by dbID, objID, l.spid, hostname, loginame
Select * from #LockSummary order by [ToLevel] Desc, [How Many] Desc, loginame, DB, object
Print '--------'
Print 'Who is blocking:'
Print '--------' + char(10)
SELECT p.spid
,convert(char(12), d.name) db_name
, program_name
, p.loginame
, convert(char(12), hostname) hostname
, cmd
, p.status
, p.blocked
, login_time
, last_batch
, p.spid
FROM master..sysprocesses p
JOIN master..sysdatabases d ON p.dbid = d.dbid
WHERE EXISTS ( SELECT 1
FROM master..sysprocesses p2
WHERE p2.blocked = p.spid )
Print '--------'
Print 'Details:'
Print '--------' + char(10)
Select left(loginame, 30) as loginame, l.spid,
left(db_name(dbid),15) as DB,
left(object_name(objID),40) as object,
mode ,
blk,
l.status
from #lock l join #who w on l.spid= w.spid
where dbID != db_id('tempdb') and blk <>0
Order by mode desc, blk, loginame, dbID, objID, l.status
(For what the lock level abbreviations mean, see e.g. https://technet.microsoft.com/en-us/library/ms175519%28v=sql.105%29.aspx)
Copied from: sp_WhoLock – a T-SQL stored proc combining sp_who and sp_lock...
NB the [Xclusive lock for command] column can be misleading -- it shows the current command for that spid; but the X lock could have been triggered by an earlier command in the transaction.
exec sp_lock
This query should give you existing locks.
exec sp_who SPID -- will give you some info
Having spids, you could check activity monitor(processes tab) to find out what processes are locking the tables ("details" for more info and "kill process" to kill it).
I have a stored procedure that I have put together, that deals not only with locks and blocking, but also to see what is running in a server.
I have put it in master.
I will share it with you, the code is below:
USE [master]
go
CREATE PROCEDURE [dbo].[sp_radhe]
AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
-- the current_processes
-- marcelo miorelli
-- CCHQ
-- 04 MAR 2013 Wednesday
SELECT es.session_id AS session_id
,COALESCE(es.original_login_name, '') AS login_name
,COALESCE(es.host_name,'') AS hostname
,COALESCE(es.last_request_end_time,es.last_request_start_time) AS last_batch
,es.status
,COALESCE(er.blocking_session_id,0) AS blocked_by
,COALESCE(er.wait_type,'MISCELLANEOUS') AS waittype
,COALESCE(er.wait_time,0) AS waittime
,COALESCE(er.last_wait_type,'MISCELLANEOUS') AS lastwaittype
,COALESCE(er.wait_resource,'') AS waitresource
,coalesce(db_name(er.database_id),'No Info') as dbid
,COALESCE(er.command,'AWAITING COMMAND') AS cmd
,sql_text=st.text
,transaction_isolation =
CASE es.transaction_isolation_level
WHEN 0 THEN 'Unspecified'
WHEN 1 THEN 'Read Uncommitted'
WHEN 2 THEN 'Read Committed'
WHEN 3 THEN 'Repeatable'
WHEN 4 THEN 'Serializable'
WHEN 5 THEN 'Snapshot'
END
,COALESCE(es.cpu_time,0)
+ COALESCE(er.cpu_time,0) AS cpu
,COALESCE(es.reads,0)
+ COALESCE(es.writes,0)
+ COALESCE(er.reads,0)
+ COALESCE(er.writes,0) AS physical_io
,COALESCE(er.open_transaction_count,-1) AS open_tran
,COALESCE(es.program_name,'') AS program_name
,es.login_time
FROM sys.dm_exec_sessions es
LEFT OUTER JOIN sys.dm_exec_connections ec ON es.session_id = ec.session_id
LEFT OUTER JOIN sys.dm_exec_requests er ON es.session_id = er.session_id
LEFT OUTER JOIN sys.server_principals sp ON es.security_id = sp.sid
LEFT OUTER JOIN sys.dm_os_tasks ota ON es.session_id = ota.session_id
LEFT OUTER JOIN sys.dm_os_threads oth ON ota.worker_address = oth.worker_address
CROSS APPLY sys.dm_exec_sql_text(er.sql_handle) AS st
where es.is_user_process = 1
and es.session_id <> ##spid
and es.status = 'running'
ORDER BY es.session_id
end
GO
this procedure has done very good for me in the last couple of years.
to run it just type sp_radhe
Regarding putting sp_radhe in the master database
I use the following code and make it a system stored procedure
exec sys.sp_MS_marksystemobject 'sp_radhe'
as you can see on the link below
Creating Your Own SQL Server System Stored Procedures
Regarding the transaction isolation level
Questions About T-SQL Transaction Isolation Levels You Were Too Shy to Ask
Jonathan Kehayias
Once you change the transaction isolation level it only changes when
the scope exits at the end of the procedure or a return call, or if
you change it explicitly again using SET TRANSACTION ISOLATION LEVEL.
In addition the TRANSACTION ISOLATION LEVEL is only scoped to the
stored procedure, so you can have multiple nested stored procedures
that execute at their own specific isolation levels.
This should give you all the details of the existing locks.
DECLARE #tblVariable TABLE(SPID INT, Status VARCHAR(200), [Login] VARCHAR(200), HostName VARCHAR(200),
BlkBy VARCHAR(200), DBName VARCHAR(200), Command VARCHAR(200), CPUTime INT,
DiskIO INT, LastBatch VARCHAR(200), ProgramName VARCHAR(200), _SPID INT,
RequestID INT)
INSERT INTO #tblVariable
EXEC Master.dbo.sp_who2
SELECT v.*, t.TEXT
FROM #tblVariable v
INNER JOIN sys.sysprocesses sp ON sp.spid = v.SPID
CROSS APPLY sys.dm_exec_sql_text(sp.sql_handle) AS t
ORDER BY BlkBy DESC, CPUTime DESC
You can then kill, with caution, the SPID that blocks your table.
kill 104 -- Your SPID
You can also use sp_who2 which gives more information
Here is some info http://dbadiaries.com/using-sp_who2-to-help-with-sql-server-troubleshooting
As per the official docs the sp_lock is mark as deprecated:
This feature is in maintenance mode and may be removed in a future
version of Microsoft SQL Server. Avoid using this feature in new
development work, and plan to modify applications that currently use
this feature.
and it is recommended to use sys.dm_tran_locks instead. This dynamic management object returns information about currently active lock manager resources. Each row represents a currently active request to the lock manager for a lock that has been granted or is waiting to be granted.
It generally returns more details in more user friendly syntax then sp_lock does.
The whoisactive routine written by Adam Machanic is very good to check the current activity in your environment and see what types of waits/locks are slowing your queries. You can very easily find what is blocking your queries and tons of other handy information.
For example, let's say we have the following queries running in the default SQL Server Isolation Level - Read Committed. Each query is executing in separate query window:
-- creating sample data
CREATE TABLE [dbo].[DataSource]
(
[RowID] INT PRIMARY KEY
,[RowValue] VARCHAR(12)
);
INSERT INTO [dbo].[DataSource]([RowID], [RowValue])
VALUES (1, 'samle data');
-- query window 1
BEGIN TRANSACTION;
UPDATE [dbo].[DataSource]
SET [RowValue] = 'new data'
WHERE [RowID] = 1;
--COMMIT TRANSACTION;
-- query window 2
SELECT *
FROM [dbo].[DataSource];
Then execute the sp_whoisactive (only part of the columns are displayed):
You can easily seen the session which is blocking the SELECT statement and even its T-SQL code. The routine has a lot of parameters, so you can check the docs for more details.
If we query the sys.dm_tran_locks view we can see that one of the session is waiting for a share lock of a resource, that has exclusive lock by other session:
Plot twist!
You can have orphaned distributed transactions holding exclusive locks and you will not see them if your script assumes there is a session associated with the transaction (there isn't!). Run the script below to identify these transactions:
;WITH ORPHANED_TRAN AS (
SELECT
dat.name,
dat.transaction_uow,
ddt.database_transaction_begin_time,
ddt.database_transaction_log_bytes_reserved,
ddt.database_transaction_log_bytes_used
FROM
sys.dm_tran_database_transactions ddt,
sys.dm_tran_active_transactions dat,
sys.dm_tran_locks dtl
WHERE
ddt.transaction_id = dat.transaction_id AND
dat.transaction_id = dtl.request_owner_id AND
dtl.request_session_id = -2 AND
dtl.request_mode = 'X'
)
SELECT DISTINCT * FROM ORPHANED_TRAN
Once you have identified the transaction, use the transaction_uow column to find it in MSDTC and decide whether to abort or commit it. If the transaction is marked as In Doubt (with a question mark next to it) you will probably want to abort it.
You can also kill the Unit Of Work (UOW) by specifying the transaction_uow in the KILL command:
KILL '<transaction_uow>'
References:
https://learn.microsoft.com/en-us/sql/t-sql/language-elements/kill-transact-sql?view=sql-server-2017#arguments
https://www.mssqltips.com/sqlservertip/4142/how-to-kill-a-blocking-negative-spid-in-sql-server/
A colleague and I have created a tool just for this.
It's a visual representation of all the locks that your sessions produce.
Give it a try (http://www.sqllockfinder.com), it's open source (https://github.com/LucBos/SqlLockFinder)

SQL Server trigger - connection info

is it possible to get MSSQL connection info?not onli SUSER_ID(), SUSER_NAME(), ORIGINAL_LOGIN(), BUT other like:
IP
Connection string
ect..
You can get some more information from sys.dm_exec_connections:
e.g.
SELECT *
FROM sys.dm_exec_connections
WHERE session_id = ##SPID
This will get the connection info available for the current process (SPID).
This doesn't give the full connection string, but does give some more info like IP address (client_net_address).
This will work for SQL Server 2005 and above.
You didn't mention the version of SQL Server that you're using, but this should work for SQL 2005 and above. You can change the ##SPID as needed.
SELECT
conn.session_ID as SPID,
conn.client_net_address as IPAddress,
sess.host_name as MachineName,
sess.program_name as ApplicationName,
login_name as LoginName
FROM
sys.dm_exec_connections conn
INNER JOIN sys.dm_exec_sessions sess ON
conn.session_ID = sess.session_ID
WHERE
conn.session_ID = ##SPID

How to find out user name and machine name to access to SQL server

My work company has a MSSQL server 2005. I have two questions about finding out current log user and any way to send out a warning message:
First question is if there is any T-SQL or SP available to find out current login user name and machine name. If the user is using SQL server sa name to remotely access to SQL server, is there any way to find out that user's windows name (the name to log to the windows)?
My next question is that if I can get the user name or id, is there any way to send out a warning message such as "currently SQL server is clean up or backup, please do not log in at this time". I guess it may be difficult. I may have to send an email out to the user.
The SQL server is only accessible in the company. The SQL server has a list of users as login users: windows users, SQL users and sa.
SELECT SUSER_SNAME(), HOST_NAME()
If the connection is "sa" (or any other SQL login) then you can't find the domain/windows user name. SQL Server only knows it's "sa" or that SQL login.
HOST_NAME may not be reliable either, it can be set in the connection string ("Application Name"). Or it could be vague eg "Microsoft Office" for by default for Access, Excel etc
You could backtrack via client_net_address in sys.dm_exec_connections and match MAC address to IP and find out who is logged on...
An easy way to find out both host and user is
EXEC sp_who2;
where you get some other information that can be good to know, as if the user is active and so on...
It does not resolve the issues that gbn announced.
Thanks for all your suggestions first. I tried all the methods and I think Joakim Backman's method meet my need. Here is summary of what I find out.
Query of sys.syslogins only list login information. The accdate does not give the current login user timestamp. I tried to login from another application to my SQL and this query does not list the login.
SELECT SUSER_SNAME(), HOST_NAME() only list one user on SQL server. For example, I log in in as my name to SQL server. The result of this query only lists my name and machine name. This query does not list current users on the SQL server.
exec sp_who2 lists information I need. It lists current user name machine name, active status, db name user's access, and command used.
In order to get the information I use in SP, I have to filter and join the information with other tables, such as emails. Here is the codes I use:
DECLARE #retTable TABLE (
SPID int not null
, Status varchar (255) not null
, Login varchar (255) not null
, HostName varchar (255) not null
, BlkBy varchar(10) not null
, DBName varchar (255) null
, Command varchar (255) not null
, CPUTime int not null
, DiskIO int not null
, LastBatch varchar (255) not null
, ProgramName varchar (255) null
, SPID2 int not null
, REQUESTID INT
)
INSERT INTO #retTable EXEC sp_who2
SELECT Status, Login, HostName, DBName, Command, CPUTime, ProgramName -- *
FROM #retTable
--WHERE Login not like 'sa%' -- if not interested in sa
ORDER BY Login, HostName