我最近使用了 pgx 库,它建议在并发期间使用连接池而不是按需创建连接。
pgx.Connect() 返回的 *pgx.Conn 表示单个连接,并且不是并发安全的
以下理由足以支持上述说法吗?
第 1 点和第 2 点是使用池的完美用例,而不是创建单个连接,但第 3 点(线程安全)也可以在常规连接中构建。
还有其他货币原因导致我们应该使用池而不是动态创建对象吗?
以下理由足以支持上述说法吗?
pgx.Connect()
设置的连接是一样的 - 如果您为多个线程共享同一个连接,它们可能会互相干扰。
部分中提到的线程安全可能指的是如果多个操作员共享相同的单个连接会发生什么情况。如果不有效地重新实现已经提供的会话隔离,您就无法针对这些问题构建可靠的安全措施。例子包括:“入门”
工作人员 A 开始交易。在 A 工作的任何时刻,工作人员 B 都可以在 A 完成之前提交、回滚或导致连接进入未定义状态。此外,在提交事务之前,共享连接的任何工作人员的任何更改都对其他人不可见,不共享连接。
temp
pg_temp
命名空间,因此任何执行类似操作的尝试都会导致与数据库上 A 的临时对象发生意外交互。工作人员 A 发出长时间运行的查询。从工作人员 B 的角度来看,数据库没有响应 - 连接等待 A 请求的结果。
任何可以让每个工作人员始终从设置自己的连接开始,而不是请求新的、现成的库存连接,但这只是速度较慢 - 池提前独立完成,节省了每个人建立、配置和部署的时间。稍后处理掉它们。
dbpool.QueryRow()
将您的查询传递到池中新鲜的干净连接,运行它并立即将连接释放回它。两个并发线程可以共享一个池,并且保证它们的查询最终位于不同的连接中,并且不会相互干扰。您不能将其用于任何依赖于交易或“可丢弃”的事物。为此,您需要
dbpool.Acquire()
,保留获取的连接,重新使用它来在其上运行整个查询链,然后
conn.Release()
返回池。