简短的故事: 我有一个分区的 postgres 数据库,其中有一个表来跟踪分区和触发器。触发器需要更改分区表上的约束(它们的valid_date [daterange] 会根据另一个分区的valid_date 更改)并且最好能够删除表,但这会导致错误,因为触发器链正在使用这些表。
cannot ALTER TABLE "core_geometryrecord_8_2" because it is being used by active queries in this session
完整的问题: 我正在对我的模式和触发器架构进行彻底的解释,以防万一,或者有人想知道为什么我觉得需要一个“复杂”的系统,尽管它可能没有必要。
我正在重构一个大型几何数据数据库,以使其更容易和更快地使用。旧系统具有保存相关几何的“几何表”(美国的 IE 县)。数据实际上应该按“date_valid”和“geometrytable_id”分组。
我们决定使用带有 date_valid(日期范围)和 geometrytable_id(外键)约束的 postgres 分区。
因为日期很敏感,并且需要大量的簿记才能保持正确,所以我亲自尝试使用触发器管理大部分数据库(我已经知道我需要一个分区表的插入触发器,所以为什么不这样做)。
我设计了一组触发器来管理分区列表并在您插入或删除几何图形时进行所有簿记。这就是他们所做的。
- 在插入分区列表表时,创建分区表并应用约束。如果某个日期的 partitionvalid 与这个新的日期重叠(呼叫更新触发器),则修剪它。如果有一个分区在此日期之后的日期有效,则将新分区的结束日期修剪为下一个分区的开始日期(保持连续的时间线)。
- 从分区列表表中删除时,删除分区表。重新计算已删除分区(如果有)周围的 partition_list 条目(调用更新触发器)的日期范围,以使日期连续。
- 在更新分区列表表时,DROP OLD DATE CONSTRAINT,将分区表中所有行的 date_valid 更改为分区的新 date_valid 值,然后用新日期创建 DATE CONSTRAINT(约束是项目具有与分区完全相同的 date_valid )。
- 在插入geometryrecord(分区表)时,找到应该使用的分区,或者插入到分区列表表中(TRIGGERS ON INSERT)。将 NEW 插入正确的分区。
- 在从几何记录中删除时,如果分区表现在为空,则从分区列表表中删除分区条目(CALLS DELETE TRIGGER)。
如果我在链中的任何触发器中完全触摸过它,它就会因为试图以任何方式改变桌子而对我生气。如果我直接插入到该表中,分区列表表的触发器可以完美地工作,但是从几何表中删除(它调用相同的触发器)会翻转,即使它所做的只是一个选择(查看分区表是否为空)。插入分区几何表也可能导致问题,因为我必须删除约束才能更改行的 date_valid。
必须有一种方法可以做到这一点,我只是不明白。(我还必须使删除表变得更加被动,“将其标记为通过 cron 作业删除”,因为我无法从源自我要删除的表的触发器调用中删除该表。)
非常欢迎任何建议。我简直不敢相信没有人需要做这样的事情,所以我想我只是不知道我在做什么:)。