NHibernate和拦截器-测量/监视SQL往返时间 [英] NHibernate and interceptors - measuring/monitoring SQL round-trip times

查看:155
本文介绍了NHibernate和拦截器-测量/监视SQL往返时间的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

拦截器似乎是了解此问题的好窗口.但是,经过试验,似乎并没有捕捉到"SQL刚回来"事件:

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

据我所知,关于NHibernate与数据库的交互,确切地缺乏管道顺序的文档,因此,在该管道中,相对于实际SQL执行本身,将调用不同的事件和拦截器调用. /p>

这是需要永久存在的东西,它位于后台,几乎不需要人工干预,除非检测到慢查询.它还需要在大型服务器场上无头运行,因此交互式工具(如NHibernate Profiler)就不可用了:从字面上讲,我们可以启用并忘记它,让它在适当的时候进行记录.

有什么我想念或误解的东西吗?

解决方案

我遇到了类似的问题.我想测量并记录所有通过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>

In order to get early-warning of a slow or potentially slow areas, I'd like to have an Interceptor for NHibernate that can act as a performance monitor, so that any database operation that takes more than a given time raises an event and (importantly) a full stacktrace into the application's logs.

Interceptors seemed to be a good window into this. However, having experimented, there doesn't seem to be anyway to catch a "just-back-from-SQL" event:

  • OnPreFlush and OnPostFlush work on full batches where writes are involved, but aren't invoked on read events.
  • OnPrepareStatement() seems to be the best to put start measuring, but to stop?
  • For read events, OnLoad might be the place to stop the clock, but it's called once-per-entity returned - how do I know when I've got to the end of all entities?
  • For write events, I can't see any post-SQL event (other than those that work on the entire batch - OnPostFlush and OnAfterTransaction; I get the impression OnSave, OnFlushDirty, etc are called before the actual database call occurs - happy to be corrected though).

From what I can tell, documentation is heavily lacking on exactly what the pipeline order is with NHibernate's interaction with the database, and thus when in that pipeline different events and interceptor calls are called in relation to the actual SQL execution itself.

This is something that needs to be permanently available, sitting in the background, pretty much that requires no human intervention except when slow queries are detected. It also needs to run headless on a large farm of servers, so interactive tools such as NHibernate Profiler are out: it's literally something that we can enable and forget about, letting it log as and when appropriate.

Is there anything I have missed or misunderstood?

解决方案

I had a similar problem. I wanted measure and log all queries that goes through NHibernate. What I did is I wrote a custom batching factory (in this case I work with oracle) but you can apply the same technique to any db:

1-) Implement batcher factory, (in this case I am extending existing factory)

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

2-) Implement the Batcher itself (in this case I am extending existing batcher). Make sure you inherit IBatcher again since we want our new methods to be called

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-) Register the factory via NHibernate config:

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

这篇关于NHibernate和拦截器-测量/监视SQL往返时间的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆