离线并发的来源
在
Web
项目中,离线并发显得尤其严重。例如,用户
A
和用户
B
同时修改数据库中的某张表的
R
行,加入
R
行有两个字段分别是
C1
,
C2
。
假如按照如下过程修改:
1
用户
A
将数据
R
(
C1,C2
)读取到
A
的浏览器中。
2
用户
B
将数据
R
(
C1,C2
)读取到
B
的浏览器中。
3
用户
A
在浏览器上将数据修改为
R
(
C1’
,
C2
),同时更新到数据库。
4
用户
B
在浏览器上将数据修改为
R
(
C1
,
C2’
),同时更新到数据库。
上述过程存在两个问题,第一,第
4
步
B
在修改数据的时候数据库中的数据和
B
的浏览器中数据已经不一致了;第二,如果程序按照哪个字段变化在数据库中更新哪个字段的方式处理的话,那么经过上述四步修改,数据库中
R
行的内容是(
C1’,C2’
),这和
A
或者
B
的想法都不同(
A
认为是(
C1’
,
C2
),
B
认为是(
C1
,
C2’
))。
上述过程中
A
对数据库的修改过程或者
B
对数据库的修改过程,都是无法根据数据库的最新内容做修改,所以成为离线。
A
和
B
同时对记录
R
进行就该叫离线。
以上的环境叫离线并发。
那么如何解决离线并发过程中遇到的问题呢?我们引入锁机制。
锁机制
锁机制,就是在需要修改的数据上加互斥锁,通过互斥锁避免数据被同时修改。锁机制更具其应用环境又分为乐观锁和悲观锁
乐观锁
乐观锁,指认为冲突很少发生,所以只是在数据修改的时候比较修改的基础数据和数据库中的数据是否相同,相同则修改,否则提示用户重新装入数据库中已经变化的数据。
实现方法
1
:在进行
update
的时候使用
where
条件,在
Where
标间中比较所有上一步中查询得到的数据。如果数据库中的数据没有变化,则
update
可以更新到内容,否则
update
语句不能更新到内容,可以根据
update
的返回值确定更新是否成功。
实现方法
2
:在每一个表中追加一个特殊字段,类型为
timestamp
,每次更新的时候比较这个字段的值是否一致,如果一致,则更新,同时将这个字段更新为当前时间,否则,说明数据已经变更。这也可以使用
update
加上
where
实现。
悲观锁
悲观锁指,需要修改的数据,在读取的时候就对数据加锁,其他用户在准备修改,读取数据的阶段判断数据是否上锁,以此来决定是否进行修改前的读操作。
实现方法:
通常在数据库中建立一张
lock
表,该表的字段包括,表明,唯一索引,时间,用户信息等。
在用户读取数据准备修改的时候,首先判断
lock
表中是否存在自己将要读取的数据。
如果不存在,则在
lock
表中添加一条记录,记录对那张表的哪行数据进行修改;如果存在,在判断时间字段是否超时。
如果超时,则更新
lock
表中本条记录的时间字段。(防止死锁的必要手段)
如果存在,也不超时,说明本条记录正在被其他用户修改,则返回并发信息。
出处:http://blog.csdn.net/struts2/archive/2007/08/14/1742686.aspx