【问题标题】:Oracle ExecuteNonQuery hangs on "Select for update nowait"Oracle ExecuteNonQuery 挂在“Select for update nowait”上
【发布时间】:2014-05-12 12:59:52
【问题描述】:

我已经被这个问题困扰了几天了,仍然无法弄清楚为什么:

我需要更新我的 Oracle 数据库中的一条记录,在执行更新查询之前,我想用“SELECT x FOR UPDATE NOWAIT”锁定数据,但是在调用 ExecuteNonQuery 时,我的 web 服务挂起。

直接对数据库执行 sql 语句可以立即工作。 这是代码:

                    OracleTransaction transact = OraDCS.BeginTransaction();
                    OracleCommand cmd = OraDCS.CreateCommand();
                    cmd.CommandText = string.Format("UPDATE FLIGHT_MANIFEST_PASSENGER SET ETAT_PASSAGER = '{2}',GATE_BOARDING = {0} WHERE REF_DOSSIER = '{1}'", ConfigurationManager.AppSettings["CodeMoyen"].ToString(), ref_dossier, etatPax);

                    OracleCommand blq = OraDCS.CreateCommand();
                    blq.CommandText = string.Format("SELECT * FROM FLIGHT_MANIFEST_PASSENGER WHERE REF_DOSSIER = '{0}' FOR UPDATE NOWAIT", ref_dossier);

                    bool blqOK = false;
                    try
                    {
                        blq.ExecuteNonQuery();
                        blqOK = true;
                    }
                    catch (Exception ex)
                    {
                        LogThreadSafe.Instance.Info("LanceSQL Error : " + blq.CommandText + " " + ex.Message);
                    }

                    if (blqOK)
                    {
                        try
                        {
                            cmd.ExecuteNonQuery();
                            transact.Commit();
                        }
                        catch (Exception ex)
                        {
                            transact.Rollback();
                            LogThreadSafe.Instance.Info("LanceSQL Error : " + blq.CommandText + " " + ex.Message);
                        }

                    }
                    else
                        transact.Rollback();

实际上是在数据库上执行了锁,但是程序仍然在这一行挂起:

blq.ExecuteNonQuery();

编辑:即使在将事务链接到命令之后,我仍然会遇到冻结。 但是,当我在服务器上部署我的 web 服务并“实时”测试它而不是在我的开发机器上调试时,它可以工作,有什么想法吗?

【问题讨论】:

  • 不是您问题的答案,但请注意,您的第二个 catch 块中有一个复制/粘贴错字 - 您是从 blq 命令发出异常消息cmd.

标签: c# oracle freeze executenonquery


【解决方案1】:

您需要将命令与事务关联:

cmd.Transaction = transact;
blq.Transaction = transact;

我还强烈建议您不要通过字符串连接来构建查询文本,而是使用参数来防止 SQL 注入。例如:

blq.CommandText = "SELECT * FROM FLIGHT_MANIFEST_PASSENGER WHERE REF_DOSSIER = :pDossier FOR UPDATE NOWAIT";
blq.Parameters.Add(new OracleParameter("pDossier", ref_dossier));

【讨论】:

  • 即使将命令与事务关联后,我仍然有问题,但我认为问题不是来自代码。当我在服务器上部署我的 web 服务并“实时”测试它而不是在我的开发机器上调试时,它可以工作并且我没有遇到冻结。你有什么线索吗?顺便说一句,感谢您的输入。
  • @JuFra 也许有另一个事务(未指定NOWAIT)阻塞了所述行?
  • 不,没有,我有一个软件来监控我的数据库上的锁,但没有。我想也许它可能与 Oracle 数据访问提供程序有关?还是我的即时客户端,某处的某个参数?无论如何,我会将您的答案标记为最佳答案,因为它很有用,而且我的问题与我认为的代码无关。谢谢
【解决方案2】:

如果我必须使用事务,我通常会这样做:

OracleCommand cmd = OraDCS.CreateCommand();
OracleTransaction transact=cmd.Connection.BeginTransaction();
cmd.Transaction=transact;
cmd.CommandText = string.Format("UPDATE FLIGHT_MANIFEST_PASSENGER SET ETAT_PASSAGER = '{2}',GATE_BOARDING {0}WHERE REF_DOSSIER = '{1}'", ConfigurationManager.AppSettings["CodeMoyen"].ToString(), ref_dossier, etatPax);

也许你的交易没有关联

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-05
    • 2017-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多