Aru*_*ath 4 sql-server resource-governor sql-server-2014
我正在尝试设置资源调控器,以限制使用 SQL 代理作业运行的进程的 IOPS。分类器函数设置为标识特定登录(使用该登录运行的任何 spid 都应使用分配给它的资源组)。然后我EXECUTE AS LOGIN = 'ResourceGovernerUser'在作业中添加,但我无法让它工作并且它回退到默认池,因为作业是'EXECUTED AS 'ServiceAccount''. 尽管如果我使用 来查看活动进程sp_WhoisActive,登录名会显示为'ResourceGovernerUser'而不是服务帐户。所以我修改了分类器函数以使用服务帐户,然后它就可以工作了。我使用 perfmon 计数器'Disk Read IO/Sec'和对象'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
Run Code Online (Sandbox Code Playgroud)
资源调控器分类器功能仅在登录过程中运行。模拟通过EXECUTE AS不会触发分类器功能。 EXECUTE AS是 SQL Server 代理在另一个登录名或用户的上下文中运行作业的方式。
指定Run As ...用户或修改Job Owner不会改变 SQL Server 代理登录到 SQL Server 的方式。让 SQL Server 代理作业在特定资源组中运行的唯一方法是将 SQL Server 代理服务帐户放入它自己的资源组中。
由于测试是了解实际情况的好方法,因此我创建了一个小型测试平台。不要在生产系统上运行它,因为它会修改资源组配置。
这将创建分类器函数,以及附加到测试资源池的几个资源组:
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
Run Code Online (Sandbox Code Playgroud)
在这里,我们将创建一个登录名,并允许它登录,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
Run Code Online (Sandbox Code Playgroud)
这将创建一个 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
Run Code Online (Sandbox Code Playgroud)
来自上述作业的 msdb 历史记录表的结果:
作业“TestResourceGovernorJob”成功启动。 以用户身份执行:ResourceGovernorTestLogin。 —— (1 行受影响) 用户名 SYSTEM_USER SESSION_USER ORIGINAL_LOGIN WorkloadGroup ------------------------------ --------------------- ---------- ------------------------------ ---------- -------------------- ------------------------------ ResourceGovernorTestLogin ResourceGovernorTestLogin 来宾 DOMAIN\USER AgentServiceAccountGroup (受影响的 1 行)。步骤成功了。
接下来,我们将为登录创建一个用户,并使用Run AsSQL Server 作业步骤的高级属性中的选项运行新版本的作业。
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
Run Code Online (Sandbox Code Playgroud)
作业运行的输出:
作业“TestResourceGovernorJob”成功启动。 以用户身份执行:ResourceGovernorTestLogin。 —— (1 行受影响) 用户名 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
Run Code Online (Sandbox Code Playgroud)
在上面的两个结果集中,您可以看到资源调控器分类器函数将每个作业放入AgentServiceAccountGroup组中;这是因为 SQL Server 代理最初使用 SQL Server 代理启动时使用的服务帐户登录到 SQL Server。