JDBC:我可以在多线程应用程序中共享连接,并享受良好的交易吗?

ful*_*ton 5 postgresql multithreading transactions jdbc

看起来处理JDBC事务的经典方法是将auto-commit设置为false.这将创建一个新事务,每次调用commit都会标记下一个事务的开始.在多线程应用程序上,我理​​解通常的做法是为每个线程打开一个新连接.

我正在编写一个基于RMI的多客户端服务器应用程序,因此我的服务器基本上可以为每个新连接无缝地生成一个线程.为了正确处理事务,我应该为每个线程创建一个新连接吗?这种架构的成本难道不高吗?

Bil*_*win 5

是的,通常您需要为每个线程创建一个新连接。您无法控制操作系统如何对线程的执行进行时间切片(尽管定义了自己的关键部分),因此您可能会无意中让多个线程尝试沿该管道发送数据。

请注意,这同样适用于任何网络通信。例如,如果您有两个线程尝试与 HTTP 连接共享一个套接字。

  • 线程1发出请求
  • 线程2发出请求
  • 线程 1 从套接字读取字节,无意中读取了线程 2 请求的响应

如果您将所有事务包装在关键部分中,并因此在整个开始/提交周期中锁定任何其他线程,那么您也许能够在线程之间共享数据库连接。但即便如此,我也不会这样做,除非您确实对 JDBC 协议有天生的了解。

如果大多数线程很少需要数据库连接(或根本不需要),您可以指定一个线程来完成数据库工作,并让其他线程将其请求排队到该线程。这将减少如此多的连接的开销。但是您必须弄清楚如何管理环境中每个线程的连接(或者在 StackOverflow 上询问有关该问题的另一个具体问题)。

更新:为了回答您在评论中的问题,大多数数据库品牌不支持单个连接上的多个并发事务(InterBase/Firebird 是我所知道的唯一例外)。

如果有一个单独的事务对象,并且能够为每个连接启动和提交多个事务,那就太好了。但供应商根本不支持它。

同样,独立于供应商的标准 API(例如 JDBC 和 ODBC)也做出相同的假设,即事务状态仅仅是连接对象的一个​​属性。