繁体   English   中英

Oracle 12. occi c ++的“select for update”的最长持续时间

[英]Oracle 12. Maximum duration for “select for update” for occi c++

我们使用occi来通过C ++进程访问Oracle 12。 其中一个操作必须确保客户端必须在数据库中选择最新数据并根据最新值进行操作。 声明是

std::string sqlStmt = "SELECT REF(a) FROM O_RECORD a WHERE G_ID= :1 AND P_STATUS IN (:2, :3) FOR UPDATE OF PL_STATUS"

(我们正在使用TYPES)。 由于某种原因,此命令没有通过,数据库表是LOCKED。 所有其他操作都在等待第一个线程完成,但线程被杀死,我们已经到达了一个deadend。

什么是避免这种灾难性事件的最佳解决方案? 我可以在语句中设置超时,以便线程可以在“select for update”上运行100%,让我们说最多10秒? 换句话说,执行线程可以锁定数据库表/行但不超过预定时间。

这可能吗?

有一个会话参数ddl_lock_timeout但没有dml_lock_timeout 所以你不能这样走。 所以要么你必须使用

SELECT REF(a) 
FROM O_RECORD a 
WHERE G_ID= :1 AND P_STATUS IN (:2, :3) 
FOR UPDATE OF PL_STATUS SKIP LOCKED

并修改应用程序逻辑。 或者您可以实现自己的中断机制。 只需触发一个并行线程,一段时间后执行OCIBreak 它是文档化和支持的解决方案。 调用OCIBreak是线程安全的。 阻止的SELECT .. FOR UPDATE语句将被释放,您将收到错误ORA-01013: user requested cancel of current operation

因此,在OCCI级别,您将不得不处理此错误。

编辑 :添加了资源管理器 ,它可以施加更精确的限制,只关注那些阻止其他人的会话......

通过资源管理器:

资源管理器允许定义比配置文件可用的更复杂的策略,在您的情况下比后者更合适。

您必须定义计划以及与计划关联的用户组,必须指定与计划/组关联的策略,最后必须将用户附加到组。 要了解如何执行此操作,您可以重用此示例@ support.oracle.com (此处似乎有点太长而无法发布),但将MAX_IDLE_TIME替换为MAX_IDLE_BLOCKER_TIME

核心路线是

dbms_resource_manager.create_plan_directive(
  plan => 'TEST_PLAN',
  group_or_subplan => 'my_limited_throttled_group',
  comment => 'Limit blocking idle time to 300 seconds',
  MAX_IDLE_BLOCKER_TIME => 300)
;

通过配置文件:

您可以限制指定IDLE_TIME的那些会话的不活动时间段。

创建档案

如果用户超过CONNECT_TIMEIDLE_TIME会话资源限制,则数据库将回滚当前事务并结束会话。 当用户进程下一次发出调用时,数据库将返回错误

为此,请指定具有maximux空闲时间的配置文件,并将其应用于相关用户(这样您就不会影响所有用户或应用程序)

CREATE PROFILE o_record_consumer
  LIMIT IDLE_TIME 2; --2 minutes timeout

alter user the_record_consumer profile o_record_consumer;

缺点是此设置是会话范围的,因此如果同一会话应该能够在其他操作过程中保持空闲,则无论如何都将强制执行此策略。

出于兴趣...

也许您已经知道其他会话可以通过多种方式协调他们对同一记录的访问:

  • FOR UPDATE WAIT x; 如果将WAIT x子句附加到select for update语句,则等待会话将在“x”秒过后放弃等待。 (整数“x”必须在那里硬编码,例如值“3”;变量不会,至少在Oracle 11gR2中)。
  • SKIP LOCKED; 如果将SKIP LOCKED子句附加到select for update语句,则select将不会返回被锁定的记录(如ibre5041已经指出的那样)。
  • 您可以发出一个额外的会话(一种监视程序)来表示您的会话启动查询,并在成功执行后向其发出有关完成的提醒。 看门狗会话可以实现其“在超时后杀死会话”逻辑。 您必须支付增加的复杂性,但是可以将超时应用于该特定语句,而不是应用于会话。 为此,请参阅ORACLE-BASE - DBMS_PIPE3.2 DBMS_ALERT:向用户广播警报,作者:Steven Feuerstein,1998年

最后,可能是您正在尝试实现自制的队列基础结构。 在这种情况下,请记住Oracle已经拥有自己的名为Advanced Queue的队列机制,只需使用它们就可以获得很多东西; 请参阅ORACLE-BASE - Oracle高级队列

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM