并发大了,经常出现这个提示:
/”应用程序中的服务器错误。
事务(进程 ID 133)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
说明: 执行当前 Web 请求期间,出现未经处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.Data.SqlClient.SqlException: 事务(进程 ID 133)与另一个进程被死锁在 锁 资源上,并且已被选作死锁牺牲品。请重新运行该事务。
源错误:
执行当前 Web 请求期间生成了未经处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。
估计就是抢锁造成的,查看了这篇文章终于找到了解决方案:SELECT COUNT(*) FROM Example WITH(NOLOCK)
,加上WITH(NOLOCK)
就可以了
NOLOCK
NOLOCK在概念上类似于READ UNCOMMITTED隔离级别,并且只针对于SELECT查询语句,它不会获取表的共享锁,换句话说不会阻止排它锁来更新数据行。当我们对表进行NOLOCK有什么好处呢?它能够提高并发性能,因为此时SQL Server数据库引擎不必去维护共享锁,由于不会对正在读取的表获取共享锁,所以可能导致未提交的事务也会被读取,所以此时缺点显而易见将导致脏读
SELECT COUNT(*) FROM Example WITH(NOLOCK)
READPAST
当在表中用READPAST指定提示时此时SQL Server数据库引擎在返回结果集时将不会返回锁定的行或者数据页。它除了和NOLOCK一样不会导致查询阻塞外,因为不会返回锁定的行记录所以其优点好包括不存在脏读。但是其缺点则是因为不包含锁定的行记录但是很难保证结果集或者修改语句是否包含我们所必须需要返回的行。有可能在我们的业务逻辑中,需要返回我们必须需要的行。它的使用方式和NOLOCK一样
SELECT COUNT(*)FROM Example WITH(READPAST)
UPDLOCK
UPDLOCK只是针对于表中的某一行记录来锁定从而阻止其他操作对该行的数据更新,说到这里想必我们已经明了,UPDLOCK是行级别,而排它锁则是表级别,二者不可同日而语。也就说当我们对某一行添加UPDLOCK提示时并不会阻塞其他查询操作
BEGIN TRAN
select * from Example WITH (UPDLOCK) where SaleID = 1
此时我们再来开一个窗口进行查询,如下:
select * from Example
HOLDLOCK
使用HOLDLOCK提示时,此时查询将锁定表且被强制序列化,直到事务完成,才会被释放,其类似于SERIALIZABLE最高隔离级别
BEGIN TRAN
select * from Example WITH (UPDLOCK,HOLDLOCK) where SaleID = 1