我有一个表,其中包含需要由多个程序获取和设置的最大值。当获得旧值并在C#中更新new时,如何锁定表一段时间?换句话说:
string sql = "lock table MaxValueTable in exclusive mode";
using (DbCommand cmd = cnctn.CreateCommand())
{
cmd.CommandText = sql;
// execute command somehow!!
}
maxValue = GetMaxValue();
SetMaxValue(maxValue + X);
sql = "lock table MaxValueTable in share mode";
using (DbCommand cmd = cnctn.CreateCommand())
{
cmd.CommandText = sql;
// execute command somehow!!
}
答案 0 :(得分:2)
答案 1 :(得分:2)
将提供程序用于指定的数据库通常是一种很好的做法。 Oracle在他的网站上有一个专门的Microsoft.Net提供商,我建议使用它。请注意,所有专用提供程序都实现相同的基本classess,因此保留了一定的抽象级别。其次,U肯定需要交易。我建议通过调用存储过程(通过executeNonQuery()或executeScalar()方法)来实现,具体取决于U需要的结果。
如果您无法使用存储过程(U无法创建它们),那么您必须使用提供商提供的转换。 Ole提供商和ORacle提供商都提供交易
using (Transaction t = cnctn.BeginTransation())
`//set some options like timeout, use serialization level like //Serializable in .Net TransactionScope
{
string sql = "lock table MaxValueTable in exclusive mode";
using (DbCommand cmd = cnctn.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
// execute command somehow!!
}
maxValue = GetMaxValue();
SetMaxValue(maxValue + X);
//I presume U need to update the value in the table so some Update would be nice
sql = "lock table MaxValueTable in share mode";
using (DbCommand cmd = cnctn.CreateCommand())
{
cmd.CommandText = sql;
cmd.ExecuteNonQuery();
// execute command somehow!!
}
cnctn.Commit();
}
catch(SQLException e)
{
//log whatever, gracefully handle things
t.Rollback();
//throw;?
}
finally
{
cntn.close();
}
答案 2 :(得分:1)
听起来你应该使用Oracle Sequence - 正如我在评论中已提到的那样:)
每当调用NEXTVAL
时,它都会返回唯一的数字。
如果由于某种原因你无法使用序列,只需在该行上执行UPDATE
即可。在您结束事务(COMMIT
或ROLLBACK
)之前,Oracle将锁定该行,并且所有其他更新将等到锁定被释放。
修改强>:
如果ADO
不支持交易,您也可以使用AUTONOMOUS_TRANSACTION
将其放入Oracle程序中:
CREATE OR REPLACE PROCEDURE allocate_sequence_numbers(
in_size IN max_value_table.val%TYPE,
out_next_sequence_number OUT max_value_table.val%TYPE
)
AS
PRAGMA AUTONOMOUS_TRANSACTION;
next_sequence_number max_value_table.val%TYPE;
BEGIN
UPDATE max_value_table
SET val = val + in_size
RETURNING val - in_size
INTO out_next_sequence_number;
COMMIT;
END allocate_sequence_numbers;
它将更新您的表以“分配”指定数量的值,并返回您分配的序列的第一个数字。调用它的下一个应用程序将接收下一个序列号。
UPDATE
导致该行的锁定,因此其他调用必须等待释放该锁定。通过在COMMIT
中使用AUTONOMOUS_TRANSACTION
,锁定会被释放,而您自己的交易不会受到影响。
答案 3 :(得分:0)
有一个锁定表命令
LOCK TABLE [schema.] table IN lockmode EXCLUSIVE [NOWAIT]
注意:在结束交易之前,您无法重置锁定。因此,如果您锁定了桌子,则无法解锁。
答案 4 :(得分:0)
要在获取它的语句之后保持锁定,您需要一个事务。
答案 5 :(得分:-1)
您可以尝试其他方法。首先在表上启用表锁定。说我的桌子是T
。然后
SQL> alter table t enable table lock
2 /
现在,你可以选择,任何其他选择都会等待,因为你有一个锁。
SQL> select *
2 from t
3 for update
4 /
因此,任何其他会话中的select命令都不会返回并等待释放锁。请记住,您需要执行COMMIT
才能解除锁定。