我会尽快描述一下我必须理解这个问题的目的 . 我有用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)'
谢谢!最好的问候Artem
2 回答
我认为你要找的术语是“isolation level” . 我想你的应用程序的某些部分可能会容忍脏读,不可重写的读取或幻像读取 . 但在当前版本的PostgreSQL中,writers don't block readers, and readers don't block writers .
所以我的问题是:你怎么知道延迟是由锁定造成的,而不是由磁盘I / O,连接负载,其他进程(与dbms无关的进程,如长期运行的cron作业)引起的, 或者是其他东西?
PostgreSQL中不需要“WITH NOLOCK”,因为读者永远不会被作者阻止 . 阻止表上的SELECT的唯一方法是使用独占访问手动锁定表 - 这不是普通DML语句所做的事情 . 只有ALTER TABLE才能获得这样的锁 .
但我不确定我是否明白你的问题 .
你有死锁的问题吗?或者你认为没有测试你会拥有它们吗?