【问题标题】:Oracle Update HangsOracle 更新挂起
【发布时间】:2009-07-23 14:58:49
【问题描述】:

我在进行 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 上运行了一个查询,并且有一条记录引用了这个表,但我认为那是没有完成的更新。

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

更重要的是,为什么这里没有抛出异常?我希望呼叫等待五秒钟,然后超时。

【问题讨论】:

  • 什么版本的Oracle?你能运行这个查询吗:“select * from v$version”并复制出第 1 行。它应该类似于:“Oracle Database 10g Release 10.2.0.4.0 - Production”。另外,这是一个真正的表还是一个视图而不是触发器?它有任何之前/之后的触发器吗?

标签: .net database oracle


【解决方案1】:

由于它在搜索结果中的页面排名,我正在处理这个问题。

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

提交 SqlPlus 更新解决了该问题。

【讨论】:

  • 正是发生在我身上的事情。只要我在 SQLPlus 中执行rollback,它就会返回。
  • 救命稻草 - 4 年后!
  • 在我的例子中,我使用的是 Oracle SQL Developer,并且在提交之后它工作了!
  • 我也在做同样的事情。谢谢!
  • 妈妈#)#$,这也发生在我身上。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    我遇到了一个类似的问题,该问题是由尚未提交的 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();
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

        我经常遇到这个问题,而且不仅仅是更新查询(特别是“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 可靠的情况相比,非常频繁运行的查询可能会遇到性能下降。不过考虑到这个问题,跑得慢一点总比挂着好。

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-05-02
            • 2010-11-17
            • 2014-07-15
            • 2014-10-03
            • 1970-01-01
            • 2018-07-13
            • 2011-07-14
            • 1970-01-01
            相关资源
            最近更新 更多