跨线程共享 django 事务

Share django transaction across threads

我遇到一个问题,其中一个 API 在 django (3.2) 网络应用程序中实现 运行 gunicorn (gevent) 必须从多个 API 中获取不同的价格并存储return 发送给客户端之前数据库 (Postgres 13) 中的那些价格。 我想将插入放在同一个事务中,所以如果发生意外情况,则不会插入任何内容。

我现在首先调用所有 api,每个都在一个绿色线程 (gevent) 中,然后在所有这些 return 之后,我批量插入结果。

但事实证明我真的很好奇是否有可能让不同的线程(绿色或非绿色)共享同一个事务。我看到 psycopg2 可以以非阻塞方式执行。 现在的问题是每次我在 django 中启动线程时,新线程都在新事务中。我将深入研究 django 数据库后端源以了解发生了什么,但也许有人可以解决这个问题。

Tldr;不同的线程可以在同一个事务中执行查询吗?

您绝对不想在没有锁定机制的情况下尝试在多个线程之间共享单个 transaction/postgres 连接,以确保它们不会以某种令人讨厌的方式在连接上交错 activity导致错误。

相反,更简单、更安全的解决方案是从主请求线程启动绿色线程,然后 gevent.join([<green thread1>, <green thread2>...]) 所有这些都从同一个主请求线程启动。每个绿色线程将从 API 获取数据,并且 return 它作为每个线程的出口。

然后让主请求线程遍历每个退出的绿色线程对象 (greenlet),并通过 Greenlet.get() 为每个对象获取 return 值。然后使用其正常的 transaction/connection.

在主请求线程上执行插入

更新

如果您想变得更复杂以获得更好的性能,您可以使用池并让每个 greenlet 将其结果放在从主线程读取的队列中。这样您就可以在结果可用时开始将结果保存到数据库,而不是等到它们全部完成。