我曾经在一家拥有第三方数据仓库解决方案的公司工作。显然,所有对象和表都隐藏在支持数据库中,所以我不清楚某些存储过程中到底发生了什么。我在那里看到了这个有趣的存储过程,并想在我自己的解决方案中复制它,但我无法理解它是如何工作的。我正在描述下面的存储过程,如果有人能给我一些关于如何实现这一点的想法,那将非常有帮助。如果你能建议我如何让它变得更好,那就更好了。
存储过程称为进程日志。它具有 DBID、ObjectId、Step、Status、Remarks、Reads、Inserts、Updates、Delete 等参数
我们要做的是,在每个存储过程中,我们必须执行这个状态为 2 (In Progress) 的存储过程。的可变步长。基于 Insert update select 和 delete 语句的行数,我们应该在各自的存储过程参数变量中记录值。最后,您可以执行状态为 3(已完成)的相同存储过程,或者如果该过程以 catch 块结束,则在备注部分中状态将为 4(失败),我们可以复制 SQL 的错误消息。
要查看所有这些信息,我们可以访问报告,显然我没有源代码,但报告显示了存储过程在完成时开始的时间,状态是多少插入更新删除并读取它做过。如果失败,错误信息是什么?
我已经没有什么改进商店的想法了,谁开始的?参数的值是多少?对于谁开始存储过程部分,我很困惑。大多数这些存储过程作为不同作业的一部分运行。我们所有的作业都作为服务帐户用户运行,但作业是由不同的用户手动启动的。我需要找出哪个用户启动了它,就像在存储过程中一样,作为当前用户,它总是会显示服务帐户。同样对于参数值,是否有更好的动态方法来找出这一点?而不是手动设置变量的值。我想使用 INPUTBUFFER 的输出,但它只显示参数的名称而不是值。
如果有人可以指导我有关此审计 SP 的后端表结构和脚本,那将非常有帮助。也欢迎任何更多的改进想法。
我的主要困惑:我相信他们有一些存储这些存储过程值的表,如果 SP 已经在运行,他们确实在记录中更新然后执行插入,但他们如何确定在场景中执行插入而不是更新其中存储过程严重失败并且未执行 catch 块。
这是一个至少非常接近的结构。
没有编程方式来获取参数(不幸的是)。您需要将它们格式化为 XML 才能传入。
启动 SQL 代理作业的登录似乎只记录在 , 的
message
列msdb.dbo.sysjobhistory
中step_id = 0
。可以提取此值,但不能在作业执行期间提取。你得到 ObjectID 从
@@PROCID
.下面是架构(2 个表)和存储过程(3 个过程)。这个概念是将“init”、“in process”和“completed (success or error)”日志分开。这允许仅在适当的时间设置某些列(例如,只需要在开始时设置
DatabaseID
,StartedAt
等)。分离事件的类型还可以更容易地拥有特定于事件的逻辑(是的,甚至可以在单个 proc 中拥有它,但是当您只需要每个事件类型的一个子集时,您仍然拥有所有输入参数)。“进程”记录通过其 IDENTITY(和集群 PK)值进行更新。这是具有“事件类型”分离的另一个好处:它可以更容易地处理捕获
SCOPE_IDENTITY()
并将其传递回以用于其他两个日志记录存储过程。如果存储过程失败并且没有进入CATCH
块,则无需担心意外更新该过程记录,因为下次任何存储过程(正在记录的)启动时,它将获得一个新的/唯一的 ID更新。清理(可选)和架构
表和索引
在“记录”存储过程的最开始调用的存储过程
除了最后一步之外,要调用的存储过程
在最后一步之后和/或在 CATCH 块中调用的存储过程
演示存储过程(输入参数格式为 XML)
将“StepNumber”放入变量中的原因是可以将值传递给
CATCH
块。该@StepNumber
变量在每次操作之前递增。如果操作成功,则该值用于调用“日志”存储过程,该过程捕获该步骤受影响的行数和调用时间。如果操作失败,则使用相同的@StepNumber
值来调用“停止”存储过程,该过程将过程标记为“失败”并传入错误消息。这使得数据不那么混乱,因为Step
失败记录的列将是错误发生时它实际工作的步骤。笔记:
关于获取 SQL Server 代理作业的“调用者”登录:
step_id = 0
在作业完成(成功或失败)之前,记录(这是该信息存在的唯一位置)不存在。因此,它在存储过程运行时不可用,更不用说在开始时了。MAX(sjh.[instance_id]) FROM msdb.dbo.sysjobhistory sjh
现在我们为当前会话捕获当前正在执行的作业。稍后(即在作业完成后),可以将其替换为作业调用程序登录。我通常建议不要将这种类型的日志记录添加到非常频繁执行的存储过程中,因为额外的读写操作会对性能产生负面影响。
附录
这是一个内联表值函数 (ITVF),用于根据
instance_id
捕获到ProcessLog.StartedBy
列中的值获取作业结果信息(包括“由”用户或计划或其他任何内容)。结果集中返回的instance_id
值是step_id = 0
.