问题 多线程和数据库连接


所以我试图找出数据库连接的最佳实践。我有一个大的.NET GUI,作为MySQL数据库的前端。目前我打开了一个关于应用程序负载的连接,并将其用于我需要的任何交互。但是,整个GUI是单线程的。

当我开始为大型查询添加BackgroundWorkers并执行时,我担心我的开放连接。我知道,例如,我在该连接上一次只能打开一个dataReader。使用多个线程,用户可以尝试实例化更多。

为应用程序保持一个打开的连接与为每个交互打开一个新连接有什么优点/缺点?

这有哪些常见的设计模式?

谢谢-

乔纳森


2912
2018-02-22 15:39


起源



答案:


使用线程安全的连接池并保持特定于线程的连接(不要跨线程共享连接)。

我相信MySQL .NET连接框架内置了一个。如果对所有连接使用相同的连接字符串,只需在连接字符串中添加“pooling = true”即可。 (资源  - 没有超链接片段,所以在表中查找“池”)

这种方法的缺点是一些线程将阻塞,直到连接可用。您需要在程序结构中考虑到这一点。


6
2018-02-22 15:46





有两种方式:

  1. 单一连接 - 在这种情况下,连接创建1次并在所有请求之间分配,如果大量同时请求导致生产力下降,您必须自己控制线程保存。

  2. 每个请求的连接 - 在这种情况下,您必须打开连接并在执行请求后立即关闭它。但是,服务器可以限制同时打开的连接数。这里,创建连接的开销总是存在,但是使用线程安全的连接池来解决,这是很好的做法。

您需要分析和预测应用程序的行为并选择适当的路径。如果您有一个简单的应用程序,则可能不需要使用这些池。如果应用程序需要严重的负载和未来的可伸缩性,那么使用池是正确的。


3
2018-02-22 15:54





使用一个打开的连接,您应该拥有数据库的最大吞吐量。但是,您最终会在应用程序中编写复杂的代码来共享连接。

这里 是一篇关于资源共享模式的文章。这些例子都在Ada中,但我相信无论如何你都可以阅读它。


1
2018-02-22 15:49





连接到数据源可能非常耗时。为了最小化打开连接的成本,ADO.NET使用称为连接池的优化技术,这可以最大限度地降低重复打开和关闭连接的成本。对于.NET Framework数据提供程序,连接池的处理方式不同。

来自MSDN。

看这里 连接池(ADO.NET)


1
2018-02-22 15:52





在决定走哪条路之前,我们已经做了一些测试。我的意思是ConnectionAlwaysOpen或ConnectAndDisconnectEachTime。

显然来自.NET与SQL Server(从未尝试使用MySQL)在任何一种方法中都没有明显的性能损失(没什么好奇的,因为较低的层在ConnectAndDisconnectEachTime场景中不会立即断开连接)。 但是有一个微妙的差异使我们决定使用ConnectionAlwaysOpen。原因是交易支持。 如果你打算使用事务,那么连接/断开将不起作用,我认为这显然是原因。

ConnectionAlwaysOpen当然可以使用现有的连接池或连接池的一些手动延迟缓存来改进,但基本思想保持不变。另一方面,在Web应用程序中,实现这种方法并使用线程安全有点困难,但它可能值得付出努力。


0
2018-02-23 09:56



如果您说ConnectAndDisconnect方案无法实现事务支持,您是否在谈论自应用程序启动以来支持回滚所有内容的“全局”事务?如果没有,即使使用ConnectAndDisconnect,您也可以获得事务支持。您必须组织代码以识别“高级”事务,然后在C#中使用例如“TransactionScope”(msdn.microsoft.com/en-us/library/...) - FrenchData
@FrenchData我讨论的是来自业务逻辑层的中级事务。我们已经尝试过TransactionScope方法,但这还不够,我们很快遇到麻烦,因为中间层代码以不同的不可预见的方式使用。解决方案在某种程度上是两种方法之间的混合,我们的ConnectionManager类支持这两种方法。当然,不需要从应用程序启动交易,这就是混合解决方案更好的原因。 - AureliusMarcus


答案:


使用线程安全的连接池并保持特定于线程的连接(不要跨线程共享连接)。

我相信MySQL .NET连接框架内置了一个。如果对所有连接使用相同的连接字符串,只需在连接字符串中添加“pooling = true”即可。 (资源  - 没有超链接片段,所以在表中查找“池”)

这种方法的缺点是一些线程将阻塞,直到连接可用。您需要在程序结构中考虑到这一点。


6
2018-02-22 15:46





有两种方式:

  1. 单一连接 - 在这种情况下,连接创建1次并在所有请求之间分配,如果大量同时请求导致生产力下降,您必须自己控制线程保存。

  2. 每个请求的连接 - 在这种情况下,您必须打开连接并在执行请求后立即关闭它。但是,服务器可以限制同时打开的连接数。这里,创建连接的开销总是存在,但是使用线程安全的连接池来解决,这是很好的做法。

您需要分析和预测应用程序的行为并选择适当的路径。如果您有一个简单的应用程序,则可能不需要使用这些池。如果应用程序需要严重的负载和未来的可伸缩性,那么使用池是正确的。


3
2018-02-22 15:54





使用一个打开的连接,您应该拥有数据库的最大吞吐量。但是,您最终会在应用程序中编写复杂的代码来共享连接。

这里 是一篇关于资源共享模式的文章。这些例子都在Ada中,但我相信无论如何你都可以阅读它。


1
2018-02-22 15:49





连接到数据源可能非常耗时。为了最小化打开连接的成本,ADO.NET使用称为连接池的优化技术,这可以最大限度地降低重复打开和关闭连接的成本。对于.NET Framework数据提供程序,连接池的处理方式不同。

来自MSDN。

看这里 连接池(ADO.NET)


1
2018-02-22 15:52





在决定走哪条路之前,我们已经做了一些测试。我的意思是ConnectionAlwaysOpen或ConnectAndDisconnectEachTime。

显然来自.NET与SQL Server(从未尝试使用MySQL)在任何一种方法中都没有明显的性能损失(没什么好奇的,因为较低的层在ConnectAndDisconnectEachTime场景中不会立即断开连接)。 但是有一个微妙的差异使我们决定使用ConnectionAlwaysOpen。原因是交易支持。 如果你打算使用事务,那么连接/断开将不起作用,我认为这显然是原因。

ConnectionAlwaysOpen当然可以使用现有的连接池或连接池的一些手动延迟缓存来改进,但基本思想保持不变。另一方面,在Web应用程序中,实现这种方法并使用线程安全有点困难,但它可能值得付出努力。


0
2018-02-23 09:56



如果您说ConnectAndDisconnect方案无法实现事务支持,您是否在谈论自应用程序启动以来支持回滚所有内容的“全局”事务?如果没有,即使使用ConnectAndDisconnect,您也可以获得事务支持。您必须组织代码以识别“高级”事务,然后在C#中使用例如“TransactionScope”(msdn.microsoft.com/en-us/library/...) - FrenchData
@FrenchData我讨论的是来自业务逻辑层的中级事务。我们已经尝试过TransactionScope方法,但这还不够,我们很快遇到麻烦,因为中间层代码以不同的不可预见的方式使用。解决方案在某种程度上是两种方法之间的混合,我们的ConnectionManager类支持这两种方法。当然,不需要从应用程序启动交易,这就是混合解决方案更好的原因。 - AureliusMarcus