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

时间:2019-02-01 04:35:48

标签: ruby-on-rails ruby locking mariadb

这是我的课程:

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却可以工作。谁能解释为什么lock!不起作用?

1 个答案:

答案 0 :(得分:2)

#lock!使用SELECT…FOR UPDATE获取锁。
根据{{​​3}}。

  

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

您需要一个事务来保持一定行的锁。

尝试
console1:

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为您获取了一笔交易,因此您不需要明确的交易。

(这是PostgreSQL文档。但是我认为其他数据库也实现了类似的逻辑。)