关于自治事务和锁 PRAGMA AUTONOMOUS_TRANSACTION & LOCK

之前遇到的一个问题, 可以稳定重现.

Oracle 的 INV 提供了一个接口 inv_lot_api_pub.auto_gen_lot() , 用来自动为 item 产生 lot number, 调用一次这个接口, lot number 就会自动 + 1; 看里头的代码, 是先从 MTL_SYSTEM_ITEMS 这个表里面取出一个字段 start_auto_lot_number, 比方说取出来的数值是1000, 那么就会把 1000 当做当前的 lot number, 接着会调用一个 procedure, 去更新这个字段, 变成 1001.
这个procedure 名字叫做 update_msi(). 最后去验证 1000 这个 lot number 是不是已经存在了. 如果存在, 那么会重新取出 1001 当做当前 lot number, 并且验证是不是存在, 直到找到没有重复的lot number, 就把它返回给调用 api 的地方.

那么这段代码会有什么问题呢? 我们假设一个场景, 有两个 session 同时调用这个 api, 那么在从 MSI 取数据的阶段, 有可能两个 session 会取出来相同的lot number. 嗯, 这个是有可能的. 如果这两个 session 是在为同一个 item 产生 lot number 就还好, 但是如果是不同的item, 就会为不同的两个 item 产生相同的 lot number. 这样数据就错了.

解决的办法就是通过锁来锁住被选择的 lot number, 并且在更新成功之后释放锁.

锁住选择的数据的方法是使用 for update 语句

     SELECT auto_lot_alpha_prefix,
            start_auto_lot_number
       INTO l_lot_prefix,
            l_lot_suffix
       FROM mtl_system_items
      WHERE organization_id = p_org_id
        AND inventory_item_id = p_inventory_item_id for update

一旦有数据被选中, 那么同样使用这个 SQL 的session 将不能获得这些数据, 这就保证了无法产生相同的lot number. 当成功更新 lot number 之后, 就可以用 commit 释放锁了.

那么问题来了, 如果我们使用 commit 提交这个事务, 将会把所有的事务处理都提交, 那么如果之后出现错误回滚了, 将会有一部分数据提交, 另一部分数据回滚了. 解决的办法是使用自治事务. 从 select for update 语句开始, 到update MSI 并 commit 为止, 我们定义一个 procedure 并声明这是一个 PRAGMA AUTONOMOUS_TRANSACTION. 这样提交事务的时候就只会提交这个自治事务所做的更改, 并且释放锁给其他语句使用. 在自治事务之外的数据更新操作都不会受到影响.

这样通过锁和声明自治事务, 就可以保证不会在两个 session 里面获取到相同的 lot number 了;

时间: 2024-08-12 00:32:22

关于自治事务和锁 PRAGMA AUTONOMOUS_TRANSACTION & LOCK的相关文章

Oracle与SQL自治事务

自治事务 自治事务是独立的事务操作,如果考虑到事务回滚,必须单独写成一个触发器来完成, 一个事务A在另一个事务B内被调用,那个事务A是自治事务,自治事务A执行过程中会脱离其session内未执行完毕的事务的影响. 如果session从B事务开始——A事务开始和结束——B事务结束 上述的A事务不受没有完成的B事务的影响,然后A事务执行完毕后再次回到B事务执行没有完成的B事务. 通过pragma autonomous_transaction将一个pl/sql程序结构设定为自治事务,pragma是编译

redis事务,分布式锁

事务:一组命令集合 主要命令multi 和exec multi set a 1 sadd s1 a ...... exec 错误处理 (1)语法错误 127.0.0.1:6379> multi OK 127.0.0.1:6379> set a 1 QUEUED 127.0.0.1:6379> set b (error) ERR wrong number of arguments for 'set' command 127.0.0.1:6379> seta c (error) ERR

Oracle的自治事务

自治事务(autonomous transaction)允许你创建一个"事务中的事务",它能独立于其父事务提交或回滚.利用自治事务,可以挂起当前执行的事务,开始一个新事务,完成一些工作,然后提交或回滚,所有这些都不影响当前所执行事务的状态.自治事务提供了一种用PL/SQL控制事务的新方法,可用于: 顶层匿名块: 本地(过程中的过程).独立或打包的函数和过程: 对象类型的方法: 数据库触发器. 使用例子演示自治事务如何工作 --创建测试表用于保存信息 [email protected]&

oracle 触发器 pragma autonomous_transaction

from:http://blog.csdn.net/ruru7989/article/details/30712987一般情况下在触发器中是不能使用DDL语句的,使用自治事务可以实现 可以在触发器中加入: pragma autonomous_transaction; 表示自由事务处理. CREATE OR REPLACE TRIGGER temp_ais AFTER insert ON atest for each row DECLARE pragma autonomous_transactio

PLSQL_自治事务和嵌套的理解和用法(案例)

2014-06-01 BaoXinjian In Capgemini 一.摘要 嵌套事物:指在一个Parent事务中嵌套的一个或多个Sub Transaction.并且主事务与其相互影响,这种事务就称为嵌套事务.以Commit作为事务的结束 自治事物:指在function,procedure等subprograms中对事务进行自治管理,当在别的pl/sql block里去调用这些subprograms的时候这些subprograms并不随着父pl/sql block的失败而回滚,而是自己管自己c

Oracle自治事务实际用例

如下,新建两个存储过程: 在主自治事务中,我们插入一条记录,然后在自治事务中,查看表中行数,然后尝试插入三条记录,查看行数,最后rollback 查看行数,最后返回主事务,查看行数. 1.如下代码: --主事务 PROCEDURE p_test_at_and_mt IS cnt NUMBER := -1; BEGIN INSERT INTO msg VALUES ('father Record'); SELECT COUNT(*) INTO cnt FROM msg; dbms_output.p

PRAGMA AUTONOMOUS_TRANSACTION

数据库事务是一种单元操作,要么是全部操作都成功,要么全部失败.在Oracle中,一个事务是从执行第一个数据管理语言(DML)语句开始,直到执行一个COMMIT语句,提交保存这个事务,或者执行一个ROLLBACK语句,放弃此次操作结束. 针对这种困境,Oracle提 供了一种便捷的方法,即自治事务.自治事务从当前事务开始,在其自身的语境中执行.它们能独立地被提交或重新运行,而不影响正在运行的事务.正因为这样, 它们成了编写错误日志表格的理想形式.在事务中检测到错误时,您可以在错误日志表格中插入一行

Oracle 通过触发器 来创建 同步临时表 及处理 通过 自治事务 来解决 查询 基表的问题

// 触发器 create or replace trigger tr_sync_BD_MARBASCLASS after INSERT or UPDATE on BD_MARBASCLASS for each row declare v_cnt integer; PRAGMA AUTONOMOUS_TRANSACTION; -- 自治事务 begin /** * Name : tr_sync_BD_MARBASCLASS * Desc : 物料分类 增量同步 触发器 * Author : wu

oracle自治事务

自治事务的使用,独立于外层的事务控制 create or replace procedure insert_err_po( OrderNo number,CycleId number ) is pragma autonomous_transaction; begin insert into tt_err_po(po_num_id,cycle_num_id) values(OrderNo,CycleId); commit; end;