多个线程同时使用相同的JDBC连接

RvP*_*vPr 6 java database-connection connection-pooling jdbc apache-commons-dbcp

我试图更好地理解如果多个线程同时使用相同的JDBC连接尝试执行不同的sql查询将会发生什么.

  • 结果是否在功能上正确?

  • 性能影响是什么?

  • 线程A是否必须等待线程B完全完成其查询?

  • 或者线程A能够在线程B发送查询后立即发送其查询,之后数据库将并行执行两个查询?


我看到Apache DBCP使用同步协议来确保从池中删除从池中获取的连接,并使它们不可用,直到它们关闭.这似乎比它需要的更不方便.我正在考虑构建自己的"池",只需创建一个静态的打开连接列表,并以循环方式分发它们.我不介意偶尔的性能下降,并且在每次使用后不必关闭连接的便利性似乎非常吸引人.这样做有什么不好吗?

RvP*_*vPr 10

我使用 AWS RDS Postgres 数据库和 Java 11 运行了以下一组测试:

  1. 创建一个包含 1100 万行的表,每行包含一个 TEXT 列,填充随机的 100 个字符的字符串

  2. 随机选取一个5个字符的字符串,在上表中搜索该字符串的部分匹配项

  3. Time 上述查询返回结果所需的时间。就我而言,大约需要 23 秒。因为返回的结果很少,我们可以得出结论,这 23 秒的大部分时间都花在等待数据库运行全表扫描上,而不是发送请求/响应数据包

  4. 使用不同的连接并行运行多个查询(使用不同的关键字)。就我而言,我看到它们都在大约 23 秒内完成。即,查询被有效地并行化

  5. 使用相同的连接在并行线程上运行多个查询。我现在看到第一个结果在大约 23 秒后返回。第二个结果在大约 46 秒后返回。约 1 分钟内的第三个。等等等等。所有结果在功能上都是正确的,因为它们匹配该线程查询的特定关键字

To add on to what Joni mentioned earlier, his conclusion matches the behavior I'm seeing on Postgres as well. It appears that all "correctness" is preserved, but all parallelism benefits are lost, if multiple queries are sent on the same connection at the same time.


Jon*_*oni 6

由于 JDBC 规范不保证并发执行,因此只能通过测试您感兴趣的驱动程序或阅读它们的源代码来回答这个问题。

在 MySQL Connector/J 的情况下,execute语句的所有方法都用synchronized块锁定连接。也就是说,如果一个线程正在运行一个查询,使用该连接的其他线程将被阻塞,直到它完成。