web-dev-qa-db-ja.com

可用性グループ-プライマリサーバーの確認-パラメーターを使用してプロシージャを呼び出せません

alwayson可用性グループに関係するサーバーで、実行中のジョブがある場合、ジョブ内で、現在のサーバーが可用性グループのprimaryかどうかを常にテストします。

したがって、 ジョブのみ実行AGのプライマリサーバー上 となります。

このようなものはうまく機能しています:

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

ただし、プロシージャの代わりにdbo.usp_some_other_procedure_without_parameteresJunoReportingというデータベースに存在します。パラメータを持つ別のプロシージャを呼び出したいのですが、SQL Serverはそれを好みません。

彼は馬の前にカートを置いていると思いますが、どうすれば彼にわかりますか?

ジョブ内に次のコードがあると、ジョブが失敗します。

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

退屈で明らかなエラーメッセージが表示されます。それが、現在のサーバーが主な役割を果たしているかどうかをテストしている理由です。

メッセージ976、レベル14、状態1、行22

ターゲットデータベース「JUNOReporting」は可用性グループに参加しており、現在クエリでアクセスできません。データの移動が一時停止されているか、可用性レプリカで読み取りアクセスが有効になっていません。このデータベースと可用性グループ内の他のデータベースへの読み取り専用アクセスを許可するには、グループ内の1つ以上のセカンダリ可用性レプリカへの読み取りアクセスを有効にします。詳細については、SQL Server Books Onlineの「ALTER AVAILABILITY GROUPステートメント」を参照してください。

これを回避する方法はありますか?プロシージャ内にそのコードを追加したくないので、parametersの問題を回避するためにSQLサーバーがその機会に持っているようです。

誤解を解消するためだけに:

私の可用性グループの2番目のサーバー(2つのサーバーのみで構成される)では、下の図に示すようにデータベースにアクセスできません。

enter image description here

2

これは、プロシージャにパラメータがあり、プロシージャがジョブステップからも呼び出されるために発生します。

ジョブコンテキスト(ssms)外でクエリを実行すると、問題なく実行されます。これが発生する正確な理由はまだはっきりしていません。プロファイラーを使用してコマンドを取得し、クエリウィンドウで再作成しようとしましたが、ダイスはありませんでした。

ただし、エージェントがジョブステップを実行すると、デフォルト以外の動作が発生する可能性があることは知っています。この例は、quoted_identifierがジョブステップコンテキスト内でオフになるという事実です。

enter image description here

マイクロソフトから:

SET QUOTED_IDENTIFIERがON(デフォルト)

ソース

とにかく、私があなたの問題に使用した回避策は、それを動的SQLに入れることです。

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

私は自分の過ちから学び、この問題の真の犯人を見つけました。

犯人は

sys.fn_hadr_is_primary_replica

問題のデータベースにアクセスします。

私の同僚は、DBの代わりにAGをチェックして、より優れた機能を提供してくれました。

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

次に、ジョブステップで関数を呼び出す:

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

これは、パラメーターを使用しても、プロシージャを呼び出す同じ問題をジョブに与えなくなりました。

SQLエージェントにはまだデフォルト以外の設定がいくつかありますが、この場合の回避策は、AGチェックでデータベースにアクセスするのではなく、可用性グループにアクセスすることです。

0
Randi Vertongen