You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Common Lisp Mito连接PostgreSQL遇连接丢失/忙问题,求解决方案

Common Lisp Mito连接PostgreSQL频繁请求报错解决方案

核心问题分析

你当前使用cl-dbi:connect-cached仅实现了单连接缓存,并非连接池。Caveman2是多线程Web框架,多个请求线程共用同一个数据库连接时,必然会触发"连接正在处理其他查询"的冲突;而连接丢失则大概率是单连接长时间闲置被PostgreSQL服务器主动回收导致的。


问题解答

1. 查询前检查连接是否正常

可以通过执行轻量测试SQL来验证连接状态,同时搭配自动重连逻辑:

;; 检查连接是否存活
(defun connection-alive-p (conn)
  (handler-case
      (progn
        (dbi:execute (dbi:prepare conn "SELECT 1"))
        t)
    (dbi:<dbi-error> () nil)))

;; 确保连接可用,失效则重建
(defun ensure-valid-connection ()
  (unless (connection-alive-p mito:*connection*)
    (setf mito:*connection*
          (apply #'dbi:connect-cached
                 '(:postgres
                   :database-name "name"
                   :username "username"
                   :password "*****")))))

每次执行查询前调用(ensure-valid-connection)即可,但这只是临时方案,无法解决多线程并发冲突。

2. 处理连接并发冲突及等待问题

cl-dbi的连接对象没有公开状态标记用于直接检查是否正在处理查询,且等待单连接释放的思路本身不符合多线程Web场景的需求。正确的解决方式是使用连接池,让每个请求线程获取独立的数据库连接。

实现连接池(基于cl-dbi-pool)

先通过Quicklisp安装cl-dbi-pool,然后配置连接池替代单连接:

;; 初始化连接池
(setf mito:*connection-pool*
      (dbi.pool:make-dbi-pool
       :driver-name :postgres
       :database-name "name"
       :username "username"
       :password "*****"
       :min-connections 2  ;; 最小空闲连接数
       :max-connections 10)) ;; 最大并发连接数

;; 封装连接池使用宏,自动获取/归还连接
(defmacro with-db-conn (() &body body)
  (let ((conn (gensym)))
    `(dbi.pool:with-connection (,conn mito:*connection-pool*)
       (let ((mito:*connection* ,conn))
         ,@body))))

;; 业务查询示例
(with-db-conn ()
  (mito:find-dao 'user :username given-username))

连接池会自动处理连接的创建、复用、回收,彻底解决多线程并发冲突和连接闲置丢失的问题。


内容的提问来源于stack exchange,提问作者leinad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:12:33