我有一些代码连接到Oracle数据库,锁定一个表,对它做一些事情并解锁它。
我想知道,如果我的程序在表锁定时冻结,锁会自动释放。如何在给定时间后自动解锁Oracle中的表?
有没有办法设置Oracle,自动执行此操作?
例如,我在想一些会说“如果用户x在表y上超过z秒保持锁定,回滚事务并释放表”。
如果这是不可能的,还有什么我可以做的,以达到相同的结果?这甚至是一个实际的问题,还是我只是偏执狂?
在此先感谢。
我有一些代码连接到Oracle数据库,锁定一个表,对它做一些事情并解锁它。
我想知道,如果我的程序在表锁定时冻结,锁会自动释放。如何在给定时间后自动解锁Oracle中的表?
有没有办法设置Oracle,自动执行此操作?
例如,我在想一些会说“如果用户x在表y上超过z秒保持锁定,回滚事务并释放表”。
如果这是不可能的,还有什么我可以做的,以达到相同的结果?这甚至是一个实际的问题,还是我只是偏执狂?
在此先感谢。
首先,锁定表格不会阻止另一个会话针对数据发出SELECT
语句。
在会话1,如果我锁表
SQL> lock table foo in exclusive mode;
Table(s) Locked.
然后我就可以开始会议2和查询数据的所有我想
SQL> select * from foo;
COL1
----------
1
1
在Oracle中,作家不阻止读者所以你永远不能阻止另一个会话查询表中的数据。
这听起来像你试图实施的是悲观锁定。在这种情况下,不是锁定表格,而是执行锁定您打算处理的特定条目的SELECT FOR UPDATE
。只要所有其他会话也尝试执行SELECT FOR UPDATE
(取决于Oracle版本,可能添加了SKIP LOCKED
限定符和/或WAIT
限定符)。锁定您正在处理的特定行,并让第二个会话选择不同的行或超时,或者根据实现的具体情况查找没有要处理的行。这并不涉及锁定表格。
锁定被释放的唯一方法是获取它的会话释放它(通常通过结束事务)或获取它的会话被终止。如果客户端应用程序仍在运行但没有做任何事情来释放锁定或终止会话,则锁定将被无限期地保留。 DBA需要明确地终止会话,让事务回滚并释放锁以使系统再次移动。如果客户端应用程序停止运行或者至少停止响应(我仍然不清楚您正在讨论的是什么故障场景),则可能会在数据库级别通过'SQLNET.EXPIRE_TIME' parameter启用死连接检测(DCD)导致数据库确定客户端无响应并自动终止会话,回滚事务并释放锁定。
但是,如果存在多个会话处理数据,那么通常使用某种形式的乐观锁定更为可取。否则,您正在设计一个系统,这将不可避免地需要DBA紧急查找和终止会话,以便让业务用户重新工作,并且需要越来越多的干预。这不是DBA津津乐道的事情,也不是商业用户喜欢抱怨的事情。一个简单的乐观锁定方案将如此类似
使用这种架构,查询数据库比较容易查看正在处理哪些行,并且例如有一项工作可以在一段时间后将状态列重新设置为“未处理”如果客户还没有完成。其他会议选择不同的行进行处理相当容易。例如,如果应用程序冻结了几个小时然后恢复,它就会相对安全,因为只要处理完一些其他会话已重新处理该行,它就会找到它。
太棒了!这几乎完美地回答了我的问题,然后是一些。非常感谢! – Paradoxyde
和这一点的代码呢?为什么它需要锁定整个桌子? –
@Paradoxyde - 为什么你的代码锁定一张表?我从来没有遇到过在Oracle中显式手动锁定表格的情况。 “冻结”是什么意思?它试图获取由另一个会话持有的数据库中的锁吗?它在数据库中遇到死锁?应用程序在客户机上崩溃并且必须被杀死?还有别的吗? –
代码在数据库中选择一个条目并“保留”它(将其状态列标记为繁忙)。客户端机器然后对数据库外的对象执行操作,返回并释放它。我知道锁定整个表有点极端,但数据库本身非常小,所以它不会真的减慢进程速度。我这样做的原因是为了防止另一个客户端执行SELECT并“选择”一个条目,从而绝对避免两个客户端保留相同的条目。另外,通过冻结,我的意思是客户端应用程序在无人值守时无限期挂起。 – Paradoxyde