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
相关产品推荐
相关产品推荐

