看看这个线程:
http ://n2cms.codeplex.com/Thread/View.aspx?ThreadId=85016
基本上它所说的可能导致此异常的原因是:
2010-02-17 21:01:41,204 1 WARN NHibernate.Util.ADOExceptionReporter - System.Data.SqlClient.SqlException:数据库“数据库名称”的事务日志已满。要找出日志中的空间不能被重用的原因,请参阅 sys.databases 中的 log_reuse_wait_desc 列
由于事务日志的大小与事务期间完成的工作量成正比,也许您应该考虑将事务边界放在命令处理程序“处理”事务写入部分的命令之间。然后,您将使用会话#X,加载您希望变异的状态,对其进行变异并提交,所有这些都作为#X 中的一个工作单元。
关于事物的读取端,您可能会有另一个读取数据的 ISession#Y;此 ISession 可用于批量读取,例如 RepeatableRead 或与 Futures 功能类似的东西,并且可以简单地从缓存中读取(尽管它确实是一个拐杖)。这样做可能会帮助您从不存在的“错误”中恢复;活锁、死锁和受害者事务。
每个请求使用事务的问题在于,您的 ISession 在您工作时会获取大量簿记数据,所有这些都是事务的一部分。因此,数据库将数据(rols、cols、表等)标记为参与事务,导致等待图跨越“实体”(在数据库意义上,而不是 DDD 意义上),这实际上不是一部分您的应用程序执行的命令的事务边界。
作为记录(其他人在谷歌上搜索),Fabio 有一篇处理数据层异常的帖子。引用他的一些代码;
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);
}
}
- 547 是约束冲突的异常编号。
- 208 是 SQL 中对象名称无效的异常编号。
- 3960 是快照隔离事务因更新冲突而中止的异常编号。
因此,如果您遇到您所描述的并发问题;请记住,它们将使您的 ISession 无效,并且您必须像上面那样处理它们。
您可能正在寻找的部分内容是 CQRS,其中您有单独的读取和写入端。这可能会有所帮助:http ://abdullin.com/cqrs/,http : //cqrsinfo.com。
所以总结一下;您的问题可能与您处理交易的方式有关。另外,尝试跑步select log_wait_reuse_desc from sys.databases where name='MyDBName'
,看看它会给你带来什么。