2013-08-01 36 views
0

有一个多线程应用程序执行一些PL/pgsql函数。该函数为极其重要的资源(表格)生成记录插入。它还执行时执行一些选择/更新/等操作。postgresql并发查询调试

问题是,有时候我们会面临重复的(2-3)记录,每个记录在并行线程中传递给函数。它们都作为函数执行结果插入到表中,而它们不应该。

它发生,因为这两个事务并行执行,并不知道相同的记录正在准备插入并行事务。

该表格非常重要,并且各种LOCK TABLE都非常不受欢迎(LOCK FOR SHARE MODE同时给了一些有用的经验)。

所以,问题是,是否有任何最佳实践如何组织PL/pgsql函数与关键资源(表)一起使用,由多线程应用程序执行并且不会对此资源产生有害的锁?

PS。我知道,应用程序中由record.ID引发的某个线程是一种可能的解决方案。但我首先对PL/pgsql解决方案感兴趣。

+0

假设您没有主键/唯一键或通过“重复”键,您的意思是除主键/唯一键之外的其他属性是否安全?锁定或序列化访问是确保条目唯一性的唯一方式,或者至少是我能想到的。 Postgresql 9.2+中可用的资源是可串行化快照隔离(https://wiki.postgresql.org/wiki/SSI),但可能有点重量级满足您的需求。 – bma

+0

我们有一个PK约束,但它是一个逻辑重复,而不是一个简单的字段逐字段匹配。对于我们来说,序列化隔离级别不是一个可接受的解决方案:它会产生序列化访问拒绝可能不可预测地影响应用程序行为的并行事务。无论如何感谢您的建议! – xacinay

+0

如果你的主键允许重复,它不是主键吗?什么*精确*你的意思是重复。 –

回答

2

有时你可以使用咨询锁 - http://www.postgresql.org/docs/current/static/explicit-locking.html。用这些锁来锁定一些数字子集。我用它来成功的平行插入同步。

+0

不幸的是,advisory_lock不能做我希望他做的事情。实际上,预计会找到一个数据库引擎模块,这将允许我声明一些锁定规则,如'从resource_tbl中选择do_lock(*),其中id在1到100之间“,这意味着数据库将不允许插入带有来自间隔的id的新记录从1到100.所有现有技术,据我所知,只允许我锁定一些已经存在的记录。无论如何,我得出了我需要的结论,感谢关注这个问题! – xacinay