The Last Day Of Summer

.NET技术 C# ASP.net ActiveReport SICP 代码生成 报表应用 RDLC
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

在学习Rails中的并发处理的处理前,我们先简单了解下并发处理的概念。

在有多个处理同时访问同一个数据库的应用程序中,可能会出现这样的情况,因为一个处理更新了数据库中的行,而使得另一个处理中持有的数据变得陈旧了。例如,AB先后从数据库中提取了相同的数据,并都做了修改,这时B先将自己的修改更新会数据库,稍后,A将自己的修改更新回数据库,这时将会覆盖B所作的修改,当B再次提取数据库后,看到的是A修改的结果,而不是自己的。

一个解决办法就是将更新的表或者行进行锁定,防止其他程序进行更新或者访问,锁定可以完全避免并发的问题,也常称作悲观锁,但是在Web项目中,这个做法是行不通的,因为在同一个时间点上,可能会有很多个用户需要访问数据。

乐观锁并没有将数据锁定的外在表现,作为替代,在将修改写回到数据库之前,进行检查来确定一条记录是否已经被修改了。在Rails里的实现方法是,每和行都包含有一个版本号(version number),不管什么时候行被更新了,版本号就会被增加,当你在你的程序中进行一个更新操作时,Active Record检查行和Model的版本号,如果不匹配,将会放弃修改并抛出一个异常。

对于任何一个包含有integer型的字段lock_version的表,乐观锁都会默认的被启用,你可以把新行的这个字段初始为0,但是,如果你忘记了,Active Record也会替你完成。

我们来看看怎样实现乐观锁,我们创建一个名为counters的表:

create table counters (

id int not null auto_increment,

count int default 0,

lock_version int default 0,

primary key (id)

);

然后我给这个表创建一个行,将这个行读入到不同的Model中,并且在其中尝试更新,

class Counter < ActiveRecord::Base

end

Counter.delete_all

Counter.create(:count => 0)

count1 = Counter.find(:first)

count2 = Counter.find(:first)

count1.count += 3

count1.save

count2.count += 4

count2.save

当我们运行上面的代码,会得到一个异常,Rails会放弃count2所作的修改,因为其中包含的已经是脏数据了。

    如果使用了乐观锁,就需要在程序中处理这些异常,也可以禁用乐观锁:

ActiveRecord::Base.lock_optimistically = false

 

    关于乐观锁,可以参考Martin Flower所著的《企业应用解决方案及模式》一种中关于并发处理和工作单元(Work Unit)模式的内容,相信对Rails的并发处理机制会有更深的了解。