在修改时用事物处理
begin tran
......
--COMMIT TRAN注释掉不提交
在系统中显示正常,也能继续insert,update操作,
在sql2005中select * from 表 发现表被锁了
select * from 表 with(nolock) 能看到后来插入的数据
当把系统退出重新登录后发现修改的数据和后来输入的数据全没了。
如何解决这种问题?如果不加事物处理是不是不会产生这种问题?
如果表真被锁了如何让insert,update不成功(insert没用事物处理)?

解决方案 »

  1.   

    增删改本身就是隐式事务,当时显式定义是更好。在没有并发的时候单纯:select * from 表会锁表?你的默认隔离级别是多少?
      

  2.   

    在修改时用事物处理
    begin tran
    ......
    --COMMIT TRAN注释掉不提交
    如果是begin tran
    update other_column=...from table where primaryKey_column=...就会Key范围的独占锁,针对于page,object级别,各有个意向排他锁。
    要是你更新其他行当数据,或者新增行,是不受上面的Key范围锁排斥,即可以进行其他更新插入操作。当select * from table ,会对表进行一次table scan ,当搜索到前面正在更新的primaryKey_column就会处于等待状态,因为select * from table过程会先是要求page & object级别上的意向共享锁,由于primaryKey_column当前是独占状态,无法释放资源,导致select * from table 一直处于等待状态。而,select * from 表 with(nolock) 其实就是降低了事务隔离级别,也就是等效于
    set transaction isolation level read uncommitted
    允许读取未提交的事务。
      

  3.   

    情况是这样的有个存储过程:把事物处理注释掉结果begin tran忘注释了,所以造成了上面说的情况。
    以前也出现过数据录入正常,系统重登录后数据丢失的情况,一直没找出原因,是不是也是表被锁造成的,
    因为很多存储过程用了事物处理,现在把所有的事物处理注释掉了,不知还会不会出现数据丢失的情况。
      

  4.   

    在修改时用事物处理
    begin tran
    ......
    --COMMIT TRAN注释掉不提交
    因为修改表有2个,结果两个表都被锁了,造成的结果是使用了上面的存储过程后,后面操作的
    数据全会丢失,我试了好多次结果都是一样的,如何避免后面操作的数据不丢失,只回滚当前修改的数据?
      

  5.   

    可能你用了长连接,后面的插入都被认为是这个事务的,从数据库角度是必须回滚的。你这个是存储过程BUG引起的,没有讨论价值,检查所有存储过程消除这类错误就是了唯一可以吸取的就是抛弃长连接,改用短连接,免得一处BUG引起其他问题。
      

  6.   

    详细分析:
    1、显示事务未提交,数据库采用先写事务日志,后更新到磁盘的方式来处理事务,先修改某一行,数据会锁定该行,并给该行加一个独占锁,这个时候,数据库默认的事务机制是无法读取到这行,导致select * 读取失败,但是查询时加了with(nolock),就会忽视被锁定的行,从而手动提高了并发性。
    2、这个时候,insert并不会有问题,因为该锁定是行锁,或者页锁,只要不是架构锁或表锁,insert 都可以。update操作如果不是针对该行操作也可以执行,否则就必须等待这个事务提交并释放该行锁。
    3、系统退出后,数据不存在,证明这个事务被回滚,按照第一点的说法,就是数据先写到内存中,但是磁盘上面的数据还是未修改之前的,这个事务因为取消了,导致事务操作失败,数据依然是未修改之前的。如果不明白,可以看看数据库针对ACID属性的说明。