繁体   English   中英

轮询数据库时最好的方法是什么?

[英]What is the best approach while polling database?

目前我正在做一个作业,其中我需要访问n个服务器的数据库以获取一些结果。我通过遍历服务器列表并为集合中的每个服务器提出任务来实现这一目标。 该任务调用一个函数,该函数基本上与数据库建立连接,运行查询并与数据库断开连接。

我的问题是,通过对数据库的每次轮询建立一个新的连接并每次都关闭它,我做对了吗?或者这是保持数据库连接打开并获取结果,然后在下一次轮询迭代中保持打开状态的最佳方法。 每次计时器都会调用PollingServerTimer()。我的轮询计时器为3秒。

像这样的东西:

private void PollingServerTimer(object sender, ElapsedEventArgs e)
{            
    foreach (var item in ServerOperationCollHandler)
    {
        if (item.RebootStatus != true)
        {
            PushItemIntoQueue(item);
        }
    }
}

public void PollingServerQueue()
{
    while (isRunning)
    {
        this.waitHandle.WaitOne();

        lock (syncRoot)
        {
            if (ServerQueue.Count > 0)
            {
                ServerOperationDataModel obj;
                try
                {
                    ServerQueue.TryDequeue(out obj);

                    Task GetCountFromDbTask = new Task(() => GetCountFromDb(obj));
                    GetCountFromDbTask.Start();

                    this.waitHandle.Reset();
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Problem encountered while finding iterim and recovery count");
                    isRunning = false;
                    break;
                }
            }
        }
    }
}

public void GetCountFromDb(ServerOperationDataModel obj)
{
    ServerOperationDataModel serverObject = (ServerOperationDataModel)obj;
    DataBaseHandler dbHandler = new DataBaseHandler(serverObject.DataBaseIP, serverObject.DataBasePort, serverObject.DataBaseName, serverObject.DataUserName, serverObject.DataUserPassword);

    int attempts = 0;

    do
    {
        try
        {
            dbHandler.connect();
        }
        catch (Exception ex)
        {
            break;
            serverObject.DataBaseConnectionStatus = false;
            log.Error("Connection attempt " + attempts + " failed.Retrying connection. Exception details :" + ex.ToString());
            attempts++;
        }
    } while (attempts < _connectiontRetryAttempts && !dbHandler.isConnected());

    if (dbHandler.isConnected())
    {
        /*Fetch Result and then get disconnect*/
        dbHandler.disConnect();
    }
    else
    {
        //string msgLog = "Server : " + obj.ServerComponentIdentifier + " | " + obj.IPstring + "Connection cannot be established with the DB: " + obj.DataBaseIP + " | "+ obj.DataBasePort + " | " + obj.DataBaseName + " after a series of retries";
        //LoggerUpdate.LogMessage(msgLog, LOGTYPE.POLLINGDATABASE, LoggerUpdate.ReturnLogDisplayObject(DateTime.Now, obj.ServerComponentIdentifier + "|" + obj.IPstring, Convert.ToInt16(LOGTYPE.POLLINGDATABASE), obj, msgLog));
    }
}

我一点也不担心。 假设您连接到SQL Server(或类似的企业级DBMS),则数据库连接将在客户端池中进行,这意味着仅当客户端首次连接到特定数据库(正式而言:连接到新数据库,以前看不见的连接字符串),然后到同一数据库的每个连接几乎不花任何费用。

如果没有用于池化,则应用程序服务器将无法处理数百个查询同一数据源的并发浏览器连接。 每3秒您将需要的不仅仅是连接,否则会导致耗尽服务器或客户端资源的任何风险。

您可以阅读有关池工作原理的更多信息

https://docs.microsoft.com/zh-cn/dotnet/framework/data/adonet/sql-server-connection-pooling

附带说明:您应该稍微完善一下代码。

例如,你有

GetCountFromDb(ServerOperationDataModel obj)

但是之后

ServerOperationDataModel serverObject = (ServerOperationDataModel)obj;

为什么需要将obj转换为相同类型的另一个变量?

catch子句中,您有break和它下面的一些代码似乎无法到达。

看一下.NET SqlDependency对象。 这使您可以向数据库注册查询,并使用OnChange处理程序在查询结果更改时接收通知。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM