【问题标题】:MySQL Connection Pool CountMySQL 连接池计数
【发布时间】:2017-04-06 00:13:17
【问题描述】:

我的 VB.NET 应用程序开始收到错误:

超时。在从池中获取连接之前超时已过。这可能是因为所有池连接都在使用中并且已达到最大池大小。

我确实有一些方法没有正确处理连接。这些已使用TryFinally 修复。

但是,今天早上我在尝试打开简单报告时再次收到错误消息。我有 MySQL Workbench 打开监视客户端连接。当时我连接了 4 个线程。

MySQL DB 会终止休眠超过 15 秒的连接。

如果确实是错误所指的,我不知道如何达到最大池大小。

应用程序是读取最大池大小设置并保存自己的连接数并在达到该数量时抛出错误,还是在每次打开新连接时直接从 MySQL DB 获取数量?

或者错误可能是由于其他原因造成的?

编辑 1

来自 MySQL Workbench 的一些统计数据
已连接的线程:3
正在运行的线程:1
创建的线程数:250
缓存的线程数:5
拒绝(超过限制):0
总连接数:2822
连接数限制:151
中止的客户:2694
中止的连接:84
错误:0

编辑 2

调用和处理连接的示例代码:

Public Shared Function GetCoursePaperCertificate(ByVal CourseTypeID As Integer) As String
Dim connx As New MySqlConnection(My.Settings.BMConnString)
Try
    Dim cmdTextx = "Select `Cert` From `Courses` WHERE `ID`=@ID"
    Dim cmdx As New MySqlCommand(cmdTextx, connx)
    cmdx.Parameters.AddWithValue("@ID", CourseTypeID)
    connx.Open()
    Dim result = cmdx.ExecuteScalar
    If result Is Nothing OrElse result Is DBNull.Value Then
        Return String.Empty
    Else
        Return result
    End If
Catch ex As Exception
    Return String.Empty
Finally
    connx.Dispose()
    connx = Nothing
End Try
End Function

【问题讨论】:

  • 在使用连接的任何地方都使用Using-statement。这意味着,只能在方法范围内使用它们,并且永远不要共享它们。
  • 正如@TimSchmelter 之前所说,在处理数据库连接时尝试使用using,以避免任何可能保持打开状态的连接出现问题。顺便说一句,问题可能是由任何花费太长时间并且使用transaction 锁定任何表的进程引起的。您是否检查过是否有任何进程可能会锁定您尝试使用的表?
  • 谢谢。我没有在项目的任何地方明确实现任何事务方法。我会将代码转换为using 似乎确实有一个线程处于打开状态并且睡眠时间超过了应有的时间。但是,我会认为有 151 个可能的连接,这不会是罪魁祸首吗?
  • 听起来您并没有在使用后处理掉您的连接。服务器杀死休眠线程不会影响连接轮询(Workbench 将无法看到)
  • @Plutonix 有没有办法查看投票中的实际连接数?

标签: mysql .net vb.net


【解决方案1】:

您的代码中有几件事。

  • 首先打开Option Strict。该函数被声明为返回一个字符串,但您试图返回 ObjectReturn result
  • 所有实现Dispose 方法的 都应该在Using 块内使用。这允许您声明和初始化一个对象,使用它并在最后处理它。
  • Parameters.Add 优于 AddWithValue。后者强制 DB Provider 根据数据猜测数据类型。
  • 根据负载以及是否经常使用该方法,您可以将数据加载到 DataTable 并对其进行查找,而不是一遍又一遍地查询数据库。

核心问题(可能)是您没有处置DBCommand 对象。看看你使用的构造函数:

Dim cmdx As New MySqlCommand(cmdTextx, connx)

DBCommand 对象被传递一个对连接的引用。即使您明确地处置了连接,cmdx 仍然具有对它的引用,并且 it 没有被处置。 Using 块可以很容易地确保事情被处理:

Dim sql = "Select `Cert` From `Courses` WHERE `ID`=@ID"

Using dbCon As New MySqlConnection(MySQLConnStr)
    Using cmd As New MySqlCommand(sql, dbCon)
        cmd.Parameters.Add("@Id", MySqlDbType.Int32).Value = CourseTypeID
        dbCon.Open()
        Dim result = cmd.ExecuteScalar

        If result Is Nothing OrElse result Is DBNull.Value Then
            Return String.Empty
        Else
            Return result.ToString()
        End If
    End Using           ' close, dispose of conn
End Using               ' dispose of DBCommand

为了减少缩进,您可以将项目“堆叠”到一个 Using 块中:

Using connx As New MySqlConnection(MySQLConnStr),
    cmd As New MySqlCommand(sql, connx)
    ...
End Using

注意第一行末尾的逗号。

如果这不是您泄漏的原因,我会感到惊讶(当然所有代码都需要更改)。

【讨论】:

    猜你喜欢
    • 2013-08-20
    • 1970-01-01
    • 2011-10-07
    • 2013-09-01
    • 2015-10-02
    • 1970-01-01
    • 1970-01-01
    • 2012-08-03
    • 1970-01-01
    相关资源
    最近更新 更多