2

我有一个 VB.NET 应用程序在我的开发机器上运行良好,但在我的服务器上产生间歇性错误。事件日志如下(对不起,如果这超出了需要发布的内容,但我的问题之一是解释事件日志)。

当两个或更多人同时运行 Web 应用程序时,服务器上似乎发生了错误。通常它看起来像挂起然后超时。然后,如果我尝试返回运行该应用程序,我会收到以下错误,直到我在服务器上重新启动网站。到目前为止,如果只有一个人运行该应用程序,则没有问题。我的服务器供应商表示这表明这是一个应用程序错误(与内存、服务器等不同)。该应用程序抓取输入数据,查询多个 MS Access 数据库(使用 ADODB)并通过 AJAX 返回一些值。这是一个相当密集的计算应用程序,需要几秒钟才能运行。

我知道我应该提供生成错误的代码,但我的第一个问题是我不确定如何读取事件日志。这在哪里告诉我错误事件发生了?我认为它与访问数据库有关?

目前,它只是读取数据,所以我假设它不可能是数据库以某种方式被锁定?我不相信我曾经打开过一个以上的连接或打开过一个以上的记录集,并且我打开/关闭每个数据库查询(同样,它在开发机器上工作)。所以看起来它必须与多个用户有关?

一般来说,我认为我不需要担心人们同时访问数据库或应用程序?或者这是意料之中的,即我是否需要总是在有问题的代码周围有一个 Try/Catch (一旦我弄清楚什么代码有问题)来捕获这些错误?

另外,我不知道这是否正常或与问题有关 - 事件日志显示的路径不是来自服务器,而是来自我的开发机器(以 C:\MyFiles... 开头的那些)。服务器如何知道这些路径?这是存储在上传到服务器的二进制 DLL 中的东西吗?

再次,如果我错过提供更多信息,我提前道歉。但也许这些初步问题可以让我更接近问题的根源。这似乎是一个有用的论坛。

在此先感谢,查克

注意:部分 IP 地址已被屏蔽

Log Name:      Application
Source:        ASP.NET 4.0.30319.0
Date:          8/6/2013 2:48:00 PM
Event ID:      1309
Task Category: Web Event
Level:         Warning
Keywords:      Classic
User:          N/A
Computer:      358797-web1
Description:
Event code: 3005

Event message: An unhandled exception has occurred.
Event time: 8/6/2013 2:48:00 PM 

Event time (UTC): 8/6/2013 7:48:00 PM 

Event ID: ca3280fb485345c194349a42e6e81a85 

Event sequence: 66 

Event occurrence: 11 

Event detail code: 0 


Application information: 

Application domain: /LM/W3SVC/12/ROOT-1-130202909916484475 

Trust level: Full 

Application Virtual Path: / 

Application Path: C:\inetpub-illustrations\wwwroot\ 

Machine name: 358797-WEB1 


Process information: 

Process ID: 760 

Process name: w3wp.exe 

Account name: NT AUTHORITY\SYSTEM 


Exception information: 

Exception type: COMException 

Exception message: Operation is not allowed when the object is open.

   at ADODB.ConnectionClass.set_ConnectionString(String pbstr)
   at clsCalc_IllustrationValues.mod_DLLUtilities.util_OpenMyDBConnection(String& strDBName,
   String& strPassword) in C:\MyFiles\Visual Studio Projects   
   \clsCalc_IllustrationValues\mod_DLLUtilities.vb:line 130
   at clsCalc_IllustrationValues.clsConvertedActVal.GetPlanData(Int32& eLOB_ActValCalcs, 
   usrUserInputType& usrUserInput, usrPolicyValuesType&    usrPolicyValues) in C:\MyFiles\Visual 
   Studio Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line 2668
   at clsCalc_IllustrationValues.clsConvertedActVal.TradSolve() in C:\MyFiles\Visual Studio 
   Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line    2063
   at clsCalc_IllustrationValues.clsActValDotNet.DoSingleSolve(DataSet dsDataSet) in
   C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues   \clsActValDotNet.vb:line 945
   at _Default.CallSingleSolve() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 2997
   at _Default.InitializeAllControls() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line
   354
   at _Default.Page_Load(Object sender, EventArgs e) in C:\inetpub-
   illustrations\wwwroot\Default.aspx.vb:line 65
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)




Request information: 

Request URL: http://xx.xx.xx.250/Default.aspx 

Request path: /Default.aspx 

User host address: xx.xx.xx.91 

User:  
    Is authenticated: False 

Authentication Type:  

Thread account name: NT AUTHORITY\SYSTEM 


Thread information: 

Thread ID: 18 

Thread account name: NT AUTHORITY\SYSTEM 

Is impersonating: False 

Stack trace:    at ADODB.ConnectionClass.set_ConnectionString(String pbstr)
   at clsCalc_IllustrationValues.mod_DLLUtilities.util_OpenMyDBConnection(String& strDBName, String& strPassword) in C:\MyFiles\Visual Studio Projects   \clsCalc_IllustrationValues\mod_DLLUtilities.vb:line 130
   at clsCalc_IllustrationValues.clsConvertedActVal.GetPlanData(Int32& eLOB_ActValCalcs, usrUserInputType& usrUserInput, usrPolicyValuesType&    usrPolicyValues) in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line 2668
   at clsCalc_IllustrationValues.clsConvertedActVal.TradSolve() in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line    2063
   at clsCalc_IllustrationValues.clsActValDotNet.DoSingleSolve(DataSet dsDataSet) in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues   \clsActValDotNet.vb:line 945
   at _Default.CallSingleSolve() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 2997
   at _Default.InitializeAllControls() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 354
   at _Default.Page_Load(Object sender, EventArgs e) in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 65
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
Custom event details: 

Event Xml:
<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="ASP.NET 4.0.30319.0" />
    <EventID Qualifiers="32768">1309</EventID>
    <Level>3</Level>
    <Task>3</Task>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2013-08-06T19:48:00.000Z" />
    <EventRecordID>30445</EventRecordID>
    <Channel>Application</Channel>
    <Computer>358797-web1</Computer>
    <Security />
  </System>
  <EventData>
    <Data>3005</Data>
    <Data>An unhandled exception has occurred.</Data>
    <Data>8/6/2013 2:48:00 PM</Data>
    <Data>8/6/2013 7:48:00 PM</Data>
    <Data>ca3280fb485345c194349a42e6e81a85</Data>
    <Data>66</Data>
    <Data>11</Data>
    <Data>0</Data>
    <Data>/LM/W3SVC/12/ROOT-1-130202909916484475</Data>
    <Data>Full</Data>
    <Data>/</Data>
    <Data>C:\inetpub-illustrations\wwwroot\</Data>
    <Data>358797-WEB1</Data>
    <Data>
    </Data>
    <Data>760</Data>
    <Data>w3wp.exe</Data>
    <Data>NT AUTHORITY\SYSTEM</Data>
    <Data>COMException</Data>
    <Data>Operation is not allowed when the object is open.
   at ADODB.ConnectionClass.set_ConnectionString(String pbstr)
   at clsCalc_IllustrationValues.mod_DLLUtilities.util_OpenMyDBConnection(String&amp; strDBName, String&amp; strPassword) in C:\MyFiles\Visual Studio    Projects\clsCalc_IllustrationValues\mod_DLLUtilities.vb:line 130
   at clsCalc_IllustrationValues.clsConvertedActVal.GetPlanData(Int32&amp; eLOB_ActValCalcs, usrUserInputType&amp; usrUserInput, usrPolicyValuesType&amp;    usrPolicyValues) in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line 2668
   at clsCalc_IllustrationValues.clsConvertedActVal.TradSolve() in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line    2063
   at clsCalc_IllustrationValues.clsActValDotNet.DoSingleSolve(DataSet dsDataSet) in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues   \clsActValDotNet.vb:line 945
   at _Default.CallSingleSolve() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 2997
   at _Default.InitializeAllControls() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 354
   at _Default.Page_Load(Object sender, EventArgs e) in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 65
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

</Data>
    <Data>http://xx.xx.xx.250/Default.aspx</Data>
    <Data>/Default.aspx</Data>
    <Data>xx.xx.xx.91</Data>
    <Data>
    </Data>
    <Data>False</Data>
    <Data>
    </Data>
    <Data>NT AUTHORITY\SYSTEM</Data>
    <Data>18</Data>
    <Data>NT AUTHORITY\SYSTEM</Data>
    <Data>False</Data>
    <Data>   at ADODB.ConnectionClass.set_ConnectionString(String pbstr)
   at clsCalc_IllustrationValues.mod_DLLUtilities.util_OpenMyDBConnection(String&amp; strDBName, String&amp; strPassword) in C:\MyFiles\Visual Studio
   Projects\clsCalc_IllustrationValues\mod_DLLUtilities.vb:line 130
   at clsCalc_IllustrationValues.clsConvertedActVal.GetPlanData(Int32&amp; eLOB_ActValCalcs, usrUserInputType&amp; usrUserInput, usrPolicyValuesType&amp;    usrPolicyValues) in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line 2668
   at clsCalc_IllustrationValues.clsConvertedActVal.TradSolve() in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues\clsConvertedActVal.vb:line    2063
   at clsCalc_IllustrationValues.clsActValDotNet.DoSingleSolve(DataSet dsDataSet) in C:\MyFiles\Visual Studio Projects\clsCalc_IllustrationValues   \clsActValDotNet.vb:line 945
   at _Default.CallSingleSolve() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 2997
   at _Default.InitializeAllControls() in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 354
   at _Default.Page_Load(Object sender, EventArgs e) in C:\inetpub-illustrations\wwwroot\Default.aspx.vb:line 65
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
</Data>
  </EventData>
</Event>

跟进更新(我查看了帮助 - 我认为我通过编辑原始问题来做到这一点是正确的。让我知道我是否应该以不同的方式跟进)。还有更多我试图缩小问题的范围(所以我理解是否有人等待回答),但我想按照要求更新代码。

首先,感谢您编辑上面的敏感信息 - 我没有意识到这是一个问题。无论如何,我发现我的代码的旧部分(我认为错误所在)正在使用不同的代码访问数据库,因此我对其进行了更新和整合,以便我所有的数据库访问都在同一个代码中进行:

Private Function GetDataSet_ODBC() As System.Data.DataSet

    Dim dsDataSet As New System.Data.DataSet

    If Me.bWriteToTraceFile Then Me.WriteToTextFile("START GetDataSet_ODBC", System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", False)
    Dim DataAdapter As New System.Data.Odbc.OdbcDataAdapter
    If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Created DataAdapter", System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
    Dim i As Integer
    Dim iUBound As Integer
    Dim iRetryCount As Integer
    Dim dStart As Double
    Dim dFinish As Double

    DataAdapter.SelectCommand = New System.Data.Odbc.OdbcCommand
    If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Created new command", System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
    With DataAdapter.SelectCommand
        .CommandType = CommandType.StoredProcedure
        .Connection = New System.Data.Odbc.OdbcConnection
        .Connection.ConnectionTimeout = 15
        .Connection.ConnectionString = "Driver={Microsoft Access Driver (*.mdb)};" & _
            "DBQ=" & tDBPath & tDBName & ";UID=;PWD=" & tDBPassword
        If Me.bWriteToTraceFile Then Me.WriteToTextFile("  ConnectionString=" & .Connection.ConnectionString, System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
    End With

    DataAdapter.InsertCommand = New System.Data.Odbc.OdbcCommand
    With DataAdapter.InsertCommand
        .CommandType = CommandType.StoredProcedure
        .Connection = DataAdapter.SelectCommand.Connection
    End With
    DataAdapter.SelectCommand.Connection.Open()
    If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Connection opened", System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
    iUBound = UBound(usrProcedures)
    For i = 0 To iUBound
        DataAdapter.SelectCommand.CommandText = "Execute " & usrProcedures(i).tName & " " & usrProcedures(i).tParameters
        iRetryCount = 0
        Do
            Try
                If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Executing... " & Str(i) & " " & usrProcedures(i).tName, System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
                DataAdapter.Fill(dsDataSet, usrProcedures(i).tTableName)
                If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Wrote to " & usrProcedures(i).tTableName, System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
                Exit Do
            Catch
                iRetryCount += 1
                If iRetryCount = 25 Then
                    If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Still won't work", System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
                    Exit Do
                End If
                dStart = Microsoft.VisualBasic.DateAndTime.Timer
                dFinish = dStart + 1
                Do Until Microsoft.VisualBasic.DateAndTime.Timer > dFinish
                Loop
                If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Try again " & Str(iRetryCount) & " " & Str(dStart) & Str(Microsoft.VisualBasic.DateAndTime.Timer), System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)
            End Try
        Loop
    Next
    DataAdapter.SelectCommand.Connection.Close()
    If Me.bWriteToTraceFile Then Me.WriteToTextFile("  Connection closed", System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)

    DataAdapter = Nothing
    If Me.bWriteToTraceFile Then Me.WriteToTextFile("FINISH GetDataSet_ODBC", System.AppDomain.CurrentDomain.BaseDirectory & "..\TraceFiles\TraceODBC.txt", True)

    Return dsDataSet

End Function

我还在没有打开“DEBUG”的情况下将构建的代码提升到服务器以加快速度。这可能是调试时的错误(我将撤消该错误)。现在,当两个人同时访问数据库时,它只会挂在第二个人身上。但是,现在我可以关闭第二个人浏览器,返回并正常运行应用程序,而无需重新启动网站。我尝试了重试次数,并正在处理跟踪文件以查看挂断的位置,但也许有些东西对你来说很突出。

仅供参考 - 上面的代码接受一个 usrProcedure() 数组,其中包含存储的 Access 参数查询的名称、参数和我想要返回的数据表的名称。一个数据集中可能有多达 10 个大部分是小表(很多只有 1 条记录,可能是一两个有 100 条记录)。我尝试只访问数据库几次,但也许我一次检索太多数据的操作过度了?但是我有一个非常强大的服务器(我认为)(专用的 Window Server 2008 Enterprise,版本 6.0 Build 6002,SP2,64 位,8gb RAM,AMD 2200 Mhz 4 核处理器——此时几乎没有流量,由 Rackspace 托管)。

无论如何,我猜测(但会尝试通过跟踪验证),第二个人要么最终循环通过 Tries,然后因为没有数据而挂起,或者挂在 Try 上。

最后,我在两个地方点击了这个数据库访问代码(一个用于检索输入控制数据,另一个用于计算)。第一次从我的页面后面的未编译代码调用代码。这似乎永远不会挂起(尽管访问的数据量大致相同,如果不是更多的话)。上面的代码在一个已编译的 DLL “实用程序”项目中。第二次,这个代码是从另一个 DLL 项目中调用的,它负责我的计算。这是事情挂起的地方。不确定这是否相关,但只是试图列出所有模式/线索。

列出的代码是否提供了任何线索?

在此先感谢,查克

后续更新 #2好的,我在整个代码中写入跟踪文件(使用 SessionID 作为文件名的一部分),以尝试查明错误实际发生的位置。仍然出现的问题是当两个用户同时点击应用程序时。一个运行成功,另一个有未处理的 3005 错误。但是,现在的错误不是上面提到的“试图打开”错误(显然我已经修复了)。现在 3005 错误发生在代码中的各个点,通常在事件查看器中表明某行有一个空变量。每个用户都发出相同的请求,因此应该得到相同的结果。我的跟踪文件告诉我,我在两个用户实例中都从数据库中读取了相同数量的记录,但其中一个实例在读取数据后的某个时间出现了错误。我有很多代码,错误发生在不同的地方,所以我不确定要发布什么。我现在正在捕获 Global.asax 文件中的错误,以重定向用户重新登录并再次运行应用程序。该应用程序在单独运行时第二次运行良好。

看起来这两个实例在某种程度上并不完全独立,并且一个实例正在以某种方式从另一个实例中删除对象或数据。根据请求到达服务器的精确时间,错误似乎发生在不同的点。我在跟踪文件中放置的日期戳似乎表明一个实例在另一个实例完成请求时出错。我检查了共享例程并消除了这些例程。我已经检查以确保调用的 DLL 的每个实例都被声明为“新的”。另外,我注意到写入跟踪文件的行并不总是按照它们应该按照代码的顺序显示。

ASP.NET 是否会自动执行代码的任何异步运行而无需我做任何特别的事情,这会不会把事情搞砸?我没有尝试明确地做任何异步的东西,因为它看起来很复杂,但是我需要在这里管理一些东西吗?

我还应该寻找什么?

再次提前感谢

4

2 回答 2

0

你得到的错误是你试图打开一个已经打开的连接。您处理连接的方式可能存在问题。很高兴看到代码。

此外,您应该始终考虑同时访问数据库的多个人。尝试在多个选项卡中打开您的应用程序,您可能会看到同样的问题发生。

于 2013-08-07T19:26:51.367 回答
0

我发现了我的问题。希望这将帮助其他有类似问题的人。

事实证明,我在常规代码模块中而不是在类模块中全局声明了一些重要变量,它们都是我的 Visual Studio 解决方案中一个项目的一部分。我没有意识到只有类模块中的代码和变量对于服务器上的每个用户都是分开的。我被他们都编译到同一个 DLL 文件中的事实所抛弃,因此认为整个 DLL 被“复制”了。当我在 Global.asax 中捕获错误、中止会话并重定向页面时,我意识到了这一点。然后我可以清楚地看到,当变量重新初始化时,第二个用户立即导致第一个用户出错(最初,我认为这是第二个用户出错了)。然后用谷歌搜索告诉我我需要知道什么。

我认为这实际上也是上述原始数据库问题的原因。我以某种方式错过的一些旧代码正在从常规代码模块访问数据库,从而导致与数据库发生冲突。当我摆脱该代码并转换为从我现在用来访问数据库的类模块中检索数据时,这个问题得到了修复(尽管当时我没有意识到它是如何修复的)。

因此,一旦我将所有变量声明移入类模块并进行了一些重大更改以通过参数将变量传递给子例程中的常规模块代码,问题就解决了(至少到目前为止)。

于 2013-08-20T16:11:31.897 回答