Michael J. Swart

August 16, 2023

Deploying Resource Governor Using Online Scripts

Filed under: Miscelleaneous SQL,SQL Scripts,SQLServerPedia Syndication,Technical Articles — Michael J. Swart @ 12:07 pm

When I deploy database changes, I like my scripts to be quick, non-blocking, rerunnable and resumable. I’ve discovered that:

  • Turning on Resource Governor is quick and online
  • Turning off Resource Governor is quick and online
  • Cleaning or removing configuration is easy
  • Modifying configuration may take some care

Turning on Resource Governor

Just like sp_configure, Resource Governor is configured in two steps. The first step is to specify the configuration you want, the second step is to ALTER RESOURCE GOVERNOR RECONFIGURE.
But unlike sp_configure which has a “config_value” column and a “run_value” column, there’s no single view that makes it easy to determine what values are configured, and what values are in use. It turns out that the catalog views are the configured values and the dynamic management views are the current values in use:

Catalog Views (configuration)

  • sys.resource_governor_configuration
  • sys.resource_governor_external_resource_pools
  • sys.resource_governor_resource_pools
  • sys.resource_governor_workload_groups

Dynamic Management Views (running values and stats)

  • sys.dm_resource_governor_configuration
  • sys.dm_resource_governor_external_resource_pools
  • sys.dm_resource_governor_resource_pools
  • sys.dm_resource_governor_workload_groups

When a reconfigure is pending, these views can contain different information and getting them straight is the key to writing rerunnable deployment scripts.

Turning on Resource Governor (Example)

Despite Erik Darling’s warning, say you want to restrict SSMS users to MAXDOP 1:

Plot a Course

use master;
 
IF NOT EXISTS (
	SELECT *
	FROM sys.resource_governor_resource_pools
	WHERE name = 'SSMSPool'
)
BEGIN
	CREATE RESOURCE POOL SSMSPool;
END
 
IF NOT EXISTS (
	SELECT *
	FROM sys.resource_governor_workload_groups
	WHERE name = 'SSMSGroup'
)
BEGIN
	CREATE WORKLOAD GROUP SSMSGroup 
	WITH (MAX_DOP = 1)
	USING SSMSPool;
END
 
IF ( OBJECT_ID('dbo.resource_governor_classifier') IS NULL )
BEGIN
	DECLARE @SQL NVARCHAR(1000) = N'
CREATE FUNCTION dbo.resource_governor_classifier() 
	RETURNS sysname 
	WITH SCHEMABINDING
AS
BEGIN
 
	RETURN 
		CASE APP_NAME()
			WHEN ''Microsoft SQL Server Management Studio - Query'' THEN ''SSMSGroup''
			ELSE ''default''
		END;
END';
	exec sp_executesql @SQL;
END;
 
IF NOT EXISTS (
	SELECT *
	FROM sys.resource_governor_configuration /* config */
	WHERE classifier_function_id = OBJECT_ID('dbo.resource_governor_classifier') )
   AND OBJECT_ID('dbo.resource_governor_classifier') IS NOT NULL
BEGIN
	ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = dbo.resource_governor_classifier); 
END

And when you’re ready, RECONFIGURE:

Make it so

IF EXISTS (
	SELECT *
	FROM sys.dm_resource_governor_configuration
	WHERE is_reconfiguration_pending = 1
) OR EXISTS (
	SELECT *
	FROM sys.resource_governor_configuration
	WHERE is_enabled = 0
)
BEGIN
	ALTER RESOURCE GOVERNOR RECONFIGURE;
END
GO

Turning off Resource Governor

Pretty straightforward, the emergency stop button looks like this:

ALTER RESOURCE GOVERNOR DISABLE;

If you ever find yourself in big trouble (because you messed up the classifier function for example), use the Dedicated Admin Connection (DAC) to disable Resource Governor. The DAC uses the internal workload group regardless of how Resource Governor is configured.

After you’ve disabled Resource Governor, you may notice that the resource pools and workload groups are still sitting there. The configuration hasn’t been cleaned up or anything.

Cleaning Up

Cleaning up doesn’t start out too bad, deal with the classifier function, then drop the groups and pools:

ALTER RESOURCE GOVERNOR DISABLE
ALTER RESOURCE GOVERNOR WITH (CLASSIFIER_FUNCTION = NULL); 
DROP FUNCTION IF EXISTS dbo.resource_governor_classifier;
 
IF EXISTS (
	SELECT *
	FROM sys.resource_governor_workload_groups
	WHERE name = 'SSMSGroup'
)
BEGIN
	DROP WORKLOAD GROUP SSMSGroup;
END
 
IF EXISTS (
	SELECT *
	FROM sys.resource_governor_resource_pools
	WHERE name = 'SSMSPool'
)
BEGIN
	DROP RESOURCE POOL SSMSPool;
END

You’ll be left in a state where is_reconfiguration_pending = 1 but since Resource Governor is disabled, it doesn’t really matter.

Modifying Resource Governor configuration

This is kind of a tricky thing and everyone’s situation is different. My advice would be to follow this kind of strategy:

  • Determine if the configuration is correct, if not:
    • Turn off Resource Governor
    • Clean up
    • Configure correctly (plot a course)
    • Turn on (make it so)

Somewhere along the way, if you delete a workload group that some session is still using, then ALTER RESOURCE GOVERNOR RECONFIGURE may give this error message:

Msg 10904, Level 16, State 2, Line 105
Resource governor configuration failed. There are active sessions in workload groups being dropped or moved to different resource pools.
Disconnect all active sessions in the affected workload groups and try again.

You have to wait for those sessions to end (or kill them) before trying again. But which sessions? These ones:

SELECT 
	dwg.name [current work group], 
	dwg.pool_id [current resource pool], 
	wg.name [configured work group], 
	wg.pool_id [configured resource pool],
	s.*
FROM 
	sys.dm_exec_sessions s
INNER JOIN 
	sys.dm_resource_governor_workload_groups dwg /* existing groups */
	ON dwg.group_id = s.group_id
LEFT JOIN 
	sys.resource_governor_workload_groups wg /* configured groups */
	ON wg.group_id = s.group_id
WHERE 
	isnull(wg.group_id, -1) <> dwg.pool_id
ORDER BY 
	s.session_id;

If you find your own session in that list, reconnect.
Once that list is empty feel free to try again.

3 Comments »

  1. […] Michael J. Swart doesn’t want to wait (or cause anyone else to): […]

    Pingback by Deploying Resource Governor with Minimal Blocking – Curated SQL — August 17, 2023 @ 8:00 am

  2. Out of curiosity, why use sp_executesql within a conditional to create the classifier function? It’s not wrong (though I don’t think that ALTER will ever run given that the test is “does this object already exist?”), it just strikes me as odd. Happy to learn something here. Thanks for all you do.

    Comment by Ben Thul — August 17, 2023 @ 12:33 pm

  3. Great question Ben,

    When creating a function, it has to be the only statement in the batch.
    So why can’t we just use the CREATE OR ALTER syntax without the IF EXISTS check? It’s because we want this script to be rerunnable.
    If we run the script successfully, we want to be able to run the script again as a no-op.

    Normally CREATE OR ALTER FUNCTION has no effect when the definition is the same.
    But if that function is already in use by RESOURCE GOVERNOR, we get this error. That’s why we can’t use it straight.

    Msg 10920, Level 16, State 2, Procedure resource_governor_classifier, Line 1 [Batch Start Line 64]
    Cannot alter user-defined function 'resource_governor_classifier'. It is being used as a resource governor classifier.

    Comment by Michael J. Swart — August 17, 2023 @ 3:09 pm

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress