Monday, September 28, 2015

Failover or Restart Results in Reseed of Identity – FIX ALWAYS ON Availability Groups

I did set up always on between 2 servers 1 active 1 passive(readable not writable)
i had  a table with identity, when failover happens and i try to insert the data , the identity went from current row to 1000, i was surprised and the with little bit of research i found a way to solve the issue...

WHEN EVER SQL restart happens or Failover happens which means a Role is changed , so when a role is changed we need to have a mechanism to notify

1. Configure role with error number =1480
and then in response execute a sql job ,and notify Operator

SQL JOB Code below: on both servers..

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 MASTER
EXEC [dbo].[sp_FixIdentityReSeeds]
END


ELSE

BEGIN

      RETURN  
END




------------The sp is below


USE [master]
GO
/****** Object:  StoredProcedure [dbo].[sp_FixIdentityReSeeds]    Script Date: 10/8/2015 2:24:08 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[sp_FixIdentityReSeeds]
AS
BEGIN

    --foreach database
    DECLARE @DatabaseName varchar(255)

    DECLARE DatabasesCursor CURSOR READ_ONLY
    FOR
        SELECT name
        FROM sys.databases
        where name not in ('master','tempdb','model','msdb') and
        sys.databases.state_desc = 'online'

    OPEN DatabasesCursor

    FETCH NEXT FROM DatabasesCursor
    INTO @DatabaseName

    WHILE @@FETCH_STATUS = 0
    BEGIN

        EXEC ('USE '+@DatabaseName + '

        --foreach identity column
        DECLARE @tableName varchar(255)
        DECLARE @columnName varchar(255)
        DECLARE @schemaName varchar(255)

        DECLARE IdentityColumnCursor CURSOR READ_ONLY
        FOR

            select TABLE_NAME , COLUMN_NAME, TABLE_SCHEMA
            from INFORMATION_SCHEMA.COLUMNS
            where COLUMNPROPERTY(object_id(TABLE_NAME), COLUMN_NAME,
                                 ''IsIdentity'') = 1 and TABLE_NAME not like ''%syncobj_0x%''

        OPEN IdentityColumnCursor

        FETCH NEXT FROM IdentityColumnCursor
        INTO @tableName, @columnName, @schemaName

        WHILE @@FETCH_STATUS = 0
        BEGIN

            print ''['+@DatabaseName+'].[''+@tableName+''].[''+
                            @schemaName+''].[''+@columnName+'']''
            EXEC (''declare @MAX int = 0
                    select @MAX = max(''+@columnName+'')
                    from ['+@DatabaseName+'].[''+@schemaName+''].[''+@tableName+'']
                    if (@MAX IS NULL)
                    BEGIN
                        SET @MAX = 0
                    END
                    DBCC CHECKIDENT(['+@DatabaseName+'.''+
                                    @schemaName+''.''+@tableName+''],RESEED,@MAX)'')

            FETCH NEXT FROM IdentityColumnCursor
            INTO @tableName, @columnName, @schemaName

        END

        CLOSE IdentityColumnCursor
        DEALLOCATE IdentityColumnCursor')

        FETCH NEXT FROM DatabasesCursor
        INTO @DatabaseName

    END

    CLOSE DatabasesCursor
    DEALLOCATE DatabasesCursor
END




EXEC sp_configure 'show advanced options', 1 ;

No comments:

Post a Comment

https://blog.sqlauthority.com/2009/06/27/sql-server-fix-error-17892-logon-failed-for-login-due-to-trigger-execution-changed-database-context...