如何在给定时间后自动解锁Oracle中的表?

Par*_*yde 3 database oracle session locking

我有一些代码连接到Oracle数据库,锁定表,做一些事情并解锁它.
我想知道,如果我的程序在表被锁定时冻结,则锁会自动释放.

有没有办法设置Oracle,自动执行此操作?

例如,我正在考虑一些事情会说"如果用户x在表y上保持锁定超过z秒,则回滚事务并释放表."

如果不可能,我还能做些什么来达到同样的效果吗?这甚至是一个实际问题还是我只是偏执狂?

提前致谢.

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喜欢做的事情,也不是商业用户喜欢抱怨的事情.一个简单的乐观锁定方案就像这样

  • 选择要处理的密钥以及指示上次更新行的某种日期.
  • 将状态列更新为"处理",以便其他会话不会尝试处理同一行.
  • 处理您的申请中的条目
  • 完成处理后,使用您在第一步中选择的键和时间更新数据.如果您更新了1行,则您知道自从您选择它以来没有其他会话修改过相关数据.如果更新0行,则表示您选择了某些其他会话已修改数据.

使用这种体系结构,查询数据库以查看正在处理的行是相对容易的,例如,如果客户端没有,则在一段时间后将状态列设置为"未处理"的作业完了.对于其他会话来说,选择要处理的不同行非常容易.例如,如果应用程序冻结了几个小时然后恢复,则它相对安全,因为它只是在完成处理后才发现其他会话已经重新处理了该行.