Sql server 通过NHibernate查询SQL Server时超时
我有一个ASP.NETMVC应用程序,它通过NHibernate使用SQLServer2005。我偶尔收到以下错误消息: “System.Data.SqlClient.SqlException(0x80131904):超时已过期。 在完成操作或操作之前经过的超时时间 服务器没有响应。位于 System.Data.SqlClient.SqlConnection.OnError(SqlException异常, 布尔断开连接)在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException 异常,布尔断开连接)位于 System.Data.SqlClient.TdsParser.throweexception和warning()位于 System.Data.SqlClient.TdsParser.Run(RunBehavior, SqlCommand cmdHandler、SqlDataReader数据流、, BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject (b)在 System.Data.SqlClient.SqlDataReader.SetMetaData(_SqlMetaDataSet 元数据,Boolean moreInfo)位于 System.Data.SqlClient.TdsParser.Run(RunBehavior, SqlCommand cmdHandler、SqlDataReader数据流、, BulkCopySimpleResultSet bulkCopyHandler,TdsParserStateObject stateObj)位于System.Data.SqlClient.SqlDataReader.ConsumerMetadata()处 位于System.Data.SqlClient.SqlDataReader.get_MetaData()处 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, 运行行为运行行为,字符串重置选项字符串)位于 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior、RunBehavior、Boolean returnStream、Boolean 异步)在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior、布尔返回流、字符串 方法,DbAsyncResult(结果)位于 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior、布尔返回流、字符串 方法)在 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior 行为,字符串方法)在 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior 行为)在 System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()Sql server 通过NHibernate查询SQL Server时超时,sql-server,nhibernate,locking,Sql Server,Nhibernate,Locking,我有一个ASP.NETMVC应用程序,它通过NHibernate使用SQLServer2005。我偶尔收到以下错误消息: “System.Data.SqlClient.SqlException(0x80131904):超时已过期。 在完成操作或操作之前经过的超时时间 服务器没有响应。位于 System.Data.SqlClient.SqlConnection.OnError(SqlException异常, 布尔断开连接)在 System.Data.SqlClient.SqlInternalCon
在NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd)
在NHibernate.Loader.Loader.GetResultSet(IDBST命令,布尔值 自动发现转换类型、布尔可调用、行选择、, ISessionImplementor会话)在 NHibernate.Loader.Loader.DoQuery(ISessionImplementor会话, QueryParameters QueryParameters,布尔返回代理)位于 NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor 会话,查询参数,查询参数,布尔返回代理)
在NHibernate.Loader.Loader.DoList(ISessionImplementor会话, 查询参数查询参数“ 大多数情况下,系统工作正常,响应速度非常快。我已经查看了系统上的锁,我通常会发现一个查询被另一个查询阻塞:
"SELECT TOP 10 d.Id, d.Name FROM Documents d INNER JOIN Users u ON..."
正在被以下内容阻止:
"SELECT TOP 10 Id, Name FROM Users"
查看blocking语句所持有的锁,在与Users表无关的各种表上大约有十几个排他(X)和(IX)页锁和键锁(但它们是被阻止的查询的一部分)
此处不涉及更新、插入或删除-因此,为什么一个只读查询会阻止另一个,为什么对Users表的简单查询会导致许多其他表被锁定。这会导致问题:
begin transaction
update Documents
set SomeField = 'SomeValue'
where SomeCondition = 'XXXX'
select top 10 Id, Name from Users
commit
在更新期间在文档表上创建的锁在提交事务之前不会被释放。这意味着一个连接可以将select语句作为其最近的语句,但仍然持有来自上一次更新的锁
一些想法:
最后要注意(nolock)锁提示的想法。读取未提交的数据很少是个好主意。这会导致以下问题:
begin transaction
update Documents
set SomeField = 'SomeValue'
where SomeCondition = 'XXXX'
select top 10 Id, Name from Users
commit
在更新期间在文档表上创建的锁在提交事务之前不会被释放。这意味着一个连接可以将select语句作为其最近的语句,但仍然持有来自上一次更新的锁
一些想法:
最后要注意(nolock)锁提示的想法。读取未提交的数据很少是个好主意。SQL Server gotcha是数据库上的非默认“隔离级别”设置。SQL Server的默认隔离级别(锁定策略)为ReadCommitted,这意味着读锁会尽快释放,但写锁在事务提交之前不会释放。在Andy的回答中,默认隔离级别将导致select被阻止。但是,如果数据库设置为RepeatableRead或Serializable,则selects将在事务期间始终相互阻止。可以使用以下hibernate.cfg.xml配置在NHibernate中控制此设置:
<session-factory>
...
<add key="hibernate.connection.isolation" value="ReadCommitted" />
...
</session-factory>
...
...
SQL Server gotcha是数据库上的非默认“隔离级别”设置。SQL Server的默认隔离级别(锁定策略)为ReadCommitted,这意味着读锁会尽快释放,但写锁在事务完成之前不会释放