MySQL - 持久连接 vs 连接池

67
为了避免每次查询 MySQL 时建立新连接的开销,有两个可用的选项:
  1. 持久连接,即在请求新连接时,检查是否已经存在“相同”的连接,如果有则使用它。
  2. 连接池,即客户端维护一组连接,以便需要使用连接的每个线程将从池中检出连接,并在完成后将其返回到池中。
因此,如果我有一个多线程服务器应用程序,预计每秒处理数千个请求,并且每个线程需要对数据库发出查询,则哪种方法更好?
据我所知,使用持久连接时,我的应用程序中所有线程都会尝试使用相同的持久连接到数据库,因为它们都在使用相同的连接。因此,这是一种被多个应用程序线程共享的连接,结果请求很快就会在数据库方面被阻塞。
如果我使用连接池机制,则所有应用程序线程都共享一组连接。因此,阻塞请求的可能性较小。但是,使用连接池时,应用程序线程是否应等待从池中获取连接,还是应以轮询的方式向池中的连接发送请求,并在数据库上让队列(如果有)发生?
2个回答

38

持久连接并不意味着所有线程都使用同一个连接。它只是表示您保持连接处于打开状态(与每次需要连接时打开连接相反)。打开连接是一项昂贵的操作,因此通常情况下,您会尽量避免比必要更频繁地打开连接。

这就是为什么多线程应用程序通常使用连接池的原因。该池负责打开和关闭连接,并且每个需要连接的线程都从池中请求一个连接。重要的是要确保线程尽快将连接返回给池,以便另一个线程可以使用它。

如果您的应用程序只有少数需要连接的长时间运行的线程,您也可以为每个线程打开一个连接并保持其打开状态。

仅使用一个连接(如您所描述的)等同于具有最大大小为1的连接池。这将成为您的瓶颈,因为所有线程都必须等待连接。这可能是对数据库操作进行序列化(按照某种顺序执行它们)的选项,尽管有更好的选项可以确保序列化。


在连接池的情况下,应用程序开发人员可以控制何时以及打开/关闭多少个连接。对于MySQL,如何控制“相同”的持久连接数量?是否有相应的服务器配置参数? - user1259642
2
在我使用的池中,您可以设置最小和最大池大小,并定义空闲时间,在此之后将关闭连接(还有其他一些内容)。 - mrab

25

更新:新的 X 协议支持异步连接,像 Node 的新驱动程序可以利用这一点。

关于你关于应用服务器是否应该等待连接的问题,答案是肯定的。

MySQL 连接是阻塞的。当从 MySQL 服务器发出请求时,在收到服务器响应之前,该连接将等待空闲。

没有办法在同一连接上发送两个请求并查看哪个先返回。你只能一次发送一个请求。

因此,通常,连接池中的单个线程由一个客户端连接 (在你的情况下,应用服务器是客户端) 和一个服务器端连接 (数据库) 组成。

您的应用程序应该等待可用的连接线程从池中取出,当需要时允许池增长,并在不太忙时缩回到默认线程数。


MySQL连接正在阻塞。为什么会阻塞?它不能像Node.js / Golang一样是非阻塞IO,这样所有连接就可以在一个TCP连接中处理吗? - jiajianrong
也许我错了,但是 MySql 并没有阻塞。一个事务才会阻塞。你可以打开两个会话并同时发送一些查询,MySQL 将同时处理你的查询。除非你显式地设置锁定。 - user3502626
@user3502626,这个答案已经有10年了。显然,像Node使用的新驱动程序使用更新的X协议并支持异步连接。我会看看能否更新答案。 - Marcus Adams
@jiajianrong,请看我的更新。 - Marcus Adams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接