【问题标题】:NHibernate and interceptors - measuring/monitoring SQL round-trip timesNHibernate 和拦截器 - 测量/监控 SQL 往返时间
【发布时间】:2014-03-11 09:32:20
【问题描述】:

为了对慢速或潜在慢速区域进行预警,我想要一个 NHibernate 拦截器,它可以充当性能监视器,以便任何花费超过给定时间的数据库操作都会引发事件和(重要的)应用程序日志中的完整堆栈跟踪。

拦截器似乎是一个很好的窗口。但是,经过试验,似乎无论如何都无法捕捉到“刚刚从 SQL 中返回”的事件:

  • OnPreFlushOnPostFlush 处理涉及写入但不在读取事件中调用的完整批次。
  • OnPrepareStatement() 似乎是最好的开始测量,但停止?
  • 对于读取事件,OnLoad 可能是停止时钟的地方,但它称为每个实体返回一次 - 我如何知道何时到达所有实体的末尾?
  • 对于写入事件,我看不到任何 post-SQL 事件(除了那些在整个批次上工作的事件 - OnPostFlushOnAfterTransaction;我得到的印象是 OnSaveOnFlushDirty 等在实际的数据库调用发生之前调用 - 虽然很高兴得到纠正)。

据我所知,文档严重缺乏关于 NHibernate 与数据库交互的管道顺序的确切信息,因此当在管道中调用与实际 SQL 执行本身相关的不同事件和拦截器调用时。

这是需要永久可用的东西,位于后台,几乎不需要人工干预,除非检测到慢查询。它还需要在大型服务器场上无头运行,因此 NHibernate Profiler 等交互式工具已经过时:它实际上是我们可以启用和忘记的东西,让它在适当的时候记录。

我有什么遗漏或误解的吗?

【问题讨论】:

  • 我认为拦截器并不难实现,但是 sqlserver 能够为您监控。
  • 实现拦截器不是问题——我想知道的是事件管道,所以我把我的计时器放在 right 事件上,而不是依赖于 Heristics说“好吧,这是一次读取,因此我需要在这一点停止时钟;但如果发生这种情况[等],我不能重置开始时间”。虽然 SQL Server 可以监控这一点,但它不能做的是链接回 NHibernate 查询。记住:NHibernate 发布动态 SQL。我需要能够将一段随机的动态 SQL 追溯到调用它的代码中:SQL Server 无法提供给我。

标签: nhibernate iinterceptor


【解决方案1】:

我遇到了类似的问题。我想要测量并记录通过 NHibernate 的所有查询。 我所做的是我编写了一个自定义批处理工厂(在这种情况下我使用 oracle),但是您可以将相同的技术应用于任何数据库:

1-) 实现批处理工厂,(在这种情况下我正在扩展现有工厂)

public class OracleLoggingBatchingBatcherFactory : OracleDataClientBatchingBatcherFactory
{
    public override IBatcher CreateBatcher(ConnectionManager connectionManager, IInterceptor interceptor)
    {
        return new OracleLoggingBatchingBatcher(connectionManager, interceptor);
    }
}

2-) 实现批处理器本身(在这种情况下,我正在扩展现有的批处理器)。确保您再次继承 IBatcher,因为我们希望调用我们的新方法

public class OracleLoggingBatchingBatcher : OracleDataClientBatchingBatcher, IBatcher
{
      .... // here override ExecuteNonQuery, DoExecuteBatch and ExecuteReader. 
           //You can do all kind of intercepting, logging or measuring here
           //If they are not overrideable just implement them and use "new" keyword if necessary
           //since we inherit IBatcher explicitly it will work polymorphically.
           //Make sure you call base implementation too or re-implement the method from scratch
}

3-) 通过 NHibernate 配置注册工厂:

    <property name="adonet.factory_class">OracleLoggingBatchingBatcherFactory, MyAssembly</property>

【讨论】:

  • 除非我从头开始实施,否则我似乎无法覆盖 ExecuteNonQueryExecuteReader。结果,我无法捕获单个语句,只能捕获批处理。 DoExecuteBatch 给了我一些东西,但我不确定它是否完全有效,因为一批五个更新仅在 IDbCommand.CommandText 中列为单个更新。但是我会继续戳,看看我是否遗漏了什么(我正在覆盖 SqlClientBatchingBatcher)。
  • 您不必覆盖它们,您也可以“新建”它们并隐藏旧的实现。由于您明确继承 IBatcher,它仍然可以多态工作!
  • 啊——C# 的一个特性,我以前从来没有理由使用过。这似乎工作。 Ta 为指针 :-)
猜你喜欢
  • 1970-01-01
  • 2015-01-31
  • 1970-01-01
  • 1970-01-01
  • 2017-01-22
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2018-11-29
相关资源
最近更新 更多