H2 集群怪异行为:外键上的假参照完整性违规

H2 cluster weird behavior : fake referential Integrity violation on foreign key

I 运行 H2 在集群模式下有 2 个节点。

我有两个 table。一个parent,一个child。 child 包含指向 parent table.
行 ID 的外键 我遇到了一个我无法理解的奇怪问题:在我违反唯一约束之前一切正常。

步骤:
- 一切正常
- 我违反了(故意)一个唯一约束
- 现在添加 child 行时,我在外键 (parent.id) 上遇到引用完整性冲突,但 child 行已正确添加。

脚本:

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' returns 3.

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

有人可以解释一下吗?我是不是弄错了?

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

This is one of the documented limitations of the cluster feature, see also "Clustering Algorithm and Limitations": "Using auto-increment and identity columns is currently not supported."

I'm afraid it's hard to fix it. I suggest to not use the cluster feature for this reason. Support for it will probably be removed in the future. I hope a new cluster / automatic failover feature can be added, but this will take some time.

But this might be interesting for you: https://github.com/shesse/h2ha

issue on github

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