1

I am attempting to track down... something... that is making a connection to a specific database without (apparently) doing anything with the connection. However, so far I have had no luck.

The data from this database has been migrated to other databases on the same server, and after the developers confirming that they had changed / removed all access to this particular database (including connection strings that were embedded but not used), we renamed the database to something like DBNAME_Old. However, this caused scattered errors to be generated. We renamed the DB back to the original name, and the errors disappeared. However, after examining their code, the devs still could not identify any other piece of code that could be causing the issues.

The code accessing the database is not accessible to me (or I would have searched it myself).

Next, I set up a scheduled job that attempted to identify any connections that were made to the database. I could identify processes running in the database via multiple methods, but nothing showed up while my monitoring was running (relatively infrequently, as no slamming production).

I then tried a couple of extended events procedures:

-- Attempt 1 - 
CREATE EVENT SESSION [DBToMonitorMonitoring] ON SERVER 
ADD EVENT sqlserver.connectivity_ring_buffer_recorded(
 ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text,sqlserver.username)
 WHERE ([sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'DBToMonitor') AND [sqlserver].[session_server_principal_name]<>N'[THEDOMAIN\Domain_Login]')),
ADD EVENT sqlserver.login(SET collect_options_text=(1)
 ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text,sqlserver.username)
 WHERE ([database_name]=N'DBToMonitor' OR [sqlserver].[database_name]=N'DBToMonitor')),
ADD EVENT sqlserver.logout(
 ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text,sqlserver.username)
 WHERE ([sqlserver].[database_name]=N'DBToMonitor')),
ADD EVENT sqlserver.rpc_starting(SET collect_statement=(1)
 ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text,sqlserver.username)
 WHERE ([sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'DBToMonitor') AND [sqlserver].[session_server_principal_name]<>N'[THEDOMAIN\Domain_Login]')),
ADD EVENT sqlserver.sql_batch_starting(
 ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text,sqlserver.username)
 WHERE ([sqlserver].[equal_i_sql_unicode_string]([sqlserver].[database_name],N'DBToMonitor') AND [sqlserver].[not_equal_i_sql_unicode_string]([sqlserver].[session_server_principal_name],N'AMERICAS\DTNA_S_SQLService')))
ADD TARGET package0.ring_buffer(SET max_events_limit=(400))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO
-- Attempt 2 - Found on the internet
CREATE EVENT SESSION [DBToMonitor_DB_Usage] ON SERVER 
ADD EVENT sqlserver.sql_statement_completed(
 ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.username)
 WHERE ([sqlserver].[database_name]=N'DBToMonitor'))
ADD TARGET package0.event_file(SET filename=N'D:\Traces\DBToMonitor_DB_Usage.xel',metadatafile=N'D:\Traces\DBToMonitorDB_Usage.xem')
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO

Although the second could identify direct connections made to the database, it could not identify cases such as SELECT TOP 1 * FROM DBToMonitor.dbo.SampleTable

Any recommendations for identifying any connection made to the data in a specific database, or any login even if no data is touched in the database, would be fully appreciated here, because I've reached the end of my resources here, other than to slam the server with continuous monitoring that would bring production to its knees.

Help?

asked Sep 5, 2019 at 20:43

2 Answers 2

2

One way is to set the database to AUTO_CLOSE and capture the database_started event as in the below example. Although I've included a database_id filter in this example, it's probably not needed since this will (hopefully) be the only AUTO_CLOSE database on the instance.

The database_name in the trace will reflect the context database where the database is used, such as in a cross-database query.

ALTER DATABASE DeprecatedDatabase
 SET AUTO_CLOSE ON;
GO
--get database_id value for the database
SELECT DB_ID(N'DeprecatedDatabase') AS DatabaseID;
GO
--specify above database_id value as session filter
CREATE EVENT SESSION DeprecatedDatabaseUsed ON SERVER 
ADD EVENT sqlserver.database_started(
 ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_name,sqlserver.server_principal_name)
 WHERE ([database_id]=(40)))
ADD TARGET package0.event_file(SET filename=N'DeprecatedDatabaseUsed',max_file_size=(100))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF)
GO
ALTER EVENT SESSION DeprecatedDatabaseUsed ON SERVER
 STATE = START;
GO

Note AUTO_CLOSE is generally a bad idea but I'd expect the database to be used infrequently in this case since it shouldn't be used at all.

I'll add that the app team should be able to identify where "scattered errors" occur in the code after the database is renamed. That would pinpoint where the database is being used.

answered Sep 6, 2019 at 9:41
1

What about a Logon Trigger?

You could insert the data for the application logging into the server into a table, then query it later to track the faulting application and server down.

Erik Reasonable Rates Darling
46.3k14 gold badges146 silver badges542 bronze badges
answered Sep 5, 2019 at 21:03
4
  • This is actually checked for in the first Extended Events process: ADD EVENT sqlserver.login(SET collect_options_text=(1) ACTION(sqlserver.client_app_name,sqlserver.client_connection_id,sqlserver.client_hostname,sqlserver.database_name,sqlserver.nt_username,sqlserver.server_principal_name,sqlserver.session_nt_username,sqlserver.session_server_principal_name,sqlserver.sql_text,sqlserver.username) WHERE ([database_name]=N'DBToMonitor' OR [sqlserver].[database_name]=N'DBToMonitor')), Commented Sep 5, 2019 at 22:46
  • Apparently, if your login has permissions to access both database A and database B, running SELECT * FROM B.dbo.Table when you are in A does not trigger a login. Commented Sep 5, 2019 at 22:48
  • @LaughingVergil Logins happen at the server level, not the individual database level. Commented Sep 5, 2019 at 23:27
  • That is true. However, a logon trigger is not likely to identify my access to a database in the above cited case. Commented Sep 5, 2019 at 23:45

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.