SQLエージェントジョブを使用して実行されているプロセスのIOPSを制限するようにリソースガバナーをセットアップしようとしています。分類関数は、特定のログインを識別するように設定されています(そのログインを使用して実行されているすべてのspidは、割り当てられているリソースグループを使用する必要があります)。次に、ジョブ内にEXECUTE AS LOGIN = 'ResourceGovernerUser'
を追加しましたが、機能させることができず、ジョブが'EXECUTED AS 'ServiceAccount''
であるため、デフォルトのプールにフォールバックします。 sp_WhoisActive
を使用してアクティブなプロセスを見ると、ログイン名はサービスアカウントではなく'ResourceGovernerUser'
と表示されます。そのため、サービスアカウントを使用するように分類関数を変更したところ、機能しました。これは、'Disk Read IO/Sec'
オブジェクトの下のperfmonカウンター'Disk Write IO/Sec'
および'Resource Pool Stats'
を使用して確認しました。
問題は、リソースガバナーにサービスアカウント以外のログインを使用させるにはどうすればよいですか(エージェントジョブで使用する場合)? CmdExecまたはPowerShellプロキシを使用してジョブを実行するなど、テストされていない醜いアイデアがあります。誰かが同じような状況に出くわしたり、より良いアイデアがあれば、私はそれを本当に感謝します。ありがとうございました。
--Example Setup:
USE [master]
GO
CREATE RESOURCE POOL [SqlJobPool] WITH(
min_iops_per_volume=1,
max_iops_per_volume=5000);
GO
CREATE WORKLOAD GROUP [IOGroup]
USING [SqlJobPool];
GO
CREATE FUNCTION [dbo].[fn_LimitedIO]()
RETURNS SYSNAME WITH SCHEMABINDING
AS
BEGIN
DECLARE @grp SYSNAME;
IF SUSER_NAME() = N'ResourceGovernerUser' -- When this is set to the Service Account, it works
BEGIN
SET @grp = N'IOGroup';
END
ELSE
BEGIN
SET @grp = N'default';
END
RETURN @grp;
END
GO
ALTER RESOURCE GOVERNOR with (CLASSIFIER_FUNCTION = dbo.fn_LimitedIO);
ALTER RESOURCE GOVERNOR RECONFIGURE;
GO
--Within the Agent job
EXECUTE AS Login = 'ResourceGovernerUser'
EXECUTE SomeSQLStuff
リソースガバナー分類関数は、ログインプロセス中にのみ実行されます。 EXECUTE AS
による偽装は、分類機能をトリガーしません。 EXECUTE AS
は、SQL Serverエージェントが別のログインまたはユーザーのコンテキストでジョブを実行する方法です。
Run As ...
ユーザーを指定したり、Job Owner
を変更したりしても、SQL ServerエージェントがSQL Serverにログインする方法は変わりません。ユーザー名のみを参照する分類関数を使用してSQL Serverエージェントジョブを特定のリソースグループで実行できる唯一の方法は、SQL ServerエージェントService Accountを独自のリソースグループに配置することです。
テストは実際に何が起こっているのかを理解するための優れた方法であるため、小さなテストベッドを作成しました。これはリソースグループの構成を変更するため、運用システムでは実行しないでください。
これにより、分類関数と、テストリソースプールに接続されたいくつかのリソースグループが作成されます。
USE master;
SET NOCOUNT ON;
GO
CREATE FUNCTION dbo.fnDummyClassifier()
RETURNS sysname
WITH SCHEMABINDING
AS
BEGIN
DECLARE @GroupName sysname = NULL;
IF SUSER_SNAME() = 'DOMAIN\USER'
SET @GroupName = N'AgentServiceAccountGroup';
IF SUSER_SNAME() = 'ResourceGovernorTestLogin'
SET @GroupName = N'ResourceGovernorTestLoginGroup';
IF SUSER_SNAME() = 'ResourceGovernorTestUser'
SET @GroupName = N'ResourceGovernorTestUserGroup';
IF @GroupName IS NULL
SET @GroupName = N'default';
RETURN @GroupName;
END
GO
CREATE RESOURCE POOL TestPool
WITH (MAX_CPU_PERCENT = 10);
CREATE WORKLOAD GROUP AgentServiceAccountGroup
WITH (
group_max_requests=0
, importance=Medium
, request_max_cpu_time_sec=0
, request_max_memory_grant_percent=25
, request_memory_grant_timeout_sec=0
, max_dop=0
)
USING TestPool;
CREATE WORKLOAD GROUP ResourceGovernorTestLoginGroup
WITH (
group_max_requests=0
, importance=Medium
, request_max_cpu_time_sec=0
, request_max_memory_grant_percent=25
, request_memory_grant_timeout_sec=0
, max_dop=0
)
USING TestPool;
CREATE WORKLOAD GROUP ResourceGovernorTestUserGroup
WITH (
group_max_requests=0
, importance=Medium
, request_max_cpu_time_sec=0
, request_max_memory_grant_percent=25
, request_memory_grant_timeout_sec=0
, max_dop=0
)
USING TestPool;
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = [dbo].[fnDummyClassifier]);
ALTER RESOURCE GOVERNOR RECONFIGURE;
GO
ここではログインを作成し、それをVIEW SERVER STATE
に許可して、セッションが割り当てられているリソースグループを識別できるようにします。
CREATE LOGIN ResourceGovernorTestLogin
WITH PASSWORD = '!NnrtiHummusPlenumPoodle2'
, DEFAULT_LANGUAGE = us_english
, CHECK_EXPIRATION = OFF
, CHECK_POLICY = OFF;
GRANT VIEW SERVER STATE TO ResourceGovernorTestLogin;
GO
これにより、「所有者」が先ほど作成したログインに設定されたSQL Serverエージェントジョブが作成されます。ログインはsysadminのメンバーではないため、SQL Serverエージェントはそのログインのコンテキストでこのジョブを実行します。
DECLARE @JobID uniqueidentifier;
EXEC msdb.dbo.sp_add_job @job_name = 'TestResourceGovernorJob'
, @enabled = 1
, @description = 'Tests resource governor classification'
, @start_step_id = 1
, @owner_login_name = 'ResourceGovernorTestLogin'
, @job_id = @JobID OUTPUT;
EXEC msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 1, @step_name = 'Step1'
, @subsystem = 'TSQL'
, @command = 'SELECT '''';
SELECT UserName = CONVERT(nvarchar(30), SUSER_SNAME())
, [SYSTEM_USER] = CONVERT(nvarchar(30), SYSTEM_USER)
, [SESSION_USER] = CONVERT(nvarchar(30), SESSION_USER)
, [ORIGINAL_LOGIN] = CONVERT(nvarchar(30), ORIGINAL_LOGIN())
, WorkloadGroup = CONVERT(nvarchar(30), wg.name)
FROM sys.dm_exec_requests der
INNER JOIN sys.dm_resource_governor_workload_groups wg ON der.group_id = wg.group_id
WHERE der.session_id = @@SPID;'
, @flags = 4 --write step output into msdb.dbo.sysjobstephistory
, @on_success_action = 1;
EXEC msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N'(LOCAL)';
/*
Call SQL Server Agent via msdb.dbo.sp_notify_job
which in turn calls msdb.dbo.xp_notify_job.
The SQL Server Agent executable logs into the
SQL Server instance using the service account,
then performs an "EXECUTE AS ..." to run
job step(s).
*/
EXEC msdb.dbo.sp_start_job @job_id = @JobID;
GO
WAITFOR DELAY N'00:00:01';
DECLARE @msg nvarchar(max);
SELECT @msg = sjh.message
FROM msdb.dbo.sysjobhistory sjh
INNER JOIN msdb.dbo.sysjobs sj ON sjh.job_id = sj.job_id
WHERE sj.name = 'TestResourceGovernorJob'
AND sjh.step_id = 1;
PRINT (N'');
PRINT (@msg);
PRINT (N'');
EXEC msdb.dbo.sp_delete_job @job_name = 'TestResourceGovernorJob';
GO
上記のジョブのmsdb履歴テーブルの結果:
ジョブ「TestResourceGovernorJob」が正常に開始されました。 ユーザーとして実行:ResourceGovernorTestLogin。 - (1行が影響を受けました) UserName SYSTEM_USER SESSION_USER ORIGINAL_LOGIN WorkloadGroup ----------- ------------------- ------------------------------- ----------------------------- --------------------- --------- ------------------------------ ResourceGovernorTestLogin ResourceGovernorTestLogin guest DOMAIN\USER AgentServiceAccountGroup (1行が影響を受けました)。ステップは成功しました。
次に、ログイン用のユーザーを作成し、SQL Serverジョブステップの詳細プロパティのRun As
オプションを使用して、ジョブの新しいバージョンを実行します。
CREATE USER ResourceGovernorTestUser
FOR LOGIN ResourceGovernorTestLogin;
DECLARE @JobID uniqueidentifier;
EXEC msdb.dbo.sp_add_job @job_name = 'TestResourceGovernorJob'
, @enabled = 1
, @description = 'Tests resource governor classification'
, @start_step_id = 1
, @owner_login_name = 'ResourceGovernorTestLogin'
, @job_id = @JobID OUTPUT;
EXEC msdb.dbo.sp_add_jobstep @job_id = @JobID, @step_id = 1, @step_name = 'Step1'
, @subsystem = 'TSQL'
, @database_name = 'master'
, @database_user_name = 'ResourceGovernorTestUser'
, @command = 'SELECT '''';
SELECT UserName = CONVERT(nvarchar(30), SUSER_SNAME())
, [SYSTEM_USER] = CONVERT(nvarchar(30), SYSTEM_USER)
, [SESSION_USER] = CONVERT(nvarchar(30), SESSION_USER)
, [ORIGINAL_LOGIN] = CONVERT(nvarchar(30), ORIGINAL_LOGIN())
, WorkloadGroup = CONVERT(nvarchar(30), wg.name)
FROM sys.dm_exec_requests der
INNER JOIN sys.dm_resource_governor_workload_groups wg ON der.group_id = wg.group_id
WHERE der.session_id = @@SPID;'
, @flags = 4 --write step output into msdb.dbo.sysjobstephistory
, @on_success_action = 1;
EXEC msdb.dbo.sp_add_jobserver @job_id = @JobID, @server_name = N'(LOCAL)';
/*
Call SQL Server Agent via msdb.dbo.sp_notify_job
which in turn calls msdb.dbo.xp_notify_job.
The SQL Server Agent executable logs into the
SQL Server instance using the service account,
then performs an "EXECUTE AS ..." to run
job step(s).
*/
EXEC msdb.dbo.sp_start_job @job_id = @JobID;
GO
WAITFOR DELAY N'00:00:01';
DECLARE @msg nvarchar(max);
SELECT @msg = sjh.message
FROM msdb.dbo.sysjobhistory sjh
INNER JOIN msdb.dbo.sysjobs sj ON sjh.job_id = sj.job_id
WHERE sj.name = 'TestResourceGovernorJob'
AND sjh.step_id = 1;
PRINT (N'');
PRINT (@msg);
PRINT (N'');
EXEC msdb.dbo.sp_delete_job @job_name = 'TestResourceGovernorJob';
DROP USER ResourceGovernorTestUser;
GO
ジョブのその実行からの出力:
ジョブ「TestResourceGovernorJob」が正常に開始されました。 ユーザーとして実行:ResourceGovernorTestLogin。 - (1行が影響を受けました) UserName SYSTEM_USER SESSION_USER ORIGINAL_LOGIN WorkloadGroup ----------- ------------------- ------------------------------- ----------------------------- --------------------- --------- ------------------------------ ResourceGovernorTestLogin ResourceGovernorTestLogin ResourceGovernorTestUser DOMAIN\USER AgentServiceAccountGroup (1行が影響を受けました)。ステップは成功しました。
これにより、リソースガバナーの構成がクリーンアップされ、分類機能とログインが削除されます。
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = NULL);
DROP WORKLOAD GROUP AgentServiceAccountGroup;
DROP WORKLOAD GROUP ResourceGovernorTestUserGroup;
DROP WORKLOAD GROUP ResourceGovernorTestLoginGroup;
DROP RESOURCE POOL TestPool;
ALTER RESOURCE GOVERNOR RECONFIGURE;
DROP FUNCTION dbo.fnDummyClassifier
DROP LOGIN ResourceGovernorTestLogin;
GO
上記の両方の結果セットで、リソースガバナー分類関数が各ジョブをAgentServiceAccountGroup
グループに入れていることがわかります。これは、SQL Serverエージェントの起動時に使用されるサービスアカウントを使用して、SQL Serverエージェントが最初にSQL Serverにログインするためです。