如何在READ_COMMITTED隔离下阻止INSERT?

时间:2013-01-01 20:11:43

标签: sql transactions sql-insert

给出两个表:

  • Company [id, name, balance]
  • Employee [id, name, company_id]

我想删除一家公司及其依赖项,但我无法原子地这样做,因为在我的真实项目中,公司有多个级别的依赖项,这些依赖项太复杂而无法挤入单个SQL语句中。此外,查看https://stackoverflow.com/a/5598275/14731我不确定单个SQL语句是否是原子的。

相反,我这样做:

  1. SELECT ... FOR UPDATE与公司关联的所有员工(锁定它们以防止在事务中期进行修改)
  2. 逐个删除每位员工
  3. 删除母公司。
  4. 有一个问题:如何阻止在步骤1和2之间插入引用公司的新记录?根据https://stackoverflow.com/a/3602125/14731 SELECT ... FOR UPDATE不会阻止插入。理想情况下,我想锁定公司,而不是每种可能指向它的依赖关系锁定。

    更新: 我有一个想法,但我不确定它是否有意义。

    如果有人想要插入指向公司的新记录,他们可能需要查找以确保其存在。如果我在步骤1之前在公司上SELECT ... FOR UPDATE,它应该阻止他们的读取,从而延迟后续插入。我有两个问题:

    1. SELECT ... FOR UPDATE会阻止正常SELECT次查询吗?如果没有,我必须确保在查找公司时插入线程始终使用SELECT ... FOR UPDATE
    2. 这种方法会起作用吗?

1 个答案:

答案 0 :(得分:0)

以下是一种可能的解决方案:

  1. 插入新关联的主题应该在公司上建立一个读锁定(使用REPEATABLE_READ隔离或SELECT ... FOR SHARE
  2. 删除公司的线程应使用SELECT ... FOR UPDATE写入锁定行。
  3. 写锁定将等待释放所有未完成的读锁定,并防止在DELETE操作完成之前建立新的读锁定。