我对如何使用非常具体的行为实现悲观锁定感兴趣。 (我用Sybase + Oracle + MSSQL标记问题的原因是因为我对解决方案感到满意,或者“对于其中任何一个都不可能!”)
我想要的是: 1 - 能够锁定一行(以便稍后可以更新进程,但没有其他进程可以锁定该行) 2 - 当另一个进程试图锁定同一行时,它应该得到记录被锁定的通知 - 我不希望这个进程挂起(我相信这里可以使用简单的超时) 3 - 当另一个进程尝试读取记录时,它应该能够以当前在数据库中的方式读取它(但我不想使用脏读)。
上述3个要求目前通过使用共享内存的应用程序解决 - 并在数据库外执行记录锁定。我想将锁定移动到数据库中。
到目前为止,我在#1和#3之间存在冲突 - 如果我通过将字段更新为相同值来执行'更新...'来锁定记录,而不是从另一个进程中“选择”挂起。
编辑: 我现在运气好了MSSQL上的快照隔离级别。我可以同时执行锁定,并且不使用脏读取进行读取。
我不想使用脏读的原因是,如果报表正在运行,它可能会读取多个表,并发出多个查询。快照为我提供了数据库的一致快照。如果脏读,我会有不匹配的数据 - 如果中间有任何更新。
我认为Oracle也有快照,所以现在我对Sybase最感兴趣。
答案 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个系统都不可能,因为它会损害“脏读”的定义。