begin tran
update T_A set name='AAA1' where name='AAA'执行事务后没提交,那么数据库里面是AAA还是AAA1?
如果这时我再启动个事务(已在name上用了聚集索引)
SET TRANSACTION ISOLATION LEVEL READ COMMITTED begin tran
update T_A set name='BBB' where name='AAA1'
update T_A set name='BBB' where name='AAA'执行上面两句后都会被阻塞,是否代表第一个事务执行update后数据库中有AAA和AAA1两条数据并都加了X锁?

解决方案 »

  1.   


    不会我看过它是加的行X锁,在表上加的IX锁,而且我试过了执行update T_A set name='BBB' where name='CCC' 因为CC并没有被加锁
      

  2.   

    而且我试过了执行update T_A set name='BBB' where name='CCC' 没被阻塞因为CCC并没有被加锁
      

  3.   

    现在的问题就是:
    begin tran 
    update T_A set name='BBB' where name='AAA1' --阻塞
    update T_A set name='BBB' where name='AAA' --阻塞
    update T_A set name='BBB' where name='CCC' --不阻塞
    为什么?
      

  4.   

    我的感觉是SQL SERVER虽然支持行锁,但是实际上不完全支持,这种情况下,name上有聚集索引,所以加了键锁,是一部分数据被锁了,而不是只有一行被锁
      

  5.   

    sql的默认是已提交读,默认情况下是锁定整个表,当在表上建有聚集索引的时候,锁的粒度会改变,会在行集上产生锁
      

  6.   

    1、楼主先看下你这个表的有几个数据页,
    begin tran 
    update T_A set name='AAA1' where name='AAA' 
    应该是对这个数据所在的页进行了加锁,而update T_A set name='BBB' where name='CCC' --不阻塞 
    可能是因为这个数据在另一个页面,而没有被锁,所以没有阻塞2、SET TRANSACTION ISOLATION LEVEL READ COMMITTED begin tran 
    update T_A set name='BBB' where name='AAA1' 
    update T_A set name='BBB' where name='AAA'这两个都会被阻塞,访问的是同一个页面,自然会被阻塞。因为你第一个未提交的事务已经在这个页面上加锁
      

  7.   

    事务的隔离性。在读已提交事务隔离级别中,在事务未提交前,在事务中修改的结果只能在该事务中被读取,对于其他事务都是不可见的。
    那么,对于在 name 上有索引的情况,下面的现象
    update T_A set name='BBB' where name='AAA1' --阻塞
    update T_A set name='BBB' where name='AAA' --阻塞 
    是 SQL Server 在事务未提交前对 AAA 和 AAA1 都保持有 X 锁,阻塞其他事务对这两个记录的访问。LZ 可以用 SP_LOCK 存储过程验证一下。
    如果在 name 上没有索引,则 SQL Server 只对 AAA 行保持有 X 锁(RID 锁)。那么,在使用上面两条语句更新时同样会被阻塞。只不过是在更新 AAA1 记录时,在进行表扫描查找 AAA1 时被 AAA 上的 X 锁阻塞的。
    不知道我解释的清不清楚?LZ 可以通过 Profiler 跟踪一下,可以看得更明白。
      

  8.   


    恩是不是就是意味着第一个事务的begin tran update T_A set name='AAA1' where name='AAA' 相当于数据库里临时多了一行叫'AAA1'?并且AAA1和AAA都加上了X锁?
      

  9.   

    数据库更新时,封锁等级是比较高的read comment,也就是,在事务结束前,对该表的所有访问是不允许的.
    并不是针对某条记录行加锁.
      

  10.   

    在事务未提交前,是这样的。
    往更深的讲,这个涉及到数据库存储引擎执行的是“就地更新”,还是“删除-插入更新”。
    对于 lz 的情况,在没有索引时,update 直接用新的数据替换旧的;在有索引时,update 会根据索引,先将新的数据插入索引中适合的位置,再去删除旧的(当然在事务提交后)。