摘 要:Web 应用 已由原来的网站、 电子 商务 发展 成商业应用系统的一种架构-B/S架构,它已成为一个世界性的 研究 热点。但由于Internet 网络 协议固有的局限性以及Web应用中频繁的用户交互增加了在Internet上实现长事务的困难, 从而,Web应用中的并发控制始终没能得到很好的解决。本文从Hibernate的乐观锁和悲观锁的实现原理出发,给出了实现悲观锁的基本思路和实现时的注意事项,在其它架构中得以推广和应用。[本站免费论文由中国论文联盟收集整理,转载请注明出处中国论文联盟http://www.lwlm.cn]
关键词:并发控制 Web应用 悲观锁 乐观锁
一、引言
B/S构架的应用越来越普及,但由于它有别于C/S构架的特殊性,并发控制始终没能得到很好的解决,如售票系统经常会出现同一张火车票出售多次的现象。典型的案例如下:
例如若有两个客户端,A客户先读取了账户余额2000元,之后B客户也读取了账户余额2000元的数据,A客户提取了500元,对数据库作了变更,此时数据库中的余额为1500元,B客户也要提取1300元,根据其所取得的资料,2000-1300将为700余额,若此时再对数据库进行变更,最后的余额700元就会不正确,应当是200元, 问题 的出现是由于两个客户对同一条数据进行并发访问造成的。
Web应用中并发控制的特殊性
上述问题在C/S构架中可以通过长事务来实现,但Web应用是基于Internet网络环境的,其中的并发控制有其内在的特殊性[1]:
(1)Web所基于的网络协议HTTP(Hyper Text Transfer Protocol)是一种无连接的协议,数据库服务器无法保存事务的状态信息;
(2)用户可以随时中止或启动浏览器中当前主页上的事务。
由于上述特殊性,Web应用中并发控制不能采用严格的长事务来实现,但可以长事务的思路来实现,在数据读取的时候把相应的数据锁定,在更新阶段把锁放开,然后更新数据。
二、Web应用中并发控制的实现
业务逻辑的实现过程中,往往需要保证数据访问的排他性。如在 金融 系统的日终结算处理中,我们希望针对某个cut-off时间点的数据进行处理,而不希望在结算进行过程中(可能是几秒种,也可能是几个小时),数据再发生变化。此时,我们就需要通过一些机制来保证这些数据在某个操作过程中不会被外界修改,这样的机制,就是所谓的“锁”,即给选定的目标数据上锁,使其无法被其他程序修改。有两种锁机制:即通常所说的“乐观锁(Optimistic Locking)” 和“悲观锁(Pessimistic Locking)”。
1.乐观锁(Optimistic Locking)
乐观锁(optimistic locking)则乐观的认为资料的存取很少发生同时存取的问题,因而不作数据库层次上的锁定,为了维护正确的数据,乐观锁定使用应用程序上的逻辑实现版本控制来解决。
并发控制时,数据不一致的情况一旦发生,有几个解决的 方法 ,一种是先更新为主,一种是后更新的为主,比较复杂的就是检查发生变动的数据来实现,或是检查所有属性来实现乐观锁定。
Hibernate通过版本号检查来实现后更新为主,这也是Hibernate所推荐的方式,在数据库中加入一个VERSON栏记录,在读取数据时连同版本号一同读取,并在更新数据时递增版本号,然后比对版本号与数据库中的版本号,如果大于数据库中的版本号则予以更新,否则就回报错误[2]( 135-137)。
以Hibernate实现版本号控制锁定的话,我们的对象中增加一个version属性,例如:
public class MyAccount {
private int version;
....
public void setVersion(int version) {
this.version = version;
}
public int getVersion() {
return version;
}
....
}
而在映像文件中,我们使用optimistic-lock属性设定version控制,属性栏之后增加一个标签,例如:
optimistic-lock="version">
设定好版本控制之后,在上例中如果B客户试图更新数据,将会引发StableObjectStateException例外,我们可以捕捉这个例外,在处理中重新读取数据库中的数据,同时将B客户 目前