TL; DR: нарушение ссылочной целостности срабатывает, когда нарушения не произошло.
Я запускаю H2 в режиме кластера с двумя узлами.
У меня есть две таблицы в базе данных H2 (v1.4.189), родительская и дочерняя. Дочерний элемент содержит внешний ключ к идентификатору строки родительской таблицы. Обычно я не получаю ошибок при вставке строки в дочернюю таблицу.
Но через некоторое время при вставке я получаю эту ошибку:

Referential integrity constraint violation: "CONSTRAINT_1FE: PUBLIC.CHILD FOREIGN KEY(fkey)
REFERENCES PUBLIC.PARENT(ID) (86)"

Странно то, что данные INSERT INTO, которые привели к ошибке, были успешно вставлены, и что нет нарушения ограничения внешнего ключа!

Я пытался задокументировать точные шаги для воспроизведения ошибки, но со свежей базой данных ошибка никогда не возникает:

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

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

insert into PARENT(name) values('hello');
insert into PARENT(name) values('world');
select * from PARENT; 


insert into CHILD(name, fkey) values('hello', 1); 
-- this works for a while, but someday the Referential integrity error 
-- will pop, but data will be added anyway (wtf?)
insert into CHILD(name, fkey) values('world', 2);

В базе данных я делаю только простые вещи, такие как выбор, вставка, удаление ...

Забавный факт, что после того, как эта ошибка произошла один раз, у меня появляется еще одна странная ошибка: при удалении (или обновлении) строк таблицы CHILD функции DELETE FROM или UPDATE всегда возвращают 0, даже если некоторые строки были удалены ... ( также jdbc executeUpdate () всегда возвращает 0)

База данных в какой-то момент повреждена?

Единственный способ исправить эту ошибку, который я нашел, - это удалить все таблицы и воссоздать их заново, чего я не хочу делать.

2
lmo 21 Окт 2015 в 12:34

2 ответа

Лучший ответ

Главный разработчик H2 Томас Мюллер ответил на этот вопрос на github:

Это одно из задокументированных ограничений функции кластера, см. Также «Алгоритм кластеризации и ограничения»: «Использование автоприращения и столбцов идентификации в настоящее время не поддерживается».

Боюсь, это сложно исправить. По этой причине я предлагаю не использовать функцию кластера. Поддержка этого, вероятно, будет удалена в будущем. Я надеюсь, что можно будет добавить новую функцию кластера / автоматического переключения при отказе, но это займет некоторое время.

Но это может быть вам интересно: https://github.com/shesse/h2ha

См. проблему на github

Мне удалось заставить его работать: используя последовательности и вставляя два раза:
- Получите следующее значение для этой последовательности таблицы, например: nextid = select childsequence.nextval from dual
- Затем сделайте свой INSERT INTO child и укажите идентификатор nextid

0
lmo 8 Авг 2018 в 08:02

Выдается исключение, потому что внешний ключ не найден, вам необходимо сначала вставить зависимые данные.

Примере:

// Execute below query first
INSERT INTO root_table VALUES (value1, value2)
// Execute below query after root_table
INSERT INTO sub_Table VALUES (value1, value2, FK_root_ID)
0
Victor 1 Окт 2020 в 09:32