并发问题

时间:2011-01-21 18:49:51

标签: asp.net vb.net oracle concurrency

我们在.NET 4.0中使用Oracle DB获得了一个旧系统。 在某些时候,使用以下命令进行一些微积分并且系统“锁定”在表中注册:“SELECT [将通过微积分更新的注册表] FOR UPDATE NOWAIT”。因此,如果有人试图使用该ID计算或更新注册表,它将无法正常工作。 计算完成后,系统再次连接到DB,然后通过简单地执行Rollback命令“释放”注册表。

理论上,这对系统是正确的(我不喜欢它)。

无论如何,这是事情:如果正在计算某些东西(并且这些计算结果需要花费5分钟才能完成)并且在计算中间我关闭浏览器,注册表仍将被“锁定”,仅被解锁IIS重新启动时(实际上我不知道如果它首先被释放,我强制重启IIS,因为它花了太长时间)。

有人可以告诉我如何处理这个问题吗? 或者如果你们有更好的方法来处理这种并发性,我会很高兴。

谢谢! 加布里埃尔。

添加一些代码。 在开始演算之前,这个方法叫做:

Public Shared Sub LockAndUnlock(ByVal pTable As String, ByVal pWhere As String, ByVal pConnectionString As String, ByVal pLock As Boolean)

    Dim vConnection As OleDbConnection = New OleDbConnection(pConnectionString)
    Dim vCommand As OleDbCommand = New OleDbCommand

    Try
        vCommand.Connection = vConnection
        If (pLock) Then
            vCommand.CommandText = "SELECT * " &
                                   "  FROM   " & pTable &
                                   " WHERE   " & pWhere &
                                   " FOR UPDATE NOWAIT"

            vConnection.Open()
            vCommand.ExecuteNonQuery()
        Else
            vCommand.CommandText = "ROLLBACK"

            If (vConnection.State = ConnectionState.Closed) Then
                vConnection.Open()
            End If

            vCommand.ExecuteNonQuery()
            vConnection.Close()
        End If

    Catch ex As Exception
        Throw ex
    End Try
End Sub

如果参数pLock为True,则方法锁定。否则,它会解锁。

4 个答案:

答案 0 :(得分:0)

它不依赖于浏览器,因为事务正在执行(ASP?).NET客户端连接到Oracle服务器中的。杀死IIS将解锁它,因为它会切断数据库服务器与运行事务的数据库客户端之间的连接。

现在,这里有一个问题的关键:-)一个可以使用来自Web客户端的轮询,让服务器在没有收到足够的民意调查时检测到。但是,这有一个很大的问题,即(通常)没有办法确保启动事务的Web服务工作者恢复(我认为这可以通过一些延续设置完成,但他们虽然不常见[。]

所以,我在这里提出两种方法:

1)除了某种类型的Web客户端轮询之外,还有一个额外的代理,例如可以从Web服务器获得命令的系统服务。如果民意调查停止进入,这将启动任何交易,分配ID,自动中止等。这将使得可以始终“连接回”到正确的交易以中止或提取结果或诸如此类的东西。呸。

2)由于 Web服务工作者“忙”并且在事务完成之前无法被其他连接使用...只需让Web服务器保持Web客户端连接活动直到数据库事务完成(例如,请求将在新的浏览器窗口中打开,该窗口将显示:“关闭此将中止请求<旋转事物>”)。当然,这取决于1)特定服务器流内容的能力2)当请求正常完成或流断开时确保事务关闭的能力(隐式/显式) - 我从未尝试过在(ASP?)。NET。还是哎呀。

编辑:第二个例子可以在没有流内容的情况下完成 - 例如隐藏在AJAX调用或IFRAME后面的“让用户知道事务正在页面上”。关键是它需要设置为当Web事务结束时,它将立即终止数据库事务。这将取决于网络服务器。

对于ASP.NET,请参阅Response Stream作为一种使用线程的方式来流式传输和/或检测损坏的HTTP响应连接。

答案 1 :(得分:0)

我必须看一些代码,但是当你说“系统再次连接到数据库”然后释放锁时,我很好奇你的意思。

IIS重新启动时释放锁的事实向我表明连接仍处于活动状态。您使用的是oracle提供程序还是MS Oracle提供程序?

我唯一一次处理长时间运行的流程时,我使用调度程序在非工作时间运行它 - 一个5分钟的事务实际上不适合基于Web的应用程序。

答案 2 :(得分:0)

我使用的Oracle配置文件的最大IDLE_TIME大约为10分钟。

答案 3 :(得分:0)

大多数现代dbs已经开发出一种非常好的方式来提供数据一致性,这是你实际付出的一部分,所以要好好利用。通过这个我不知道为什么这里需要选择更新。

Oracle的默认隔离级别是读取提交的,其中无法进行脏读。您将保证获得一致的结果,而不会阻止写入和写入阻塞读取(使用SCN和回滚以及更多有趣的东西,您可以通过找到here的Oracle概念获得更多信息。

无论如何,对于大多数情况,如果你想进行更新,那就去做吧(不用担心把锁放在一切)。其他用户仍将获得读取时存在的数据的读取一致视图(即使未提交的更新正在进行中)。

要添加的一件事:“for update”将在提交或回滚时释放内部锁。用户定义/维护的“pLock”逻辑有点可怕(可能是错误的)。