为什么不锁!阻止别人更新?
Why doesn't lock! stop others from updating?
这是我的 class:
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!
in testing2
不锁定,而 with_lock
in testing 确实有效。谁能解释为什么 lock!
不起作用?
#lock!
使用 SELECT … FOR UPDATE 获取锁。
根据PostgreSQL doc。
FOR UPDATE causes the rows retrieved by the SELECT statement to be locked as though for update. This prevents them from being locked, modified or deleted by other transactions until the current transaction ends.
您需要一个事务来保持对某一行的锁定。
尝试
控制台 1:
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 文档。但我认为其他数据库实现类似的逻辑。)
这是我的 class:
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!
in testing2
不锁定,而 with_lock
in testing 确实有效。谁能解释为什么 lock!
不起作用?
#lock!
使用 SELECT … FOR UPDATE 获取锁。
根据PostgreSQL doc。
FOR UPDATE causes the rows retrieved by the SELECT statement to be locked as though for update. This prevents them from being locked, modified or deleted by other transactions until the current transaction ends.
您需要一个事务来保持对某一行的锁定。
尝试
控制台 1:
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 文档。但我认为其他数据库实现类似的逻辑。)