我们的应用程序(使用NHibernate和ASP.NET MVC)在进行压力测试时会抛出很多NHibernate事务错误。主要类型是:
有人可以帮助我找出异常1的原因吗? 我知道我必须处理代码中的其他异常。有人能指出我可以帮助我以有效的方式处理这些错误的资源吗?
Q值。我们如何管理会话和交易?
一个。我们正在使用Autofac。对于每个服务器请求,我们创建一个新的请求容器,其中包含容器生命周期范围内的会话。在激活会话时,我们开始交易。请求完成后,我们提交事务。在某些情况下,交易可能很大。为简化起见,每个服务器请求都包含在事务中。
答案 0 :(得分:1)
看一下这个帖子: http://n2cms.codeplex.com/Thread/View.aspx?ThreadId=85016
基本上它说的是这个例外的可能原因:
2010-02-17 21:01:41,204 1警告 NHibernate.Util.ADOExceptionReporter - System.Data.SqlClient.SqlException: 数据库的事务日志 'databasename'已满。要找出答案 为什么日志中的空间无法重用, 请参阅中的log_reuse_wait_desc列 sys.databases中
由于事务日志的大小与事务期间完成的工作量成比例,因此您可能需要考虑将事务边界放在命令处理程序“处理”事务的写入部分上。然后,您将使用会话#X加载您希望变异的状态,将其变异并提交,这些都是#X中的一个工作单元。
关于事物的读取方面,你可能会有另一个读取数据的ISession #Y;这个ISession可以用来批量读取例如RepeatableRead或与Futures功能类似的东西,可以简单地从缓存中读取(它确实是一个拐杖)。这样做可能有助于您从“错误”中恢复;活锁,死锁和受害者交易。
每个请求使用一个事务的问题是,您的ISession在您工作时会获取大量的簿记数据,所有这些都是事务的一部分。因此,数据库将数据(rols,cols,tables等)标记为事务中的参与,导致等待图跨越“实体”(在数据库意义上,而不是DDD意义上),这实际上不是您的应用程序所执行命令的事务边界。
对于记录(其他人在谷歌上搜索),Fabio有a post处理来自数据层的异常处理。引用他的一些代码;
public class MsSqlExceptionConverterExample : ISQLExceptionConverter
{
public Exception Convert(AdoExceptionContextInfo exInfo)
{
var sqle = ADOExceptionHelper.ExtractDbException(exInfo.SqlException) as SqlException;
if(sqle != null)
{
switch (sqle.Number)
{
case 547:
return new ConstraintViolationException(exInfo.Message,
sqle.InnerException, exInfo.Sql, null);
case 208:
return new SQLGrammarException(exInfo.Message,
sqle.InnerException, exInfo.Sql);
case 3960:
return new StaleObjectStateException(exInfo.EntityName, exInfo.EntityId);
}
}
return SQLStateConverter.HandledNonSpecificException(exInfo.SqlException,
exInfo.Message, exInfo.Sql);
}
}
因此,如果您遇到类似于您描述的并发问题;请记住,它们会使您的ISession无效,并且您必须像上面那样处理它们。
您可能正在寻找的部分内容是CQRS,您可以在其中拥有单独的读写端。这可能有所帮助:http://abdullin.com/cqrs/,http://cqrsinfo.com。
总结一下;您的问题可能与您处理交易的方式有关。另外,请尝试运行select log_wait_reuse_desc from sys.databases where name='MyDBName'
并查看它为您提供的内容。
答案 1 :(得分:1)
这个帖子有一个解释: http://groups.google.com/group/nhusers/browse_thread/thread/7f5fb68a00829d13
简而言之,由于某些错误,数据库可能会自行回滚事务,因此当您尝试稍后回滚事务时,它已经回滚并处于僵尸状态。这往往会隐藏回滚的实际原因,因为你看到的只是一个TransactionException而不是实际上首先触发回滚的异常。
除了记录它并试图找出导致潜在错误的原因之外,我认为你无法做很多事情。
答案 2 :(得分:0)
压力是指millions of database entries?如果是这样,请查看以下帖子:
答案 3 :(得分:0)
我知道这篇文章有一段时间了,假设你修复它,但好像你有NHibernate ISession的线程共享问题,这不是线程安全的。基本上1个线程正在启动一个事务而另一个正在尝试关闭它导致各种混乱。