代码之家  ›  专栏  ›  技术社区  ›  TimK

Oracle更新挂起

  •  7
  • TimK  · 技术社区  · 16 年前

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

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

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

    6 回复  |  直到 11 年前
        1
  •  20
  •   Kenneth    14 年前

    因为它在搜索结果中的页面排名,所以我不想看到它。

    在我的例子中,这是因为我在sqlplus中执行了一个查询,但是我忘记提交它。在这种情况下,正如文森特所说:这一排被锁在另一个会议。

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

        2
  •  5
  •   Vincent Malgrat    16 年前

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

    你应该选择…如果不想挂起,请在更新前立即更新。

        3
  •  4
  •   wlemond    12 年前

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

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

    首先,打开sqlplus并执行commit来解决问题。

    接下来,更改代码以提交事务,或者在发生异常时回滚。这将防止问题再次发生。

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

    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
  •  2
  •   Dave Costa    16 年前

    您可以通过查询v$session_wait(在识别会话的SID之后,可能通过查看v$session)来查看会话正在等待的事件。如果事件类似于“排队”,那么您正在等待另一个会话持有的锁,在本例中,这似乎是一个可能的解释。

        5
  •  0
  •   northpole    16 年前

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

    int nRowsAffected = cmd.ExecuteNonQuery();
    cmd.Commit();
    
        6
  •  0
  •   Charles Burns    14 年前

    我经常遇到这个问题,不仅仅是更新查询(特别是“insert into…select from”查询)。这是甲骨文9i上的。

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

    Pooling=False
    

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

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

    注意:将pooling设置为false将要求查询在每次运行时确保新连接的安全。与ODP.NET可靠的情况相比,经常运行的查询可能会出现性能下降。不过,考虑到这个问题,跑得慢一点要比吊得好得多。