我的处境有点奇怪... a) 我们正在将所有 SQL Server 实例升级到 2017 年。 b) 不少受影响的数据库正在使用旧版兼容性级别/基数估计器。 c) 我们希望拥有当前(2017)CL 上的所有数据库并使用最新的 CE。
计划是在单个语句级别使用“OPTION(QUERYTRACEON 9481)”来处理与新 CE 不兼容的查询。不是作为永久修复,而是作为克服困难的一种手段(重写每个受影响的程序根本超出了当前项目的范围)。
切入主题...这似乎按预期工作,除非存储过程使用动态 SQL 并且由非 SA 用户执行。这当然是有道理的。只要在过程范围内执行“OPTION(QUERYTRACEON 9481)”,所有权链接就会提供执行基础 DBCC TRACEON 命令所需的权限。然而,动态 SQL 的使用本质上将代码视为 AD-HOC SQL,并在用户自己的安全上下文下执行...这不是 SA,因此无权执行 DBCC TRACEON;
简短或重写查询或赋予应用程序服务帐户SA角色,有人有可用的解决方案吗?
提前谢谢您,
杰森
问题:
...然而,动态 SQL 的使用本质上将代码视为 AD-HOC SQL,并在用户自己的安全上下文下执行...这不是 SA,因此无权执行 DBCC TRACEON;
解决方案:
Kimberly Tripp 在她在 sqlskills.com 上的帖子中进行了精彩的解释:
“在逐个查询(或会话)的基础上设置 CE TraceFlags”
在 msdb 数据库上创建一个存储过程,允许在没有系统管理员权限的情况下设置所需的跟踪标志。
(当然,系统管理员负责设置允许的跟踪标志值的列表)。
通过调用此存储过程来包装任何有问题的语句(动态 SQL、即席查询或过程调用),并更改执行的会话跟踪标志。
这允许具有较低权限的用户更改基数估计器以执行有问题的语句。
用法示例:
EXEC msdb.dbo.msdbSetTraceFlag 9481, 1;
GO
Problematic STATEMENT or PROCEDURE
EXEC msdb.dbo.msdbSetTraceFlag 9481, 0; -- don't remember to turn it back off!
GO
存储过程代码:
USE msdb;
GO
CREATE PROCEDURE msdbSetTraceFlag
(@TraceFlag int,
@OnOff bit = 0)
WITH EXECUTE AS OWNER
AS
DECLARE @OnOffStr char(1) = @OnOff;
-- Sysadmins can add supported trace flags and then use this
-- from their applications
IF @TraceFlag NOT IN (
9481 -- LegacyCE if database is compat mode 120 or higher
, 2312 -- NewCE if database compat mode 110 or lower
)
BEGIN
RAISERROR('The Trace Flag supplied is not supported. Please contact your system administrator to determine inclusion of this trace flag: %i.', 16, 1, @TraceFlag);
RETURN
END
ELSE
BEGIN
DECLARE @ExecStr nvarchar(100);
IF @OnOff = 1
SELECT @ExecStr = N'DBCC TRACEON(' + CONVERT(nvarchar(4), @TraceFlag) + N')';
ELSE
SELECT @ExecStr = N'DBCC TRACEOFF(' + CONVERT(nvarchar(4), @TraceFlag) + N')';
-- SELECT (@ExecStr)
EXEC(@ExecStr)
-- RAISERROR (N'TraceFlag: %i has been set to:%s (1 = ON, 0 = OFF).', 10, 1, @TraceFlag, @OnOffStr);
END;
GO
GRANT EXECUTE ON msdbSetTraceFlag TO PUBLIC --or to a specific set of users;
GO
注意: 此存储过程是在 msdb 中创建的,而不是在 master 上创建的,因为“可信”先决条件是 msdb 的默认值。
-- 不要记得将其关闭!
是“——别忘了把它关掉!” ?