简体   繁体   English

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

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

We are using occi in order to access Oracle 12 via a C++ process. 我们使用occi来通过C ++进程访问Oracle 12。 One of the operations has to ensure that the client has to pick the latest data in the database and operate according to the latest value. 其中一个操作必须确保客户端必须在数据库中选择最新数据并根据最新值进行操作。 The statement is 声明是

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"

(we are using TYPES). (我们正在使用TYPES)。 For some reason this command did not go though and the database table is LOCKED. 由于某种原因,此命令没有通过,数据库表是LOCKED。 All other operations are waiting the first thread to finish, however the thread is killed and we have reached a deadend. 所有其他操作都在等待第一个线程完成,但线程被杀死,我们已经到达了一个deadend。

What is the optimal solution to avoid this catastrophic senario? 什么是避免这种灾难性事件的最佳解决方案? Can I set a timeout in the statement in order to by 100% that a thread can operate on the "select for update", let's say for a maximum of 10 seconds? 我可以在语句中设置超时,以便线程可以在“select for update”上运行100%,让我们说最多10秒? In other words the thread of execution can lock the database table/row but no more than a predifined time. 换句话说,执行线程可以锁定数据库表/行但不超过预定时间。

Is this possible? 这可能吗?

There is a session parameter ddl_lock_timeout but no dml_lock_timeout . 有一个会话参数ddl_lock_timeout但没有dml_lock_timeout So you can not go this way. 所以你不能这样走。 So Either you have to use 所以要么你必须使用

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

And modify the application logic. 并修改应用程序逻辑。 Or you can implement your own interruption mechanism. 或者您可以实现自己的中断机制。 Simply fire a parallel thread and after some time execute OCIBreak . 只需触发一个并行线程,一段时间后执行OCIBreak It is documented and supported solution. 它是文档化和支持的解决方案。 Calling OCIBreak is thread safe. 调用OCIBreak是线程安全的。 The blocked SELECT .. FOR UPDATE statement will be released and you will get an error ORA-01013: user requested cancel of current operation 阻止的SELECT .. FOR UPDATE语句将被释放,您将收到错误ORA-01013: user requested cancel of current operation

So on OCCI level you will have to handle this error. 因此,在OCCI级别,您将不得不处理此错误。

Edit : added the Resource Manager , which can impose an even more precise limitation, just focused on those sessions that are blocking others... 编辑 :添加了资源管理器 ,它可以施加更精确的限制,只关注那些阻止其他人的会话......

by means of the Resource Manager: 通过资源管理器:

The Resource Manager allows the definition of more complex policies than those available to the profiles and in your case is more suitable than the latter. 资源管理器允许定义比配置文件可用的更复杂的策略,在您的情况下比后者更合适。

You have to define a plan and the groups of users associated to the plan, have to specify the policies associated to plan/groups and finally have to attach the users to the groups. 您必须定义计划以及与计划关联的用户组,必须指定与计划/组关联的策略,最后必须将用户附加到组。 To have an idea of how to do this, you can reuse this example @support.oracle.com (it appears a bit too long to be posted here) but replacing the MAX_IDLE_TIME with MAX_IDLE_BLOCKER_TIME . 要了解如何执行此操作,您可以重用此示例@ support.oracle.com (此处似乎有点太长而无法发布),但将MAX_IDLE_TIME替换为MAX_IDLE_BLOCKER_TIME

The core line would be 核心路线是

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)
;

by means of profiles: 通过配置文件:

You can limit the inactivity period of those session specifying an IDLE_TIME . 您可以限制指定IDLE_TIME的那些会话的不活动时间段。

CREATE PROFILE : 创建档案

If a user exceeds the CONNECT_TIME or IDLE_TIME session resource limit, then the database rolls back the current transaction and ends the session. 如果用户超过CONNECT_TIMEIDLE_TIME会话资源限制,则数据库将回滚当前事务并结束会话。 When the user process next issues a call, the database returns an error 当用户进程下一次发出调用时,数据库将返回错误

To do so, specify a profile with a maximux idle time, and apply it to just the relevant users (so you wont affect all users or applications) 为此,请指定具有maximux空闲时间的配置文件,并将其应用于相关用户(这样您就不会影响所有用户或应用程序)

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

alter user the_record_consumer profile o_record_consumer;

The drawback is that this setting is session-wide, so if the same session should be able to stay idle in the course of other operations, this policy will be enforced anyway. 缺点是此设置是会话范围的,因此如果同一会话应该能够在其他操作过程中保持空闲,则无论如何都将强制执行此策略。

of interest... 出于兴趣...

Maybe you already know that the other sessions may cohordinate their access to the same record in several ways: 也许您已经知道其他会话可以通过多种方式协调他们对同一记录的访问:

  • FOR UPDATE WAIT x; If you append the WAIT x clause to your select for update statement, the waiting session will give up the wait after "x" seconds have elapsed. 如果将WAIT x子句附加到select for update语句,则等待会话将在“x”秒过后放弃等待。 (the integer "x" must be hardcoded there, for instance the value "3"; a variable won't do, at least in Oracle 11gR2). (整数“x”必须在那里硬编码,例如值“3”;变量不会,至少在Oracle 11gR2中)。
  • SKIP LOCKED; If you append the SKIP LOCKED clause to your select for update statement, the select won't return the records that are locked (as ibre5041 already pointed up). 如果将SKIP LOCKED子句附加到select for update语句,则select将不会返回被锁定的记录(如ibre5041已经指出的那样)。
  • You may signal an additional session (a sort of watchdog) that your session is up to start the query and, upon successful execution, alert it about the completion. 您可以发出一个额外的会话(一种监视程序)来表示您的会话启动查询,并在成功执行后向其发出有关完成的提醒。 The watchdog session may implement its "kill-the-session-after-timeout" logic. 看门狗会话可以实现其“在超时后杀死会话”逻辑。 You have to pay the added complexity but get the benefit of having the timeout applied to that specific statement, not to the session. 您必须支付增加的复杂性,但是可以将超时应用于该特定语句,而不是应用于会话。 To do so see ORACLE-BASE - DBMS_PIPE or 3.2 DBMS_ALERT: Broadcasting Alerts to Users, By Steven Feuerstein, 1998 . 为此,请参阅ORACLE-BASE - DBMS_PIPE3.2 DBMS_ALERT:向用户广播警报,作者:Steven Feuerstein,1998年

Finally, it may be that you are attempting to implement a homemade queue infrastructure. 最后,可能是您正在尝试实现自制的队列基础结构。 In this case, bear in mind that Oracle already has its own queue mechanics called Advanced Queue and you may get a lot with very little by simply using them; 在这种情况下,请记住Oracle已经拥有自己的名为Advanced Queue的队列机制,只需使用它们就可以获得很多东西; see ORACLE-BASE - Oracle Advanced Queuing . 请参阅ORACLE-BASE - Oracle高级队列

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

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