2010-07-06 40 views
2

下面是代码(与服务器/密码等去掉)为什么此更新会锁定Oracle 10中的行?

public int SetUploadedInESIDatabase(string ID) 
     { 
      using (var oOracleConn = new OracleConnection()) 
      { 
       oOracleConn.ConnectionString = 
        @"Data Source=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=<ip>)(PORT=1521)))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=<dbname>)));User Id=<user>;Password=<password>;"; 
       var cmd = 
        new OracleCommand(
         "UPDATE FOO_ACCESS SET PIMAGE ='-1' WHERE CODE= '" + ID + "'", oOracleConn); 

       oOracleConn.Open(); 



       return cmd.ExecuteNonQuery(); 

      } 
     } 

这段代码的作用是它永远不会越过return语句。没有错误返回(甚至一夜之间)

我不是一个数据库专家,但我们硬压DBA说,连接被锁定(或行可能...)他杀死锁定连接,但仍然当我运行它锁定的代码。

我是否在要求Oracle更新行方面做错了(tm)?

我知道我应该使用参数化查询,但我遇到了问题,需要简单的东西! 如果我将命令复制出cmd。与调试器和运行它使用SQL Developer然后它的工作(虽然有时它也锁定了)

我可以从数据库中随意选择。

我不确定这是正常的事情还是与我们的环境有关,所以任何帮助都很乐意接受!

+0

哇,真的是什么样的Oracle连接字符串看起来像在C#中?它实际上使Oracle的Java连接字符串看起来不错! – Powerlord 2010-07-06 15:14:22

+0

@ R.Bemrose:如果您不使用Oracle TNSNAMES.ORA文件为服务器提供友好名称,那只是连接字符串的外观。否则,使用TNSNAMES看起来好多了:'Data Source = ServerName;用户ID =用户;密码= pw'。 – LBushkin 2010-07-06 15:18:54

+0

@R。 Bemrose:Oracle支持不同的连接字符串格式http://www.connectionstrings.com/oracle#p12 – devio 2010-07-06 15:20:01

回答

2

结合@托尼和@Panagiotis答案,并扩大:

你在哪里犯这个代码所做的更新?你确定它已经完成了吗?

难道这是您的方案:

  1. 发出上述UPDATE,但从来没有提交。
  2. 你没有看到你的改变,所以你再试一次。现在它挂起。

受UPDATE影响的行将被锁定以防止进一步更新,直到提交或回滚。如果您从未显式提交或回滚,则后续更新将挂起。

如果你想避免挂在你的代码,然后执行

SELECT... FOR UPDATE NOWAIT; 

你做的UPDATE之前。如果记录被锁定,select将返回一个错误,您可以捕获并处理该错误。

让你的DBA尝试此查询(汤姆凯特表示感谢):

select 
     (select username from v$session where sid=a.sid) blocker, 
     a.sid, 
     ' is blocking ', 
     (select username from v$session where sid=b.sid) blockee, 
      b.sid 
    from v$lock a join v$lock b on (a.id1 = b.id1 and a.id2 = b.id2) 
where a.block = 1 
    and b.request > 0; 

要查看会议所有排队块。

+0

感谢您的支持。我发现了这个问题(请参阅其他地方的'我的答案'),但是如果它无法获取行更新,则此错误的方法很有用,因此您可以获取Cookie :) – Loofer 2010-07-06 17:18:57

1
  • 找出究竟被锁定(表,行等)

  • 你能从 的sqlplus或的SQLDeveloper使用 相同的凭据执行该语句?

  • 是否有任何触发器连接到 表FOO_ACCESS?

+0

谢谢。我可以从sqldeveloper运行查询,它*有时*作品...在代码中它*从不*工作。我将在其他部分获取有用的DBA :) – Loofer 2010-07-06 15:58:12

1

您确定参数studentID只是一个ID吗?如果这是一个malformed bit of SQL that someone tries to inject

som unsanitized input完全有可能使其进入studentID - 并且会导致您的查询执行您期望以外的操作。

举例来说,如果你studentID = "'; DROP ALL TABLES; --"可能有一个问题...

使用的字符串连接为手段,以创建一个SQL语句是一个不安全的做法 - 和一个是完全不必要的。在.NET中使用SQL命令中的参数非常容易,这使SQL不易受注入攻击的影响,并且还提高了它们的性能(通过减少执行语句解析的需求)。

下面是一个使用参数的例子:

var cmd = new OracleCommand( 
     "UPDATE FOO_ACCESS SET PIMAGE = '-1' WHERE CODE = :code", oracleConn); 
cmd.Parametes.Add(":code", studentID); 

cmd.ExecuteNonQuery(); 

除此之外,你可以调查是什么原因造成您的查询通过使用Oracle中的V $ XXX表探索正在发生的事情表现不佳。如果您认为自己有锁,则可以查询v$lock表以查看哪些表被哪些会话锁定。

+0

目前我正在开发中,所以没有野生类型可以尝试让我。我当然只会让参数化的东西出来! (正如我在我的问题中所说的:)我没有私有数据库来查看v $ lock表,所以回到dba就是了! – Loofer 2010-07-06 16:40:03

+0

我现在已经参数化了我的查询:D它很简单,就像你说的那样,但是它使得在Visual Studio中调试起来更加困难,因为VS似乎并没有构建最终的命令,因此我无法复制并将生成的sql命令粘贴到另一个程序中进行测试。 – Loofer 2010-07-06 17:36:58

1

如果一个会话发出此更新并且未提交或回滚,则该行将被该会话锁定,直到它确实(提交或回滚)。这可能是发生在你身上的事情吗?

+0

这听起来很可能,但为什么它没有提交或回滚,如果更新失败...我可以暗​​示,我希望它停止尝试在某个时候? – Loofer 2010-07-06 15:59:13

1

您是否曾尝试在创建命令对象之前打开连接?

+0

这似乎没有效果。谢谢:) – Loofer 2010-07-06 16:20:03

1

如果多位作者尝试同时触摸它,Oracle会锁定一行。是否有其他代码试图同时修改行或表?你可能在另一个打开的连接中执行了SELECT FOR UPDATE语句吗?

+0

更新是我运行的唯一的SQL ... 我不知道SELECT FOR UPDATE ...是我应该做的事吗? – Loofer 2010-07-06 15:56:53

1

您是否尝试通过创建事务来指定隔离模式

using(OracleTransaction transaction = oOracleConn.BeginTransaction(IsolationLevel.RepeatableRead) 
{ 

cmd.Transaction = transaction 

return cmd.ExecuteNonQuery(); 
} 
+0

不......是可重复阅读我想要的东西?查看枚举也许.Chaos:D – Loofer 2010-07-06 15:56:06

1

我很好奇一件事。你可以尝试改变你的return语句,使它在使用块之外吗?

即代替:

using (..snip...) { 

    return cmd.ExecuteNonQuery(); 
} 

尝试

int rv; 
using() { 

    rv = cmd.ExecuteNonQuery(); 
} 
return rv; 
+0

它永远不会到达return语句,一直停留在cmd.ExecuteNonQuery()阶段。 – Loofer 2010-07-06 16:17:26

+0

如果你用一个简单的select来替换sql,即从foo_access中选择count(*)会发生什么?是否有你没有使用tnsnames.ora来解决连接的原因? – chris 2010-07-06 17:28:40

+0

选择工作正常。我没有使用tnsnames.ora,因为我对Oracle没有任何了解,而且dba对编程一无所知,而且我正在做任何有效的工作或似乎正在工作的东西:O – Loofer 2010-07-06 17:41:12

0

看来问题是我不完全理解我的工具。

我相信SQL Developer在某些时候创建了锁,然后当我运行我的web应用程序更新同一行时,它被锁定。在我的无奈和无知中,我强制关闭了SQL Developer,让数据库中留下了一个锁,并且我无法在没有DBA超级权力的情况下清除它。

现在已经锁清除和关闭SQL Developer的所有运行副本干净的代码,因为我第一次发布它现在的作品。 (唷!)

感谢您的帮助,选择特别的想法FOR UPDATE,看看我的更新将被拒绝之前,我发出了吧:)

+0

当您在sqldeveloper中执行更新时,需要明确提交交易。有一个自动提交的设置,但如果你打开它,我向你保证,有一天你会后悔的。 – chris 2010-07-06 17:56:30