実際、他のプロセスがDML(挿入/更新/削除、ただし選択は実行可能)を実行できないように、または「プロセスの実行」中にそのテーブルをロックできるように、テーブルにロックを適用したいと思います。
LOCK TABLE table-name IN EXCLUSIVE MODE
それをC#でどのように書くべきですか?
//.....プロセスの実行.....。
ロックを解除する方法は?コミットするかロールバックするかで推測します。
助言がありますか?
別の戦略を利用することで、この問題を回避できます。どちらもそれを解決しない:
排他的ロック (プロセスの進行中に別のトランザクションがテーブルを更新した場合、ロックが原因でテーブルを更新できなかったが、プロセスが完了するとすぐにロックが解放されたことを意味することに気付いたため、別のトランザクションがまだ保留中の場合別のトランザクションがすぐに私のテーブルを更新する.そして、それは私にとって実を結ばないだろう.)また、次の方法でそれを解決する.
IsolationLevel.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();
}
なぜテーブルをロックする必要があるのですか? トランザクション スコープ オブジェクトを使用して分離レベルを指定するだけで十分でしょうか? 例えば
TransactionOptions TransOpt = New TransactionOptions();
TransOpt.IsolationLevel = System.Transactions.IsolationLevel.Serializable;
using(TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, TransOptions))
{
...
}
要件を確認してください。
ロックはコミットまたはロールバックで解除されます
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();