2013-03-15 202 views
0

其实我想对表应用锁定,以便其他进程无法执行DML(插入/更新/删除但可以执行选择)或在'进程执行'时锁定该表。如何使用C#独占锁定Oracle数据库表?

LOCK TABLE table-name IN EXCLUSIVE MODE

我应该怎么写,在C#?

// ..... process execution .......

如何解锁?我想通过承诺或回滚。

有什么建议吗?

回答

0

通过利用另一种策略,可解决此问题。无论是解决它通过:

  1. 独占锁定(因为我意识到,如果有更新我的桌子,而我的过程是正在进行其他事务,这可能不是由于锁定,但只要我的过程完成更新表,意味着现在锁释放,如果另一个事务仍处于暂停状态,然后另一个事务将立即更新我的表,这不会取得成果对我来说)也通过解决它:。

  2. IsolationLevel.Serializable(如distrib不支持可序列化的事务隔离级别)

因此,在我表中的每个条目中,我确定是否有任何事务(无论是分布式还是本地)阻塞我的表。如果有的话,我确定会话并强行终止会话。这完全适合我的场景:

Database db = DataRepository.GetDatabase(); 

int result, session_id = 0; 
string kill_session, serial = null; 
string chk_lock = "SELECT l.session_id,v.serial# ," 
       +"object_name FROM dba_objects o, gv$locked_object l, " 
       +"v$session v WHERE o.object_id = l.object_id and " 
       +"l.SESSION_ID=v.sid"; 
DbDataReader rdr_blkAccount; 
try{ 
    //MY PROCESS RUNS HERE... 
} 
catch(Exception excep) 
{ 
    //... 
} 
finally 
{ 
    rdr_blkAccount = db.ExecuteReader(chk_lock); 

    while (rdr_blkAccount.Read()) 
    { 
     if (rdr_blkAccount[2].ToString().ToUpper() == "ACCOUNT") 
     { 
      session_id = Convert.ToInt32(rdr_blkAccount[0]); 
      serial = session_id.ToString() + ',' 
        + Convert.ToInt32(rdr_blkAccount[1]).ToString(); 
      kill_session = "alter system kill session '" + serial + "'"; 
      result = db.ExecuteNonQuery(kill_session); 
      logger.Log(LogLevel.Warning 
         , string.Format("Session_id '{0}' has been forcefully killed" 
            , serial)); 
     } 
    } 
    rdr_blkAccount.Close(); 
} 
0

锁将上relased提交或回滚

OracleConnection conn= new OracleConnection("Data Source=datasrc;User=USER;Password=passwd"); 
conn.Open(); 
OracleTransaction tr = conn.BeginTransaction(); 
OracleCommand cmd = new OracleCommand("LOCK TABLE TABLE_NAME IN EXCLUSIVE MODE",conn,tr); 
cmd.ExecuteNonQuery(); 
Console.ReadLine(); 
tr.Commit(); 
conn.Close(); 
+0

但我刚刚在msdn上发现:ExecuteNonQuery不使用游标,因此不会锁定数据库。如果您发出需要锁的命令,请勿使用ExecuteNonQuery。相反,使用ExecuteReader。如何使用?另外,在我的情况下,executenonquery返回0。但是它写在msdn上:对于UPDATE,INSERT和DELETE语句,返回值是受命令影响的行数。对于所有其他DML语句,返回值为-1 – Sadiq 2013-03-15 11:48:51

0

为什么你需要锁定一个表? 使用事务作用域对象指定隔离级别就足够了吗? 例如

TransactionOptions TransOpt = New TransactionOptions(); 
TransOpt.IsolationLevel = System.Transactions.IsolationLevel.Serializable; 
using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TransOptions)) 
{ 
... 
} 

请检查您的要求。

+0

是的隔离是一个很好的选择......但现在我又遇到了另一个问题。在事务范围中,我收到错误:试图加载格式不正确的程序。 (来自HRESULT的异常:0x8007000B)。它丢失了我已经下载的oramts.dll。我GOOGLE了这个错误,发现它是因为DIT文件的位。我的Oracle客户端是64位,因此它可能期望oramts.dll是64位。从哪里可以得到这个? – Sadiq 2013-03-22 11:02:41

+0

在我看来,你可以通过此链接帮助http://support.microsoft.com/kb/843044 – knagaev 2013-03-22 19:23:56

+0

@knagaev链接的死亡,bayb,链接的死亡...(纸浆小说参考...从来没有) – Noctis 2017-10-27 00:29:49