Postgres中的并发查询

时间:2011-03-07 14:17:31

标签: multithreading postgresql deadlock

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

此数据库同时由Web应用程序使用。所以你知道我遇到了死锁的问题。我尝试了所有的锁模型,但其中任何一个都没有帮助我。在某些时间段内,来自网络的SELECT工作时间很长。

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

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

SELECT c.id AS id,cn.name as name,c.parent_category_id AS parent_category_id,
        CASE WHEN EXISTS (
  SELECT p.id FROM category AS subcat
  INNER JOIN product AS p ON subcat.id = p.category_id
  WHERE subcat.parent_category_id=c.id LIMIT 1)
 THEN true ELSE false END AS autoupdate
        FROM category 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
        AND EXISTS
            (SELECT p.id FROM product AS p
            WHERE p.category_id = c.id OR 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`

并解释:

'Group  (cost=947.74..987.96 rows=15 width=40)'
'  ->  Sort  (cost=947.74..947.75 rows=15 width=40)'
'        Sort Key: c.sort, cn.name, c.id, c.parent_category_id'
'        ->  Merge Left Join  (cost=125.84..947.62 rows=15 width=40)'
'              Merge Cond: (c.id = subcat.parent_category_id)'
'              Filter: (SubPlan 2)'
'              ->  Sort  (cost=64.46..64.46 rows=3 width=40)'
'                    Sort Key: c.id'
'                    ->  Nested Loop  (cost=0.00..64.45 rows=3 width=40)'
'                          ->  Seq Scan on category c  (cost=0.00..41.69 rows=3 width=18)'
'                                Filter: ((id  1) AND (parent_category_id = 0))'
'                          ->  Index Scan using category_name_category_id_langid on category_name cn  (cost=0.00..7.56 rows=1 width=30)'
'                                Index Cond: ((cn.category_id = c.id) AND (cn.langid = 1))'
'              ->  Sort  (cost=61.38..62.46 rows=1084 width=16)'
'                    Sort Key: subcat.parent_category_id'
'                    ->  Seq Scan on category subcat  (cost=0.00..39.52 rows=1084 width=16)'
'              SubPlan 2'
'                ->  Limit  (cost=0.00..27.29 rows=1 width=8)'
'                      ->  Seq Scan on product p  (cost=0.00..36459.98 rows=1336 width=8)'
'                            Filter: ((category_id = $0) OR (category_id = $1))'
'  SubPlan 1'
'    ->  Limit  (cost=0.00..2.68 rows=1 width=8)'
'          ->  Nested Loop  (cost=0.00..17889.28 rows=6684 width=8)'
'                ->  Seq Scan on category subcat  (cost=0.00..40.60 rows=10 width=8)'
'                      Filter: (parent_category_id = $0)'
'                ->  Index Scan using product_category_id on product p  (cost=0.00..1764.16 rows=668 width=16)'
'                      Index Cond: (p.category_id = subcat.id)'

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

2 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

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

但我不确定我理解你的问题。

你已经遇到了死锁问题吗?或者你认为没有测试你会拥有它们吗?