Sql Server - how to get last server restart (DMV reset date/time) - sql-server

I'm using some modifications to Glenn Berry's excellent DMV queries!
However, I would like to add to the resultset the 'last server restart', or to be more specific, the date/time the statistics for (all, the specific) DMV was reset.
Since it would be quite important to know last reset when looking at the statistics, I want to make absolutely sure the date/time is accurate and shown.
Question: How can you get the most accurate date/time of when a/all DMV statistic was reset?
Thanks!
-D

SELECT sqlserver_start_time FROM sys.dm_os_sys_info

Using a prior question (different key words), I ended up using this approach. As always, up to the individual what would be 'best' for them!
SELECT create_date
FROM sys.databases
WHERE name = 'tempdb'
source: Find out how long the sql server service has been running, from t-sql

This will work but you have to know the service name also its only available with R2 and later
SELECT last_startup_time
FROM sys.dm_server_services
WHERE servicename = "Your Service name"
Although this won't be totally accurate since you can also reset the DB specific views via a DB detach or a DB close.
Also there are two views that can be reset on a live db sys.dm_os_latch_stats and sys.dm_os_wait_stats

There are many ways to check when was SQL server restarted last time.
Below mentioned SQL queries can be used to quickly find out the
server restart date time.
SELECT sqlserver_start_time FROM sys.dm_os_sys_info;
SELECT login_time FROM sys.dm_exec_sessions WHERE session_id = 1;
select start_time from sys.traces where is_default = 1 ;
SELECT crdate FROM sysdatabases WHERE name='tempdb' ;
SELECT create_date FROM sys.databases WHERE name = 'tempdb' ;

There are various way to find out SQL Server reboot time. Following are the codes which return the server re-boot date:
SELECT sqlserver_start_time FROM sys.dm_os_sys_info;
SELECT login_time FROM sys.dm_exec_sessions WHERE session_id = 1;
SELECT start_time from sys.traces where is_default = 1;
SELECT crdate FROM sysdatabases WHERE name='tempdb';
SELECT create_date FROM sys.databases WHERE name = 'tempdb';

Related

SQL Server logs location

How can I retrieve all T-SQL statements fired by users in last one month in SQL Server database?
I have looked at sys tables but I am not able to figure out where the logs are stored.
In SQL Server we don't keep track of users who execute queries, except for some DML/DDL captured by the default trace or run SQL Profiler
Better to create a server side trace or enable SQL Audit to track down activity from users that you want to track or you don't trust.
If you are using any DMV for capture data, remember that DMV data gets reset if the DMV is cleared out, sql server is restarted, etc.
SQL query:
USE master
go
SELECT sdest.DatabaseName
,sdes.session_id
,sdes.[host_name]
,sdes.[program_name]
,sdes.client_interface_name
,sdes.login_name
,sdes.login_time
,sdes.nt_domain
,sdes.nt_user_name
,sdec.client_net_address
,sdec.local_net_address
,sdest.ObjName
,sdest.Query
FROM sys.dm_exec_sessions AS sdes
INNER JOIN sys.dm_exec_connections AS sdec ON sdec.session_id = sdes.session_id
CROSS APPLY (
SELECT db_name(dbid) AS DatabaseName
,object_id(objectid) AS ObjName
,ISNULL((
SELECT TEXT AS [processing-instruction(definition)]
FROM sys.dm_exec_sql_text(sdec.most_recent_sql_handle)
FOR XML PATH('')
,TYPE
), '') AS Query
FROM sys.dm_exec_sql_text(sdec.most_recent_sql_handle)
) sdest
where sdes.session_id <> ##SPID
--and sdes.nt_user_name = '' -- Put the username here !
ORDER BY sdec.session_id
Query Store (SQL Server 2016+) instead of the DMV's. This gives better ability to look into historical data, as well as faster lookups and very efficient to capture short-running queries that can't be captured by sp_who/sp_whoisactive as well.

inactive databases

On our company's SQL server, there are a bunch of databases that don't appear to be used. Is there a way to determine the last time someone used a particular db, connected to it, or ran a query against it?
I don't think there's a per-database statistic for last used date.
What you can do is attach SQL Server profiler to the database, with a filter on database name. You can leave this running for a few weeks and see if there's any activity.
Another option is to check Database Properties -> Reports -> Standard Reports -> Index Usage Statistics. If the last use of any index is very old, that's a good indication the database is not being used.
Alternatively, have a look at SQL Server Auditing. I haven't used it myself, but it looks like it might suit your needs.
Here is actually a query I use. It tells you what DB was used last since its last restart. It gives a date it was last used and days since it was last used. This should be what you need. It is dynamic and will work on any server because is uses system views. Run this on the master DB.
DECLARE #RESTART DATETIME
SELECT #RESTART = login_time
FROM sysprocesses
WHERE spid = 1
SELECT ##SERVERNAME AS SERVER_NAME
,DB_NAME(db.database_id) AS 'DATABASE'
, db.state_desc AS 'State'
, #RESTART AS 'SYSTEM_RESTART'
, MAX(coalesce(us.last_user_seek, us.last_user_scan, us.last_user_lookup,#RESTART)) AS 'LAST_USE'
,CASE
WHEN DATEDIFF(DAY,#RESTART, MAX(coalesce(us.last_user_seek, us.last_user_scan, us.last_user_lookup,#RESTART))) = 0
THEN 'Prior to restart ' + CONVERT(VARCHAR(5),DATEDIFF(DAY,MAX(coalesce(us.last_user_seek, us.last_user_scan, us.last_user_lookup,#RESTART)), CURRENT_TIMESTAMP)) +' days ago'
ELSE CONVERT(VARCHAR(5),DATEDIFF(DAY,MAX(coalesce(us.last_user_seek, us.last_user_scan, us.last_user_lookup,#RESTART)), CURRENT_TIMESTAMP))
END AS 'DAYS_SINCE_LAST_USE'
FROM sys.databases db
LEFT OUTER JOIN sys.dm_db_index_usage_stats us ON db.database_id = us.database_id
/* IF you want to exclude offlinbe Dbs in your output
then remove the comment '--AND STATE != 6' below.
*/
WHERE db.database_id > 4 --AND STATE != 6
GROUP BY DB_NAME(db.database_id), db.state_desc
ORDER BY DB_NAME(db.database_id)

How can I get a list of all of the user databases via t-sql?

I want to get a list of all of the user databases from an mssql server instance. What's the best way to do this?
I know I can select from sys.databases, but I don't see any way to filter out system databases besides hardcoding a list of names to exclude.
I need the script to work on 2000/2005 and 2008.
If the approach I listed above is the only way to go, what are list of names I should exclude? I don't know if 2005 or 2008 added any new system databases off the top of my head.
Was looking in to this again today and decided to profile what Management Studio was doing to populate the Object Explorer details.
Turns out the solution Microsoft have implemented is pretty simplistic and boils down to the following:
SELECT *
FROM master.sys.databases
WHERE Cast(CASE WHEN name IN ('master', 'model', 'msdb', 'tempdb') THEN 1 ELSE is_distributor END As bit) = 0
Please note that this was performed using SSMS 2008R2 (10.50.4033.0).
The first query will return a table with data regarding all of the databases on the instance:
Select *
From sys.databases
From this table you'll notice you can narrow down the scope of data you're looking for by using the WHERE clause. For example, the following queries will essentially return the same result table (the one you're most likely looking for):
Select *
From sys.databases
Where database_id > 5
Select *
From sys.databases
Where len(owner_sid)>1
These queries will work in SQL Server 2008 and 2012.
On SQL Server 2008 R2 Express, looks like I cannot reliably use any of the above methods. INFORMATION_SCHEMA.SCHEMATA only shows me information in the current database, db_id (database_id) #5 is my first user database, and owner_sid on two of my user databases on one of my mirrored databases (running on SQL Server 2008 R2 Standard) shows owner_sid = 1 for my two most recently created databases. (PablolnNZ's comment above is correct: I did not set an explicit owner for those two databases so it still shows as having an owner of 'sa'.)
The only reliable means I was able to use was the following:
SELECT name FROM sys.databases
WHERE name NOT IN ('master', 'model', 'tempdb', 'msdb', 'Resource')
This works in 2005, not 100% sure about the other versions but I think it will fly. It's a bit of a hack but might get you what you need:
select * from sys.databases where len(owner_sid)>1
As nasty as it sounds to hardcode things. The names and number of system databases has been fairly consistent for several versions of SQL. However, if that is too unpleasant you could semi-hardcode them into a table and then plug that into your query.
Not sure if you can offhand. One note -- on 2k you'll have to use master.dbo.sysdatabases and not master.sys.databases (which doesn't exist in 2k).
Starting with SQL Server 2008 you have access to a view called sys.databases which when joined with sys.server_principals can eliminate the databases owned by sa, which you can (most often) safely discern are the "system databases". Thus, allowing you to filter these items out.
select
d.name
,d.database_id
from
sys.databases d
join
sys.server_principals p
on p.sid = d.owner_sid
where
p.name <> 'sa';

Get list of databases from SQL Server

How can I get the list of available databases on a SQL Server instance? I'm planning to make a list of them in a combo box in VB.NET.
Execute:
SELECT name FROM master.sys.databases
This the preferred approach now, rather than dbo.sysdatabases, which has been deprecated for some time.
Execute this query:
SELECT name FROM master.dbo.sysdatabases
or if you prefer
EXEC sp_databases
in light of the ambiguity as to the number of non-user databases, you should probably add:
WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb');
and add the names of the reporting services databases
To exclude system databases:
SELECT [name]
FROM master.dbo.sysdatabases
WHERE dbid > 6
Edited : 2:36 PM 2/5/2013
Updated with accurate database_id, It should be greater than 4, to skip listing
system databases which are having database id between 1 and 4.
SELECT *
FROM sys.databases d
WHERE d.database_id > 4
SELECT [name]
FROM master.dbo.sysdatabases
WHERE dbid > 4
Works on our SQL Server 2008
Use the query below to get all the databases:
select * from sys.databases
If you need only the user-defined databases;
select * from sys.databases WHERE name NOT IN ('master', 'tempdb', 'model', 'msdb');
Some of the system database names are (resource,distribution,reportservice,reportservicetempdb) just insert it into the query if you have the above db's in your machine as default.
Since you are using .NET you can use the SQL Server Management Objects
Dim server As New Microsoft.SqlServer.Management.Smo.Server("localhost")
For Each db As Database In server.Databases
Console.WriteLine(db.Name)
Next
SELECT [name]
FROM master.dbo.sysdatabases
WHERE dbid > 4 and [name] <> 'ReportServer' and [name] <> 'ReportServerTempDB'
This will work for both condition, Whether reporting is enabled or not
I use the following SQL Server Management Objects code to get a list of databases that aren't system databases and aren't snapshots.
using Microsoft.SqlServer.Management.Smo;
public static string[] GetDatabaseNames( string serverName )
{
var server = new Server( serverName );
return ( from Database database in server.Databases
where !database.IsSystemObject && !database.IsDatabaseSnapshot
select database.Name
).ToArray();
}
If you want to omit system databases and ReportServer tables (if installed)
select DATABASE_NAME = db_name(s_mf.database_id)
from sys.master_files s_mf
where
s_mf.state = 0 -- ONLINE
and has_dbaccess(db_name(s_mf.database_id)) = 1
and db_name(s_mf.database_id) NOT IN ('master', 'tempdb', 'model', 'msdb')
and db_name(s_mf.database_id) not like 'ReportServer%'
group by s_mf.database_id
order by 1;
This works on SQL Server 2008/2012/2014. Most of query comes from "sp_databases" system stored procedure. I only removed unneeded column and added where conditions.
Not sure if this will omit the Report server databases since I am not running one, but from what I have seen, I can omit system user owned databases with this SQL:
SELECT db.[name] as dbname
FROM [master].[sys].[databases] db
LEFT OUTER JOIN [master].[sys].[sysusers] su on su.sid = db.owner_sid
WHERE su.sid is null
order by db.[name]
In SQL Server 7, dbid 1 thru 4 are the system dbs.
perhaps I'm a dodo!
show databases; worked for me.
If you are looking for a command to list databases in MYSQL, then just use the below command. After login to sql server,
show databases;
To exclude system databases :
SELECT name FROM master.dbo.sysdatabases where sid <>0x01

Determine Active Node in SQL Failover Cluster

Does anyone know how to determine the active node of a SQL Active-Passive Failover Cluster programmatically from T-SQL?
##SERVERNAME only returns the virtual server name, which is identical from both nodes.
I don't plan to make any decisions based on the data - I trust the failover to do its thing - but I would like to include the information in an event log so I can tell which node in the cluster was active when the event occurred, or help determine if exceptions come up as a result of a failover.
Select ServerProperty('ComputerNamePhysicalNetBIOS')
This works in newer versions:
SELECT * FROM fn_virtualservernodes();
full details at
https://learn.microsoft.com/en-us/sql/relational-databases/system-functions/sys-fn-virtualservernodes-transact-sql?view=sql-server-2017
SELECT * FROM sys.dm_os_cluster_nodes;
full details at https://learn.microsoft.com/en-us/sql/relational-databases/system-dynamic-management-views/sys-dm-os-cluster-nodes-transact-sql?view=sql-server-2017
Try this, this checks if Server is the Primary server in the Availability Group and then based on this condition do X:
IF EXISTS (SELECT ars.role FROM sys.dm_hadr_availability_replica_states ars JOIN sys.availability_groups ag ON ars.group_id = ag.group_id WHERE ars.role_desc = 'PRIMARY')
BEGIN
SELECT 'PRIMARY' -- DO STUFF IF PRIMARY
END
ELSE
BEGIN
SELECT 'NOT PRIMARY' --- DON'T DO STUFF
END

Resources