【问题标题】:Concurrent queries in PostgresPostgres 中的并发查询
【发布时间】:2011-07-10 09:30:43
【问题描述】:

我将尝试简要描述我必须了解的这个问题的目的。 我有用 Java 开发的大型多线程应用程序。每个线程都有硬逻辑来加载、验证和解析文件,然后将这些数据插入数据库。在线程中插入/更新数据库的阶段也是如此。每个线程运行多个更新一个表的存储过程。这些存储的过程是每个线程的几个。

此数据库同时被 Web 应用程序使用。如您所知,我遇到了死锁问题。我尝试了所有的锁模型,但其中任何一个都没有帮助我。在某些时间范围内 SELECT from web 工作时间很长。

到底我的问题是什么。有 postgres 机制/手段来同步存储过程或查询吗?我知道它必须通过锁定模型来完成,但我没有成功。作为 MS Server 的解决方案,我对 SELECT 语句使用“WITH NOLOCK”。我可以通过代码同步的方式来解决这个问题,但是这确实是一个复杂的逻辑。

根据要求,我发布了更新过程中慢查询的示例。

SELECT c.id AS id,cn.name 作为名字,c.parent_category_id AS parent_category_id, 存在时的情况( SELECT p.id FROM category AS subcat INNER JOIN 产品 AS p ON subcat.id = p.category_id WHERE subcat.parent_category_id=c.id LIMIT 1) THEN true ELSE false END AS 自动更新 从类别 AS c INNER JOIN category_name AS cn ON c.id=cn.category_id LEFT JOIN category AS subcat ON subcat.parent_category_id = c.id WHERE c.parent_category_id=0AND cn.langid=1 AND c.id != 1 并且存在 (从产品中选择 p.id 作为 p 其中 p.category_id = c.id 或 p.category_id = subcat.id LIMIT 1) GROUP BY c.sort,c.id,cn.name,c.parent_category_id ORDER BY c.sort, cn.name`

并说明:

'组(成本=947.74..987.96 行=15 宽度=40)' '-> 排序(成本=947.74..947.75 行=15 宽度=40)' '排序键:c.sort、cn.name、c.id、c.parent_category_id' ' -> 合并左连接(成本=125.84..947.62 行=15 宽度=40)' '合并条件:(c.id = subcat.parent_category_id)' '过滤器:(子计划 2)' '-> 排序(成本=64.46..64.46 行=3 宽度=40)' '排序键:c.id' ' -> 嵌套循环(成本=0.00..64.45 行=3 宽度=40)' ' -> 类别 c 的 Seq 扫描(成本 = 0.00..41.69 行 = 3 宽度 = 18)' '过滤器:((id 1) AND (parent_category_id = 0))' ' -> 在 category_name cn 上使用 category_name_category_id_langid 进行索引扫描(成本=0.00..7.56 行=1 宽度=30)' '索引条件:((cn.category_id = c.id) AND (cn.langid = 1))' '-> 排序(成本=61.38..62.46 行=1084 宽度=16)' '排序键:subcat.parent_category_id' ' -> 类别子猫的 Seq 扫描(成本 = 0.00..39.52 行 = 1084 宽度 = 16)' '子计划 2' '-> 限制(成本=0.00..27.29 行=1 宽度=8)' ' -> 对产品 p 进行 Seq 扫描(成本=0.00..36459.98 行=1336 宽度=8)' '过滤器:((category_id = $0) OR (category_id = $1))' '子计划 1' '-> 限制(成本=0.00..2.68 行=1 宽度=8)' ' -> 嵌套循环(成本=0.00..17889.28 行=6684 宽度=8)' ' -> Seq Scan on category subcat (cost=0.00..40.60 rows=10 width=8)' '过滤器:(parent_category_id = $0)' ' -> 使用产品 p 上的 product_category_id 进行索引扫描(成本=0.00..1764.16 行=668 宽度=16)' '索引条件:(p.category_id = subcat.id)'

谢谢! 最好的祝福 阿尔乔姆

【问题讨论】:

  • 感谢查询计划,但我没有要求EXPLAIN query;我要求EXPLAIN ANALYZE query。它们不是一回事。

标签: multithreading postgresql deadlock


【解决方案1】:

我认为您要查找的术语是“isolation level”。我想你的应用程序的某些部分可能会容忍脏读、不可重复读或幻读。但在当前版本的 PostgreSQL 中,writers don't block readers, and readers don't block writers.

所以我的问题是:你怎么知道延迟是由锁引起的,而不是由磁盘 I/O、连接负载、其他进程(与 dbms 无关的进程,如长时间运行cron 作业),还是其他?

【讨论】:

  • 只有一个应用程序更新数据库。所以任何其他“工作”都做不到。当应用程序停止时,永远不会长时间不选择查询。如果更新用于选择的同一个表,则选择查询需要“很长时间”。我通过 PgAdmin 尝试了监视器锁定。顺便说一句,我使用 posgres9
  • 编辑您的原始问题,并发布EXPLAIN ANALYZE query 的结果,其中“query”是您从网络上运行的 SELECT 语句。
【解决方案2】:

您不需要在 PostgreSQL 中使用“WITH NOLOCK”,因为读者永远不会被作者阻止。在表上阻止 SELECT 的唯一方法是手动锁定具有独占访问权限的表 - 这不是普通 DML 语句所做的事情。只有 ALTER TABLE 才能获得这样的锁。

但我不确定我是否理解您的问题。

您是否已经遇到过死锁问题?或者你认为你会拥有它们,而无需测试?

【讨论】:

  • 我已经死锁了。 Postgres 写道,我永远不会遇到选择问题。但实际情况并非如此。在更新过程中,简单查询的工作时间很长(但不超过更新过程)。我的意思是从同时更新的同一张表中选择。
  • 除非您使用SELECT ... FOR UPDATE,否则不会阻止更新运行时的选择。您在应用程序运行时检查了锁吗?
  • 是的,应用程序可以在生产服务器上运行,并且有时会抱怨某些操作运行缓慢。经过额外调查后,我确定在更新此表时选择工作缓慢。如果我没记错的话SELECT ... FOR UPDATE 使用 back to frontfor 来锁定更新。举个简单的例子:UPDATE table1 SET column1 = column1 *10同时执行SELECT * FROM teble1
  • 那么你无能为力。使用SELECT ... FOR UPDATE 时,您基本上是在告诉 Postgres 在锁定方面您更聪明。避免这种情况的唯一方法是删除 FOR UPDATE
猜你喜欢
  • 2021-05-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
  • 2016-11-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多