有没有办法专门锁定一个表以便在Oracle(10g)中读取?我对Oracle不太熟悉,所以我问DBA,他说在Oracle中锁定表是不可能的?
我实际上正在寻找类似SQL Server(TABLOCKX HOLDLOCK)提示的内容。
修改:
回答一些答案:我需要锁定表进行读取的原因是实现一个可以被多个客户端读取的队列,但是2个客户端不可能读取相同的记录。所以实际发生的是:
也许还有另一种方法(更有效率)?
答案 0 :(得分:14)
如果您只是想阻止任何其他会话修改数据,您可以发出
LOCK TABLE whatever
/
这会阻止其他会话更新数据,但我们无法阻止其他会员阅读它。
请注意,在Oracle中,很少需要这种表锁定,因为Oracle运行读取一致性策略。这意味着如果我们运行一个需要十五分钟才能运行的查询,则返回的最后一行将与第一行保持一致;换句话说,如果结果集按相反顺序排序,我们仍会看到完全相同的行。
修改强>
如果要实现队列(实际上没有使用Oracle built-in Advanced Queueing functionality),那么SELECT ... FOR UPDATE
就是可行的方法。此构造允许一个会话选择并锁定一个或多个行。其他会话可以更新未锁定的行。但是,实现真正的队列非常麻烦,除非您使用的是11g。只有在最新版本中,Oracle才支持SKIP LOCKED
子句。 Find out more
答案 1 :(得分: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
这将允许多个进程使用队列中的项目。
答案 2 :(得分:2)
您提到的TABLOCKX
和HOLDLOCK
提示似乎用于写入,而不是读取(基于http://www.tek-tips.com/faqs.cfm?fid=3141)。如果这就是您所追求的,SELECT FOR UPDATE
是否符合您的需求?
更新:根据您的更新,SELECT FOR UPDATE
应该有效,假设所有客户都使用它。
更新2:您现在可能无法对此做任何事情,但这种问题实际上非常适合关系数据库以外的其他事情,例如AMQP。
答案 3 :(得分:0)
如果你的意思是,锁定一个表,以便没有其他会话可以从表中读取,那么不,你不能。无论如何,你为什么要这样做?