Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 可以保证任何时间戳值在整个数据库中只出现一次)_Java_Database_Oracle_Concurrency - Fatal编程技术网

Java 可以保证任何时间戳值在整个数据库中只出现一次)

Java 可以保证任何时间戳值在整个数据库中只出现一次),java,database,oracle,concurrency,Java,Database,Oracle,Concurrency,你说你关心“回归错误”。我说“为什么您需要关注应用程序中明显无法治愈的“回归bug”。因为你的老板为他们收到的垃圾支付了很多钱,而你又不想成为一个因带来信息而被枪杀的钢琴家?“我必须以正确的方式管理索引(所有顺序索引,没有重复索引),可能有数百人同时申请旅行 在表中插入行程记录时,获取索引的方法是 从表中选择MAX(索引编号)+1作为下一个索引编号 并将其用作新索引(这是在Java端完成的,然后是一个新的查询来插入记录)。很明显,为什么我们对同一索引有多个点或保留。” 嗯。Oracle的MVCC

你说你关心“回归错误”。我说“为什么您需要关注应用程序中明显无法治愈的“回归bug”。因为你的老板为他们收到的垃圾支付了很多钱,而你又不想成为一个因带来信息而被枪杀的钢琴家?

“我必须以正确的方式管理索引(所有顺序索引,没有重复索引),可能有数百人同时申请旅行

在表中插入行程记录时,获取索引的方法是

从表中选择MAX(索引编号)+1作为下一个索引编号

并将其用作新索引(这是在Java端完成的,然后是一个新的查询来插入记录)。很明显,为什么我们对同一索引有多个点或保留。”

嗯。Oracle的MVCC(“快照隔离”)被一开始就不应该使用的人错误地使用

真的,彼得是对的。您的索引号是,或者应该是,他提到的有序时间戳上的一种“排名号”(这要求DBMS可以保证任何时间戳值在整个数据库中只出现一次)


你说你关心“回归错误”。我说“为什么您需要关注应用程序中明显无法治愈的“回归bug”。因为你的老板为他们得到的垃圾付出了很多钱,而你又不想成为一名钢琴家,因为传达了信息而被枪毙?

解决方案取决于你掌握了什么。我假设您可以同时更改数据库和Java代码,但不要修改数据库方案,因为您必须适应过多的Java代码

一个便宜的解决方案可能是在对(trip\u id,index\u nr)上添加唯一性约束,或者如果只有一次trip,则仅在index\u nr上添加唯一性约束。另外添加一个检查约束检查(索引编号>0)-除非索引编号已经未签名。然后,所有其他的事情都在Java中完成:当按照您的描述插入一个新的申请者时,您必须添加捕获其他人同时被插入时的异常的代码。如果某个记录被更新或删除,您要么必须在序列号之间留有洞(通过选择16个索引最低的候选项,如Quassnoi在其视图中所示),要么在每次更新/删除后手动填充(类似于Aaron建议的)


如果index_nr在应用程序中主要用作只读,则更好的解决方案可能是将Peter和Quassnoi的答案结合起来:使用时间戳(通过将当前时间定义为默认时间由数据库自动插入)或自动递增整数(由数据库默认插入)作为表中存储的值。并使用视图(如Quassnoi定义的视图)从Java访问表和自动计算的索引。但也要定义这两个约束,如廉价解决方案。

解决方案取决于您控制的内容。我假设您可以同时更改数据库和Java代码,但不要修改数据库方案,因为您必须适应过多的Java代码

一个便宜的解决方案可能是在对(trip\u id,index\u nr)上添加唯一性约束,或者如果只有一次trip,则仅在index\u nr上添加唯一性约束。另外添加一个检查约束检查(索引编号>0)-除非索引编号已经未签名。然后,所有其他的事情都在Java中完成:当按照您的描述插入一个新的申请者时,您必须添加捕获其他人同时被插入时的异常的代码。如果某个记录被更新或删除,您要么必须在序列号之间留有洞(通过选择16个索引最低的候选项,如Quassnoi在其视图中所示),要么在每次更新/删除后手动填充(类似于Aaron建议的)


如果index_nr在应用程序中主要用作只读,则更好的解决方案可能是将Peter和Quassnoi的答案结合起来:使用时间戳(通过将当前时间定义为默认时间由数据库自动插入)或自动递增整数(由数据库默认插入)作为表中存储的值。并使用视图(如Quassnoi定义的视图)从Java访问表和自动计算的索引。但也要定义这两个约束,比如廉价解决方案。

不想让它变得复杂。我自己也喜欢KISS()解决方案,但代码库已经存在。我也在寻找替代方案,但也在寻找实现上述目标的方法。通过这种方式,我可以以较小的影响(减少回归错误的可能性)修复无法正常工作的行为,然后修改应用程序的其他位置以适应新的行为。如果必须避免更改,可以选择在index_nr列上设置唯一约束,这样DB本身就可以避免重复,缺点是您必须捕获它将抛出的sqlexception,并确保使用新的更高的索引重试。\n您可以使用序列而不是时间戳。如果在RAC上,则需要ORDER子句来确保在每个节点上分配的序列号是有序的。噢,解雇java开发人员,因为他们显然不知道“并发性”和“原子性”的概念。不想让它变得复杂。我自己也喜欢KISS()解决方案,但代码库已经存在。我也在寻找替代方案,但也在寻找实现上述目标的方法。通过这种方式,我可以以较小的影响(减少回归错误的可能性)修复无法正常工作的行为,然后修改应用程序的其他位置以适应新的行为。如果必须避免更改,可以选择在index_nr列上设置唯一约束,这样DB本身就可以避免重复,缺点我
select count(*)
from CompetitionEntry
where PersonOrder < 16
  and Active = 1
    update (
        select *
        from TABLE
        where ...
        order by ID
    )
    set INDEX_NR = INDEXSEQ.NEXTVAL
-- Initial Setup
CREATE TABLE NUMBER_SOURCE (ID NUMBER(4));

INSERT INTO NUMBER_SOURCE(ID) VALUES 0;

-- Your regular code
SELECT ID AS NEXT_INDEX_NR FROM NUMBER_SOURCE FOR UPDATE; -- lock!

UPDATE NUMBER_SOURCE SET ID = ID + 1;

INSERT INTO TABLE ....

COMMIT; -- releases lock!
CREATE OR REPLACE VIEW v_person
AS
SELECT  id, name, ROW_NUMBER() OVER (ORDER BY id) AS index_rn
FROM    t_person

CREATE OR REPLACE TRIGGER trg_person_ii
INSTEAD OF INSERT ON v_person
BEGIN
        INSERT
        INTO    t_person (id, name)
        VALUES  (:new.id, :new.name);
END;

CREATE OR REPLACE TRIGGER trg_person_iu
INSTEAD OF UPDATE ON v_person
BEGIN
        UPDATE  t_person
        SET     id = :new.id,
                name = :new.name
        WHERE   id = :old.id;
END;

CREATE OR REPLACE TRIGGER trg_person_id
INSTEAD OF DELETE ON v_person
BEGIN
        DELETE
        FROM    t_person
        WHERE   id = :old.id;
END;

INSERT
INTO    v_person
VALUES  (1, 'test', 1)

SELECT  *
FROM    v_person

--
id   name   index_rn

 1   test          1

INSERT
INTO    v_person
VALUES  (2, 'test 2', 1)

SELECT  *
FROM    v_person

--
id   name   index_rn

 1   test          1
 2   test 2        2


DELETE
FROM    v_person
WHERE   id = 1

SELECT  *
FROM    v_person

--
id   name   index_rn

 2   test 2        1