如何使用C#独占锁定Oracle DB表?

时间:2013-03-15 09:32:13

标签: c# oracle

实际上我想在表上应用锁定,这样任何其他进程都不能执行DML(插入/更新/删除但可以执行选择)或在“进程执行”时锁定该表。

LOCK TABLE table-name IN EXCLUSIVE MODE

我应该如何用C#写出来?

// .....流程执行.......

如何解锁?我想通过提交或回滚。

有什么建议吗?

3 个答案:

答案 0 :(得分:0)

锁定将在提交或回滚时释放

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();

答案 1 :(得分:0)

为什么需要锁定一张桌子? 是否足以使用事务范围对象指定隔离级别? 例如

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

请检查您的要求。

答案 2 :(得分:0)

通过利用另一种策略,可以解决这个问题。无论如何解决它:

  1. 独占锁定(因为我意识到在我的进程正在进行时是否有另一个事务更新了我的表,由于Lock而无法更新表,但是一旦我的进程完成,就意味着Lock现在已经发布了,如果另一个交易仍然处于暂停状态,那么另一个交易将立即更新我的表格。这对我来说无济于事。)也不能通过以下方式解决:

  2. IsolationLevel.Serializable (由于分布式事务不支持可序列化事务隔离级别。)

  3. 因此,在我的表中的每个条目上,我都会识别是否存在阻止我的表的任何事务(无论是分布式的还是本地的)。如果有,我会识别该会话并强制终止该会话。这完全适合我的情况:

    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();
    }