【发布时间】:2021-12-14 10:30:15
【问题描述】:
如何防止过程在参数相同时运行,而在参数不同时允许。让我解释一下确切的问题
创建构建脚本
drop table datalock_test;
create table datalock_test
(year_ number) tablespace wad;
drop TYPE test_lock_type_arr;
drop TYPE test_lock_type;
create or replace TYPE test_lock_type AS OBJECT
(
year_ number
);
/
create or replace TYPE test_lock_type_arr IS TABLE OF test_lock_type
;
/
drop procedure insert_to_lock_test;
create or replace procedure insert_to_lock_test (p_year number)
as
l_arr test_lock_type_arr := test_lock_type_arr();
begin
select test_lock_type(year_) bulk collect into l_arr from (select p_year as year_ from dual) a
where not exists (select NULL from datalock_test b
where a.year_ = b.year_);
dbms_lock.sleep(15);
forall i IN l_arr.first .. l_arr.last SAVE EXCEPTIONS
insert into datalock_test
values
(
l_arr(i).year_
);
commit;
end;
/
truncate table datalock_test;
正常测试:-
现在如果我在下面运行代码,将插入一条记录
begin
insert_to_lock_test(p_year => 1999);
end;
/
现在,如果我再次重新运行上述代码,则不会插入任何记录。
硬测试:-
但如果我在下面运行,则会插入重复的记录,这是不可取的。
begin
dbms_scheduler.create_job (
job_name => 'load1',
job_type => 'plsql_block',
job_action => 'begin
insert_to_lock_test(p_year => 2000);
end;',
enabled => true);
dbms_scheduler.create_job (
job_name => 'load2',
job_type => 'plsql_block',
job_action => 'begin
insert_to_lock_test(p_year => 2000);
end;',
enabled => true);
end;
/
这种重复是我必须避免的。
约束:-
- 我无法创建唯一索引或主键。
- 我不能使用任何额外的检查和存在条件。
我尝试过的:-
- 已尝试独占锁定。但这里的问题是它也阻止了以下功能。在以下情况下,参数不同,因此进程应该能够并行运行。让我提供有关如何完成此操作的代码
重新创建过程如下
create or replace procedure insert_to_lock_test (p_year number)
as
l_arr test_lock_type_arr := test_lock_type_arr();
lv_lockhandle VARCHAR2(500);
lv_ret_code PLS_INTEGER;
lv_retcode NUMBER;
p_nm varchar2(200) := 'testlock';
begin
dbms_lock.allocate_unique(p_nm, lv_lockhandle);
lv_retcode := dbms_lock.request(lockhandle=>lv_lockhandle,
lockmode => dbms_lock.x_mode);
select test_lock_type(year_) bulk collect into l_arr from (select p_year as year_ from dual) a
where not exists (select NULL from datalock_test b
where a.year_ = b.year_);
dbms_lock.sleep(15);
forall i IN l_arr.first .. l_arr.last SAVE EXCEPTIONS
insert into datalock_test
values
(
l_arr(i).year_
);
commit;
lv_ret_code := dbms_lock.release(lv_lockhandle);
end;
/
发布这个让我们以相同的参数并行运行代码
begin
dbms_scheduler.create_job (
job_name => 'load1',
job_type => 'plsql_block',
job_action => 'begin
insert_to_lock_test(p_year => 2000);
end;',
enabled => true);
dbms_scheduler.create_job (
job_name => 'load2',
job_type => 'plsql_block',
job_action => 'begin
insert_to_lock_test(p_year => 2000);
end;',
enabled => true);
end;
/
没有重复插入,只有一条记录,这是可取的。但现在的问题是当我们在代码下面运行时
begin
dbms_scheduler.create_job (
job_name => 'load1',
job_type => 'plsql_block',
job_action => 'begin
insert_to_lock_test(p_year => 2020);
end;',
enabled => true);
dbms_scheduler.create_job (
job_name => 'load2',
job_type => 'plsql_block',
job_action => 'begin
insert_to_lock_test(p_year => 2021);
end;',
enabled => true);
end;
/
这里插入2021耗时太长,参数不同时延迟不理想。
【问题讨论】:
-
你想解决什么问题
-
让我们假设一个 SP1 正在运行,参数 a,b,c 传递给它。现在,如果我尝试使用参数 a、b、c 再次运行 SP1,那么它不应该允许我,但是如果我使用参数 p、q、r 运行 SP1,那么它应该运行。这是我要解决的问题
-
你错过了我的问题。为什么不希望它们同时运行。你想防止什么问题?请提供一个同时运行时遇到的问题的工作示例
-
“这是我要解决的问题” 这就是您要解决的技术问题,作为一些解决方案业务问题。与其将时间浪费在构思不周的技术解决方案上,不如说明业务问题并让社区致力于最佳技术解决方案。总之,你问的是经典x-y question
-
业务流程可能非常简单@EdStevens。该过程根据参数值执行不同的任务。该过程可以从多个并发会话中调用,但所有执行的参数值必须不同 - 必须阻止尝试使用当前正在运行的参数值进行调用。