- ActiveRecord不支持嵌套事务。
- 为了简单我们在ApplicationController里做了个filter,于是所有POST/PUT/DELETE的action都被包裹在一个事务里,事务边界是整个请求。
- 偏偏有时候你希望让某个操作中的某个部分不被包含在事务里。原因是当某些操作同时进行,你想看到的不是原子的结果,而是所有同时进行的操作汇总的最终结果
- 比如说,“审核改进措施”这个操作中包含了“重新算分”。
- 某企业有两项改进措施R1和R2,分别对应考核类别C1和C2。C1的原始分数是98,C2的原始分数是89。
- R1能给C1加回1分,R2能给C2加回11分。也就是说审核R1之后C1变成99分,审核R2后C2变成100分。
- 但,“重新算分”是在整个“审核”的事务之中的,于是如果R1和R2同时审核,你一定会看到下列两种原子结果之一:
- C1 99分,C2 89分;或者
- C1 98分,C2 100分。
- 其实这个时候我们不想让“重新算分”跟“审核”成为原子操作,我们希望把“算分”从“审核”的事务里拿出来,这样最后一次算分一定能体现最终的分数状态。
- 可以开一个线程或者进程(比如Kernel.system)把算分的逻辑分出来。
- 因为可以确定“算分”不会跟“审核”发生死锁,所以把这个线程join起来。
- 一定要小心,要是算分跟审核修改到同一条数据那么就会死锁…因为审核等待算分线程结束,而算分线程等待审核交出数据锁。
- 多个算分线程之间是不会死锁滴…为了确保时序可以一上来就锁自己最后要更新的分数记录。