2009-09-28 102 views
2

有没有办法在Oracle(10g)中专门锁定表格进行阅读?我对Oracle不是很熟悉,所以我问DBA,他说在Oracle中锁定一张表是不可能的?Oracle 10g上的独占表(读)锁?

我实际上在寻找像SQL Server(TABLOCKX HOLDLOCK)这样的提示。

编辑

在回应一些问题的答案:我需要锁定表的读数是实现能够被多个客户端读取队列的原因,但它应该为2是不可能的客户读取相同的记录。那么,实际情况是:

  1. 锁表
  2. 队列
  3. 阅读下一个项目
  4. 从队列中删除项目
  5. 删除表锁

也许有这样做的另一种方式(更有效率)?

+2

我有相反的情况:我了解Oracle,但对SQL Server不太了解。 “锁定桌子阅读”是什么意思?你想阻止什么发生? – APC 2009-09-28 15:16:59

回答

14

如果你只是想阻止修改数据的任何其他会话可以发出

LOCK TABLE whatever 
/

这阻止更新数据其他会话,但我们不能从阅读它阻止其他peple。

请注意,在Oracle中,这种表锁定很少需要,因为Oracle运行读取一致性策略。这意味着如果我们运行一个需要15分钟运行的查询,返回的最后一行将与第一行一致;换句话说,如果结果集按照相反的顺序排序,我们仍然可以看到完全相同的行。

编辑

如果你想实现一个队列(实际上并没有使用Oracle的built-in Advanced Queueing functionality),那么SELECT ... FOR UPDATE是要走的路。该构造允许一个会话选择并锁定一行或多行。其他会话可以更新未锁定的行。然而,除非你使用11g,否则实现一个真正的队列非常麻烦。只有在最新版本中,Oracle才支持SKIP LOCKED条款。 Find out more

+0

请参阅编辑我对我的问题 – 2009-09-28 18:31:00

+1

+1,这是我该怎么做;良好的联系。 – DCookie 2009-09-29 00:38:36

0

如果你的意思是锁定一张表,使其他会话无法从表中读取,那么不行。无论如何,你为什么要这么做?

+0

看我的编辑。我可能会错过一些明显的... – 2009-09-28 17:55:34

2

TABLOCKXHOLDLOCK提示您提到似乎用于写入,而不是读取(基于http://www.tek-tips.com/faqs.cfm?fid=3141)。如果这就是你想要的,SELECT FOR UPDATE是否符合你的需求?

更新:根据您的更新,SELECT FOR UPDATE应该工作,假设所有客户使用它。

更新2:您现在可能无法做任何事情,但这类问题实际上非常适合关系数据库以外的其他应用,例如AMQP

+0

TABLOCKX将独占锁定表(当另一个客户端上有TABLOCKX锁时,没有其他客户端可以锁定该表)。这有效地防止其他客户端读取表(如果他们也请求锁当然) – 2009-09-28 17:54:50

+0

一般来说,Oracle不锁定读取。 – 2009-09-28 18:55:11

4
1. Lock table 
    2. Read next item in queue 
    3. Remove item from the queue 
    4. Remove table lock 

在这种模式下,很多会话将只会等待锁定,这似乎是一种浪费。高级队列将是一个更好的解决方案。

如果你想要一个'自己动手'的解决方案,你可以看看SKIP LOCKED。它直到11g才被记录,但是它存在于10g中。在这个算法中,你会做

1. SELECT item FROM queue WHERE ... FOR UPDATE SKIP LOCKED 
    2. Process item 
    3. Delete the item from the queue 
    4. COMMIT 

这将允许多个进程消耗队列中的项目。

+0

我不认为SKIP LOCKED子句可用于这种方式。选择更新执行“正常”选择和(概念上)比锁定选定的行。使用SKIP LOCKED,您只需在尝试锁定选定行并锁定您所能锁定的行时不会挂起。没有看到这可以如何帮助(2个会话发出“相同”的选择结束,一个锁定所有选定的行,第二个锁定并返回0行) – 2009-09-29 06:04:26

+0

SKIP LOCKED如上所述工作。有2场会议。该查询应该作为游标打开,然后获取一行。每个会话都会得到一个不同的会话。 – 2016-06-29 19:00:19