Determine Active Node in SQL Failover Cluster - sql-server

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

Related

Unique ID of the SQL Server Database

There are many SQL Server databases created from the same .BAK file.
I need to get the unique ID-value of each one. Getting UID of the DBfiles returns everywhere the same value.
Different situation with Oracle. It has a unique ID of each DB service.
Please, let me know what trick or method would be used in my case?
It should be just one SQL query.
Thanks.
This should do it:
Select * from Sys.Databases
In your case I think you need name, database_id and owner_sid columns, not sure if they're all relevant to your question.
I needed to get a unique database ID for product licensing reasons and eventually went with service_broker_guid. Eg
SELECT db.service_broker_guid FROM sys.databases db WHERE db.name = 'MyDatabase';
Result: ED2E8477-CDC3-49DF-ABEE-341B3E9277DF
NOTE: This value is usually 00000000-0000-0000-0000-000000000000 for databases where is_broker_enabled = 0. In our case, though, we just hunted for the first value that wasn't zeros:
SELECT TOP(1) service_broker_guid FROM sys.databases WHERE service_broker_guid <> '00000000-0000-0000-0000-000000000000' ORDER BY database_id;
I think you're fairly safe with that unless the database is moved or recreated but I haven't exhaustively tested that. (We'd just issue a new license key in the event of a customer issue.)

Tracking deletes on SQL Server

I intend to track delete actions done on a SQL Server DB whose recovery model is simple.
Do such actions get logged when the DB is in this mode?
You can achieve your goal in many different way. If you want you can read delete operations from sql server transaction log, but you will "loose" it after each transaction log backup if you are in full recovery model. In simple recovery model you can not control the transaction log contents.
To find delete operations for a particular table you can use the following query:
DECLARE #MonitoredTable sysname
SET #MonitoredTable = 'YouTable'
SELECT
u.[name] AS UserName
, l.[Begin Time] AS TransactionStartTime
FROM
fn_dblog(NULL, NULL) l
INNER JOIN
(
SELECT
[Transaction ID]
FROM
fn_dblog(NULL, NULL)
WHERE
AllocUnitName LIKE #MonitoredTable + '%'
AND
Operation = 'LOP_DELETE_ROWS'
) deletes
ON deletes.[Transaction ID] = l.[Transaction ID]
INNER JOIN
sysusers u
ON u.[sid] = l.[Transaction SID]
Another approach you can use is to write an "audit trigger" or you can use directly sql server auditing features/Sql server extended events as well explained in this Apex webpage:
SQL Server database auditing techniques

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

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';

SQL Server failover cluster - determine active node

Is there a way to programmatically determine which node in a SQL Server failover cluster is the active node? Or at least determine whether the current machine is the active node?
I have a Windows program which runs on both physical nodes in a failover cluster, but that should operate differently depending on whether it is running on the active node. Part of the reason is that this program should not run simultaneously on the inactive and the active node.
(I've read a bit about making the program cluster aware, but that seems heavily overkill for this simple scenario.)
From SQL Server:
Select ServerProperty('ComputerNamePhysicalNetBIOS')
You can also access it through the Microsoft.SqlServer.Management.Smo Namespace as shown here.
You can check like that:
1. Check Availability Group Status:
if (select
ars.role_desc
from sys.dm_hadr_availability_replica_states ars
inner join sys.availability_groups ag
on ars.group_id = ag.group_id
where ag.name = 'AvailabilityGroupName'
and ars.is_local = 1) = 'PRIMARY'
begin
-- this server is the primary replica, do something here
end
else
begin
-- this server is not the primary replica, (optional) do something here
end
*Remember to change AvailabilityGroupName
or
2. prevent executing job on secondary:
IF master.dbo.svf_AgReplicaState('AvailabilityGroupName')=0  raiserror ('This is not the primary replica.',2,1)
or
3. check write availability on secondary:
IF (SELECT CONVERT(sysname,DatabasePropertyEx(DB_NAME(),'Updateability'))) != 'READ_ONLY'
BEGIN
-- this server is the primary replica, do something here
END
or
4. for SQL2014 and newer:
IF master.dbo.fn_hadr_database_is_primary_replica('Admin') = 1
    BEGIN 
        -- this server is the primary replica, do something here
    END
ELSE 
    BEGIN 
        -- this server is not the primary replica, (optional) do something here
    END

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)

Resources