2010-07-06 25 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

相關問題