Database 版 (精华区)
发信人: lizhenguo (夸父·追日), 信区: Database
标 题: 9
发信站: 哈工大紫丁香 (2001年09月26日18:40:07 星期三), 站内信件
并发控制
并发能力是指多用户在同一时间对相同数据同时访问的能力。一般的关系型数据库都具
有并发控制的能力,但是这种并发功能也会对数据的一致性带来危险。试想若有两个用户
都试图访问某个银行用户的记录并同时要求修改该用户的存款余额时,情况将会怎样呢?
我们可以对PowerBuilder中的DataWindow进行设置来进行并发控制。所谓并发控制就是
指在用户数据修改的过程中保证该数据不被覆盖或改变的方式,在下面的例子中我们将看
到如何设置DataWindow来控制开发访问。为了说明问题,我们举这样一个简单的银行系统
中的例子,某用户的存款状况如右:
我们假设事情的经过是这样的:公司的某员工在银行前台取款2,000元,银行出纳查询用户
的存款信息显示银行存款余额20,000元;正在这时,另一银行帐户转帐支票支付该帐户5,
000元,机器查询也得到当前用户存款20,000元,这时银行的出纳员看到用户存款超过了取
款额,就支付了客户2,000元并将用户存款改为18,000元,然后银行的另一名操作员根据支
票,将汇入的5,000元加上,把用户的余额改为25,000元,那么数据库管理系统是否可以接
受这些修改呢?
在DataWindows的设计中,我们选择菜单Rows|Update…,会出现Specify Update Charact
eristics的设置窗口,在这个窗口中我们设置Update语句中Where子句的生成,以此来进行
开发控制。在这里有三个选项,我们分别看一看在本例中这三个选项的结果:
(1)Key Columns:生成的Where子句中只比较表中的主键列的值与最初查询时是否相同来
确定要修改的记录。在上述的例子中,转帐支票的操作将覆盖出纳员作出的修改,这样银
行损失两千元。
(2)Key and Updateable Columns:生成的Where子句比较表中主键列和可修改列的值与最
初查询时否是相同。在上例中两次查询出的结果都是有两万余额,当第一个人修改余额时
,余额仍是二万元,所以修改成立,而支票转帐操作时余额已不是二万,所以该列不匹配,修
改失败。
(3)Key and Modified Columns:Where子句比较主键和将要修改的列,在本例中,结果与K
ey and Updateable Columns的选择相同,因为余额已改变,不再与最初的查询相同,因此
仍然不能修改。
让我们作另外一个假设,我们把银行后台作支票转帐操作改为冻结用户存款,即把状态字
段的值改为冻结,而且事件发生的次序如下表,那么表中的次序4…前台出纳的修改能不能
成立呢:
1.Key Columns:Where子句只比较主键值,显然出纳员的修改是允许的。
2.Key and Updateable Columns:生成的Where子句包括比较所有可修改的列,因此出纳修
改时Statue字段为冻结与出纳查询时的tive不符,修改失败,同时显示错误信息。
3.Key and Modified Columns:Where子句的比较包括主键和要修改的列,由于本列中修改
列仍为20,000元没有变化,所以出纳的修改可以成立。
在本例中,我们可以看到Key and Updateable Columns的选项最严格,可以避免出现状态
列发生改变时余额作修改的错误,但是这也会禁止我们作一些本当允许的并发修改,如出
纳修改存款余额,而业务员修改用户的联系地址等。因此我们应当根据实际情况,选择适
当的Update设置。
根据我们使用数据库的不同,我们还有一些其他的控制并发访问和修改的选择方案,如对
数据加锁。锁是一个用户避免其他用户对指定行作修改的操作。在结束一个事务如执行
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中,不管用户后台连接何种数据库,只要表中带有timest
amp的列名且数据类型为datetime,PB将自动忽略Update characteristics的选项,而在w
here子句中生成主键和时间戳列的比较。
如果您所用的数据库不支持时间戳但支持触发器,您也可以在表中增加一列整数型的列。
当有对表中某种记录作修改时,该列自动加1。下列使用的是Watcom数据库,对Shipper表
增加Updcnt字段并作两个触发器,这样任何用户或进程试图修改某行记录时,该字段均可
发生变化。
对INSERT触发器的编写如下:
DROP TRIGGER INS—SHIPPER’
CREATE TRIGGER SHIPPER BEFORE INSERT ON SHIPPER
REFERENCING NEW AS Newvalue
FOR EACH ROW
BEGIN
SET newvalue.UpdCnt=newvalue.UpdCnt+1;
END'
同理可编写UPDATE触发器。
在您的PowerBuilder应用之中,除表的主键外,必须再加上这一列作为检测列加入Update
语句中的Where子句中,这样再作Update操作时,后台数据库会比较修改时与用户作Retri
eve操作时数据是否相等,以确认是否能作修改。在DataWindows中在Specify Update Ch
aracteris-tics的对话框的右下角的Unique key column(s)中加上Updcnt一项,同时注意
where clause中选择Key columns,这样PowerBuilder在构造where子句时就会认为Updcn
t亦是表的主键,而成为检测项。
当数据窗口的Update函数被调用后,触发器将修改过记录中的Updcnt列表为新值,为保证
下一次修改能够有效,您应当立即作Retrieve()以使DataWindow缓冲区中Updcnt的值与数
据库相同。显然修改后立即查询的代价要比其他任何一种并
发控制的代价要小得多。
--
《列子·汤问》:“夸父不量力,欲追日影,逐之于隅谷之际。渴欲 得饮,赴饮河渭
。河渭不足,将走北饮大泽。未至,道渴而死。”
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.229.154]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.487毫秒