处理与MySql丢失的连接

时间:2017-04-17 15:10:51

标签: c# mysql

我想检测MySql数据库的连接状态。我的数据库部署在与我的应用程序不同的服务器中,很有可能通过网络丢失与它的连接。所以我必须考虑这个场景。

这是我到目前为止所尝试的(简化的测试示例):

static string connectionString = "***";
public static MySqlConnection Connection;
static System.Timers.Timer _timer; 

static void _timer_Elapsed(object sender, ElapsedEventArgs e)
{
    try
    {
        if (Connection.State != System.Data.ConnectionState.Open)
            Connection.Open();
        // Call method to invoke MySqlCommand.ExecuteNonQuery
        mysqlCommand.ExecuteNonQuery();
    }
    catch (MySqlException ex)
    {
        Console.WriteLine("SQL EXCEPTION: " + ex);
        // Handle all type of database exceptions
        switch(ex.Number)
        {...}
    }
    catch (Exception ex)
    {
        Console.WriteLine("OTHER EXCEPTION: " + ex);
    }
}

static void Main(string[] args)
{
    Connection = new MySqlConnection(connectionString);

    _timer = new System.Timers.Timer(3000); 
    _timer.Elapsed += new ElapsedEventHandler(_timer_Elapsed);
    _timer.Enabled = true; 

    Console.ReadKey();
}

如果与MySql的连接丢失,我得到一般例外:

  

IOException:无法将数据写入传输连接:An   建立的连接被主机中的软件中止   机。

我期待MySqlException被解雇但事实并非如此。 此外,如果恢复与MySql的连接,我仍然得到IOException而不是执行查询。好像,MySqlConnection对象尚未更新,并且它并不关心新的连接状态。

  1. 处理连接丢失异常的最佳方法是什么?
  2. 如何在恢复连接时刷新MySqlConnection
  3. 注意:我无法为每个新查询实例化一个新的MySqlConnection对象,因为我尝试更改的程序有一个 Singleton }类型,只初始化一次。我知道这是一个糟糕的设计,但我现在不想改变这个设计。我只想捕获连接丢失的异常并尝试刷新MySqlConnection以继续正常工作。

2 个答案:

答案 0 :(得分:0)

如果您的MySqlConnection实例失去与MySQL服务器的连接,则不能指望实例的连接能够自动恢复或以其他方式恢复。

您需要尝试重新连接MySqlConnection的新实例。失去连接的那个现在处于终端状态,无法重复使用。

要做到这一点,我想你可以做这样的事情

  ...
  catch (MySqlException ex)
  {
     if (/*ex is a connection drop */) {
        Connection?.Dispose();
        Connection = new MySqlConnection(...);
        Connection.ConnectionString = /* your connection string */;
        Connection.Open();
     }
     else {
        throw;
     }
  }

你的设计有缺陷是正确的。如果没有测试,你的缺陷是否致命是很难说的。

这些连接实例非线程安全或以任何方式可重入。如果在计时器处理程序或线程中使用一个,则可以在该上下文中使用它。否则,如果在调用计时器或线程时它已经在使用,那么事情就会变得冒险。如果你很幸运,你会得到一个例外。如果您不太幸运,您的MySQL服务器将从您的客户端收到乱码并检测到它。如果你运气不好,你的数据就会被搞砸。

ADO.NET和MySqlConnection object implement connection pooling。这很重要,因为它会打开连接,使用它们然后关闭它们,比你预期的要便宜很多。

有时,MySQL会丢弃程序长时间保持打开状态的连接。如果这是你的问题,这篇文章可能有所帮助。 How can I change the default Mysql connection timeout when connecting through python?

答案 1 :(得分:0)

当您由于网络问题而失去连接时,连接对象不会更改Status属性,因此请在执行命令之前无法对其进行评估。 但是,数据库属性(connection.database)变为空字符串,因此您可以对其进行评估,以便可以关闭连接并恢复它:

oConn is an instance of MySQLConnection (it works on odbcconnection)

[VB.NET]
 If Not IsNothing(oConn) Then
    If (oConn.Database.Equals(String.Empty)) Then oConn.Close()
 End If

[C#]
 If (Not IsNothing(oConn)){
    If (oConn.Database.Equals(String.Empty)) oConn.Close();
 }