最近在做数据库项目,遇到并行修改的问题。数据库sql,数据集adoquery,
属性
cursorLocation:clUseClient
cursorType:ctStatic
LockType:ltBatchOptimistic
如果 A B 都在访问同一条记录,A修改后更新没问题,此时B再更新就会出现“无法为更新定位行......”的错误,这问题应该怎么解决?如果需要自己加锁,有多少种锁,怎么加锁和解锁?还有怎么判定某一条记录有没有上锁呢?

解决方案 »

  1.   

    更新的数据多数是明细表的数据,用sql更新首先要定位,所以只能按行更新,不如批量更新来的快。
      

  2.   

    sql可以多个update一起提交,更可以一个update更改多条记录
    快肯定的sql快,关键是sql需要自己组织,批量是ado自动帮你组织成(其实也是通过sql)
      

  3.   

    如果用sql,像下面的明细表
    更改前:
    单据号   商品编码      数量
    100      aa            10
    100      bb            20
    100      cc            30
    ……
    更改后:
    单据号   商品编码      数量
    100      aa            15
    100      bb            31
    100      cc            28
    ……
    就只能每一行用一条set...where...语句,有100行就循环100次,相当繁琐。还有,能保证query读和sql更新之间的时间段,记录不被别人修改,甚至不被别人找到吗?例如有一条记录
    单据号   付款余额
    100      123元
    付款余额不能小于0(但数据库没有定义约束)A人query读:付款余额=123;
      B人query读:付款余额=123;
      B人sql:付款余额:=付款余额(123)-60;
             执行
    A人sql:付款余额:=付款余额(63)-70;
           执行
    (付款余额<0错误)
    或者
    A人query读:付款余额=123;
      B人query读:付款余额=123;
      B人sql:temp:=付款余额(123)-60;
             付款余额(63):=temp;
             执行
    A人sql:temp:=付款余额(123)-70;
           付款余额(53):=temp;
           执行
    (覆盖更新错误)sql能执行相应的语句,但结果都不是想要的结果。
      

  4.   

    后一种情况,sql更新也是会发生错误,并且这种错误是‘合法’的,数据库能做到,不会抛出错误,但不是我想要的结果。当然,规定‘只有一个人能修改’就能解决冲突,但只有一个人能修改的情况下,用sql更新比用ADO方法更新的优势已经没有了,反而显得繁琐。
      

  5.   


    你说的问题好像是类似 脏数据 的问题
    这种情况,应该通过一个锁定/互斥的机制来保证,无论sql更新还是ado更新,都是需要的
      

  6.   

    我相信delphi有相应的方法或者设置来应用这种机制,但我接触delphi的时间短,还不明白应该在哪里设置。网上转一圈都没个确切说法,大家都来说说嘛!
      

  7.   

    这个跟ado没有关系,是你使用的数据库来管理操作冲突的问题
    比如oracle数据库在操作的时候就提供了行锁定或者表锁定的选择,ado本身只是向数据库提交一个操作请求,如果担心这个问题的话可以用存储过程来实现数据的操作另外你可以试着用ado的事务处理,当出现冲突执行失败的时候让事务回滚,并给个提示,让操作人员重新操作一遍.
      

  8.   

    用TABLOCKX或者ROWLOCK。TABLOCKX可以select的时候直接加上,那么你这个表别的线程或者处理过程直接就读不了了,所以,你就独占了。
    ROWLOCK可以让你锁定一行,别的处理过程还可以读取表的其他行。
      

  9.   

    我试了一下这个方法,但用了rowlock后,别的query还是能搜索到这条记录第一条sqlselect * from 进货 with (ROWLOCK)
    where 单号='2'第二条sqlselect * from 进货运行时先开第一个,再开第二个。看看问题出在哪?
      

  10.   


    这样的话,你最好用表锁吧。如果你觉得不放心,那么在你的应用程序中做处理(你的意思就是有一个处理过程在读取数据之后别的过程不能读取的),用mutex就可以,反正都是同一时刻是有一个过程在处理数据库。另:如果你有很多的客户端在读取、处理数据,最好用表锁,因为你的客户端不可能都在同一台机器上运行,所以,锁只能在服务器侧做。
      

  11.   


    呃……不好意思,没看完,现在明白你的意思了。
    用READPAST可以跳过已经锁定的行。
      

  12.   

    我试了一下,有一个问题:似乎select语句的锁都只在本条查询过程中起作用,查询完毕就自动解锁了。如上图,我查询中进行锁表,但运行后查看企业管理器,test数据库的锁定模式还是S共享锁,我想要修改的这条记录,别人还是能找到,如下图。能不能做到select后就一直锁定这条记录直到释放呢?
      

  13.   

    这个问题跟DELPHI和ADO有关系吗?设计上的缺陷,需要在设计上来弥补。对于脏数据的处理,我想解决办法有很多了,没必要这么“执着”。
      

  14.   

    我想问下,用锁机制是通过事务或者存储过程锁定吗?我试过开始一个事务但未提交,select的锁定模式是行锁定,其他程序用带readpast搜索可以忽略锁定行,但更新非锁定行也无法更新,这也属于误锁定吗?
    互斥机制要怎么做?加一个bit类型的标识列吗?
      

  15.   


    普通打开,都是select的结果,
    如果用户想修改,按一个按钮,进入修改,此时,其它人无法再浏览,
    如果已经有其它人在浏览或修改,则本次“进入修改”失败,
    修改完毕,保存后退出“修改”,
    程序崩溃或断网,长时间后自动退出“修改”,此时程序(本崩溃而是断网后恢复)想保存,也无法保存了表+记录id+修改状态,专门通过一个表来维护