This is default featured slide 1 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 2 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 3 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 4 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

This is default featured slide 5 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.This theme is Bloggerized by Lasantha Bandara - Premiumbloggertemplates.com.

Saturday 14 December 2019

Find Status or percentage completed of any DBCC Shrink Databse files

1.First try to find the space used and empty space left in databases


SET NOCOUNT ON

DBCC UPDATEUSAGE(0)

-- DB size.
EXEC sp_spaceused

 --- Table row counts and sizes.
CREATE TABLE #t
(
    [name] NVARCHAR(128),
    [rows] CHAR(11),
    reserved VARCHAR(18),
    data VARCHAR(18),
    index_size VARCHAR(18),
    unused VARCHAR(18)
)

INSERT #t EXEC sp_msForEachTable 'EXEC sp_spaceused ''?'''

SELECT *
FROM   #t

-- # of rows.
SELECT SUM(CAST([rows] AS int)) AS [rows]
FROM   #t

DROP TABLE #t

2. Find the Status or percentage completed of any DBCC Shrink Databse files with below query

SELECT
    percent_complete,
    start_time,
    status,
    command,
    estimated_completion_time,
    cpu_time,
    total_elapsed_time
FROM
    sys.dm_exec_requests
WHERE
    command = 'DbccFilesCompact'

Backup databases on SQL server Express edition

please see below on how to create backups on SQL Express edition,

SQL Server express edition do not have SQL agent .

1.create a linked server from any non express edition ,make sure you have sys admin previlage on the sql login you use
2.create SP(as below) on Express edition master database.
3.Schedule a JOB to call SP from non express edition.

use master
go
Create  PROC SP_Backup
AS
BEGIN
DECLARE @path1  VARCHAR(100)
Declare @DeleteDate datetime
SET @Path1='R:\'
SET @DeleteDate= DATEADD(day, -2, GETDATE())---older than 2 days
EXEC master.sys.xp_delete_file 0,@path1,'BAK',@DeleteDate,0;


DECLARE @destination VARCHAR(300),
@now VARCHAR(50),
@now_date DATETIME,
@exec_str VARCHAR(200),
@db_name VARCHAR(30),
@path  VARCHAR(100)

SET @Path='R:\'--Location of the files going to be
SELECT @now_date = GETDATE()
SELECT @Now = RIGHT(CONVERT(VARCHAR(4),DATEPART(yy,@now_date)),4) + RIGHT( '00' + CONVERT(VARCHAR(2),DATEPART(mm,@now_date)),2) +
RIGHT( '00' + CONVERT(varchar(2),DATEPART(dd,@now_date)),2) +'_'+ RIGHT( '00' + CONVERT(varchar(2),DATEPART(hh,@now_date)),2) +
RIGHT( '00' + CONVERT(varchar(2),DATEPART(mi,@now_date)),2) + RIGHT( '00' + CONVERT(varchar(2),DATEPART(ss,@now_date)),2)

SET NOCOUNT ON
DECLARE db_cursor CURSOR FOR
SELECT name FROM master.sys.databases
where name not in ('tempdb')
ORDER BY name

OPEN db_cursor
FETCH db_cursor INTO @db_name

WHILE (@@fetch_status = 0)
BEGIN

SELECT  @destination = 'R:\' + @db_name + '_Full_' + @Now +'.bak'
SELECT  @exec_str = 'BACKUP DATABASE ' + @db_name + ' TO DISK = ''' + @destination + ''' WITH COMPRESSION'
--PRINT @exec_str
EXEC (@exec_str)

FETCH db_cursor INTO @db_name
END

CLOSE db_cursor
DEALLOCATE db_cursor
 END

Notify if a database backup missing

declare @ServerName varchar(250)

declare @DatabaseList varchar(4000)
declare @CountMissingBackups int
declare @MailSubject varchar(250)
declare @MailText varchar (4000)
 
;WITH CTE as
(
SELECT
   CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS [Server],
   msdb.dbo.backupset.database_name
FROM    msdb.dbo.backupset
WHERE     msdb.dbo.backupset.type = 'D'
GROUP BY msdb.dbo.backupset.database_name
HAVING      (MAX(msdb.dbo.backupset.backup_finish_date) < DATEADD(hh, - 24, GETDATE()))
 
UNION
 
--Databases without any backup history
SELECT    
   CONVERT(CHAR(100), SERVERPROPERTY('Servername')) AS [Server],
   master.dbo.sysdatabases.NAME AS database_name
FROM
   master.dbo.sysdatabases LEFT JOIN msdb.dbo.backupset
       ON master.dbo.sysdatabases.name  = msdb.dbo.backupset.database_name
WHERE msdb.dbo.backupset.database_name IS NULL AND master.dbo.sysdatabases.name <> 'tempdb'
--ORDER BY msdb.dbo.backupset.database_name
)
select @CountMissingBackups = count(*), @ServerName = [Server] ,@Databaselist = COALESCE(@DatabaseList + ', ', '') + CAST(database_name AS varchar(250))
from CTE
group by [Server], database_name
 
 
-- send the mail
 
if @CountMissingBackups > 0
begin
 
set @MailSubject = 'Backups on '+@ServerName
set @MailText = 'The following databases have not been backed up in the past 24 hours: '+@Databaselist
 
EXEC msdb.dbo.sp_send_dbmail 
@profile_name='Default',
@recipients='abc@XYZcom',
@subject=@MailSubject,
@body=@MailText
 
end
   

send the result of stored proceedure via email

declare @subject varchar(1000)

set @subject = 'Space Alerts on FPVI-Xweb1'
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'Default',
@recipients = 'abc@xyz.com',
@query = 'EXEC [FPVI-XWEB1].Master.dbo.XP_FixedDrives',
@subject = @subject
GO

Send email when Blocking Happens and Track Queries

 --This script will send an email to operator if blocking process counter rise above 0

USE [msdb]
GO
EXEC msdb.dbo.sp_update_alert @name=N'Blocking',
@message_id=0,
@severity=0,
@enabled=1,
@delay_between_responses=120,
@include_event_description_in=0,
@database_name=N'',
@notification_message=N'',
@event_description_keyword=N'',
@performance_condition=N'SQLServer:General Statistics|Processes blocked||>|0',
@wmi_namespace=N'',
@wmi_query=N'',
@job_id=N'401a9e4d-ae94-47ca-9ac4-deb4c244690a'
GO

-----------------------------JOB NAME "Blocking Job"
 --------------------when blocking happens to notify what script blocking , we can have the below script run to keep track of blocking transaction
--CREATE TABLE AuditBlocking
--    (
--      session_id INT ,
--      Databasename VARCHAR(100) ,
--      DatetimeEvent DATETIME NOT NULL
--                             DEFAULT ( GETDATE() ) ,
--      SQL_text VARCHAR(MAX) ,
--      blocking_session_id INT ,
--      wait_time INT ,
--      wait_type VARCHAR(100) ,
--      last_wait_type VARCHAR(100) ,
--      wait_resource VARCHAR(100) ,
--      transaction_isolation_level INT ,
--      lock_timeout INT
--    )
--GO


      WAITFOR DELAY '00:01:00';
      IF EXISTS ( SELECT    session_id ,
                            DB_NAME(database_id) AS 'Database_Name' ,
                            GETDATE() ,
                            sql_text.text AS 'Text' ,
                            blocking_session_id ,
                            wait_time --Milliseconds(1000 miliosec=1 sec) ,
                            wait_type ,
                            last_wait_type ,
                            wait_resource ,
                            transaction_isolation_level ,
                            ( er.wait_time / 1000 ) ,--added this
                            lock_timeout
                  FROM      sys.dm_exec_requests er
                            CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sql_text
                  WHERE     ( er.wait_time / 1000 ) > 60 --added this
)
        BEGIN

            INSERT  INTO AuditBlocking---i have created this table before
                    SELECT  session_id ,
                            DB_NAME(database_id) AS 'Database_Name' ,
                            GETDATE() ,
                            sql_text.text AS 'Text' ,
                            blocking_session_id ,
                            wait_time --Milliseconds(1000 miliosec=1 sec) ,
                            wait_type ,
                            last_wait_type ,
                            wait_resource ,
                            transaction_isolation_level ,
                            ( er.wait_time / 1000 ) ,--added this
                            lock_timeout
                    FROM    sys.dm_exec_requests er
                            CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sql_text
                    WHERE   ( er.wait_time / 1000 ) > 60;  --added this


            DECLARE @AlertMessage VARCHAR(MAX);
            SET @AlertMessage = 'There is Blocking happening on' + ' '
                + @@SERVERNAME + ' '
                + 'Server. Please see AuditDB.dbo.AuditBlocking Table for more Information';
            EXEC msdb.dbo.sp_send_dbmail @profile_name = 'Default',
                @recipients = 'abc@xyz.com', @body = @AlertMessage,
                @importance = 'Low', @subject = 'Blocking Alert';

        END; 




-----------------------------TESTING
USE AuditDB
GO
CREATE TABLE ##Employees
    (
      EmpId INT IDENTITY ,
      EmpName VARCHAR(16) ,
      Phone VARCHAR(16)
    )
GO
INSERT  INTO ##Employees
        (EmpName,Phone )
VALUES  ('Martha','800-555-1212'),
        ('Jimmy','619-555-8080')
GO

CREATE TABLE ##Suppliers
    (
      SupplierId INT IDENTITY ,
      SupplierName VARCHAR(64) ,
      Fax VARCHAR(16)
    )
GO
INSERT  INTO ##Suppliers
        ( SupplierName, Fax )
VALUES  ('Acme', '877-555-6060' ),
        ('Rockwell', '800-257-1234' )
GO

USE AuditDB
GO
BEGIN TRANSACTION
SELECT  *
FROM    ##Employees WITH ( TABLOCKX, HOLDLOCK );
WAITFOR DELAY '00:02:00'
 ---Wait a minute!
ROLLBACK TRANSACTION
--Release the lock



 ----another query window
 SELECT *
 FROM   ##Employees


 --------------------------check results

 SELECT * FROM dbo.AuditBlocking
 ORDER BY DatetimeEvent asc

SELECT * FROM AuditBlocking
--WHERE   blocking_session_id>=50


/*testing
 SELECT * FROM AuditBlocking
 SP_who2 'Active'

--SELECT * FROM sys.messages
--WHERE message_id IN (823,824,825) AND language_id=1033

--SELECT * FROM sys.messages
--WHERE severity IN (016,017,018,019,020,021,022,023,024,025) AND language_id=1033
*/

Send email when DeadlockHappens and track Queries

CAUTION, as this is going to use the error log , please make sure you test in test environment before implementing in Production.


/*Capture deadlocks

CREATE Alert Deadlock ERROR 1205>SQL SERVER Performance Condition Alert>Locks>Number OF deadlocks/sec>_total>raises above 0
Response> CREATE a JOB WITH below script amd notify dba >options email


---To ensure the deadlock related errors are logged
EXEC master.sys.sp_altermessage 1205, 'WITH_LOG', TRUE;
GO
EXEC master.sys.sp_altermessage 3928, 'WITH_LOG', TRUE;
GO

--DBCC TRACEON (3605,1204,1222,-1)
Description:
3605 the results of the DBCC output to the error log.
1204 returns the resources and types of locks participating in the deadlock and the current command affected.
1222 Back to the resources and types of locks participating in the deadlock, and the use does not comply with any XSD schema in XML format affected the current command (further than 1204, SQL 2005 and available).
-1 Open the specified trace flag globally.
DBCC TRACEON (1204, -1)
DBCC TRACEON (1222, -1)----this is going to add 100 lines in log file


*/
--== This is for SQL 2005 and higher. ==--
--== We will create a temporary table to hold the error log detail. ==--
--== Before we create the temporary table, we make sure it does not already exist. ==--
 IF OBJECT_ID('tempdb.dbo.ErrorLog') IS Not Null
 BEGIN
 DROP TABLE tempdb.dbo.ErrorLog
 END
 --== We have checked for the existence of the temporary table and dropped it if it was there. ==--
 --== Now, we can create the table called tempdb.dbo.ErrorLog ==--
CREATE TABLE tempdb.dbo.ErrorLog (Id int IDENTITY (1, 1) NOT NULL,
logdate DATETIME, procInfo VARCHAR(10), ERRORLOG VARCHAR(MAX))
--== We create a 3 column table to hold the contents of the SQL Server Error log. ==--
--== Then we insert the actual data from the Error log into our newly created table. ==--
 INSERT INTO tempdb.dbo.ErrorLog
 EXEC master.dbo.sp_readerrorlog 0
--== With our table created and populated, we can now use the info inside of it. ==--
 BEGIN
--== Set a variable to get our instance name. ==--
--== We do this so the email we receive makes more sense. ==--
 declare @servername nvarchar(150)
 set @servername = @@servername
--== We set another variable to create a subject line for the email. ==--
 declare @mysubject nvarchar(200)
 set @mysubject = 'Deadlock event notification on server '+@servername+'.'
 --== Now we will prepare and send the email. Change the email address to suite your environment. ==--
 EXEC msdb.dbo.sp_send_dbmail
 @profile_name='Default',
 @recipients='abc@xyz.com,
 @subject = @mysubject,
 @body = 'Deadlock has occurred. View attachment to see the deadlock info',
 @query = 'select logdate, procInfo, ERRORLOG from tempdb.dbo.ErrorLog where Id >= (select TOP 1 Id from tempdb.dbo.ErrorLog WHERE ERRORLOG Like ''%Deadlock encountered%'' order by Id DESC)',
 @query_result_width = 600,
 @attach_query_result_as_file = 1
 END
 --== Clean up our process by dropping our temporary table. ==--
 DROP TABLE tempdb.dbo.ErrorLog

 --------------testing
-----------------------------------TESTING Below
 --DROP TABLE ##Employees
 --DROP TABLE ##Suppliers

USE AuditDB
 GO
 CREATE TABLE ##Employees ( EmpId INT IDENTITY, EmpName VARCHAR(16), Phone VARCHAR(16) )
 GO
 INSERT INTO ##Employees (EmpName, Phone)
 VALUES ('Martha', '800-555-1212'), ('Jimmy', '619-555-8080')
 GO

 CREATE TABLE ##Suppliers( SupplierId INT IDENTITY, SupplierName VARCHAR(64), Fax VARCHAR(16) )
 GO
 INSERT INTO ##Suppliers (SupplierName, Fax) VALUES ('Acme', '877-555-6060'), ('Rockwell', '800-257-1234')
 GO

 --TAB1
 BEGIN TRAN;
 UPDATE ##Suppliers
 SET Fax = N'676-1019'
 WHERE supplierid = 1


 ----IN the query tab 2
 --BEGIN TRAN;
 --UPDATE ##Employees
 --SET EmpName = 'Brian'
 --WHERE empid = 1

 --Now again in the query tab 1 EXECUTE
 UPDATE ##Employees
 SET phone = N'555-9999'
 WHERE empid = 1
 COMMIT


 ----And in the query tab 2  EXECUTE
 --UPDATE ##Suppliers
 --SET Fax = N'676-1019'
 --WHERE supplierid = 1
 --COMMIT 

Tuning areas where we need to Look

Tuning areas where we need to Look


PAGEIOLATCH—DISK
CXPACKET—Big Queries
SOS_Scheduled_yield—Lots of functions may be missing Indexes
LATCH_EX—Parallelism or missing Indexes 

How licensing works with AlwaysOn Availability groups

How licensing works with AlwaysOn Availability groups

I would like to share some knowledge on how licensing works with AlwaysOn Availability groups.
It took 1 week to figure it out, Having calls with Microsoft and help from forums


Min Requirements for having AlwaysOn Availability groups.:

  • Two Windows Servers 2012 R2 Standard Edition
  • Ensure that each computer is a Node in a Windows Server Fail over Clustering (WSFC)
  • All two Windows Servers should reside on one Cluster and One Domain
  • Each SQL Server Instance involved in AlwaysOn Availability Groups must be running Enterprise Edition of SQL Server 2012 or later (2014)
  • Must use same network links for communications between WSFC members and availability Replicas
  • All Databases should be in Full recovery model, only User databases can participate in AlwaysOn Availability Groups 
  • Recommended to keep all configurations/Settings/Drives identical between two nodes


Advantages of using AlwaysOn Availability Groups:
  • AlwaysOn Availability Groups build on Top of Windows Server Fail over Clustering (WSFC)
  • Automatics Failover(Synchronous mode), No witness server needed for automatic failover, uses Windows Server Failover Clustering to do Automatic Failover
  • Can have multiple copies of secondary, but here at FrontPoint we are not going to use secondary
  • Backups and DBCC Check DB operations cane be done on secondary( but need to pay for License)
  • Applications connect to Virtual Server Name any given time, and we do not need to change any in connection strings even after Failover happens 
  • Secondary Replica can be same or different location 
  • More than one secondary and cane be readable and run synchronous mode 
  • Multiple database failover -AlwaysOn Availability Groups ensures all databases are connected when failover happen to secondary Replica
  • No shared Storage is required in AlwaysOn Availability Groups 
AlwaysOn Availability Groups Support Fail over In any of the following  Events
  • Operating System goes down
  • SQL Server Instance, Database goes offline/Shutdown
  • Disk Failures(hardware failures) in which databases cannot be accessed 
  • Network goes down or someone unplug Network cables
  • Manual failover whenever needed in emergency situations
  • Upgrade/Patch Failed/Restarting SQL services 

Manage Jobs and Replication:
  • Jobs should be created on both primary and secondary Replicas with some logic.
  • Jobs run on both servers all times, but which ever is primary actually execute the job and secondary will not pass validation Skip the job to execute the actual code
  • Replication Jobs will be Created on Both server and have to create publications on both servers and configure Distribution database to use remote distributor
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 = 'YourAvailabilityGroupName'
         AND ars.is_local = 1
   ) = 'PRIMARY‘
BEGIN
---this server is the primary replica, Put all Job code here 
 END;
ELSE
BEGIN
PRINT 'no';    -- this server is not the primary replica, (optional) do something here
    END;


Finally, How licensing works with AlwaysOn Availability groups ?

 
I am going to explain how it works when we have like below environment

SQL Server 2014 Always ON Availability Groups between 2 nodes(servers) and using SQL server Enterprise edition on top of WSFC, Node1 is primary replica(read/Write)  and Node2 is secondary replica(NON READABLE)  and databases are Restoring mode only and will not use or read/write  data until disaster (failover)happens.

As per documentation , SQL server  Services, Agent  services should run on both servers at anytime but only Primary Replica's  jobs executes at anytime using Some checks like i provided above t SQL script, so we should have JOBS running at both servers, we will have to put a logic inside the jobs , if this is primary execute else come out of the job..--this code or logic make sure the jobs run on PRIMARY REPLICA (now, or after failover)

so we need only 1 SQL SERVER ENTERPRISE Licence to setup ENVIRONMENT like above.....

Note:

1.You probably shouldn't take my word for it, since I don't work for Microsoft, but I'm pretty sure that isn't a problem, You need to have the server ready to take over for any failure. Having your jobs already configured and scheduled is an important part of that.

2.Passive fail-over rights permit a customer to run passive instances of SQL Server in a separate operating system environment (OSE) without requiring the passive server to be licensed for SQL Server. A passive SQL Server instance is one that is not serving SQL Server data to clients or running active SQL Server workloads.e over for any failure. Having your jobs already configured and scheduled is an important part of that.


Some Useful Information:
For each server licensed with SQL Server 2014 and covered by active SA, customers can run up to the same number of passive failover instances in a separate, on-premises OSE to support failover events.
A passive SQL Server instance is one that is not serving SQL Server data to clients or running active SQL Server workloads. The passive failover instances can run on a separate server. These may only be used to synchronize with the primary server and otherwise maintain the passive database instance in a warm standby state in order to minimize downtime due to hardware or software failure.

The secondary server used for failover support does not need to be separately licensed for SQL Server as long as it is truly passive, and the primary SQL Server is covered with active SA. If it is serving data, such as reports to clients running active SQL Server workloads, or performing any “work”, such as additional backups being made from secondary servers, then it must be licensed for SQL Server. 

http://download.microsoft.com/download/B/4/E/B4E604D9-9D38-4BBA-A927-56E4C872E41C/SQL_Server_2014_Licensing_Guide.pdf

So long as the agent jobs only actually perform "work" on the primary, and the other conditions are met, it would be passive. 

Find Unused databases

Step1:
---Create a table to keep track of connectios:
USE AuditDB;
GO
CREATE TABLE [dbo].[TrackDBConnections]
    (
      ServerName VARCHAR(50) NOT NULL ,
      DatabaseName VARCHAR(30) NOT NULL ,
      NumberOfConnections INT NOT NULL ,
      LoginTime DATETIME NOT NULL ,
      LastBatch DATETIME NOT NULL ,
      DateTimeRecordInsertd DATETIME NULL ,
      Status VARCHAR(100) NULL ,
      HostName VARCHAR(100) NULL ,
      ProgramName VARCHAR(1000) NULL ,
      NTusername VARCHAR(100) NULL ,
      Loginame VARCHAR(100) NULL
    )
ON  [PRIMARY];
GO





Step2:--Main Step
---create a SP to insert the Data into the [TrackDBConnections] Table:
USE AuditDB
GO
CREATE PROCEDURE usp_TrackDBConnections
AS
BEGIN

 /*    The main purpose of the SP is to keep track of Connections which get connect to Databases
                and decide on which database is being used or not being used by any applications and then make OFFLINE for fewdays, backup and then drop..
 */


 SET NOCOUNT ON;
INSERT INTO [TrackDBConnections](ServerName, DatabaseName,LoginTime,LastBatch,DateTimeRecordInsertd,NumberOfConnections,Status,HostName,ProgramName,NTusername,Loginame)
  
  SELECT  @@ServerName AS SERVER ,
        name ,
        login_time ,
        last_batch ,
        GETDATE() AS DATE ,
        COUNT(status) AS number_of_connections ,
        status ,
        hostname ,
        program_name ,
        nt_username ,
        loginame
FROM    sys.databases d
        LEFT JOIN sysprocesses sp ON d.database_id = sp.dbid
WHERE   database_id NOT BETWEEN 0 AND 4
        AND loginame IS NOT NULL
GROUP BY name,status,login_time ,
        last_batch,hostname ,
        program_name ,
        nt_username ,
        loginame;

END


--Step3:-Create a Job to schedule to run every 10 Minutes
       --Let it run for Few days/1 week and see the results with below query,Detailed SQL Server Connection Information



--Step4: CHECK results
----count
SELECT  DatabaseName ,
 COUNT(status) AS number_of_connections,
ProgramName
FROM    TrackDBConnections
 GROUP BY DatabaseName,ProgramName,Status
 GO

--Details
 SELECT *  from TrackDBConnections
GO

Managing jobs in always on Availability groups



Managing jobs in always on Availability groups


DBA has Setup Always on Availability Groups between 2 servers and has a Script that wanted to put in Job and run the job only on primary at any time..(one active and one secondary)
USE MASTER
GO
DECLARE @ServerName NVARCHAR(256)  = @@SERVERNAME
DECLARE @RoleDesc NVARCHAR(60)

SELECT @RoleDesc = a.role_desc
    FROM sys.dm_hadr_availability_replica_states AS a
    JOIN sys.availability_replicas AS b
        ON b.replica_id = a.replica_id
WHERE b.replica_server_name = @ServerName

IF @RoleDesc = 'PRIMARY'

BEGIN
USE TestAG
Insert into CheckAvailabilityRoleJobs(InsertDate,ServerName,RoleDescription)
SELECT GETDATE(),@@SERVERNAME, a.role_desc
FROM      sys.dm_hadr_availability_replica_states AS a
JOIN sys.availability_replicas AS b ON b.replica_id = a.replica_id
where   b.replica_server_name=@@SERVERNAME
END

ELSE

BEGIN

      RETURN
END 
DBA wanted to keep this job running 24X7 on both servers, but insert happens only on Primary at any time , in secondary the JOB exits with out actually inserting...
the script  is running good on PRIMARY, but when DBA try to run on SECONDARY it is failing ...
the script should actually exit on SECONDARY after checking Primary or not but it is trying too connect TESTAG database which is not accessible on secondary
Msg 976, Level 14, State 1, Line 16
The target database, 'TestAG', is participating in an availability group and is currently not accessible for queries. Either data movement is suspended or the availability replica is not enabled for read access. To allow read-only access to this and other databases in the availability group, enable read access to one or more secondary availability replicas in the group.  For more information, see the ALTER AVAILABILITY GROUP statement in SQL Server Books Online.

Answer:
DBA found out that ...secondary server should be Readable ..it is not possible to run jobs/check in secondary servers  which are not readable 

Notify when SQL SERVER and Agent Restarts (works for both)

Notify when SQL SERVER and Agent Restarts (works for both)

-- Alert on SQL Server Agent and/or SQL Server service restarts
-- Replace your recipients in line # 14

-- declare the required variables
DECLARE @Message VARCHAR(MAX)
, @Subject VARCHAR(123)
, @Recipients VARCHAR(123)
, @IsDBMailEnabled BIT
, @MailProfile VARCHAR(123)
, @IsClustered VARCHAR(1) -- this is because SERVERPROPERTY('IsClustered') is a sql_variant data type
, @CurrentNodeName VARCHAR(123)
, @InstanceName VARCHAR(123)
, @RestartTime VARCHAR(123)

set @Recipients = 'naresh.koudagani@xyz.com' -- specify the recipients here, separate with ;

SELECT @InstanceName = CONVERT(VARCHAR, SERVERPROPERTY('ServerName'))
, @IsClustered = CONVERT (VARCHAR, SERVERPROPERTY('IsClustered'))
, @CurrentNodeName = CONVERT (VARCHAR, SERVERPROPERTY('ComputerNamePhysicalNetBIOS'))

-- SQL Server service has been restarted
IF (
SELECT DATEDIFF(MI, CREATE_DATE,GETDATE() )
FROM SYS.DATABASES
WHERE NAME = 'TEMPDB'
) <= 3 -- SQL Server service restarted in the past 3 minutes
BEGIN
SELECT @RestartTime = CONVERT(VARCHAR, create_date, 13)
FROM SYS.databases
WHERE NAME = 'TEMPDB'

SET @Message = @InstanceName + ' SQL Server Agent service and SQL Server service have been restarted at: ' +@RestartTime
SET @Subject = @InstanceName + ' SQL Server Agent service and SQL Server service have been restarted!'


IF @IsClustered = '1'
BEGIN
SET @Message = @Message + ' and the current active node is: ' +@CurrentNodeName+ '.'
SET @Subject = @Subject + ' The current active node is: ' +@CurrentNodeName+ '.'
END
END
ELSE 
BEGIN
SET @Message = @InstanceName + ' SQL Server Agent service has been restarted!'
SET @Subject = @InstanceName + ' SQL Server Agent service restarted!'
END

SET @Message = @Message + CHAR(10)
SET @Message = @Message + 'If this is not a planned maintenace. Please verify the status of the databases before restarting any application services and review the log files to find the possible root causes!'

-- Find the database mail profile name
create table #dbmail_profile
(
profileid int null,
profilename varchar(125) null,
accountid int null,
accountname varchar(125) null,
sequencenumber int null
)
insert #dbmail_profile
EXECUTE msdb.dbo.sysmail_help_profileaccount_sp;

select @MailProfile = profilename
from #dbmail_profile
where sequencenumber = 1

drop table #dbmail_profile

EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'DBMAIL',
@recipients = @Recipients,
@subject = @Subject,
@body_format = 'TEXT',
@body = @Message;

Add a new table to existing publication

Add a new table to existing publication

use dbname
go
EXEC sp_changepublication
@publication = ' Pub_name',
@property = N'allow_anonymous',
@value = 'false'
GO


EXEC sp_changepublication
@publication = 'pub_name'
@property = N'immediate_sync',
@value = 'false'
GO

EXEC sp_addarticle  @publication = N'Pub_name',
@article = N'Time',
@source_object=N'Time'
GO

 --same above if you another table


--Should run on publisher
EXEC sp_refreshsubscriptions @publication = N'Pub_name'
GO

 ----Should run on publisher
EXEC sp_startpublication_snapshot @publication = N'Pub_name'
go


Removing a table from replication

--remove table from replication
 EXEC  sys.sp_dropsubscription
    @publication = N'Pub_name',
    @article = N'Time',
    @subscriber = N'SQL4',
    @destination_db = 'db_name'' ;
GO


EXEC sys.sp_droparticle
    @publication = N'Pub_name',
    @article = N'Time',
    @force_invalidate_snapshot = 1 ;
GO

Friday 13 December 2019

Logins, Roles and Permissions , Sysadmins

TSQL Script to find out what login has what role and who are sysadmins?

Script-1: Logins with DB Roles on all Databases.


SET NOCOUNT ON

CREATE TABLE #DatabaseRoleMemberShip
   (
        Username VARCHAR(100),
        Rolename VARCHAR(100),
        Databasename VARCHAR(100)
       
    )DECLARE @Cmd AS VARCHAR(MAX)DECLARE @PivotColumnHeaders VARCHAR(4000)           SET @Cmd = 'USE [?] ;insert into #DatabaseRoleMemberShip
select u.name,r.name,''?'' from sys.database_role_members RM inner join
sys.database_principals U on U.principal_id=RM.member_principal_id
inner join sys.database_principals R on R.principal_id=RM.role_principal_id
where u.type<>''R'''EXEC sp_MSforeachdb @command1=@cmd

SELECT  @PivotColumnHeaders =                        
  COALESCE(@PivotColumnHeaders + ',[' + CAST(rolename AS VARCHAR(MAX)) + ']','[' + CAST(rolename AS VARCHAR(MAX))+ ']'                    
  )                    
  FROM (SELECT DISTINCT rolename FROM #DatabaseRoleMemberShip )a ORDER BY rolename  ASC


SET @Cmd = 'select
databasename,username,'+@PivotColumnHeaders+'
from
(
select   * from #DatabaseRoleMemberShip) as p
pivot
(
count(rolename  )
for rolename in ('+@PivotColumnHeaders+') )as pvt'

--drop table #DatabaseRoleMemberShip
EXECUTE(@Cmd )      


Script-2: Logins having SysAdmin Server Role

SELECT   name,type_desc,is_disabled
FROM     master.sys.server_principals
WHERE    IS_SRVROLEMEMBER ('sysadmin',name) = 1
ORDER BY name