源代码分析
首先看 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 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
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的作用是一样的。
Code
都是一样的!
这些对象的方面或类方面, 到最后都是转换成SQL,让数据库来执行, 如果明白这个,一切都变得简单了!
就从SQL而言 "model.transaction do" 只是执行 Begin, "end" 执行Commit. 对于MYSQL个别是引挚支持的存储点功能不在本文讨论范围之内。补充一下, 目前只是SQLServer支持事务嵌套,所以如果说ROR支持事务嵌套也就有点勉强!