代码之家  ›  专栏  ›  技术社区  ›  Henry Yang

为什么不锁门!阻止其他人更新?

  •  1
  • Henry Yang  · 技术社区  · 6 年前

    class Plan < ActiveRecord::Base
      def testing
        self.with_lock do
          update_columns(lock: true)
          byebug
        end
      end
    
      def testing2
        self.lock!
        byebug
      end
    end
    

    我打开了两个rails控制台。

    在第一个控制台中:

    p = Plan.create
    => (basically success)
    p.id
    => 12
    p.testing2
    (byebug) # simulation of halting the execution,
    (BYEBUG) # I just leave the rails console open and wait at here. I expect others won't be able to update p because I still got the lock.
    

    在第二个控制台上:

    p = Plan.find(12)
    => (basically said found)
    p.name = 'should not be able to be stored in database'
    => "should not be able to be stored in database"
    p.save!
    => true # what????? Why can it update my object? It's lock in the other console!
    

    lock! 在里面 testing2 不锁的时候 with_lock 不起作用?

    1 回复  |  直到 6 年前
        1
  •  2
  •   s sato    6 年前

    #lock! 使用“选择更新”获取锁。
    PostgreSQL doc .

    FOR UPDATE导致SELECT语句检索到的行被锁定,就像FOR UPDATE一样。这可以防止它们被其他事务锁定、修改或删除,直到当前事务结束。

    尝试

    Plan.transaction{Plan.find(12).lock!; sleep 100.days}
    

    控制台2:

    p = Plan.find(12)
    p.name = 'should not be able to be stored in database'
    p.save 
    

    #with_lock 为您获取一个事务,因此您不需要显式事务。