在 64 位 SQL Server 2008R2 企业版中,我们创建了一个数据库来跟踪 DDL 更改。
我受到这个解决方案的启发:https ://www.mssqltips.com/sqlservertip/2085/sql-server-ddl-triggers-to-track-all-database-changes/
然后我们在每个数据库上创建一个触发器,如下所示:
CREATE TRIGGER [CaptureChanges] ON DATABASE
FOR CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE
AS ....
在 as 之后,代码在审计数据库中进行了简单的插入。
起初,它工作得很好,但是当一个用户,一个数据库的所有者,但没有审计数据库的权限,试图改变一个存储的,SQL Server 会出现一个权限不足的错误。
这是正确的,因为用户没有审计数据库的权限。
所以我使用EXECUTED AS使用具有sysadmin角色的用户:
CREATE TRIGGER [CaptureChanges] ON DATABASE
WITH EXECUTE AS 'useradmin'
FOR CREATE_PROCEDURE, ALTER_PROCEDURE, DROP_PROCEDURE
但现在它不起作用,因为这个错误:
Msg 916, Level 14, State 1, Procedure CaptureChanges, Line 0 [Batch Start Line 0] The server principal "useradmin" is not able to access the database "userdatabase" under the current security context.
看起来,当您使用 EXECUTED AS 时,您被沙盒化到一个数据库: http: //www.sommarskog.se/grantperm.html#EXECUTE_AS
所以,我不能使用 EXECUTED AS,因为它不能跨数据库工作。我不喜欢创建表来跟踪用户可以是dbowner的每个数据库中的更改的想法。
我可以为每个用户分配在目标表中写入的权限,但是我需要为每个新用户记住这一点。肯定有人会忘记这一点。
我也考虑过跟踪,但它可以很容易地停止,或者它不会在服务器启动时重新启动。
是不是触发方式不对?我能以某种方式解决这个问题吗?
您可以将服务器端跟踪作为 SQL 代理作业,并将作业设置为在 SQL 代理启动时启动,并设置第二个计划每 xx 分钟启动一次。这样工作将始终开始,如果有人错误地停止它,第二个时间表将负责。
我建议您创建一个数据库角色并让所有用户成为该角色的成员。我理解您担心忘记将用户添加到角色或分配权限。我个人不喜欢有太多的用户有权更改我的数据库中的模式,因此列表应该很小并且角色将使您更容易管理权限。