web-dev-qa-db-fra.com

Groupes de disponibilité - Vérification du serveur principal - Impossible d'appeler une procédure avec des paramètres

Dans mes serveurs impliqués dans les groupes de disponibilité alwayson S'il existe des emplois en cours d'exécution, dans les travaux, je teste toujours si le serveur actuel est le primary dans le groupe de disponibilité.

Donc, le le travail ne fonctionne quesur le serveur principal de l'AG .

quelque chose comme ça fonctionne bien:

If sys.fn_hadr_is_primary_replica ('JUNOReporting') =1  
BEGIN 
        declare @reportYear int, @reportMonth int, @reportMonthPrevious int

        SELECT @reportYear  = CASE WHEN month(getdate()) = 1 THEN year(getdate()) - 1 ELSE year(getdate()) END, 
               @reportMonth = CASE WHEN month(getdate()) = 1 THEN 12 ELSE month(getdate()) - 1 END

        SELECT @reportMonthPrevious  = @reportMonth - 1
        EXEC JUNOReporting.dbo.usp_some_other_procedure_without_parameteres 
END

Cependant, si au lieu de la procédure dbo.usp_some_other_procedure_without_parameteres Cela vit dans la base de données appelée JunoReporting, je souhaite appeler une procédure différente comportant des paramètres, puis SQL Server n'aime pas cela.

Je pense qu'il met le chariot devant les chevaux, mais comment puis-je lui dire?

lorsque j'ai le code suivant dans un emploi, le travail échoue:

declare @reportYear int, @reportMonth int, @reportMonthPrevious int

SELECT @reportYear  = CASE WHEN month(getdate()) = 1 THEN year(getdate()) - 1 ELSE year(getdate()) END, 
       @reportMonth = CASE WHEN month(getdate()) = 1 THEN 12 ELSE month(getdate()) - 1 END

SELECT @reportMonthPrevious  = @reportMonth - 1

If sys.fn_hadr_is_primary_replica ('JUNOReporting') =1  
begin
    -- this server is the primary replica, do something here
    print 'yes, primary'

            IF @reportMonthPrevious >= 1
            BEGIN
                EXEC JUNOReporting.dbo.usp_ins_feesDuePaid_ForMonth @reportYear, @reportMonthPrevious

            END
            EXEC JUNOReporting.dbo.usp_ins_feesDuePaid_ForMonth @reportYear, @reportMonth
END

avec le message d'erreur ennuyeux et évident - c'est exactement pourquoi je testais si le serveur actuel est dans le rôle principal de toute façon:

MSG 976, niveau 14, état 1, ligne 22

La base de données cible, "Junoporting", participe à un groupe de disponibilité et n'est actuellement pas accessible pour les requêtes. Soit le mouvement de données est suspendu ou la réplique de disponibilité n'est pas activée pour l'accès en lecture. Pour permettre un accès en lecture seule à cette information et d'autres bases de données dans le groupe de disponibilité, permettez l'accès en lecture à une ou plusieurs répliques de disponibilité secondaire dans le groupe. Pour plus d'informations, voir l'instruction ALTER DISPONIBILITABLES GROUPE dans SQL Server Books Online.

Des idées comment travailler autour de celui-ci? Je préfère ne pas ajouter ce morceau de code à l'intérieur de la procédure, donc en évitant le serveur SQL parameters émetteur SQL semble avoir à l'occasion.

Juste pour effacer tout malentendu:

Sur le serveur Seconday de mon groupe de disponibilité (se compose de 2 serveurs uniquement), les bases de données ne sont pas accessibles comme vous pouvez le constater sur l'image ci-dessous.

enter image description here

2

Cela se produit car la procédure a des paramètres et la procédure est également appelée à partir d'une étape d'emploi.

Lorsque vous exécutez la requête en dehors du contexte de travail (SSMS), il doit s'exécuter simplement. La raison exacte pour laquelle cela se produit n'est toujours pas clair pour moi, j'ai essayé d'obtenir les commandes à travers le profileur et de le recréer dans ma fenêtre de requête, mais pas de dés là-bas.

Cependant, je sais que lorsque l'agent exécute des étapes de travail, le comportement non par défaut peut se produire. Un exemple de ceci est le fait que citer_identifier est désactivé dans le contexte de l'étape du travail:

enter image description here

De Microsoft:

Définir cible_identifier est activé (par défaut)

source

Quoi qu'il en soit, la solution de contournement que j'ai utilisée pour votre problème est de la mettre en SQL dynamique.

declare @reportYear int, @reportMonth int, @reportMonthPrevious int,@sql varchar(max)

SELECT @reportYear  = CASE WHEN month(getdate()) = 1 THEN year(getdate()) - 1 ELSE year(getdate()) END, 
       @reportMonth = CASE WHEN month(getdate()) = 1 THEN 12 ELSE month(getdate()) - 1 END

SELECT @reportMonthPrevious  = @reportMonth - 1

If sys.fn_hadr_is_primary_replica ('JUNOReporting') =1  
begin
    -- this server is the primary replica, do something here
    print 'yes, primary'

            IF @reportMonthPrevious >= 1
            BEGIN
               set @sql = 'EXEC JUNOReporting.dbo.usp_ins_feesDuePaid_ForMonth '+ cast(@reportYear as varchar(20)) +', '+ cast(@reportMonthPrevious as varchar(20))
               exec(@sql)
            END
                set @sql = 'EXEC JUNOReporting.dbo.usp_ins_feesDuePaid_ForMonth '+ cast(@reportYear as varchar(20)) +', '+ cast(@reportMonth as varchar(20))
                exec(@sql)
END
0
Randi Vertongen

J'ai appris de mes erreurs et j'ai trouvé le vrai coupable de cette question.

Le coupable est

sys.fn_hadr_is_primary_replica

qui accède à la base de données en question.

Un collègue de mienne m'a donné une meilleure fonction de travailler avec, en vérifiant l'AG au lieu de la DB.

CREATE FUNCTION [dbo].[fn_hadr_group_is_primary] (@AGName sysname)

RETURNS bit

AS

        BEGIN



                DECLARE @PrimaryReplica sysname;



                SELECT @PrimaryReplica = hags.primary_replica

                FROM

                        sys.dm_hadr_availability_group_states hags

                        INNER JOIN sys.availability_groups ag ON ag.group_id = hags.group_id

                WHERE

                        ag.name = @AGName;



                IF UPPER(@PrimaryReplica) =  UPPER(@@SERVERNAME)

                        RETURN 1; -- primary



                RETURN 0; -- not primary



        END;



GO

puis appelant la fonction dans une étape de travail avec :

IF [dbo].[fn_hadr_group_is_primary] 'AG1' = 1
BEGIN
EXEC DBO.TestProc @dbname = 'test'
END

Ce qui n'a plus donné le même problème sur mon travail qui appelle une procédure, même avec des paramètres.

Bien que l'agent SQL ait toujours des paramètres non par défaut, dans ce cas, la solution de contournement n'accède pas à la DB avec le chèque AG, mais le groupe de disponibilité à la place.

0
Randi Vertongen