多人同时修改(并发)一张采购单据(单据数据从数据库的表里取出来),如何用锁防止数据不一致的情况?

nimeide1234567890 2013-03-19 12:45:39
procedure TFormKcspAdd.SpeedButton1Click(Sender: TObject);
begin
with ADOQuery1 do
begin
try
SQL.Clear;
strSql:='update table1 set ';
strSql:=strSql+'pname='''+Edit1.Text+''', ';
strSql:=strSql+'pmoney='''+Edit2.Text+''', ';
strSql:=strSql+'pnumber='''+Edit3.Text+''' ';
strSql:=strSql+'where bh='''+Edit10.Text+'''';
SQL.Add(strSql);
ExecSQL;

SQL.Clear;
strSql:='update table2 set ';
strSql:=strSql+'pamount='''+strtofloat(Edit2.Text)*strtofloat(Edit3.Text)+''' ';
strSql:=strSql+'where f_bh='''+Edit10.Text+'''';
SQL.Add(strSql);
ExecSQL;
except
end;
end;
end;

问题是这样的:
A取出一张单据修改,随后B也取出这张单据修改,B先保存,这个时候A也要保存,可是B已经修改了,那A得到的数据就与数据库内的数据产生了不一致,
有很多办法防止这种情况发生,那我现在只想知道用锁是怎么实现的(数据库是sql server 2000(2005,2008)),
有具体的例子或代码吗(不要理论,也不要粘贴的链接),或者如上代码如何改成锁,从而防止如上情况发生?
...全文
4510 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
meing1 2015-07-27
  • 打赏
  • 举报
回复
增加一列,列内保存更新时的服务器时间或为时间戳。读数据或开始修改时,读一下单据这一列的值,保存起来,此时称为值A。保存时,再读一下,此时称为值B。如A=B,则表示修改期间无人改,可以保存。如A<B,则表示有人改过,不能保存。
doloopcn 2014-12-01
  • 打赏
  • 举报
回复
楼猪的意思是不是多人协同把一个单据填写完? 如果是的话:用ID作为唯一标识,把字段分配好给每个修改的人:如张三员工负责修改字段ABC,李四员工负责修改DEF。 编辑完之后: 张三保存:update thetable set 字段A,字段B,字段C where id=?? 李四保存:update thetable set 字段d,字段e,字段f where id=??
ilovemovieboy 2014-11-08
  • 打赏
  • 举报
回复
不能理解现实中有这种业务:多人需同时修改同一张单据。
tyoui17 2014-11-07
  • 打赏
  • 举报
回复
感觉这是一个业务问题而不是技术问题啊。 如果非要多人操作同一个单子的话,为了保证所有人看到的数据是一致的吗,可以在用户读取数据的时候就加上标示,该用户可写,后来者只能读不能写。当那个第一读取数据的用户退出页面的时候,清除他的标示,下一个进入的人再写上标示。
ppluming 2014-11-06
  • 打赏
  • 举报
回复
ADOQueryTmp.Connection.BeginTrans; try //原功能代码 finally ADOQueryTmp.Connection.CommitTrans; end;
ppluming 2014-11-06
  • 打赏
  • 举报
回复
AB两个人进入数据库的时候,在客户端,直接用事务来处理,就完事了~
lyhoo163 2014-11-05
  • 打赏
  • 举报
回复
抱歉上面有误:就为 这个问题,要分类处理: 1、先将修改前的记录保存; 2、在修改后,提交前再读取一次数据: A::如果前后数据未变,执行变更; B::如果数据已变,保存新的数据,提示数据已变,重新修改。 3、循环进入2。
iamduo 2014-11-05
  • 打赏
  • 举报
回复
业务上,谁开的单子,(在被审核前),谁才有权限修改。 不存在有两个人同时修改一张单据的情况。 就算有,也是A操作上半页,B操作下半页。 其实,也是两张单子。 新增的就不说了,肯定不需要锁。。。 那么,你的业务是否健全呢?
lyhoo163 2014-11-02
  • 打赏
  • 举报
回复
这个问题,要分类处理: 1、先将修改前的记录保存; 2、在修改后,提交再读取数据: A::如果数据未变,执行变更; B::如果数据未变,保存新的数据,提示数据已变,重新修改。
编程保姆 2014-11-02
  • 打赏
  • 举报
回复
从管理角度来说,如果多人去修改一个记录,则是很混乱的事情,在数据库层面,谁最后保存以谁的为准,不必 锁什么的,这样只会搞累人。
zl54 2014-06-06
  • 打赏
  • 举报
回复
select for update
liangpei2008 2014-05-12
  • 打赏
  • 举报
回复
上悲观锁,乐观锁改动量要大一些。 如果业务允许,把业务上的并行操作转为串行操作,即在打开单据时就上锁,并为锁设置生命周期。
鹏程万li 2014-05-12
  • 打赏
  • 举报
回复
引用 13 楼 zbdzjx 的回复:
[quote=引用 12 楼 ITpengcheng 的回复:] [quote=引用 11 楼 tcmakebest 的回复:] 这个问题不是数据库本身的问题,用锁是解决不了的,我觉得这样解决比较好: 增加一个更新时间字段,每次保存的时候这个字段就写入当前时间,但同时必须提供上一次的时间,如果正确就保存,这样就保证了后者需要重新获取时间记录,才能保存。
这样不行吧!我现在是使用这个方法,理论让应该是如果我是A,另一个用户是B,我A新增了一张单据,B登录系统将这张单据继续编辑,你说这个逻辑对吗? 还有如果我有点击保存了这张单据,如果没有关闭当前单据,那别的用户怎么修改? 应该是同一个单据只能有一个人进入编辑,而且是这张单据应该是我正在新增的时候,别人不能进行修改,但是有时我单据会不关闭,或者是电脑死机,无意中关闭,等情况应该如何做?[/quote] 通常情况下,都是在保存时判断是否正确。也有的系统是点了修改后,其他人都只能看不能改。 1、保存时判断:可以在记录中增加一个修改时间字段,在读此记录时,也读取出来,保存时判断一下这个字段是否一致,如果一致,就保存,并更改这个字段为当时时间;如果不一致,就提示错误,提示已经被人修改了。 2、只能一个人修改:在记录中增加一个字段存放当前用户账号,要修改时,先看这个字段是否为空,如果为空,可修改;如果不为空,不可修改。为了防止意外,可以不断的判断用户是否在线,如果不在线,删除掉这个字段中此用户的资料。[/quote] 方法二可行
英年渐肥 2014-05-04
  • 打赏
  • 举报
回复
我想这必须考虑业务需求。A和B修改的业务逻辑是否正确,如果两者修改都是正确,则都应该有修改权限。此外就是每个人保存时是否查找自己修改记录的原始记录,如果没有则是否应该进行提示,否则数据进行保存并以最后保存为准。另外系统应该设定一个数据保护机制,记录的建立者之外的人是否可以修改记录。记录的审定等。有数据库的锁来决定记录是否能修改并不能达到这种需求。也不应该交予数据库来实现业务需求。
zbdzjx 2014-04-22
  • 打赏
  • 举报
回复
引用 12 楼 ITpengcheng 的回复:
[quote=引用 11 楼 tcmakebest 的回复:] 这个问题不是数据库本身的问题,用锁是解决不了的,我觉得这样解决比较好: 增加一个更新时间字段,每次保存的时候这个字段就写入当前时间,但同时必须提供上一次的时间,如果正确就保存,这样就保证了后者需要重新获取时间记录,才能保存。
这样不行吧!我现在是使用这个方法,理论让应该是如果我是A,另一个用户是B,我A新增了一张单据,B登录系统将这张单据继续编辑,你说这个逻辑对吗? 还有如果我有点击保存了这张单据,如果没有关闭当前单据,那别的用户怎么修改? 应该是同一个单据只能有一个人进入编辑,而且是这张单据应该是我正在新增的时候,别人不能进行修改,但是有时我单据会不关闭,或者是电脑死机,无意中关闭,等情况应该如何做?[/quote] 通常情况下,都是在保存时判断是否正确。也有的系统是点了修改后,其他人都只能看不能改。 1、保存时判断:可以在记录中增加一个修改时间字段,在读此记录时,也读取出来,保存时判断一下这个字段是否一致,如果一致,就保存,并更改这个字段为当时时间;如果不一致,就提示错误,提示已经被人修改了。 2、只能一个人修改:在记录中增加一个字段存放当前用户账号,要修改时,先看这个字段是否为空,如果为空,可修改;如果不为空,不可修改。为了防止意外,可以不断的判断用户是否在线,如果不在线,删除掉这个字段中此用户的资料。
鹏程万li 2014-04-22
  • 打赏
  • 举报
回复
引用 11 楼 tcmakebest 的回复:
这个问题不是数据库本身的问题,用锁是解决不了的,我觉得这样解决比较好: 增加一个更新时间字段,每次保存的时候这个字段就写入当前时间,但同时必须提供上一次的时间,如果正确就保存,这样就保证了后者需要重新获取时间记录,才能保存。
这样不行吧!我现在是使用这个方法,理论让应该是如果我是A,另一个用户是B,我A新增了一张单据,B登录系统将这张单据继续编辑,你说这个逻辑对吗? 还有如果我有点击保存了这张单据,如果没有关闭当前单据,那别的用户怎么修改? 应该是同一个单据只能有一个人进入编辑,而且是这张单据应该是我正在新增的时候,别人不能进行修改,但是有时我单据会不关闭,或者是电脑死机,无意中关闭,等情况应该如何做?
tcmakebest 2013-04-04
  • 打赏
  • 举报
回复
这个问题不是数据库本身的问题,用锁是解决不了的,我觉得这样解决比较好: 增加一个更新时间字段,每次保存的时候这个字段就写入当前时间,但同时必须提供上一次的时间,如果正确就保存,这样就保证了后者需要重新获取时间记录,才能保存。
山东蓝鸟贵薪 2013-03-22
  • 打赏
  • 举报
回复
并发有时是个难处理的问题 有时因为外部问题,修改记录时死机了锁定标志没有修改、 百再进来一位要修改这条记录,老提示[锁定状态]不可修改,、 这个问题就不太好处理 的
zbdzjx 2013-03-22
  • 打赏
  • 举报
回复
之前有看到过,说是ADO是先将修改前的记录保存,在修改完后,提交时,先判断数据库中的记录与之前保存的记录是否一致,如果不一致,则表示有人改过了,提示错误。
「已注销」 2013-03-22
  • 打赏
  • 举报
回复
如果要避免脏读后的修改, 设数据 d = 3 用户a读取 用户b读取 用户a修改为4,提交 用户b修改为5,提交 这是b读的数据是脏数据,,如果要避免脏读,我提供一个思路: 针对一笔单据,提供一个GUID或时间戳,读取的时候,时间戳也读取过来了,修改完提交的时候,先做数据库事务锁定,然后读取最新的时间戳,比对先前读取的时间戳,若相同,表示没有被他人修改过,则可以提交,否则不能提交。 这是逻辑上的乐观锁,也避免了脏读。 如果不管脏读的情况,就无所谓了。 最坏的情况是逻辑上的悲观锁,就是在读取数据的时候就把数据加锁,直到修改提交完成。这种锁肯定不太合理,会把数据库冻住。
加载更多回复(7)

2,497

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧