我们有一个具有多个批次的应用程序,其中一些批次导入了大量数据,并且我们使用drop / create。 这些数据存储在postgresql 9.4中,删除花费了太多时间,因此要正常工作,我们选择在批处理开始时删除外键约束,然后在结束时重新创建它们。
但是我们必须处理死锁...在批处理过程中,某些客户端想要发布数据,并且该帖子会自动运行更新。 在创建过程中或放开约束时会发生“死锁”。
实际上,我们尝试了很多事情,并且发现了一些有趣的事情。 我已经阅读了近90%的有关postgresql锁定模式的文档。现在我知道僵局在哪里(我认为),几乎在什么时候出现。.
我们做一个变更表(批量做):
alter table A add CONSTRAINT fk_A_B FOREIGN KEY (id_B) REFERENCES B (id) NOT VALID;
要么 :
àlter table A drop constraint fk_A_B
客户端的帖子运行此更新:
UPDATE B SET colunmofb= ?, DATE_NOTIF = now() WHERE CAST(columndatetime AS DATE) = CAST(? AS DATE) AND x= ? AND 1 <= (SELECT count(B.id) FROM B INNER JOIN A a ON a.id_B = b.id ... other inner join and where clause
实际上,我已经添加了not valid
来更快地创建fk约束,但是当应用程序发送放置/创建请求时,我们可能会在客户端发布帖子时处理死锁,而这恰恰是在UPDATE
时。
我认为这是在很短的时间内出现的..当我们在表A上drop/create constraint
引用B且UPDATE
作为开始但尚未在子查询中选择数据时?那是真的还是我完全错了?
但是为什么它出现在掉落约束上? 我在postgresql网站上的放置限制期间找不到关于锁定模式的任何信息..我认为放置需要在放置限制之前访问引用表以执行一些操作,这是真的吗?如果是真的,该如何避免死锁?
有什么要求吗? 谢谢;)
编辑1:我读到一些有关fk_constraint涉及的触发器约束的内容,并写道我们需要在表上使用ExclusiveLock,因为以一种方式,它会删除表A的触发器,该触发器负责在插入中进行验证,并在表中的触发器上进行验证B负责对删除进行验证,以告知“此行不能删除,因为一个或多个行引用了此行” 我不知道这是真的吗?
编辑2:我验证了,就是这样,当运行带有外键约束(更改或添加约束)的alter表时,postgresql将等待在两个表上锁定accessExclusive
。因此,潜在的僵局非常重要。即使这段时间确实很短,也会出现死锁。
因此,在Postgres 9.4上用外键删除约束完全不安全。但是我无法解释我为什么postgres需要引用表上的这个独占访问锁
PS:很抱歉我的英语写得很快,因为我真的需要一个答案:/