在这个sql语句中
INSERT INTO child (parentId, value) SELECT parentId, value FROM temptable
child.parentId
是指向parent.id
的外键。 parent
表中的行可能随时被删除,而这个长期运行的INSERT INTO
语句(可能插入几百万行)正在运行。
如果child
表在parent
之前没有相应的外键 INSERT INTO
语句开始运行,或parent
中有一行从child
引用的表已被删除而此INSERT INTO
正在运行,我希望INSERT INTO
默默地忽略该特定行(并且只是跳过插入child
违反外键约束的行,而不是整个语句失败。
我怎样才能做到这一点?我不熟悉在这种情况下任何竞争条件如何运作。
答案 0 :(得分:2)
您可以尝试在parent
中锁定表SELECT
的引用行:
INSERT INTO child (parent_id, value)
SELECT t.parent_id, t.value
FROM temptable t
JOIN parent p ON t.parent_id = p.id
FOR UPDATE OF p;
但请注意,如果表parent
同时被其他事务强烈修改,则此预防性锁定可能会显着增加执行时间。
作为补救措施,您可以考虑通过将数据划分为逻辑分区来执行多个事务中的插入,例如
INSERT
...
WHERE parent_id < 1000
INSERT
...
WHERE parent_id BETWEEN 1001 AND 2000 -- and so on.