透明思考


Transparent Thoughts


Hack Rails的事务机制

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