需要管理 MySql 连接的帮助

发布于 2024-09-01 10:41:53 字数 462 浏览 5 评论 0 原文

我无法找到连接池的清晰解释。我正在使用从 mysql.com 下载的 .NET 连接器构建一个应用程序。该应用程序仅需要一个数据库连接,但将在我的网络上大约 6 台计算机上同时运行。通常,我会在启动时创建连接并保留它。但我看到很多人发帖说这是不好的做法。我还担心超时。我的应用程序将 24/7 运行,并且可能会长时间没有数据库活动。

我倾向于以下内容:

using (MySqlConnection conn = new MySqlConnection(connStr))
{
    conn.Open();
    // use connection
}

但我不确定我是否理解背景中发生的事情。这实际上是关闭连接并允许 gc 杀死对象,还是有内置的池行为来保留对象并在我下次尝试创建对象时重新传递它?

我当然不希望每次访问数据库时应用程序都通过网络重新进行身份验证。

有人能给我一些建议吗?

I'm having trouble finding a clear explanation of connection pooling. I'm building an app using the .NET connector I downloaded from mysql.com. The app only needs one db connection but will be running simultaneously on about 6 machines on my network. Normally, I'd create the connection at startup and just leave it. But I'm seeing lots of posts from people who say that's bad practice. Also I'm concerned about timeouts. My app will run 24/7 and there may be extended periods without database activity.

I'm leaning toward the following:

using (MySqlConnection conn = new MySqlConnection(connStr))
{
    conn.Open();
    // use connection
}

But I'm not sure I understand what's going on in the background. Is this actually closing the connection and allowing gc to kill the object, or is there a built in pooling behavior that preserves the object and redelivers it the next time I try to create one?

I certainly don't want the app reauthenticating across the network every time I hit the database.

Can anyone offer me some advise?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

感悟人生的甜 2024-09-08 10:41:53

.net 提供商习惯在这种情况下使用连接池。

连接应该在您使用结束时返回到池中。

我还没有使用 mysql 分析器进行研究,但我有依赖它的代码 - 没有遇到任何问题。

更新:我只是查看了在处置过程中完成的调用,它肯定会进行连接池,即它最终调用:

internal void CloseFully()
{
    if (this.settings.Pooling && this.driver.IsOpen)
    {
        if ((this.driver.ServerStatus & ServerStatusFlags.InTransaction) != 0)
        {
            new MySqlTransaction(this, IsolationLevel.Unspecified).Rollback();
        }
        MySqlPoolManager.ReleaseConnection(this.driver);
    }
    else
    {
        this.driver.Close();
    }
    this.driver = null;
}

更新2/回答评论: MySqlConnection 实例是不同的一,因为 using 语句 仅处理处置(释放资源)。因此,您不需要检查它是否已关闭。 MySqlConnection 在内部使用其他类/实例,即它获取适当的实例。这对您的代码是透明的,因此您可以像使用新的+不同的连接一样使用它/就像在您发布的代码中一样。

就像你说的,为了能够重用较低级别的连接(在mysql连接器代码中称为Driver),每个池都是由连接字符串决定的。

Its customary of the .net providers to use connection pooling in that scenario.

The connection should be just returning to the pool at the end of your using.

I haven't looked under the hook with a mysql profiler, but I have code in place that depends on it - haven't had trouble with it.

Update: I just looked at the calls done during dispose and it definitely does connection pooling i.e. it ends up calling:

internal void CloseFully()
{
    if (this.settings.Pooling && this.driver.IsOpen)
    {
        if ((this.driver.ServerStatus & ServerStatusFlags.InTransaction) != 0)
        {
            new MySqlTransaction(this, IsolationLevel.Unspecified).Rollback();
        }
        MySqlPoolManager.ReleaseConnection(this.driver);
    }
    else
    {
        this.driver.Close();
    }
    this.driver = null;
}

Update 2 / answering the comment: the MySqlConnection instance is a different one, as the using statement just deals with disposing (freeing of resources). Because of that, you don't need to check if its closed. The MySqlConnection internally uses other classes / instances, which is were it grabs the approppiate instance. That's transparent to your code, so you use it just like if it were a new+different connection / just like in the code you posted.

Like you said, in order to be able to reuse the lower level connection (called Driver in the mysql connector code), each pool is determined by the connection string.

青萝楚歌 2024-09-08 10:41:53

根据这篇文章,连接保持活动状态,并且关闭前默认池化 60 秒。

According to this post the connections are kept alive and pooled by default for 60 seconds before being closed.

温柔戏命师 2024-09-08 10:41:53

断开连接的模型是全世界使用最广泛的模型,尽管没有一次又一次地滥用身份验证。

断开连接模式

以下是您希望在大多数时间断开连接工作的一些原因:

  1. 为您的数据库服务器购买的 CLA(客户端许可协议)数量(好吧,这里并不适用,因为它是 MySQL) ;
  2. 如果同时连接的人太多,则会降低 DBE(数据库引擎)的速度;
  3. 保持连接打开会使网络保持繁忙,而太繁忙的网络更有可能出现故障;
  4. 当用户编辑客户详细信息时,他不需要保留与数据库服务器的连接,并且可能锁定一行或数据表,这会导致大的并发锁定问题。

此代码:

using(MySqlConnection conn = new MySqlConnection(connStr)) {
    if (conn.State == ConnectionState.Closed)
        try {
            conn.Open();
        } catch (MySqlException ex) {
            // Exception handling here...
        }
    // Use of connection here...
}

using 关键字用于自动处置其中实例化的对象,如文章参考所述:

定义一个范围,在该范围之外将处理一个或多个对象。

这样,您可以确保一旦不再需要连接,就可以将其丢弃。因此,是的,一旦该连接再次实例化,将需要新的身份验证,因为它不再存在。这里会在短时间内进行一些民意调查,但这不是您需要担心的。

连接模式

为了确保在整个应用程序中仅使用一个此类连接,您应该将其用作 单例。但是,一旦连接字符串发生更改,有一天,您必须确保所有应用程序都关闭并重新打开,以便该连接获得刷新的连接字符串。这是不可行的,但我不知道你的背景。

使用企业库数据访问应用程序块

为了使连接池易于管理,您可能需要使用企业库 数据访问应用程序块

DAAB 是一个易于使用、完全可配置的数据访问层,由 Microsoft 工程师和其他参与公司设计。那么,管理连接池就可以像 1-2-3 一样简单!

我认为使用 DAAB 可以让您受益匪浅,它可以在 XML 文件中完全配置,并且需要很少的维护。

编辑 如果我可以更进一步,我可能会考虑将 Façade 设计模式与工厂一起使用。

有效使用外观和工厂设计模式

拥有“智能”外观,正是它为您提供了所需的连接。因此,这是一个简单的示例(假设您有一个名为“DefaultConnectionString”的项目设置):

public static class ApplicationFacade {
    private static readonly ApplicationFactory _applicationFactory = new ApplicationFactory();

    public static DefaultConnectionString {
        get {
            return Properties.Settings.Default.DefaultConnectionString;
        }
    }

    public static IList<ICustomer> GetCustomers() {
        using(var connection = OpenConnection())
           _applicationFactory.GetCustomers(connection);
    }

    public MySqlConnection OpenConnection() {
        var newConnection = new MySqlConnection(DefaultConnectionString);
        try {
            newConnection.Open();
        } catch (Exception ex) {
            // Exception handling...
        }
        return newConnection;
    }
}

internal sealed class ApplicationFactory {
    internal ApplicationFactory() {
    }

    internal IList<ICustomer> GetCustomers(MySqlConnection connection) {
        if (connection.State != ConnectionState.Open)
            throw new InvalidOperationException()

        IList<ICustomer> customers = new List<ICustomer>();

        var command = new MySqlCommand(connection, @"select * from Customers");
        // Place code to get customers here...

        return customers;
    }
}

// So you'll be able to use share the same connection throught your factory whenever needed, preventing the overkill of authentication over and over again. Here's how this would be used:

public partial class MainForm : Form {
    private void PopulateGrid() {
        dataGridView1.DataSource = ApplicationFacade.GetCustomers();
        // And you never care about the connection! All you want is the list of customers, that's all!
    }
}

这是我在开发项目中经常使用的模式。它允许我的类库有一个入口点,而且它们非常易于使用。

嗯,这可能超出了您的要求,但我希望它有所帮助。

The disconnected model is the most used throughout the world, though not abusing on authentication over and over again.

Disconnected Mode

Here are some reason why you want to work disconnected most of the time:

  1. The number of CLA (Client Licences Agreements) bought for your database server (well, not really applicable here as it is MySQL);
  2. If too many people are connected at once, this slows down the DBE (Database Engine);
  3. Keeping connections opened keeps the network busy, and too busy network are more likely to fail;
  4. While a user is editing, let's say a customer details, he doesn't need to preserve his connection to the database server, and perhaps lock a row or a data table, which would result of big concurrent locking problems.

This code:

using(MySqlConnection conn = new MySqlConnection(connStr)) {
    if (conn.State == ConnectionState.Closed)
        try {
            conn.Open();
        } catch (MySqlException ex) {
            // Exception handling here...
        }
    // Use of connection here...
}

The using keyword is used to automatically dispose objects instantiated within it as the article reference states:

Defines a scope, outside of which an object or objects will be disposed.

This way, you ensure that once the connection is no longer required, you dispoe of it. So yes, a new authentication will be required once this connection is instantiated again, as it no longer exists. There's a little polling done here for a short time, but this is nothing you need to worry about.

Connected Mode

In order to ensure the use of only one such connection throughout your application, you should use it as a singleton. However, once your connection string changes, someday, you'll have to ensure that all the application gets closed and reopen, so that this connection gets a refreshed connection string. That is not viable, but I don't know your context.

Using Enterprise Library Data Access Application Block

In order to bring your connection pool manageable, you may want to use the Enterprise Library Data Access Application Block.

The DAAB is an easy to use, fully configurable data access layer engineered by Microsoft engineers and other participating companies. Then, managing connection pool can be as easy as 1-2-3!

I think you could gain a lot using the DAAB which is fully configurable within XML file and requires very low maintenance.

EDIT If I may push a little further, I would perhaps consider using the Façade design pattern with Factories.

Using Facade and Factories Design Pattern Effectively

Having an "intelligent" façade, it is this that provide you with the connection you need. As such, here's a simple example (assuming you have a project setting called "DefaultConnectionString"):

public static class ApplicationFacade {
    private static readonly ApplicationFactory _applicationFactory = new ApplicationFactory();

    public static DefaultConnectionString {
        get {
            return Properties.Settings.Default.DefaultConnectionString;
        }
    }

    public static IList<ICustomer> GetCustomers() {
        using(var connection = OpenConnection())
           _applicationFactory.GetCustomers(connection);
    }

    public MySqlConnection OpenConnection() {
        var newConnection = new MySqlConnection(DefaultConnectionString);
        try {
            newConnection.Open();
        } catch (Exception ex) {
            // Exception handling...
        }
        return newConnection;
    }
}

internal sealed class ApplicationFactory {
    internal ApplicationFactory() {
    }

    internal IList<ICustomer> GetCustomers(MySqlConnection connection) {
        if (connection.State != ConnectionState.Open)
            throw new InvalidOperationException()

        IList<ICustomer> customers = new List<ICustomer>();

        var command = new MySqlCommand(connection, @"select * from Customers");
        // Place code to get customers here...

        return customers;
    }
}

// So you'll be able to use share the same connection throught your factory whenever needed, preventing the overkill of authentication over and over again. Here's how this would be used:

public partial class MainForm : Form {
    private void PopulateGrid() {
        dataGridView1.DataSource = ApplicationFacade.GetCustomers();
        // And you never care about the connection! All you want is the list of customers, that's all!
    }
}

That is a pattern that I often use in my development projects. It allows one single entry point to my class libraries, and they're very easy to use.

Well, that's perhaps more than what you asked for, but I hope it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文