Wednesday, September 16, 2020

Automate refresh of a SQL Server database that is part of an Availability Group

 

 we cannot restore a database that is part of availability group. We need to first remove the SQL Server database from the Availability Group in order to restore the database. In this tip we look at how we can automate this process to ensure that AlwaysOn is re-established after the restore without manual intervention.

First we walk through the steps that need to take place and then talk about how this can be automated using jobs.

Remove SQL Server Database From AlwaysOn Availability Group on Primary

The first step is to remove the database from the Availability Group. We can achieve this using the below command.

Note: you would need to replace the <Availability Group> and <Database Name> with your values.

-- runs on primary server

USE master 
GO
 
ALTER AVAILABILITY GROUP [<Availability Group>] REMOVE DATABASE [<Database Name>]; 
GO 

Restore SQL Server Database on Primary

The next step would be to restore the backup to refresh the database on your primary server. You can also add additional steps for any specific requirements to run after the restore such as granting permissions, etc.

This is the backup that is coming from the other server that will be used to refresh the database on the primary server.

-- runs on primary server

USE master 
GO
 
RESTORE DATABASE [<Database Name>] 
FROM DISK='<Shared Network Location>\<Database Name>.bak' WITH REPLACE 
GO

Ensure Restored SQL Server Database is in Full Recovery on Primary

We need to ensure the database recovery mode is set to FULL in order to meet AlwaysOn requirements.

-- runs on primary server

USE master 
GO
 
ALTER DATABASE [<Database Name>] SET RECOVERY FULL WITH NO_WAIT 
GO 

Backup SQL Server Database and Log on Primary

Next you need to take a full backup and a transaction log backup of this restored database.  To make this easier for the restore you should create the backups on a network share which is accessible from both the PRIMARY and SECONDARY servers. This will avoid having to copy the backup from the PRIMARY to the SECONDARY and will also save time by eliminating the copy step.

-- runs on primary server

BACKUP DATABASE [<database Name>] 
TO DISK='<Shared Network Location>\<Database Name>.bak' WITH FORMAT, INIT, COMPRESSION 
GO
 
BACKUP LOG [<database Name>] 
TO DISK='<Shared Network Location>\<Database Name>.trn' WITH FORMAT, INIT, COMPRESSION  
GO 

Add SQL Server Database to Availability Group on Primary

Next we need to add the database back to the Availability Group.


-- runs on primary server

USE master 
GO
 
ALTER AVAILABILITY GROUP [<Availability Group>] ADD DATABASE [<Database Name>];  
GO

Now you are done with all the steps on the PRIMARY server.

Restore SQL Server Database on Secondary

Next we need to restore the full backup and log backup on the secondary server. 

-- runs on secondary server

USE master 
GO
 
RESTORE DATABASE [<database Name>] 
FROM DISK='<Shared Network Location>\<Database Name>.bak' WITH FILE=1, REPLACE, NORECOVERY 
GO
 
RESTORE LOG [<database Name>] 
FROM DISK='<Shared Network Location>\<Database Name>.trn' WITH FILE=1, REPLACE, NORECOVERY  
GO 

Check Status of SQL Server Database and then Add to Availability Group on Secondary

The next step is important, this enables data synchronization after the database has been restored and is ready to join the Availability Group.

-- runs on secondary server

-- Wait for the replica to start communicating 
begin try 
   declare @conn bit 
   declare @count int 
   declare @replica_id uniqueidentifier 
   declare @group_id uniqueidentifier 
   set @conn = 0 
   set @count = 30 -- wait for 5 minutes 
  
   if (serverproperty('IsHadrEnabled') = 1) 
      and (isnull((select member_state 
                   from master.sys.dm_hadr_cluster_members 
                   where upper(member_name COLLATE Latin1_General_CI_AS) = upper(cast(serverproperty('ComputerNamePhysicalNetBIOS') as nvarchar(256)) COLLATE Latin1_General_CI_AS)), 0) <> 0) 
      and (isnull((select state 
                   from master.sys.database_mirroring_endpoints), 1) = 0) 
   begin 
      select @group_id = ags.group_id 
      from master.sys.availability_groups as ags 
      where name = N'<Availability Group>' 

      select @replica_id = replicas.replica_id 
      from master.sys.availability_replicas as replicas 
      where upper(replicas.replica_server_name COLLATE Latin1_General_CI_AS) = upper(@@SERVERNAME COLLATE Latin1_General_CI_AS) and group_id = @group_id 

      while @conn <> 1 and @count > 0 
      begin 
         set @conn = isnull((select connected_state from master.sys.dm_hadr_availability_replica_states as states where states.replica_id = @replica_id), 1) 
         if @conn = 1 
         begin 
            -- exit loop when the replica is connected, or if the query cannot find the replica status 
            break 
         end 
         waitfor delay '00:00:10' 
         set @count = @count - 1 
      end 
   end 
end try 

begin catch 
   -- If the wait loop fails, do not stop execution of the alter database statement 
end catch 

ALTER DATABASE [<Database Name>] SET HADR AVAILABILITY GROUP = [<Availability Group>]; 
GO 

SQL Server Agent Jobs

To automate this process we can create SQL Server Agent jobs on both servers:

  1. Primary Server - Create one job that does the following:
    1. Removes database from Availability Group
    2. Restores the database
    3. Sets recovery model of database to FULL
    4. Adds database to Availability Group
    5. Creates database backup and log backup
    6. optional - runs job on secondary server using sp_start_job (there are other things you would need to setup to do this)
  2. Secondary Server - Create one job that does the following:
    1. Restores database backup and log backup
    2. Checks database status and adds database to Availability Group

If you don't have the primary server start the job on the secondary server you would need to figure out when to schedule this job to run after the job on the primary server completes.

How to Find which user deleted the database in SQL Server

 SQL Server: How to Find which user deleted the database in SQL Server

There are two different methods by which one can easily find who deleted the database in SQL Server. The first method is using builtin Schema Changes History Report. The second method is to load the SQL Server Default Trace into a table to see who deleted the database.

Steps to find who deleted the User database in SQL Server Using SQL Server Schema Changes History Report

1. Open SQL Server Management Studio and Connect to the SQL Server Instance.

2. Right click SQL Server Instance and Select Reports -> Standard Reports -> Schema Changes History as shown in the below snippet.

SQL Server Schema Changes History Report to Find which user deleted the database in SQL Server
SQL Server Schema Changes History Report to Find which user deleted the database in SQL Server

3. This will open up Scheme Changes History report which will have the details about who deleted the SQL Server Database along with the timestamp when the database was deleted. Refer the below snippet for more information.

Steps to Identify who deleted the user database using Using Default Trace Files

The SQL Server Default Trace file gives very useful information to a DBA to understand what is happening on the SQL Server Instance. 

Execute the below query to find the default path of trace file in SQL Server.

SELECT
	 path AS [Default Trace File]
	,max_size AS [Max File Size of Trace File]
	,max_files AS [Max No of Trace Files]
	,start_time AS [Start Time]
	,last_event_time AS [Last Event Time]
FROM sys.traces WHERE is_default = 1
GO
SQL Server Trace File Location

How to Load SQL Server Trace File in SQL Server Table

Execute the below script to load the default trace file content in a temporary table to read the relevant information with respect to who deleted the user database on the instance of SQL Server. If you don’t find the relevant information in the latest trace file then it is recommended to load the data from all the available trace files on the server to explore the information.

USE tempdb
GO

IF OBJECT_ID('dbo.TraceTable', 'U') IS NOT NULL
	DROP TABLE dbo.TraceTable;

SELECT * INTO TraceTable
FROM ::fn_trace_gettable
('G:\Program Files\Microsoft SQL Server\MSSQL10_50.SQL2008R2\MSSQL\Log\log_12.trc', default)
GO

SELECT
	 DatabaseID
	,DatabaseName
	,LoginName
	,HostName
	,ApplicationName
	,StartTime
	,CASE
		WHEN EventClass = 46 THEN 'Database Created'
		WHEN EventClass = 47 THEN 'Database Dropped'
	ELSE 'NONE'
	END AS EventType
FROM tempdb.dbo.TraceTable
	WHERE DatabaseName = 'MyTechMantra'
		AND (EventClass = 46 /* Event Class 46 refers to Object:Created */
			OR EventClass = 47) /* Event Class 47 refers to Object:Deleted */
GO

From the above snippet you could see that the event class 46 represents the database creation time along with the user who created it and event class 47 represents the database deletion time along with the user who deleted the database.

Conclusion

In this article we have seen how easily one can find out who deleted the user database in SQL Server with the help of in built SQL Server Schema Changes History Report.

How to fix login failed with error cannot open user default db...

 Fix Cannot open user default database. Login failed. Login failed for user SQL Server Error..

In this article we will take a look at the steps which you need to follow when you receive “Cannot open user default database. Login failed. Login failed for user ‘UserName’. (Microsoft SQL Server, Error: 4064)“ SQL Server Error message.

Error Message

Cannot open user default database. Login failed. 
Login failed for user ‘UserName’. (Microsoft SQL Server, Error: 4064).
Cannot open user default database Login failed Login failed for user
Cannot open user default database Login failed Login failed for user

You may end up receiving this error when a Windows or SQL Server Login is not able to connect to the default database which is assigned to the user.

If you double click the user (Expand Security -> Logins) you would end up seeing no database being assigned to Default Database as shown in the snippet below.

SQL Server Login Properties Default Database Name is Missing
SQL Server Login Properties Default Database Name is Missing

How to Fix “Cannot open user default database. Login failed. Login failed for user Error Message”

In the Connection Properties specify the database name as TempDB for Connect to Database and click the Connect button to connect to the SQL Server Instance.

In SSMS Connection Properties Specify Default Database as TempDB and Click Connect

Once you are connected to the SQL Server Instance execute the below TSQL to assign the login a new default database.

Use master
GO

ALTER LOGIN [MonitorDB] WITH DEFAULT_DATABASE = TempDB
GO

Conclusion

As a Best Practice it is always recommended to assign the default database to a user as TempDB. This database is recreated every time SQL Server is restarted and this way you can avoid getting these errors.

How to Identify CPU Bottlenecks...

 How to Identify CPU Bottlenecks in SQL Server Using Performance Counters..

There are instance when you are facing CPU bottlenecks on your SQL Server Instance. In this article we will take look at How to Identify CPU Bottlenecks in SQL Server Using Performance Counters.The most common reason for a CPU bottleneck will be insufficient hardware. However, as a database administrator one can make certain configuration changes and tune the SQL Server queries to improve the performance. To begin with Performance Monitor is a great tool which can be used to quickly identify CPU bottlenecks on your SQL Server Instance. Monitoring the below counters can help you in Performance Tuning of SQL Server.

Most important CPU counters to be looked at are: –

Processor: % Processor Time

This counter gives you information with respect to how much time the processor has actually spent working on productive threads and how often it was busy serving such requests. If you find the value of this counter hovering above 80% per CPU then this gives a clear indication that the server is clearly facing CPU bottlenecks.

System: Processor Queue Length

This counter gives you information with respect to the number of threads in the processor queue. This counter basically displays the ready threads; it doesn’t count the threads which are running. Even if you have multiple processors on the system this counter will display a cumulative value. Hence if you have 5 processors on a system and the value for the system turns out to be 60 then it mean on an average the Processor Queue Length for a single processor is 12. Ideally the average processor queue length should be less than 10.

System: % Total Processor Time

This counter gives you information with respect to the total performance of the entire system i.e. it is an average of all the processors together on the system.

SQL Server: SQL Statistics: Batch Requests/sec

This counter gives you information with respect to the number for TSQL command batches received per second.

SQL Server: SQL Statistics: SQL Compilations/sec

This counter gives you information with respect to number of SQL Compilations happening per second.

SQL Server: SQL Statistics: SQL Re-Compilations/sec

This counter gives you information with respect to number of TSQL statement recompiles per second. This counter has the count of number of times statement recompile is triggered by the database engine. This counter value should be very low. Ideally SQL Statistics: SQL Re-Compilations/sec value should not be more than one percent of SQL Statistics: Batch Requests/sec.

For example if your system has 1000 SQL Statistics: Batch Requests/sec then the value of SQL Statistics: SQL Re-Compilations/sec shouldn’t exceed 10 (> 1%) after the SQL Server is stable and its up and running for more than 24 hours.

SQL Server: Cursor Manager By Type: Cursor Requests/Sec

This counter gives you information with respect to number of SQL cursor requests received by server. If you end up seeing 100 of cursor requests per sec then it’s a worrying factor. This means that the code needs to be rewritten to avoid as much cursor usage as possible to improve the overall performance.

COMMON SQL SERVER BACKUP FAILURE ERRORS AND ISSUES

  One of the most common task for a DBA’s are to perform installation of new SQL Server versions and installing patches. Most often or not e...