Python postgres使用更新和外键锁定

Python postgres使用更新和外键锁定,python,sql,postgresql,concurrency,sqlalchemy,Python,Sql,Postgresql,Concurrency,Sqlalchemy,我的Postgres表: 表演者 身份证 等级 组id引用组 表演 身份证 支付 执行者id引用执行者 团体 身份证 我经常需要从一个组中选择所有的表演者并更新他们的等级。但这通常会导致死锁,因为我正在执行SELECT。。。对于更新select,其他线程同时插入INSERT 我在Python SqlAlchemy中看到了很多错误示例: 我也有一些这样的例子 我怎样才能解决这个问题?我可以切换到其他事务锁定级别吗?我不希望只是中止并必须重试—我希望数据库为我处理这个争用 一定有办法解决

我的Postgres表:

表演者

  • 身份证
  • 等级
  • 组id引用组
表演

  • 身份证
  • 支付
  • 执行者id引用执行者
团体

  • 身份证
我经常需要从一个组中选择所有的表演者并更新他们的等级。但这通常会导致死锁,因为我正在执行
SELECT。。。对于更新
select,其他线程同时插入INSERT

我在Python SqlAlchemy中看到了很多错误示例:

我也有一些这样的例子

我怎样才能解决这个问题?我可以切换到其他事务锁定级别吗?我不希望只是中止并必须重试—我希望数据库为我处理这个争用


一定有办法解决这个问题-我想做的很简单

如果所有并发写操作都以相同的唯一顺序进行,则可以避免死锁。在锁定语句中添加
orderby
,并在任何地方使用相同的排序顺序。比如:

SELECT ... FROM performers WHERE ... ORDER BY performers.id FOR UPDATE
选择。。。从表演者那里。。。按执行者排序。更新的id
其中,
id
将是主键(或任何其他稳定、明确的列组合)

此外,如果您的操作涉及多个列,则在表之间以完全相同的顺序执行锁定

更多详细信息,请参阅。


将触发器(和外键约束)保持在必要的最小值。无论哪种方式,首先为更新排序
锁。这也许能解决你的问题。如果不是,考虑不同的。我们应该做到这一点。但是,您必须准备重试事务,直到它们成功。

插入操作如何?这显然不适用于那里,对吗?@lollercoaster:对。你不能锁定(还没有)的东西。不过,我不知道插入将如何死锁?您可能会遇到重复的密钥冲突,但这是另一种问题。是的,当我将来自不同线程的多个值同时插入到性能表中时,会出现死锁-我怀疑是因为外键?实际上我不知道为什么。这里有一个例子:,这里有另一个:@lollercoaster:对,外键可能会对您产生影响。当插入到
性能中时,请在每个不同的
执行者\u id
之后提交,以避免与更新交叉锁定。事实上,它是一个
共享锁
,这强烈表明它是用于FK的。PostgreSQL发送回客户端的错误消息缺少关于其他事务的信息,以避免向客户端泄漏信息。PostgreSQL日志文件对这两个事务有何说明?
SELECT ... FROM performers WHERE ... ORDER BY performers.id FOR UPDATE