【发布时间】:2012-12-16 08:00:08
【问题描述】:
给定两个表:
-
Company[id, name, balance] -
Employee[id, name, company_id]
我想删除一家公司及其依赖项,但我不能自动删除,因为在我的实际项目中,一家公司有多个级别的依赖项,这些依赖项过于复杂,无法压缩到单个 SQL 语句中。此外,看看https://stackoverflow.com/a/5598275/14731,我不确定单个 SQL 语句是否是原子的。
相反,我这样做:
-
SELECT ... FOR UPDATE与公司相关的所有员工(锁定他们以防止在交易中修改) - 逐个删除每个员工
- 删除母公司。
有一个问题:如何防止在第 1 步和第 2 步之间插入引用公司的新记录? 根据https://stackoverflow.com/a/3602125/14731 SELECT ... FOR UPDATE 不会阻止插入。理想情况下,我想在 Company 上加一把锁,而不是每一种可能指向它的依赖项都加一把锁。
更新: 我有一个想法,但我不确定它是否有意义。
如果有人想要插入指向公司的新记录,他们可能需要查找它以确保它存在。如果我在第 1 步之前在公司上SELECT ... FOR UPDATE,它应该阻止他们的读取,从而延迟随后的插入。我有两个问题:
-
SELECT ... FOR UPDATE会阻止正常的SELECT查询吗?如果不是,我必须确保在查找公司时插入线程始终使用SELECT ... FOR UPDATE。 - 这种方法行得通吗?
【问题讨论】:
-
你不能把你的删除操作包装在一个事务中:开始事务,用一个语句删除所有员工,删除母公司,错误回滚,否则提交,结束事务?
-
您使用的是哪个 DBMS?甲骨文? PostgreSQL? DB2?
-
@LordPeter,在您删除所有员工和删除公司之间,没有什么能阻止另一个线程插入新员工。
-
@a_horse_with_no_name,我正在寻找与数据库无关的解决方案。如果这不可行,请随时提供特定于数据库的解决方案。
-
如果您只运行两个单一查询,那么插入新员工的机会将会降低。如果发生这种情况,那么您可能有 FK 约束,这将导致公司删除失败,因此您将回滚并重试。或者,只是级联公司删除以取出“孤儿”员工?程序方法很少是正确的方法。
标签: sql transactions sql-insert