H2群集奇怪的行为:对外键

时间:2016-05-09 09:00:01

标签: sql database cluster-computing h2

我在群集模式下使用2个节点运行H2。

我有两张桌子。父母和孩子。子项包含父表行的ID的外键 我遇到了一个我无法理解的奇怪问题:一切正常,直到我违反了一个独特的约束。

步骤:
- 一切正常工作
- 我违反了(在这里的目的)一个独特的约束
- 现在,在添加子行时,我在外键(parent.id)上获得了参照完整性违规,但正确添加了子行。

脚本:

create table CHILD(id int auto_increment, name varchar(255), fkey int);
create table PARENT(id int auto_increment, name varchar(255) UNIQUE);

ALTER TABLE `CHILD` ADD FOREIGN KEY (fkey) REFERENCES `PARENT` (`id`)  ON DELETE CASCADE;

-- Insert the first parent, id will be '1'. Then insert the child, this works.
insert into PARENT(name) values('parent1');
insert into CHILD(name, fkey) values('child1', 1); 

-- By purpose, we violate the Unique constraint violation on PARENT.name : Unique index or primary key violation: "CONSTRAINT_INDEX_8 ON PUBLIC.PARENT(NAME) VALUES ( /* 2 */ 'parent1' )"
insert into PARENT(name) values('parent1');

-- Then I delete this parent (by cascade, all childs are deleted)
delete from PARENT where name='parent1';

-- Then I re-insert this parent, this create the row (3, "parent3")
insert into PARENT(name) values('parent3');

-- I try to insert a child with the parent '3', 
-- I get a Referential integrity constraint violation: "CONSTRAINT_3: PUBLIC.CHILD FOREIGN KEY(FKEY) REFERENCES PUBLIC.PARENT(ID) (3)"
insert into CHILD(name, fkey) values('child3', 3); 
-- But the child was propertly added !

我找到的解决方法是将最后insert into替换为:

insert into CHILD(name, fkey) values('child3', SELECT ID from parent where name='parent3'); 

但这太奇怪了,因为SELECT ID from parent where name='parent3'会返回3

使用序列而不是auto_increment时也会发生这种情况 当我不使用auto_increment或序列时,不会发生,所以当我自己管理id时(但我不想)。
当我在没有群集的情况下运行H2时,不会发生这种情况。 用H2 v1.3.176和H2 v1.4.189测试。

有人可以解释一下吗?我在这里犯了错误吗?

1 个答案:

答案 0 :(得分:0)

H2主要开发者thomas mueller在github上回答了这个问题:

  

这是群集功能的一个记录限制,请参阅   还有“聚类算法和限制”:“使用自动增量和   目前不支持标识列。“

     

我担心修复它很难。我建议不要使用群集   出于这个原因。可能会删除对它的支持   未来。我希望新的集群/自动故障转移功能可以   补充说,但这需要一些时间。

     

但这对你来说可能很有意思:https://github.com/shesse/h2ha

请参阅issue on github

我设法让它工作:使用序列并插入两次:
- 获取此表序列的nextval,例如: nextid = select childsequence.nextval from dual
- 然后执行INSERT INTO child并指定ID nextid