Ruby教程(五十一)- ActiveRecord基础(并发处理)

来源:岁月联盟 编辑:zhu 时间:2009-01-10

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

  在有多个处理同时访问同一个数据库的应用程序中,可能会出现这样的情况,因为一个处理更新了数据库中的行,而使得另一个处理中持有的数据变得陈旧了。例如,A和B先后从数据库中提取了相同的数据,并都做了修改,这时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的并发处理机制会有更深的了解。