其实我想对表应用锁定,以便其他进程无法执行DML(插入/更新/删除但可以执行选择)或在'进程执行'时锁定该表。如何使用C#独占锁定Oracle数据库表?
LOCK TABLE table-name IN EXCLUSIVE MODE
我应该怎么写,在C#?
// ..... process execution .......
如何解锁?我想通过承诺或回滚。
有什么建议吗?
其实我想对表应用锁定,以便其他进程无法执行DML(插入/更新/删除但可以执行选择)或在'进程执行'时锁定该表。如何使用C#独占锁定Oracle数据库表?
LOCK TABLE table-name IN EXCLUSIVE MODE
我应该怎么写,在C#?
// ..... process execution .......
如何解锁?我想通过承诺或回滚。
有什么建议吗?
通过利用另一种策略,可解决此问题。无论是解决它通过:
独占锁定(因为我意识到,如果有更新我的桌子,而我的过程是正在进行其他事务,这可能不是由于锁定,但只要我的过程完成更新表,意味着现在锁释放,如果另一个事务仍处于暂停状态,然后另一个事务将立即更新我的表,这不会取得成果对我来说)也通过解决它:。
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();
}
锁将上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();
为什么你需要锁定一个表? 使用事务作用域对象指定隔离级别就足够了吗? 例如
TransactionOptions TransOpt = New TransactionOptions();
TransOpt.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TransOptions))
{
...
}
请检查您的要求。
是的隔离是一个很好的选择......但现在我又遇到了另一个问题。在事务范围中,我收到错误:试图加载格式不正确的程序。 (来自HRESULT的异常:0x8007000B)。它丢失了我已经下载的oramts.dll。我GOOGLE了这个错误,发现它是因为DIT文件的位。我的Oracle客户端是64位,因此它可能期望oramts.dll是64位。从哪里可以得到这个? – Sadiq 2013-03-22 11:02:41
在我看来,你可以通过此链接帮助http://support.microsoft.com/kb/843044 – knagaev 2013-03-22 19:23:56
@knagaev链接的死亡,bayb,链接的死亡...(纸浆小说参考...从来没有) – Noctis 2017-10-27 00:29:49
但我刚刚在msdn上发现:ExecuteNonQuery不使用游标,因此不会锁定数据库。如果您发出需要锁的命令,请勿使用ExecuteNonQuery。相反,使用ExecuteReader。如何使用?另外,在我的情况下,executenonquery返回0。但是它写在msdn上:对于UPDATE,INSERT和DELETE语句,返回值是受命令影响的行数。对于所有其他DML语句,返回值为-1 – Sadiq 2013-03-15 11:48:51