`
mlzboy
  • 浏览: 723805 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论
阅读更多

Rails 的 transaction 事务处理

程序开发 2009年11月10日 07:56

最近太做一个数据排名统计,统计过程中需要删除旧的缓存统计数据,最开始写的时候就直接 CachePostTotal.connection.execute("truncate table cache_post_totals") 先把这个表给重置了,然后再循环往里面插入新的统计数据。

但后面发现,这样的做法存在大问题:

  1. 当我 truncate table 的时候, cache_post_totals 表已经被清除了。但新的数据还没有存上去,如果在这个时候有人读取这张表时,就会找不到数据,这样是有问题的。
  2. 在中间插入新数据的循环中有可能会出现异常、Model验证不通过等情况而使得统计流程中断,但这个时候 cache_post_totals 表的数据已被改变。

要解决这个问题哪就要上 事务 了!

Rails ActiveRecord 对事务的处理实现的很方便,只用Model.transaction do ... end 将对 Model 表的操作的代码包起来就可以了,这样一来,在 transaction do .. end 之间的数据更新动作并不会立刻改变表里面的数据,而是要等到完全执行完成后,过了 end 才更新。

来看一下这一段例子:

begin
Post.transaction do
# 删除旧数据
Post.delete_all

# 例子 新数据
datas [{:title => "title1", :slug => "title-1"},{:title => "Title 2", :slug => "Title 2"}]
counter = 0
datas.each do |d|
post = Post.new(d)
if not post.save
raise "*** #{post.errors.full_messages}"
end
end
end
puts "=== Done"
rescue Exception => ex
puts "*** transaction abored!"
puts "*** errors: #{ex.message}"
end

 

另外有个小细节需要注意,如果你是使用 Model.connection.execute() 方法执行的语句,那么事务将不会起作用!

 

 

 

 

   
    这是一个老问题了, 也是做web开发必须要弄明白的, 其实是很简单的东西, 想想上学时被它搞得迷糊就觉得好笑!上班后做了开发, 渐渐明白, 共享一下, 希望对大家有所帮助!
   
    一 先说说http吧, 这个是web的根本大法

HTTP协议本身是无状态的,客户端只需要简单的向服务器请求,如:www.google.com/abc.html.服务器将文件内容返回给客户。无论是客户端还是服务器都没有必要纪录彼此过去的行为。然而人们很快发现如果能够提供一些按需生成的动态信息会使web变得更加有用,如www.google.com/search=美女。这种需求一方面迫使 HTML逐步添加了表单、脚本、DOM等客户端行为,另一方面在服务器端则出现了CGI规范以响应客户端的动态请求。 后来用户对WEB有了更高的要求, 如购物, 一个网络商店每天处理N个客户请求,当接到一个请求时,就需要知道这个客户在站点订了几个商品,有没有付款等。为此HTTP协议添加了cookie特性。cookie的作用就是为了解决HTTP协议无状态的缺陷所作出的努力。至于后来出现的session机制则是又一种在客户端与服务器之间保持状态的解决方案。
   引用网上朋友的用例(忘记URL了,不好意思):
   让我们用几个例子来描述一下cookie和session机制之间的区别与联系。X曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微乎其微,这时就需要某种方式来纪录某位顾客的消费数量。想象一下其实也无外乎下面的几种方案:
1、该店的店员很厉害,能记住每位顾客的消费数量,只要顾客一走进咖啡店,店员就知道该怎么对待了。这种做法就是协议本身支持状态。
2、发给顾客一张卡片,上面记录着消费的数量,一般还有个有效期限。每次消费时,如果顾客出示这张卡片,则此次消费就会与以前或以后的消费相联系起来。这种做法就是在客户端保持状态。
3、发给顾客一张会员卡,除了卡号之外什么信息也不纪录,每次消费时,如果顾客出示该卡片,则店员在店里的纪录本上找到这个卡号对应的纪录添加一些消费信息。这种做法就是在服务器端保持状态。
    由于HTTP协议是无状态的,而出于种种考虑也不希望使之成为有状态的,因此,后面两种方案就成为现实的选择。具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案。同时我们也看到,由于采用服务器端保持状态的方案在客户端也需要保存一个标识,所以session机制可能需要借助于cookie来达到保存标识的目的,但实际上它还有其他选择。注意session并不HTTP的内容,它是保存客户端状态的一种机制。
   
    二 理解cookie

    cookie简单来说就是服务器设置一些信息,将它存储在客户端, 就像上面的例子2。(客户端脚本如JavaScript或者VBScript也可以生成cookie,但是目的都是为了存储信息),当客户再次访问服务器时, 浏览器会带上cookies发送请求给服务器。浏览器处理cookies的是有规则的,只发送附和条件的cookies. 意思是,当访问麦当劳时,只需出示麦当劳的会员卡。
   
    三 理解session

    session其实更简单, 就像例子3,在客户端只有一个卡号,他每回来的时候,一出示卡号,服务器会查找当前卡号的信息,就知道他的状态了。它的实现可以用cookies,也可以用其它方法,如:作为查询字符串附加在URL后面。
    在谈论session机制的时候,常常听到这样一种误解“只要关闭浏览器,session就消失了”。其实可以想象一下会员卡的例子,除非顾客主动对店家提出销卡,否则店家绝对不会轻易删除顾客的资料。对session来说也是一样的,除非程序通知服务器删除一个session,否则服务器会一直保留,程序一般都是在用户做log off的时候发个指令去删除session。然而浏览器从来不会主动在关闭之前通知服务器它将要关闭,因此服务器根本不会有机会知道浏览器已经关闭,之所以会有这种错觉,是大部分session机制都使用会话cookie来保存session id,而关闭浏览器后这个session id就消失了,再次连接服务器时也就无法找到原来的session。如果服务器设置的cookie被保存到硬盘上,或者使用某种手段改写浏览器发出的 HTTP请求头,把原来的session id发送给服务器,则再次打开浏览器仍然能够找到原来的session。恰恰是由于关闭浏览器不会导致session被删除,迫使服务器为seesion设置了一个失效时间,当距离客户端上一次使用session的时间超过这个失效时间时,服务器就可以认为客户端已经停止了活动,才会把session删除以节省存储空间。
    
     
posted @ 2009-08-21 12:04 坏份子 阅读(41) | 评论(0) | 编辑

2009年7月14日 #

源代码分析

首先看 transaction 方法

ActiveRecord::Transactions Public Class methods
     # File vendor
/rails/activerecord/lib/active_record/transactions.rb, line 187
187:     def transaction(&block)
188:       self.class.transaction(&block)
189:     end

 可以看出他是调用类方法,类方法代码如下:

       # File vendor/rails/activerecord/lib/active_record/transactions.rb, line 75
      def transaction(
&block)
        increment_open_transactions

        begin
          #connection 
is kind of MysqlAdapter
          connection.transaction(Thread.current[
'start_db_transaction'], &block)
        ensure
          decrement_open_transactions
        end
      end

#connection.transaction call method 
in
# File vendor
/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb, line 58
      # Wrap a block 
in a transaction.  Returns result of block.
      def transaction(start_db_transaction 
= true)
        transaction_open 
= false
        begin
          
if block_given?
            
if start_db_transaction
              begin_db_transaction
              transaction_open 
= true
            end
            
yield
          end
        rescue Exception 
=> database_transaction_rollback
          
if transaction_open
            transaction_open 
= false
            rollback_db_transaction
          end
          raise unless database_transaction_rollback.is_a
? ActiveRecord::Rollback
        end
      ensure
        
if transaction_open
          begin
            commit_db_transaction
          rescue Exception 
=> database_transaction_rollback
            rollback_db_transaction
            raise
          end
        end
      end

 

 上面的代码即实现了rails中的transaction,可见ActiveRecord是不支持事务嵌套的。 如果模型使用的是相同的数据库, 那么用 ModelA.transaction 或 ModelB.transaction的作用是一样的。



      objecta.transaction do
        objectb.save
!
      end
  或者
      objectb.transaction 
do
        objecta.save
!
      end
  或者
      ModelA.transaction 
do
        objectb.save
!
      end

  都是一样的!

  这些对象的方面或类方面, 到最后都是转换成SQL,让数据库来执行, 如果明白这个,一切都变得简单了! 

就从SQL而言 "model.transaction do" 只是执行 Begin, "end" 执行Commit. 对于MYSQL个别是引挚支持的存储点功能不在本文讨论范围之内。补充一下, 目前只是SQLServer支持事务嵌套,所以如果说ROR支持事务嵌套也就有点勉强! 

 

原创  rails 多表事务 收藏

 

  1. def self.down  
  2.   ActiveRecord::Base.transaction do  
  3.     drop_table :users  
  4.     drop_table :roles_users  
  5.     drop_table :roles  
  6.     drop_table :static_permissions  
  7.     drop_table :roles_static_permissions  
  8.   end  
  9. end  
 

 

从上可以看到一种多个表同时操作的事情的方法

分享到:
评论

相关推荐

    rails敏捷开发的购物车系统

    在添加或删除商品时,更新购物车模型,并确保事务处理正确,以防止数据不一致。 在视图层,使用ERB(Embedded Ruby)模板语言来渲染HTML,展示商品列表和购物车内容。可以创建一个购物车组件(partial),在多个...

    Advanced Rails

    2. **复杂的路由**:Rails的路由系统允许灵活地定义资源和URL结构。高级Rails会讲解如何创建更复杂的路由规则,如命名空间、嵌套资源和条件路由。 3. **ActiveRecord高级用法**:ActiveRecord是Rails的ORM(对象...

    Rails进行敏捷Web开发(所有版本的源码rails3.0-4.0)

    2. Rails 3.1: 这个版本引入了Asset Pipeline,它管理应用程序的CSS、JavaScript和其他静态资源,提高了加载速度并支持压缩和合并。另外,它还引入了CoffeeScript和Sass作为默认的JavaScript和CSS预处理器,提升了...

    rails 3.2 API

    `,以及更强大的事务处理能力。 5. **ActiveResource**:这个组件用于构建RESTful客户端,连接到其他Web服务。虽然在后续版本中被逐渐废弃,但在Rails 3.2中仍然是可用的。 6. **ActionPack**:包含Action...

    Beginning Rails 4

    #### 第2章:入门指南 本章是针对不同操作系统(Windows、OS X 和 Linux)的安装指南,指导读者如何安装 Ruby、Rails 以及 SQLite 数据库。这一章节对于确保所有读者都在相同的技术平台上至关重要,为后续章节的...

    Ruby on Rails 指南 v5.0.1 中文版

    - **事务回调**:讨论如何在数据库事务中使用回调。 #### ActiveRecord关联 - **为什么使用关联**:解释关联对于简化数据库查询和提高代码可读性的重要性。 - **关联的类型**:列举各种关联类型,包括一对一、一对...

    rails配置sqlserver2000

    在实际开发中,可能还需要处理诸如时间戳类型转换、字符编码、事务处理等其他问题。此外,SQLServer 2000的安全性和性能可能已经落后,因此升级到更现代的版本,如SQLServer 2012或更高版本,可能会带来更好的开发...

    Rails3的ActiveRecord 查询API.doc

    在 Rails 2.x 中,许多使用哈希参数的查询方法如 `:conditions`, `:include`, `:joins` 等在 Rails 3.1 中被标记为过时,虽然在3.1版本中仍然可用,但计划在 Rails 3.2 中完全移除。这些变化主要是为了引入一个新的...

    Ruby-Rails实战之B2C商城开发

    订单状态的跟踪和管理是复杂部分,需要良好的数据库设计和事务处理以确保数据一致性。 5. 支付集成:与第三方支付平台如支付宝、微信支付的接口对接。Rails提供了OmniAuth等库进行身份验证,Stripe、PayPal等支付...

    influxdb-rails-源码.rar

    尽管InfluxDB本身不支持事务,但`lib/influxdb/rails/transaction.rb`文件通过模拟事务行为,确保在一组操作中的数据一致性。这在处理多个写入操作时尤为重要,可以避免因单个操作失败而导致的数据不一致。 最后,`...

    Rails相关电子书汇总二

    2. **Rails框架核心概念**:包括路由(Routing)、控制器(Controllers)、模型(Models)、视图(Views)和ActiveRecord,这些都是Rails开发的核心组件。 3. **数据库交互**:Rails使用ActiveRecord作为ORM(对象...

    rails 开发手册

    2. **Gemfile与依赖管理**:Rails使用Bundler来管理项目依赖,Gemfile用于声明项目所需的Ruby gems。手册将解释如何配置Gemfile,以及如何安装和更新gem。 3. **ActiveRecord**:这是Rails的ORM(对象关系映射)库...

    Agile Web Development with Rails中文版 3rd Edition

    **13.2 迭代I2: Exploring Strategies for Content** 探索了不同类型的国际化策略,以更好地适应不同语言环境。 #### 十四、任务T: 测试 这部分介绍了如何为Depot应用编写测试用例。 **14.1 加上测试** 介绍了...

    结合使用 Oracle 和 Ruby on Rails 教程

    2. **Ruby on Rails 框架**:Rails是基于Ruby语言的MVC(模型-视图-控制器)框架,以其DRY(Don't Repeat Yourself)原则和生产力著称。它简化了Web开发,提供了丰富的库和工具。 3. **JDBC驱动**:由于Rails默认...

    Pro Active Record. Databases with Ruby and Rails

    2. **Ruby on Rails与Active Record** - **集成方式**:在Rails中,Active Record是核心ORM(Object-Relational Mapping)组件,几乎所有的模型类都会继承自`ActiveRecord::Base`。 - **关联关系**:Active Record...

Global site tag (gtag.js) - Google Analytics