美文网首页Ruby
rails事务处理

rails事务处理

作者: biubiudog | 来源:发表于2018-11-12 15:17 被阅读0次

    一、属性

    transaction(options = {}, &block)   事务要么同时成功,继续往下走;要么同时失败,回滚。

    事务的4个属性(通常被称为ACID特性):

        原子性:一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。

        一致性:事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。

        隔离性:一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。

        持久性:持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。


    事务中包含多个不同的model,通常调用不同的model。

    事务绑定的是数据库,而非一个model 对象。

    只有对多个记录进行操作,并且希望这些操作是一个整体的时候,事务才有必要。

    Rails提供的事务,可以作为类方法,也可以作为实例方法调用。

    二、事务回滚

    事务回滚通过rollback实现,在rails中,rollback只会被一个Exception触发。很多事务块中的代码不会触发异常,即使出错,也不会触发异常。

    如:

    这是因为在rails中,update_attribute在调用失败也不会触发异常,只是简单的返回false,必须保证transaction块中在失败时会抛出异常。

    正确的写法是这样:

    注意:Rails 中约定,带有叹号的函数一般会在失败时抛异常。

    find_by, find_by_ 方法在查询找不到记录时,会返回nil,find方法在找不到记录时,抛出一个ActiveRecord::RecordNotFound 异常

    因为find_by并不会抛出异常,所以可以修改为:

    当错误出现时,事务本身会回滚,同时异常也会在外层抛出,因此,你的调用方法必须考虑 catch 这个异常,并进行相应的处理。

    有一个特殊的异常,ActiveRecord::Rollback,当它被抛出时,事务本身会回滚,但是它并不会被重新抛出,因此你也不需要在外部进行 catch 和处理。

    三、嵌套事务:

    Exception异常:

        抛出Exception异常时,子事务被回滚,同时,父事务也能捕获到此异常,因此,父事务也会被回滚。

    ActiveRecord::Rollback异常

    抛出ActiveRecord::Rollback异常时,子事务被回滚,但是异常不会被父事务捕获,父事务可以正常的执行。

    1.rollback回滚

    ActiveRecord::Rollback不会传播到上层的方法中去,因此这个例子中父元素不会接受到子元素抛出的异常。因为子事务块中的内容也被合并到了父事务中去,因此这两条 User 记录都会被创建。

    为了保证一个子事务的 rollback 被父事务知晓,必须手动在子事务中添加 :require_new => true 选项。比如下面的写法:

    事务是跟当前的数据库连接绑定的,因此,如果你的应用同时向多个数据库进行写操作,那么必须把代码包裹在一个嵌套事务中去。比如:

    2、Exception异常

     子事务出现异常,父事务捕获到异常,所以两个user创建语句都不会被执行

    四:事务相关的回调

    save和destroy方法被自动包裹在一个回调里,因此相关的回调 如:after_save 仍然属于事务的一部分,因此回调代码时也有可能被回滚。

    因此,如果你希望代码在事务外部执行的话,那么可以使用 after_commit 或者 after_rollback 这样的回调函数

    参考链接:ruby on rails 事务处理 - 简书

    相关文章

      网友评论

        本文标题:rails事务处理

        本文链接:https://www.haomeiwen.com/subject/jjmqfqtx.html