Ale*_*nko 11 postgresql deadlock locking update
我正在运行这样的并发 Postgres 查询:
UPDATE foo SET bar = bar + 1 WHERE baz = 1234
Run Code Online (Sandbox Code Playgroud)
每个查询都会影响固定的 K 行数,我找不到强制执行更新行顺序的方法,最终导致死锁。目前我通过手动执行订单来解决这个问题,但这意味着我必须执行比平时更多的查询,同时还将搜索复杂度从 O(log N + K) 提高到 O(K log N)。
有没有办法提高性能而不会最终容易陷入死锁?我怀疑如果Postgres 以扫描它们的相同顺序更新行,用(baz)
索引替换(baz, id)
索引可能会起作用,这是一种值得追求的方法吗?
Erw*_*ter 16
有没有ORDER BY
在SQL UPDATE
命令。Postgres 以任意顺序更新行:
为了绝对确定地避免死锁,您可以在可序列化事务隔离中运行您的语句。但这更昂贵,您需要准备在序列化失败时重复命令。
您最好的做法可能是SELECT ... ORDER BY ... FOR UPDATE
在子查询中或SELECT
事务中的独立对象中显式锁定- 在默认的“已提交读”隔离级别中。在 pgsql-general 上引用 Tom Lane 的话:
应该没问题 --- FOR UPDATE 锁定始终是 SELECT 管道中的最后一步。
这应该可以完成这项工作:
BEGIN;
SELECT 1
FROM foo
WHERE baz = 1234
ORDER BY bar
FOR UPDATE;
UPDATE foo
SET bar = bar + 1
WHERE baz = 1234;
COMMIT;
Run Code Online (Sandbox Code Playgroud)
多列索引(baz, bar)
可能非常适合性能。但是由于bar
显然更新了很多,所以单列索引(baz)
可能会更好。取决于几个因素。每行多少行baz
?如果没有多列索引,是否可以进行HOT 更新?...
如果 baz
同时被更新,还有一个不太可能的极端情况对冲突的机会(每个文件):
这是可能的
SELECT
,在运行命令READ COMMITTED
事务隔离级别,并使用ORDER BY
和锁定子句返回行乱序。...
此外,如果您应该有一个涉及 的唯一约束bar
,请考虑一个DEFERRABLE
约束以避免同一命令中的唯一违规。相关回答:
归档时间: |
|
查看次数: |
10808 次 |
最近记录: |