简短故事: 我有一个分区的postgres数据库,带有一个表来跟踪分区和触发器。触发器需要改变分区表上的约束(它们的valid_date [daterange]根据其他分区的valid_date而改变)并且最好能够删除表,但这会导致错误,因为触发链正在使用这些表'。
cannot ALTER TABLE "core_geometryrecord_8_2" because it is being used by active queries in this session
完整问题: 我正在全面解释我的架构和触发架构,以备需要或有人想知道为什么我觉得需要一个'复杂'系统,尽管可能没有必要。
我正在重构几何数据的大型数据库,以便更轻松,更快速地使用。旧系统具有“几何表”,其中包含相关的几何形状(美国的I.E.Counties)。数据应该按“date_valid”和“geometrytable_id”进行分组。
我们决定在date_valid(日期范围)和geometrytable_id(外键)上使用带有约束的postgres分区。
因为日期是敏感的并且需要大量的簿记才能保持正确,所以我亲自尝试用触发器管理大部分数据库(我已经知道我需要为分区表插入一个触发器,为什么不呢) 。
我设计了一组触发器来管理分区列表,并在插入或删除几何图形时完成所有簿记。这是他们的所作所为。
如果我在链中的任何触发器中完全触摸它,我会一直生气地试图以任何方式改变表格。如果我直接插入到该表中,分区列表表的触发器将完美地工作,但是从几何表(调用相同的触发器)中删除即使它所做的只是一个选择(查看分区表是否为空),也会翻转。插入分区几何表也可能导致问题,因为我必须删除约束才能更改行的date_valid。
必须有一种方法可以做到这一点,我只是不明白。 (我还必须删除表格更加被动'将其标记为由cron作业删除',因为我无法从源自我要删除的表的触发器调用中删除该表。)
非常欢迎任何建议。我简直无法相信没有人需要做这样的事情,所以我想我只是不知道我在做什么:)。
答案 0 :(得分:1)
因此,在挖掘并尝试之后,我想出了我需要的东西,并认为我会记录我的发现。
以下是关于基本postgres分区如何为感兴趣的人工作的文档页面:http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html
要知道的关键点是,对于每个分区,您必须设置约束来指定可以在分区中找到的内容(拆分id,因此每个表中只有200,000条记录,每个表只需要一个约束)。这样,当您查询主表时,它会根据所有子表的约束快速检查请求。仅查询查询属于表约束范围的表。如果您这样做,则只能真正查询一个表。
至于我学到的东西:
首先,我认为根本不可能从自己的触发器中删除表。我的解决方案就是将其标记为通过其他一些机制(比如稍后要删除的事物表)。这个问题是它一直存在,直到Cron作业运行。由于也无法从自己的触发器中更改表,因此该表仍将是一个分区,只是标记为稍后删除。如果您的分区正确,这可能不会造成任何问题。在我的情况下,可以有两个重叠的分区(一个标记为丢弃,一个应该在那里)。这样做的副作用是,对于指定可能在这些表中的任何一个表中的内容的查询将同时命中两个表。这对我很好,直到Cron的工作来了,所以我很好,但有些情况可能不适用于这个问题。
其次,我意识到正在改变他们没有写入的表的插件工作正常,但触发相同触发器链的删除和更新失败,因为会话正在使用这些表。我认为这是疯狂的事情,但真正的问题是我在日期和外键上进行了分区,但是正在删除记录的id。这导致postgres检查所有表的所有约束,这使得它无法了解要使用哪个表,因此它只检查了所有表。我必须做的就是让删除工作是指定我分区的信息,因此它知道要查看哪个表而不是扫描整个表集来查找id。
TLDR 如果在某些任意(一组)列上对postgres表进行分区,请确保通过提供已分区的列来删除或更新记录,以便postgres可以知道哪些表查看,而不必扫描整套。