Jus*_*ave 11
首先,锁定表不会阻止另一个会话SELECT
针对数据发出语句.
在会话1中,如果我锁定表
SQL> lock table foo in exclusive mode;
Table(s) Locked.
Run Code Online (Sandbox Code Playgroud)
然后,我可以启动第2节并查询所有我想要的数据
SQL> select * from foo;
COL1
----------
1
1
Run Code Online (Sandbox Code Playgroud)
在Oracle中,编写器不会阻止读取器,因此您永远不能阻止另一个会话查询表中的数据.
听起来你想要实现的是悲观锁定.在这种情况下,不是锁定表,而是锁定SELECT FOR UPDATE
要处理的特定条目.只要所有其他会话也尝试执行a SELECT FOR UPDATE
(取决于Oracle版本,可能添加SKIP LOCKED
限定符和/或WAIT
限定符).这会锁定您正在处理的特定行,并允许第二个会话选择不同的行或超时,或者发现没有要处理的行,具体取决于实现的具体情况.这不涉及锁定表.
锁定被释放的唯一方法是获取它的会话释放它(通常通过结束事务)或者获取它的会话终止.如果客户端应用程序仍在运行但未执行任何操作以释放锁定或终止会话,则锁定将无限期地保留.DBA需要显式终止会话,让事务回滚并释放锁以使系统再次移动.如果客户端应用程序停止运行或者至少停止响应(我仍然不清楚您正在讨论的故障情况),则可以通过"SQLNET.EXPIRE_TIME"参数启用死连接检测(DCD)在数据库级别将导致数据库确定客户端无响应并自动终止会话,回滚事务并释放锁定.
但是,如果存在多个会话处理数据,则通常更优选使用某种形式的乐观锁定.否则,您正在设计一个系统,该系统将不可避免地需要DBA紧急查找和终止会话,以便让业务用户再次工作,这将需要越来越多的干预,使其更加繁忙.这不是DBA喜欢做的事情,也不是商业用户喜欢抱怨的事情.一个简单的乐观锁定方案就像这样
使用这种体系结构,查询数据库以查看正在处理的行是相对容易的,例如,如果客户端没有,则在一段时间后将状态列设置为"未处理"的作业完了.对于其他会话来说,选择要处理的不同行非常容易.例如,如果应用程序冻结了几个小时然后恢复,则它相对安全,因为它只是在完成处理后才发现其他会话已经重新处理了该行.