大伙是如何解决C/S数据库中多人同时修改一条记录的?(100分)

  • 主题发起人 zhbforce
  • 开始时间
Z

zhbforce

Unregistered / Unconfirmed
GUEST, unregistred user!
请大伙多帮忙,俺是个新人。
我想知道大伙是如何解决C/s数据库中多人同时修改一条记录的,我在Oracle中找了
半天关于记录加锁的语句,可是一无所获。
希望提出实现代码和主要思想。
 
G

ggqq

Unregistered / Unconfirmed
GUEST, unregistred user!
select * from tb for update

会在选中的行上加行级锁

还可以 select * from tb for update with nowait 这样如果记录已经被锁住,就不等待,直接返回错误
 
E

expect

Unregistered / Unconfirmed
GUEST, unregistred user!
可以象 ggqq 说的那样做。
如果遇到特殊的限制需求的话,可以自己
建一个专门纪录锁信息的表,在模拟PV原语的原理
来实现它,当然,像你这样的问题,可以象 ggqq 说的那样做
既简单又方便。
或者可以用事物来控制也可以。
 
X

xdks_21cn

Unregistered / Unconfirmed
GUEST, unregistred user!
同意上边的兄弟
 
Z

zhbforce

Unregistered / Unconfirmed
GUEST, unregistred user!
你好,expect;
您能说的详细点吗? 俺听不大懂,什么叫专门纪录锁信息的表?
什么叫模拟PV原语的原理?
 

小猪

Unregistered / Unconfirmed
GUEST, unregistred user!
pv原语是操作系统的概念,主要是解决进程同步和异步的问题的。
我觉得用事务处理来实现比较不错,把这个事务放到数据库的一个
存储过程中,这样数据库可以自动处理有关记录锁定的问题。
当然,pv也不错。不过好象有点难为这位老兄了。
 
A

angshuangxi

Unregistered / Unconfirmed
GUEST, unregistred user!
用starttransaction ,commit,rollback行不行
 
T

terry_lzs

Unregistered / Unconfirmed
GUEST, unregistred user!
不过上面提到的那个语句好像是对oracle的,microsoft sql好像不支持这样的语句
请问microsoft sql应该怎解决这样的问题?
 
E

expect

Unregistered / Unconfirmed
GUEST, unregistred user!
microsoft sql是
Begin Transection
.
.
Commit
.
.
Rollback
 
Z

zhangkan

Unregistered / Unconfirmed
GUEST, unregistred user!
if DataBase.InTransaction then DataBase.Commit;
DataBase.StartTransaction;
try

except
DataBase.Rollback;
exit;
end;
DataBase.Commit;
只要你及时提交,就不会锁等待了.
 
Z

zhbforce

Unregistered / Unconfirmed
GUEST, unregistred user!
大伙的意思是sql server7 没有直接加锁的语句,只能支持事务处理,是吗?
如果在一个事务处理中不能处理所有的语句,也就是说发生错误的时候,比如说,
两个或多个用户同时修改同一条语句发生错误的时候,让事务自动回滚。
各位大侠,对吗?
 
Y

yh

Unregistered / Unconfirmed
GUEST, unregistred user!
用李维老师的原理,上面提到就是乐观锁定与悲观锁定的问题。

如果象ggqq所言,事先锁定记录,再修改,则为悲观锁定,
反之,不锁定,而直接改,再post,则为乐观锁定,如果用delphi
来开发应用,建议采用后一种锁定方法,用事务或midas相观的技术即可。
 
G

ggqq

Unregistered / Unconfirmed
GUEST, unregistred user!
To:terry_lzs

Sql Server 中利用TIMESTAMP 字段来解决这种问题。

当有任何修改时,TIMESTAMP的值都会改变,这样,当你试图修改别人已经改过的数据时,
WHERE 子句找不到你的TIMESTAMP字段的值,就会抱错,你就知道数据已经被别人改过了。

这是最经典的用法。
 
Z

zhbforce

Unregistered / Unconfirmed
GUEST, unregistred user!
大家说的好精彩啊!我都听得入迷了,ggqq能再解释一下timestamp,
给我一个sample,好吗?

yh: 你好,你说的悲观加锁与乐观加锁与ADO中的locktype中的加锁属性是一回事吗?

我有一个想法,这样来防止多人同时修改同一条记录:
1,当将表中的全部记录或一个子集显示给用户看的时候,这时并不进行任何的加锁处理。
2,当用户修改了记录集中的一条或几条时,就通过程序判断一下那几条记录被修改,
然后将用户修改的记录加上行级锁,提交修改。
3,提交事务。

zhbforce.
 
Z

zhbforce

Unregistered / Unconfirmed
GUEST, unregistred user!
To zhangkan:
你好,非常感谢你的帮助!
在数据库中用事务确实非常好,但是在同一网络中如果有太多的用户同时修改表的的
时候,可能会造成用户多次点击提交,而失败的事情发生。
太多的事务回滚是不是也会让人头疼?

Best Regards.
Zhbforce.
 
T

terry_lzs

Unregistered / Unconfirmed
GUEST, unregistred user!
to ggpp:
谢谢你,不过我在使用timestamp时有这样一个问题,一条记录我进行了一次修改,当
我再次进行修改的时候就会提示出错,例如:
adoquery1.edit;
adoquery1.fieldbyname('s').asstring:='ddd';
adoquery1.post;
中间可能经过了很多操作,但可以保证没有其他用户进行修改
adoquery1.edit;
adoquery1.fieldbyname('a').asstring:='fff';
adoquery1.post;
只要是同一记录就会出错,除非我进行了
adoquery1.active:=false;
adoquery1.active:=true;
而如果不用timestamp字段就不会出现这种情况,为什么客户端缓存中的数据不能和数据库
中同步,即我第一次对记录进行了修改,缓存中的timestamp字段能够和数据库中的该字段
一致,不会使得第二次修改因为该字段不同而使得服务器认为提交前其他用户已对记录进行
修改而使得第二次提交失败。
 
L

liuxiaouo

Unregistered / Unconfirmed
GUEST, unregistred user!
if not DataBase.StartTransaction then
DataBase.StartTransaction;
try

except
DataBase.Rollback;
exit;
end;
DataBase.Commit;
我就是这样处理的。没问题;
补充一句。用query更新,修改,增加并加上缓冲提交,
千万不要用Ttable控件。否则你的麻烦可大了;
 
Z

zhbforce

Unregistered / Unconfirmed
GUEST, unregistred user!
楼上的兄弟:
打扰一下? 可以简单地通过事务来解决所有的多人共同修改同一条记录吗?
 
C

caili314

Unregistered / Unconfirmed
GUEST, unregistred user!
SQL SERVER中可以使用HOLDLOCK,ROWLOCK来解决,就象ORACLE中FOR UPDATE一样
 
G

ggqq

Unregistered / Unconfirmed
GUEST, unregistred user!
To :terry_lzs

你修改完数据后,要记得再重新刷新数据,因为此时的timestamp已经改变,所以需要刷新。

其实,timestamp只是提供的一种方便的方法而已,其中心思想就是更改时的where子句的写法,看能不能定位。

WHERE子句有KEY,MODIFUED,ALL,ALL + timestamp这些种类。

你的问题只需要更新后及时刷新就可以。

另外,caili314说的方法也是对的,确实有这种写法。
 

Similar threads

D
回复
0
查看
730
DelphiTeacher的专栏
D
D
回复
0
查看
702
DelphiTeacher的专栏
D
顶部