如何使用c#独占锁Oracle DB表
本文关键字:Oracle DB 何使用 | 更新日期: 2023-09-27 18:04:06
实际上我想在表上应用锁,这样在'进程执行'时,没有其他进程可以执行DML(插入/更新/删除,但可以执行Select)或锁表。
LOCK TABLE table-name IN EXCLUSIVE MODE
我应该如何写在c# ?
//……进程执行.......
如何释放锁?我想要么提交,要么回滚。
有什么建议吗?
锁将在提交或回滚时被释放
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();
为什么需要锁表?也许使用事务作用域对象指定隔离级别就足够了?例如
TransactionOptions TransOpt = New TransactionOptions();
TransOpt.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TransOptions))
{
...
}
请检查您的要求
可以利用另一种策略来解决这个问题。
-
EXCLUSIVE LOCKING(因为我意识到如果有另一个事务更新了我的表,而我的进程正在进行中,由于锁无法更新表,但一旦我的进程完成,意味着锁现在释放,如果另一个事务仍然处于暂停状态,那么另一个事务将立即更新我的表。这对我来说不会有结果。)
-
IsolationLevel。Serializable(由于分布式事务不支持Serializable事务隔离级别)
因此,在我的表中的每个条目上,我确定是否有任何事务(无论是分布式的还是本地的)阻塞了我的表。如果存在,我就会识别该会话并强制终止该会话。这非常适合我的场景:
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();
}