我在一个 common Lisp 项目中使用 mito 来连接到 postgres 数据库。我有一个在数据库上运行多次的请求,并且收到以下两个错误:
DB Error: Connection to database server lost.
DB Error: This connection is still processing another query.
有没有办法在尝试执行查询之前检查是否找到与数据库的连接(又称为“未丢失”)?
有没有办法检查数据库连接是否正忙于执行另一个查询?如果是这样,我该如何等待它完成?类似于 JS 中的
await
。
连接丢失似乎是不正确的,因为如果后面的请求不是那么多,彼此距离不那么近,那么后面的请求就会起作用。
添加上下文:我正在一个 caveman2 项目中执行此操作,对于来自浏览器的给定会话,服务器可能会分配一个线程来处理特定路由,因此,该客户端的给定线程该路由的会话只能访问一个连接。我不确定这是否正确或导致此问题的原因。任何帮助将不胜感激!
对于来自浏览器的给定会话,服务器可能会分配一个线程来处理特定路由,因此,该路由的客户端会话的给定线程只能访问一个连接。
我认为这是对正在发生的事情的准确描述。
例外来自:cl-postgres/public.lisp:L328,在宏
using-connection
中,它在处理请求时禁止使用相同的连接。文档说:
这个 当您使用单个数据库时也可能会引发错误 来自多个线程的连接,但你根本不应该这样做。
正如 mito/issues/40 所暗示的,解决方案是在每个线程中使用
dbi:connect-cached
。
CL-DBI/连接池的文档说:
dbi:connect-cached 如果数据库已连接,则返回现有连接。由于将为每个线程创建一个缓存,因此在多线程应用程序中使用是安全的。
因此您可能有兴趣编写自己的包装宏,例如:
(with-db (db)
...)
展开为:
(let ((db (dbi:connect-cached ...)))
...)
如果以后您需要在主体周围添加更多代码,您可以更新宏,并且所有使用它的地方将在重新编译后更新。您可以为每个请求创建一个新连接,但在我看来,为每个请求创建一个线程和一个数据库连接可能无法很好地扩展,并且很容易受到 DDOS 攻击。也许您可以拥有一个工作人员池和一个数据库连接池。