什么使数据库池并发安全?

问题描述 投票:0回答:1

我最近使用了 pgx 库,它建议在并发期间使用连接池而不是按需创建连接。

pgx.Connect() 返回的 *pgx.Conn 表示单个连接,并且不是并发安全的

以下理由足以支持上述说法吗?

  1. 池启动连接并准备好在请求时被使用
  2. 确保数据库不会同时加载无限连接。
  3. 连接是线程安全的。

第 1 点和第 2 点是使用池的完美用例,而不是创建单个连接,但第 3 点(线程安全)也可以在常规连接中构建。

还有其他货币原因导致我们应该使用池而不是动态创建对象吗?

postgresql go concurrency database-connection pgx
1个回答
0
投票

以下理由足以支持上述说法吗?

  1. 如果配置正确则为 True。您可以设置一个连接数量不足的池。一旦耗尽,可以将进一步的请求设置为失败或等待 - 因此,连接将不再在请求时准备好被消耗
  2. 如果它是唯一的连接来源,则为真。
  3. 就泳池而言确实如此。您可以以非线程安全的方式使用从池中获取的连接。来自池的连接和使用 pgx.Connect() 设置的连接是一样的 - 如果您为多个线程共享同一个连接,它们可能会互相干扰。
    
    

3(线程安全)也可以构建在常规连接中。

“入门”
部分中提到的线程安全可能指的是如果多个操作员共享相同的单个连接会发生什么情况。如果不有效地重新实现已经提供的会话隔离,您就无法针对这些问题构建可靠的安全措施。例子包括:

工作人员 A 开始交易。在 A 工作的任何时刻,工作人员 B 都可以在 A 完成之前提交、回滚或导致连接进入未定义状态。此外,在提交事务之前,共享连接的任何工作人员的任何更改都对其他人不可见,不共享连接。

    工作人员 A
  1. 设置会话或事务级别设置。工作人员 B 意外地受到它的影响,并且可以随时突然取消设置或覆盖它。
  2. 工作人员 A 创建一个
  3. temp
  4. 对象。在同一连接中操作,工作线程 B 共享相同的
  5. pg_temp 命名空间,因此任何执行类似操作的尝试都会导致与数据库上 A 的临时对象发生意外交互。
    工作人员 A 发出长时间运行的查询。从工作人员 B 的角度来看,数据库没有响应 - 连接等待 A 请求的结果。
    任何
  6. 会话级别的事情
  7. 都会成为工作人员之间的潜在摩擦点。话虽这么说,您可以提出不使用会话的任何线程不安全设施的工作流程,并发现上面
  8. 4
引入的随机延迟是可以接受的。对于这些使用常规的线程安全设置会更安全、更可持续。

还有其他货币原因导致我们应该使用池而不是动态创建对象吗?


在这种情况下,线程安全是通过让每个工作人员使用自己的会话/连接来保证的。您
可以

让每个工作人员始终从设置自己的连接开始,而不是请求新的、现成的库存连接,但这只是速度较慢 - 池提前独立完成,节省了每个人建立、配置和部署的时间。稍后处理掉它们。

dbpool.QueryRow() 将您的查询传递到池中新鲜的干净连接,运行它并立即将连接释放回它。两个并发线程可以共享一个池,并且保证它们的查询最终位于不同的连接中,并且不会相互干扰。您不能将其用于任何依赖于交易或“可丢弃”的事物。为此,您需要

dbpool.Acquire()

,保留获取的连接,重新使用它来在其上运行整个查询链,然后 
conn.Release() 返回池。
    
© www.soinside.com 2019 - 2024. All rights reserved.