0

我根据答案重写了以下内容。

我有一个网站导致数据库服务器上出现高 CPU 问题,以至于服务器变得不可用。回收应用程序池可解决此问题。根据服务器管理员http://www.microsoft.com/downloads/details.aspx?FamilyID=28bd5941-c458-46f1-b24d-f60151d875a3&displaylang=en显示有大约一个小时的活动线程。

在我们向应用程序添加 Web 表单路由之前,与数据库的交互非常简单且有效。

它们仅由整个应用程序中的此类代码组成。是的,这段代码并不完美,但不是这段代码有问题,因为在我们添加路由之前,没有问题。

  private string GetPublishedParagraphs()
  {
    string query, paragraphs = "";
    try
    {

      m_sql_connection = new SqlConnection(m_base_page.ConnectionString());
      query = "select * from PublishedParagraphs where IDDataContent_page='" + m_IDDataContent_page + "'";

      SqlDataAdapter da = new SqlDataAdapter(query, m_sql_connection);
      DataSet ds = new DataSet();
      da.Fill(ds, "paragraph");

      if (ds.Tables["paragraph"].Rows.Count > 0)
        paragraphs = (string)ds.Tables["paragraph"].Rows[0]["paragraphs"];

      ds.Dispose();
     da.Dispose();
   }
   finally
   {
     m_sql_connection.Close();
   }

   paragraphs = paragraphs.Replace("™", "™");

   return paragraphs;
}

连接字符串如下所示:

server_name; User ID=server_user; Password=server_password

我们仔细检查了对数据库 Open() 的每次调用都跟在 Close() 之后。当我们在本地运行应用程序时,我们通过查看它们来测量没有打开的连接,并且连接数不会通过以下方式增加:

SELECT SPID,
       STATUS,
       PROGRAM_NAME,
       LOGINAME=RTRIM(LOGINAME),
       HOSTNAME,
       CMD
FROM  MASTER.DBO.SYSPROCESSES
WHERE DB_NAME(DBID) = 'TEST' AND DBID != 0 

(但是,如果我们不关闭连接,就会出现泄漏)

我们的应用程序与它工作时的区别在于通过 Web 表单添加了 asp.net 路由。这也会调用数据库,但会在连接打开后再次关闭它们。

我们不确定我们还能检查什么。程序员有什么想法吗?

回答

我们通过 Query Profiler 发现了问题。这向我们展示了一个使用率很高的查询。将查询追溯到代码显示了一遍又一遍地调用数据库的无限循环。很难找到,因为循环是由机器人调用网站上不再存在的页面启动的。

4

3 回答 3

1
  • 在您显示的代码中, ds 和 da .Dispose 进入 finally 块。更好的是,使用 using () {} 结构来确保对象处置

  • 将自己的字符串构建为查询的模式不仅是一个巨大的安全漏洞,而且效率也非常低。请改用存储过程和参数。

  • 进程查询过于严格。如果您遇到导致连接被拒绝的资源问题,它不会仅限于单个数据库。关于我唯一要限制的是当前命令 --> where spid != @@spid

  • 真的需要一些错误信息和上下文——它们在哪里被看到?告诉我们更多信息,我们可以提供帮助!

祝你好运!


  • 首先,很棒的附加信息!感谢您的跟进。

  • 我建议如果您非常确定您发布的代码与您将其从问题中删除的问题无关。然而,这些问题不仅仅是“不完美”的问题。正确处理内存密集型对象 - 初始开发人员认为足够密集以包含 dispose() 方法的对象 - 与数据库交互的对象 - 当您遇到无法解释的数据库问题时,无论如何我认为这不是一个小问题.

  • 我做了一些谷歌搜索,发现了这个。虽然我不会说这是问题所在,但它确实让我开始思考。当“活跃了大约一个小时的线程”时,是在数据库服务器还是在 Web 服务器上测量的?我不熟悉该工具,但是您可以使用该工具发布日志吗?

  • 在网络服务器上,您是否能够监控路由代码的操作?路由代码是否以防止无限循环的方式编写/设置 - 请参阅此处的问题和答案文本

  • 在我回答的早期版本中,我对您说,仅查看特定数据库的 @ 连接对您的任务来说过于严格。对您问题的澄清并不表示您已更正此查询。我会建议:


    SELECT 
        is_being_blocked = sp.blocked
        , sp.cpu
        , DB_NAME ( dbid )
        , sp.status
        , LOGINAME=RTRIM(sp.LOGINAME)
        , sp.HOSTNAME
        , sp.Hostprocess
        , sp.CMD
    FROM  SYSPROCESSES sp
    WHERE spid != @@SPID
    ORDER BY 
        sp.blocked ASC
        , sp.cpu DESC

  • 日志 - 在重新启动 Web 应用程序之前 10 分钟和之后 10 分钟的时间跨度内,SQL Server 日志的内容是什么?

  • 您是否尝试过并且这个问题在开发中是否可以重复?

  • 请告诉我们以下语句对您的应用程序的含义 - 错误消息或其他:“服务器不可用”

  • 我强烈建议您使用探查器启动 sql server 的跟踪。根据您在这个问题中所说的话,这就是我将跟踪保存到表(在另一个 sql server 上)或保存到文件(在另一台机器上而不是 sql server 框上)的内容。此跟踪用于查找严重阻碍生产的问题。这不是您想要定期运行的东西。

我会捕捉这些事件

* Errors and Warnings - all of them
* Security Audit 
** Audit Login
** Audit Logout
* Sessions
** Existing Sessions
* TSQL
** SQL: Stmt Starting
** SQL: Stmt Completed
** Prepare SQL
** Exec Prepared SQL

除了预设,我不会使用任何过滤器。

于 2010-07-01T01:02:38.433 回答
1

您是否尝试在 SQL Server Management Studio 中运行“sp_who2”查询以查看有多少活动数据库连接,因为代码看起来不错。

您可能希望将m_sql_connection变量的范围从类范围更改为成员范围。也许这可能是你的问题?

于 2010-07-01T02:00:48.593 回答
0

“用完应用程序池”是什么意思?你是说连接池吗?

如果您的数据库似乎工作过度,也可能是因为用户可以自由支配您的 m_IDDataContent_page 变量。此数据访问代码易受 sql 注入攻击。

于 2010-07-01T00:33:59.200 回答