关于自增列引发的并发性问题

herosandro 2004-08-06 04:07:47
现象:
1、数据窗口提交时报sqlcode=-3 ;
2、对数据窗口中的数据进行修改或删除,后来却发现修改或删除到了其它的数据 ;
3、从数据窗口中取出自增列作为key进行其它操作,发现得到的数据并非自己想要的。

原因:
当一个数据窗口以自增列为key column,它在新增行后提交时,数据库产生一自增值,然后先写入数据库,再从数据库中提取出来放回datawindow,而提取的这个值是取最后生成的自增值,如果在产生与取回之间有其它的列插入,那么取值就会出错,并且是一种无法回避的错误。

解决方法:
1、将数据窗口的update属性为设为 “key and updateable columns”,数据不会被保存,但会出现“现象1”的问题,在并发性强的场合这种提示可用“频繁”来形容,很难被用户接受。
2、将数据窗口update属性为设为 “key”,数据可以被保存,但如果要在不重新retrive的情况下对datawindow中的数据进行操作的话,将出现“现象2”与“现象3”的问题;出现数据错误我想是每一个程序员都不能容忍的吧。
3、重新设计表结构与数据窗口,使用可控字段作为主键,能解决问题,但如果产品成型,改动太大。
4、……
还请大家一起来讨论有没有更好的解决办法。

...全文
243 点赞 收藏 6
写回复
6 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
herosandro 2004-08-09
添加更多的字段作为datawindow的key,确保这些字段不会全部相同,将datawindow的update属性设为 “key”(第一项) ,可避免修改与删除错误(遇到错误数据会提示sqlca.sqlcode=-3),也可避免将update属性设为"key and updateable columns" 时引起的新增时频繁报错;但请不要直接从datawindow中用getitemnumber取出自增列的值来进行操作,这样可能会取到错误的id而造成数据混乱。
我想这可能是最简单易行的修改方法,如果有朋友与我犯了同样的错误,我希望他能从该帖子中找到可行的方法。
谢谢各位朋友提出的意见,我将在明天结贴,希望大家在我结贴前再来这里做做客.
回复
10975037 2004-08-08
根据我们使用数据库的不同,我们还有一些其他的控制并发访问和修改的选择方案,如对数据加锁。锁是一个用户避免其他用户对指定行作修改的操作。在结束一个事务如执行commit,rollback,disconnect等语句时自动将锁释放。如果您使用的DBMS支持锁的操作,在Power-Builder的DataWindow设计时,Select语句可在from子句中加上with holdlock:即在data Window的SQL Window中,在表窗口的标题处点击右鼠标,弹出菜单的最后一个选项即为Holdlock。选择该项,生成的SQL语句将在re-trievel()函数执行后将所查询的数据加锁,以避免其他用户的修改访问,直至commit,rollback等事件发生后解锁。这种方式带来的问题是,当用户查询完数据后可能离开计算机长时间不用,这段时间内其他用户均无法修改数据。此外有些DBMS如Sybase等不支持行级锁,也就是说当你对某一行查询时更多的行都被上了锁,这就更增加了并发处理的局限性。另一个值得注意的问题是在多窗口应用中某一个窗口的事务提交将会导致使用一事务中其他数据窗口的查询行解锁,这时修改将可能发生错误。某些DBMS系统支持一个称作"时间戳(timestamp)"的数据项来控制并发性。每张表中都有一个时间戳的数据列,当Insert语句或Update语句对数据行作修改时该列自动被修改为当前时间。当你要作修改时,where子句可检查时间戳列在查询时和修改时两个值是否相符,以此来确保您作出的修改不会覆盖别人的修改,因此这种确认方式与key and Updateable Columns选项相同。即使两个用户对同一行的不同列作修改,后一个修改者也将失败。在常用的关系型数据库中Sybase和Microsoft的SQL Server支持时间戳的使用。而在PowerBuilder中,不管用户后台连接何种数据库,只要表中带有timestamp的列名且数据类型为datetime,PB将自动忽略Update characteristics的选项,而在where子句中生成主键和时间戳列的比较。
如果您所用的数据库不支持时间戳但支持触发器,您也可以在表中增加一列整数型的列。当有对表中某种记录作修改时,该列自动加1。下列使用的是Watcom数据库,对Shipper表增加Updcnt字段并作两个触发器,这样任何用户或进程试图修改某行记录时,该字段均可发生变化。
同理可编写UPDATE触发器。
在您的PowerBuilder应用之中,除表的主键外,必须再加上这一列作为检测列加入Update语句中的Where子句中,这样再作Update操作时,后台数据库会比较修改时与用户作Retrieve操作时数据是否相等,以确认是否能作修改。在DataWindows中在Specify Update Characteris-tics的对话框的右下角的Unique key column(s)中加上Updcnt一项,同时注意where clause中选择Key columns,这样PowerBuilder在构造where子句时就会认为Updcnt亦是表的主键,而成为检测项。
回复
lzheng2001 2004-08-07
基本同意楼主的做法
回复
鸡翅多 2004-08-06
那你就lock table
回复
herosandro 2004-08-06
是用的sqlserver,取到最后的key值有什么用,pb的数据窗口就是这么取的,也是这么错的
回复
鸡翅多 2004-08-06
你用的sqlserver?
我记的sqlserver里有一个功能可以取到最后的那个key值
回复
相关推荐
发帖
数据库相关
创建于2007-09-28

738

社区成员

PowerBuilder 数据库相关
申请成为版主
帖子事件
创建了帖子
2004-08-06 04:07
社区公告
暂无公告