2

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

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

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

到目前为止,我在#1 和#3 之间存在冲突——如果我通过将字段更新为相同值来执行“更新...”来锁定记录,那么来自另一个进程的“选择”就会挂起。

编辑:我现在对 MSSQL 上的快照隔离级别有一些运气。我可以在不使用脏读的情况下进行锁定和读取。

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

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

4

2 回答 2

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 不允许脏读

于 2012-07-30T17:28:37.070 回答
0

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

因此,如果您希望这样:是的,对于所有 3 个系统,您想要的都是不可能的,因为它损害了“脏读”的定义。

于 2012-07-30T14:13:03.563 回答