1、select语句也能加锁共享锁
共享 (S) 锁允许并发事务读取 (SELECT) 一个资源。资源上存在共享 (S) 锁时,任何其它事务都不能修改数据。2、死锁问题往往和效率相关,提高查询、修改效率是一举两得的事情

解决方案 »

  1.   

    select * from T(nolock)  --加上nolock
      

  2.   

    select * from T  with (nolock)  
    --with 可以省略
      

  3.   

    但加with (Nolock)不是解决的办法,应该监测是什么原因导致了表锁定,其它进程无法访问。
      

  4.   

    或者對某個交易set deadlock_priority low,讓SQL選擇一個程序犧牲
      

  5.   

    with lock 后面可以加 time limit... 吗?
      

  6.   

    with lock 后面可以加 time limit... 吗?------------------------------
    不能。至少SQL Server 2000不支持这种写法。
      

  7.   

    select * from Tablename  with (nolock)
      

  8.   

    TO CSDMN(冒牌经理 V0.3) 
    问题是我现在作为牺牲品的只是一个查询而已,根本不存在更新,不需要获得任何资源的锁啊!!!问什么SQL Server 会认为我这个查询需要锁定某个资源而牺牲这个查询呢???我现在需要的是不管这个表有没有锁定我都可以查询,我不需要更新,只要能够查询就可以了!如果我在查询中加上(nolock) 那是不是说尽管别人锁定了该表我都可以查询还是说我在查询这个表的时候不加锁呢???在什么情况下会造成一个查询会对表加上共享锁呢???
      

  9.   

    使用With (nolock)。共享锁,即用于不更改或不更新数据的操作(只读操作),如 SELECT 语句。
      

  10.   

    使用SQL2005的话,用快照隔离级别,Select语句不需要共享锁。
      

  11.   

    你的死锁信息都打出来的,还说没有update操作?! :)你的死锁原因大致是:多个连接同时为一个表加了S锁(select造成的),而一个进程在进行update操作想取得X锁的时候要等待其他进程释放S锁,这个时候其他进程也在等待它释放S锁,所以导致了死锁!执行:
    DBCC TRACEON(1204, -1)DBCC TRACEON(1205, -1)DBCC TRACEON(3605, -1)把错误提示再发出来。可以找出死锁对象。解决方案:
    可以尝试在select时加上X锁,防止其他进程同时锁定。如:select * from table1 with(ROWLOCK,XLOCK)
      

  12.   

    TO ashzs((可以包含中文字符)) 
    我上面的信息就是通过DBCC TRACEON(1204, -1)在日志中得到的
    你的DBCC TRACEON(1205, -1),DBCC TRACEON(3605, -1)跟踪什么的呢?好像没有这两个跟踪标志吧.按照帮助中讲产生死锁的原因是因为两个事务交叉申请彼此锁定的资源造成的.但我现在是一个执行查询语句的事务怎么可能和另外一个事务产生交叉锁定呢?按理只会造成阻塞啊!我上面的跟踪已经是几个死锁信息的了.有什么办法使到查询语句不锁定表(使用With (nolock)吗?).
      

  13.   

    ashzs((可以包含中文字符)) :
    解决方案:
    可以尝试在select时加上X锁,防止其他进程同时锁定。如:select * from table1 with(ROWLOCK,XLOCK)-----------------------------------------------
    很难明白你的方案会有效,如果加S锁都死锁了,加X锁怎么可能解决问题呢?会不会变成频频出错?
    我感觉楼主的系统一定有性能问题,select返回的数据太多太慢会造成S锁长期不释放,更新操作只能等待;更新操作太慢造成X锁不释放,其他操作只能等待。
    所以有以上的回复,希望楼主能正视效率问题。
      

  14.   

    TO zicxc(冒牌邹建 V0.3)我的系统的确存在效率问题,但由于系统比较复杂一时比较难优化(也不是没有优化的,该优化的都优化了)主要是一个更新存储过程耗时比较长(由于业务逻辑比较复杂).如果主要表的记录数在50万以下,并发量在5个连接的情况下还好一点,一但超出这个范围,每天的死锁情况在10次以上,多的达到上百次啊!!!这个问题已经长期困扰我了,由于以前数据量不大这个问题没有那么突出,随着数据量的增大,问题越来越严重了啊!!!唉~~~
      

  15.   

    对C++builder开发软件、及数据库管理应用等等等等感兴趣的朋友请加入群:32428641
      

  16.   

    to allanli(若尘):我上面的信息就是通过DBCC TRACEON(1204, -1)在日志中得到的
    你的DBCC TRACEON(1205, -1),DBCC TRACEON(3605, -1)跟踪什么的呢?好像没有这两个跟踪标志吧.按照帮助中讲产生死锁的原因是因为两个事务交叉申请彼此锁定的资源造成的.但我现在是一个执行查询语句的事务怎么可能和另外一个事务产生交叉锁定呢?按理只会造成阻塞啊!我上面的跟踪已经是几个死锁信息的了.有什么办法使到查询语句不锁定表(使用With (nolock)吗?).
    -------------------------------------
    一般检测死锁的方法是:使用traceon跟踪和profiler同时定位死锁信息。你上面的信息确实是1204打出来的,但是还有些信息上面是无法提供的。如果你看了sql2k的帮助文档你会发现sql server建议使用1204和3605来确定死锁。所以多些信息对死锁的监测时有好处的!还有帮助文档中说的两个互相等待的事务你没有发现。那是因为你不知道有其他的因素会和你的使用导致死锁,所以你才要找呀!而且两个事务互相等待对方的资源说明的是死锁的原理,但是这个原理会有很多表现的现象,甚至有的时候你会发现数据库自身的字典表和内部线程资源发生了死锁。使用With (nolock)还是With (ROWLOCK,XLOCK)要根据你的业务需求,如果是否update要由select的结果来决定的话,你只能用后者。如果没有直接联系,前者也是可以的。这要根据你对死锁原因排查后,再作决定。
      

  17.   

    TO zicxc(冒牌邹建 V0.3):
    很难明白你的方案会有效,如果加S锁都死锁了,加X锁怎么可能解决问题呢?会不会变成频频出错?
    我感觉楼主的系统一定有性能问题,select返回的数据太多太慢会造成S锁长期不释放,更新操作只能等待;更新操作太慢造成X锁不释放,其他操作只能等待。
    所以有以上的回复,希望楼主能正视效率问题。
    --------------------------------------------------
    首先要理解S锁和X锁的区别。S锁是指多个数据库连接可以在同一时间共同加持在相同的资源上。而X锁是排他的,在同一时间只能有一个数据库连接取得资源的使用权。而楼主的死锁原因就是因为高并发情况下,有多个数据库连接同时对同一资源加了S锁,而其中某一个数据库连接update的时候,要升级S锁为X锁。但是它只有等待其他数据库连接释放S锁,他才能升级为X锁,所以他在等。但是在他等待别人释放S锁的时候,那个连接却也要进行update,也要升级为X锁,因此造成了互相等待对方释放资源的局面,因此导致了死锁!
    如果在select的时候加上With (ROWLOCK,XLOCK),其实就是首先杜绝大家同时施加S锁的可能,即对这个资源大家要串行访问,虽然效率低,但是最大限度避免死锁。最典型的例子应该是自己写的生成主键存储过程的时候,这种现象最容易发生。
      

  18.   

    根据我自己的经验的总结:
       select 时候产生死锁的原因.往往是别外一个用户进行批理对表进行增删改的时候才会发生.
      

  19.   

    谢谢ashzs((可以包含中文字符)) 
    他的解释应该说明了楼主的死锁主要产生过程从解决问题方面来说,设法提高效率(或者说性能优化,不过性能优化的范围大了些)是成本最低的好像楼主一直没说硬件情况
      

  20.   

    zicxc(冒牌邹建 V0.3) ,客气了!to allanli(若尘),建议你最好使用profiler和打开1205跟踪。这样定位死锁非常容易。如果你分析不出来,也可以贴出来让大家帮你分析。
      

  21.   

    现在把大部分查询改为select xxx from xxx with(nolock)可以明显减少死锁了(减为原来的1/10),从这说明死锁是由于大量的并发造成大量S锁产生,部分S锁又需要升级为X锁造成的.
    但不知道这样做的后遗症大不大.如果改为with(ulock)又怕降低并发量.按照现在的死锁频率
    基本可以满足我的要求了.真的很感谢大家的提示与意见啊!!!
      

  22.   

    to:ashzs((可以包含中文字符)) 
    一般检测死锁的方法是:使用traceon跟踪和profiler同时定位死锁信息。你上面的信息确实是1204打出来的,但是还有些信息上面是无法提供的。如果你看了sql2k的帮助文档你会发现sql server建议使用1204和3605来确定死锁。所以多些信息对死锁的监测时有好处的!
    -------------------------------
    3605是用来将信息发送到log中的,而使用1205可以得到更多的信息。
      

  23.   

    我也遇到过类似情况,SQL2000中SELECT确实会产生锁。解决的办法是让SELECT尽量使用索引,从而减小锁的范围,减小死锁产生的机会
      

  24.   

    在select前面加上这么一句配置,实现脏读,应该是别的dml语句锁了你要查询的表
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED