在我的程序数据模型中,存在一个包含两列的表,如下所示:
Id_1
和 Id_2
数据类型为 Number
。此表没有任何主键和唯一键。
我有一个程序包,其过程为 persist
。此过程用于向表中添加一行。
我在包中的过程如下:
procedure persist(id_1 out Number,
id_2 out Number)is
begin
insert into middle_table values(id_1,id_2);
end;
问题是:我有一个场景如下: 线程 1 和线程 2 使用相同的参数并发调用上面的过程,结果是:2 等于行添加到上面的表,这在我的应用程序中是错误的。
我的问题是:我在程序中做了什么来防止这种情况?
最佳答案
你应该总是有一个约束,但在某些情况下这个要求可能仍然有效。
一个简单而优雅的解决方案是执行MERGE
或执行SELECT
和INSERT
。那么proc执行了多少次,你就安全了。
您可以通过将过程调用放在线程类的 syncronized
方法中来实现客户端。因此,它不能并行运行。
public void your_method() {
// Other statements
synchronized( this ) { // blocks "this" from being executed by parallel threads
// call your oracle stored proc here
}
}
但是如果有多个跨不同平台的client,你可能要自己在Oracle里面写点东西!
一个简单而优雅的解决方案是执行 MERGE
或执行 SELECT
和 INSERT
procedure persist(id_1 out Number,
id_2 out Number)
is
retcode NUMBER := 0;
begin
retcode := 100;
/* Checking for semaphore, else wait ! */
WHILE(retcode = 100)
LOOP
retcode = check_semphore(); /* Returns 100 if present else 0 */
IF(retcode = 100) THEN
/* Semaphore present */
NULL;
ELSE
write_semaphore;
/* probably a entry in a table with commit,
have to use savepoints, else every other transactions would be comitted! */
MERGE INTO middle_table m
USING (SELECT id_1,id_2 FROM dual) new_Values
ON ( new_Values.id_1 = m.id_1
AND new_Values.id_2 = m.id_2)
WHEN NOT MATCHED
THEN
INSERT INTO middle_table VALUES(id_1,id_2);
delete_semaphore;
/* delete tht entry */
EXIT;
END IF;
END LOOP;
end;
/
关于java - 同步了一个从 jdbc 调用的 oracle 包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21060946/