【问题标题】:MySQL - Single connection versus a PoolMySQL - 单连接与池
【发布时间】:2016-04-27 12:52:28
【问题描述】:

由于之前我已经回答了一些关于 MySQL 同步特性的问题,我开始质疑人们使用连接池的原因,以及在我的场景中是否应该移至池。

目前我的应用程序保持单个连接处于活动状态。在我的应用程序中只有一个 connection, statement, and result set 被回收利用。我所有的数据库任务都放在一个队列中,并在一个单独的线程上背靠背执行。 一个数据库查询线程,一个数据库访问连接。如果连接有问题,它将处理连接并创建一个新连接。

据我了解,无论有多少查询被发送到 MySQL 进行处理,它们都将按照收到的顺序同步处理。这些查询是来自单个来源还是多个来源都没有关系,它们将按照收到的顺序执行。

话虽如此,拥有多个连接和线程将查询粉碎到数据库的处理队列中的意义何在,不管它无论如何都要一个一个地处理它们。一个查询在完成处理之前不会执行,同样在我不使用池的场景中,下一个查询在前一个查询完成处理之前不会执行。

现在你可以说:

处理 MySQL 查询提供的结果所花费的时间将增加执行查询之间的时间。

这显然是正确的,这就是为什么我有一个工作线程来处理查询结果。查询完成后,我将结果转换为Map<> 格式并从内存中释放语句/结果集并开始处理下一个查询。 Map<> 被发送到单独的 Worker 线程进行处理,因此它不会阻塞查询执行线程。

谁能告诉我我做事的方式是否合适,以及我是否应该花时间转移到连接池而不是持久连接。最重要的是为什么。我开始这个线程是为了提供信息。

编辑:2016 年 4 月 29 日

我想补充一点,我知道连接池是什么,但是我更好奇在查询处理期间表锁定来自所有连接的请求时,在单个持久连接上使用池的好处.

【问题讨论】:

  • 您可以并行执行多个读取操作,您对管道危险 RAW、WAR 和 WAW 感兴趣吗?无论如何,连接池保持连接打开/空闲/等待,打开一个新连接是一项繁重的任务,所以如果您有多个客户端,最好有一个池。
  • @RC - 不相关,也是错误信息。

标签: java mysql database multithreading


【解决方案1】:

只是尝试这个 StackOverflow 的东西,但是,

在与数据库的每个连接中,大部分时间都是空闲的。当您在与INSERTUPDATE 表的连接中执行查询时,它会锁定表,防止并发编辑。虽然这很好,但可以防止数据覆盖或损坏,这意味着当第一个连接/查询仍在运行时,没有其他连接可以进行编辑。

但是,启动新连接需要时间,而且在大型基础架构中试图撇去所有多余的时间浪费,这并不好。因此,连接池是一整组处于空闲状态的连接,为下一次查询做好准备。

最后,如果您正在运行一个小型项目,通常没有理由使用连接池,但如果您正在运行一个大型站点,UPDATEs 和 INSERTs 每毫秒都在运行,那么连接池可以减少开销时间.

【讨论】:

    【解决方案2】:

    related answer: 池可以进行额外的“连接健康检查”(通过检查 SQL 异常代码) 并刷新连接以减少内存使用(请参阅答案中有关“maxLifeTime”的注释)。 但所有这些事情可能不会超过使用一个连接的更简单的方法。

    另一个需要考虑的因素是(阻塞)网络 I/O 时间。考虑一下这个(粗略的)场景:

    客户端准备查询 --> 客户端通过网络发送数据 --> 服务器从网络接收数据 --> 服务器执行查询,准备结果 --> 服务器通过网络发送数据 --> 客户端从网络接收数据 --> 客户端准备结果集

    如果数据库是本地的(与客户端在同一台机器上),那么网络时间几乎不会被注意到。 但是如果数据库是远程的,网络 I/O 时间就会变得可测量并影响性能。 假设隔离级别处于“已提交读”,并行运行选择语句可能会变得更快。 根据我的经验,同时使用 4 个连接而不是 1 个通常可以提高性能(或吞吐量)。 这确实取决于您的具体情况:如果 MySQL 确实主要是在等待锁被释放, 添加额外的连接在速度方面不会有太大的作用。 同样,如果客户端是单线程的,客户端实际上可能不会察觉到任何明显的速度提升。

    这应该很容易测试:比较一个程序的执行时间,它有 1 个线程,使用 1 个连接来执行 X 数量的选择查询 (即重用您当前的程序)与另一个程序使用 4 个线程,每个线程使用 1 个单独的连接 执行相同的 X 数量的选择查询除以 4 个线程(或仅并行运行第一个程序 4 次)。

    关于连接池的一点说明(如HikariCP):连接池必须保证没有事务 当连接返回池时保持打开状态,这可能意味着每次连接返回池时都会发送“回滚” (关闭)当自动提交关闭并且之前没有发送“提交”或“回滚”时。 这反过来会增加而不是减少网络 I/O 时间。所以一定要测试 在您的查询或一组查询完成后自动提交或确保始终发送提交或回滚。

    【讨论】:

    • 感谢您的信息。我购买了Blitz.IO 是为了对我的 API 进行一些高范围的并发用户压力测试。我将使用池/单一连接发布我的发现。
    【解决方案3】:

    连接池和持久连接不是一回事。 一是SQL连接数限制,二是单Pipe问题。 问题通常是将 SQL 输出传输到服务器所花费的时间比查询执行时间。因此,如果您打开两个 cli SQL 客户端并触发两个查询,一个具有大输出,另一个具有小输出(按此顺序),较小的先完成,而较大的仍在滚动其输出。 这里的重点是多连接确实解决了上述情况的问题。

    当您有多个请求查询的前端请求时,您可能更喜欢持久连接,因为它为您提供了多路复用不同连接(大输出与小输出)的好处,并防止了会话设置/拆除的开销。

    连接池 API 具有内置的错误检查和处理功能,但大多数 API 仍然希望您手动声明是否需要持久连接。

    所以实际上有 3 个变量,池,持久性和通过 API 配置的参数。必须混合和匹配池大小、持久性和连接数量以适应自己的环境

    【讨论】:

      猜你喜欢
      • 2013-08-20
      • 1970-01-01
      • 1970-01-01
      • 2012-11-02
      • 2016-05-08
      • 2018-07-15
      • 2012-07-10
      • 1970-01-01
      • 2011-10-07
      相关资源
      最近更新 更多