Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 轨道3。嵌套事务。子块中的异常_Ruby On Rails_Activerecord_Transactions_Sqlite_Nested Transactions - Fatal编程技术网

Ruby on rails 轨道3。嵌套事务。子块中的异常

Ruby on rails 轨道3。嵌套事务。子块中的异常,ruby-on-rails,activerecord,transactions,sqlite,nested-transactions,Ruby On Rails,Activerecord,Transactions,Sqlite,Nested Transactions,为什么ActiveRecord在子块中出现异常后不回滚嵌套事务中的更改 以下是一些例子: 1. >> Client.transaction do ?> Client.create(:name => 'Pavel') >> Client.transaction do ?> Client.create(:name => 'Elena') >> raise ActiveRecord::Rollback >> end >> end => nil >> Client.all.

为什么ActiveRecord在子块中出现异常后不回滚嵌套事务中的更改

以下是一些例子:

1.


>> Client.transaction do
?>   Client.create(:name => 'Pavel')
>>   Client.transaction do
?>     Client.create(:name => 'Elena')
>>     raise ActiveRecord::Rollback
>>   end
>> end
=> nil
>> Client.all.map(&:name)
=> ["Pavel", "Elena"] # instead of []

>> Client.transaction do
?>   Client.create(:name => 'Pavel')
>>   Client.transaction(:requires_new => true) do
?>     Client.create(:name => 'Elena')
>>     raise ActiveRecord::Rollback
>>   end
>> end
=> nil
>> Client.all.map(&:name)
=> ["Pavel", "Elena"] # instead of ["Pavel"]
2.


>> Client.transaction do
?>   Client.create(:name => 'Pavel')
>>   Client.transaction do
?>     Client.create(:name => 'Elena')
>>     raise ActiveRecord::Rollback
>>   end
>> end
=> nil
>> Client.all.map(&:name)
=> ["Pavel", "Elena"] # instead of []

>> Client.transaction do
?>   Client.create(:name => 'Pavel')
>>   Client.transaction(:requires_new => true) do
?>     Client.create(:name => 'Elena')
>>     raise ActiveRecord::Rollback
>>   end
>> end
=> nil
>> Client.all.map(&:name)
=> ["Pavel", "Elena"] # instead of ["Pavel"]
谢谢

Debian GNU/Linux 5.0.6

Ruby 1.9.2

RubyonRails 3.0.1


SQLite 3.7.3.

我也有同样的问题,我可以准确地复制您的结果。如果我在外部块中启动ActiveRecord::Rollback,那么整个事务将回滚,否则,不会回滚任何内容

显然,当前版本的ActiveRecord不知道如何使用SQLite3执行嵌套事务,尽管ActiveRecord应该使用保存点实现嵌套事务,并且SQLite从3.6.8开始就支持保存点

作为ActiveRecord还不支持这一点的进一步证据,请尝试以下

> List.connection.supports_savepoints?
=> false
Ubuntu 11.04-纳蒂独角鲸

ruby 1.8.7(2010-04-19 patchlevel 253)[i486 linux],MBARI 0x8770,ruby企业版2010.02

RubyonRails 3.0.3

sqlite3 gem 1.3.3


SQLite 3.7.2

rails事务实现不使用数据库用于支持嵌套事务的保存点(或类似技术)。 真正的嵌套事务不受数据库本身的支持

例如:

begin -- starts transaction 1
  begin -- start transaction 2

    insert into something (foo) values ('bar');

  commit -- ends transaction 1
rollback -- is ignored
第一个
commit
rollback
总是关闭最多的事务

有一种方法,数据库实际上可以进行嵌套。这将使用前面提到的保存点。范例

只要事务处于打开状态,就可以在彼此之间嵌套任意多个保存点

对于rails本身,有一个陷阱:函数在事务中创建和包装自己。因此,您的第一个示例生成以下sql

begin  -- transaction.do
  begin  -- Client.create
    insert into clients ( name ) values ('Pavel')  -- Client.create
  commit  -- Client.create, closes the out-most transaction
  begin -- transaction.do
    begin  -- Client.create
      insert into clients ( name ) values ('Elena')  -- Client.create
    commit  -- Client.create, closes the out-most transaction
所以你的特例来得太晚了

您可以修补此问题,但必须针对每个连接适配器进行修补

附言:
您可能会被sql中的
--
弄糊涂。这些都是mysql中的单行注释。

我刚刚提交了一份关于这个问题的通知单:是的,尽管SQLite3支持保存点,但它们似乎还没有实现。然而,这一事实并没有反映在报告中,因此我感到困惑。谢谢你的关注。我发现MySQL在3.0.8中也有同样的行为。下面是一个非常酷的行为解释: