Oracle Update挂起

时间:2009-07-23 14:58:49

标签: .net database oracle

我在使用Oracle更新时遇到问题。对ExecuteNonQuery的调用无限期地挂起。

代码:

using (OracleCommand cmd = new OracleCommand(dbData.SqlCommandStr, conn))
{
    foreach (string colName in dbData.Values.Keys)
        cmd.Parameters.Add(colName, dbData.Values[colName]);

    cmd.CommandTimeout = txTimeout;
    int nRowsAffected = cmd.ExecuteNonQuery();
}

CommandTimeout设置为5,参数设置为小整数值。

查询:

UPDATE "BEN"."TABLE03" SET "COLUMN03"=:1,"COLUMN04"=:2 WHERE COLUMN05 > 0

查询从sqlplus快速运行,并且通常从我的代码快速运行,但每隔一段时间它就会永远挂起。

我在v $ locked_object上运行了一个查询,并且有一条记录引用了这个表,但我认为这是未完成的更新。

我想知道两件事:什么可能导致更新挂起?

更重要的是,为什么这里不会抛出异常?我希望通话等待五秒钟,然后超时。

6 个答案:

答案 0 :(得分:20)

由于搜索结果中的网页排名,我碰到了这个。

在我的情况下,这是因为我在SqlPlus中执行了一个查询,但是我忘了提交它。在这种情况下,正如文森特所说的那样:该行被锁定在另一个会话中。

提交SqlPlus更新解决了这个问题。

答案 1 :(得分:5)

当简单更新挂起时,通常意味着您被另一个会话阻止。 Oracle不允许多个事务更新行。在事务提交或回滚其修改之前,它将锁定已更新/删除的行。这意味着如果其他会话想要修改相同的行,则必须等待。

如果你不想无限制地挂起,你应该在UPDATE之前选择... FOR UPDATE NOWAIT。

答案 2 :(得分:4)

我遇到了一个类似的问题,这个问题是由一个尚未提交的Sql命令引起的 - 我猜这个程序在某个时刻崩溃了。

以下是我解决问题的方法:

首先,打开SqlPlus并提交修复问题。

接下来,如果发生异常,请更改代码以提交事务或回滚。这将使问题再次发生。

您可以将代码更改为以下内容:

using (OracleTransaction transaction = conn.BeginTransaction())
{
    using (OracleCommand cmd = new OracleCommand(dbData.SqlCommandStr, conn))
    {
        foreach (string colName in dbData.Values.Keys)
            cmd.Parameters.Add(colName, dbData.Values[colName]);

        cmd.CommandTimeout = txTimeout;

        try
        {
            int nRowsAffected = cmd.ExecuteNonQuery();
            transaction.Commit();
        }
        catch
        {
            transaction.Rollback();
        }
    }
}

答案 3 :(得分:2)

您可以通过查询V $ SESSION_WAIT来查看会话正在等待的事件(在识别会话的SID之后,可能通过查看V $ SESSION)。如果事件类似于“入队”,那么您正在等待另一个会话持有的锁定,这在这种情况下看起来似乎是一种可能的解释。

答案 4 :(得分:0)

似乎数据库正在等待提交/回滚,因此它会锁定行。我建议添加

int nRowsAffected = cmd.ExecuteNonQuery();
cmd.Commit();

答案 5 :(得分:0)

我经常遇到这个问题,不仅仅是更新查询(特别是“INSERT INTO ... SELECT FROM”查询)。这是在Oracle 9i上。

我找到了解决方案,所以决定找到这个相关的SO主题: 在连接字符串中,设置:

Pooling=False

在连接字符串中。 完整的工作连接字符串可能如下所示:

DATA SOURCE=k19.MYDOMAIN.com/plldb;PERSIST SECURITY INFO=True;Pooling=False;USER ID=IT;Password=SECRET

警告:将池设置为false将要求您的查询在每次运行时都保护新连接。与ODP.NET可靠的情况相比,频繁运行的查询可能会降低性能。考虑到这个问题,运行速度稍微慢一点就好了。