2012-07-30 53 views
1

我对如何实现悲观锁定感兴趣,具有非常特定的行为。 (我加了标签的问题与Sybase + ORACLE + MSSQL究其原因,是因为我很乐意与解决方案或“那是不可能的!”他们中的任何一个)执行悲观锁定

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

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

到目前为止,我有间#1和#3的冲突 - 如果我通过更新字段相同的值做“更新......”锁记录,不是从另一个进程挂起“选择”。

编辑: 我有与MSSQL快照隔离级别现在一些运气。我可以同时执行锁定和读取而不使用脏读。

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

我认为甲骨文也有快照,所以现在我最感兴趣的是Sybase。

+2

你能否更详细地解释为什么你不想用脏读?这就是你在#3中要求的定义。 – mwigdahl 2012-07-30 14:19:04

回答

2

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

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

如果另一个进程试图执行它得到一个例外相同statment:

ORA-00054: resource busy and acquire with NOWAIT specified 

直到第一个进程(会话)执行commit或rollback。

正常,甲骨文不允许脏读

0

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

所以,如果你想这样:是的,你想要什么,因为它伤害了“脏读”的定义是不可能的全部3个系统。

+0

#1和#3没有固有冲突。这就是Oracle的多版本读取一致性在默认情况下所做的。它不允许脏读,它可以防止作者阻止读者,并防止作者阻止读者。 SQL Server的快照隔离级别提供了类似的功能。 – 2012-07-30 17:31:59

+0

@JustinCave是的,有冲突:他希望能够在#3中“按照它当前在数据库中的方式阅读”,但没有脏读。但是读取一个锁定的元素是一个脏读 - 被授予:不是定义;但从逻辑上讲,实现不阻止任何事情的锁定功能是没有意义的。我对吗? – Argeman 2012-07-31 07:05:18

+0

快照是我猜我在找什么。它锁定了作者,但不是读者。我所引用的陈述并不是很好,但快照确实允许我读取一致的数据,即使它不是'数据库中当前的数据',它对于某些特定的时间片是一致的。 – Alex 2012-07-31 15:40:04