假设我们有两个表user
和book
。
在应用程序级别,为了确保数据完整性并避免竞争条件,我们在事务开始时锁定实体。
问题一:
假设在应用程序级别我们有两个请求同时运行:
请求 1(应用程序级别):
start trx
lock for update user with id 1
lock for update book with id 2
do changes
commit
请求 2(应用程序级别):
start trx
lock for update book with id 2
lock for update user with id 1
do changes
commit
可能会出现两个请求第一个锁都先于第二个锁申请的情况,即用户 1 的请求 1 锁和图书 2 的请求 2 锁,这将导致死锁。
我们怎样才能避免这种情况呢?我唯一的想法是在某个地方写下所有表的锁定顺序,user->book
并确保我们遵循它。
问题2:
如果我们在不同的请求中执行两个查询,以在突变之前锁定实体
- 要求1
SELECT * FROM user WHERE id IN [1,2] FOR UPDATE
- 要求2
SELECT * FROM user WHERE id IN [2,1] FOR UPDATE
这会导致僵局吗?例如,如果出于某种原因,一个查询将首先锁定用户 1,然后切换到请求 2,然后再返回锁定用户 2。