Rails 中的事物處理

1. 使用事物的緣由數據庫

保證數據一致性, 當其中出現一個失敗的時候,操做能夠回滾app

好比:框架

ActiveRecord::Base.transaction do 
    david.withdrawal(100) # withdrawal失敗必須觸發 exception
    mary.deposit(100) # deposit失敗必須觸發 exception
end

return false 不會出發操做回滾, 因此事物中要使用!的方法, 好比 save! update!ide

before_save 等callback也包含在事物中, 若是但願觸發事物回滾, 須要能拋出異常測試

若是不希回滾則不拋出異常 或者放在事物以外 用after_commit等callbacl來處理spa

事務陷阱

不要在事務內部去捕捉 ActiveRecord::RecordInvalid 異常。由於某些數據庫下,這個異常會致使事務失效,好比 Postgres。一旦事務失效,要想讓代碼正確工做,就必須從頭從新執行事務。翻譯

另外,測試回滾或者事務回滾相關的回調時,最好關掉 transactional_fixtures 選項,通常的測試框架中,這個選項是打開的。rest

常見的事務反模式

  1. 單條記錄操做時使用事務
  2. 沒必要要的使用嵌套式事務
  3. 事務中的代碼不會致使回滾
  4. 在 controller 中使用事務

 

Exception handling and rolling back (待翻譯)

Also have in mind that exceptions thrown within a transaction block will be propagated (after triggering the ROLLBACK), so you should be ready to catch those in your application code.code

One exception is the ActiveRecord::Rollback exception, which will trigger a ROLLBACK when raised, but not be re-raised by the transaction block.blog

Warning: one should not catch ActiveRecord::StatementInvalid exceptions inside a transaction block. ActiveRecord::StatementInvalid exceptions indicate that an error occurred at the database level, for example when a unique constraint is violated. On some database systems, such as PostgreSQL, database errors inside a transaction cause the entire transaction to become unusable until it's restarted from the beginning. Here is an example which demonstrates the problem:

# Suppose that we have a Number model with a unique column called 'i'.
Number.transaction do
  Number.create(i: 0)
  begin
    # This will raise a unique constraint error...
    Number.create(i: 0)
  rescue ActiveRecord::StatementInvalid
    # ...which we ignore.
  end

  # On PostgreSQL, the transaction is now unusable. The following
  # statement will cause a PostgreSQL error, even though the unique
  # constraint is no longer violated:
  Number.create(i: 1)
  # => "PGError: ERROR:  current transaction is aborted, commands
  #     ignored until end of transaction block"
end
相關文章
相關標籤/搜索