实现悲观锁定

时间:2012-07-30 14:07:52

标签: sql-server oracle sybase-ase

我对如何使用非常具体的行为实现悲观锁定感兴趣。 (我用Sybase + Oracle + MSSQL标记问题的原因是因为我对解决方案感到满意,或者“对于其中任何一个都不可能!”)

我想要的是: 1 - 能够锁定一行(以便稍后可以更新进程,但没有其他进程可以锁定该行) 2 - 当另一个进程试图锁定同一行时,它应该得到记录被锁定的通知 - 我不希望这个进程挂起(我相信这里可以使用简单的超时) 3 - 当另一个进程尝试读取记录时,它应该能够以当前在数据库中的方式读取它(但我不想使用脏读)。

上述3个要求目前通过使用共享内存的应用程序解决 - 并在数据库外执行记录锁定。我想将锁定移动到数据库中。

到目前为止,我在#1和#3之间存在冲突 - 如果我通过将字段更新为相同值来执行'更新...'来锁定记录,而不是从另一个进程中“选择”挂起。

编辑: 我现在运气好了MSSQL上的快照隔离级别。我可以同时执行锁定,并且不使用脏读取进行读取。

我不想使用脏读的原因是,如果报表正在运行,它可能会读取多个表,并发出多个查询。快照为我提供了数据库的一致快照。如果脏读,我会有不匹配的数据 - 如果中间有任何更新。

我认为Oracle也有快照,所以现在我对Sybase最感兴趣。

2 个答案:

答案 0 :(得分:2)

在Oracle中,您可以使用select for update nowait来锁定记录。

select * from tab where id=1234 for update nowait;

如果另一个进程尝试执行相同的语句,则会出现异常:

ORA-00054: resource busy and acquire with NOWAIT specified

直到第一个进程(会话)执行提交或回滚。

通常,oracle不允许脏读

答案 1 :(得分:0)

您描述的#1和#3之间的冲突是合乎逻辑的:您可以让数据库执行脏读或阻止读取。如果您可以读取锁定的行,则根据定义它是脏读的。这与您使用的特定数据库系统无关!

所以,如果你想要那样:是的,你想要的是所有3个系统都不可能,因为它会损害“脏读”的定义。