Подтвердить что ты не робот

MySQL: ограничения внешнего ключа, которые превышают максимальную глубину

У меня есть MySQL Server 5.1.62, установленный на рабочем сервере. Я каждый день отслеживаю файл журнала ошибок mysql server, и вдруг я обнаружил ниже ошибку в файле журнала ошибок.

InnoDB: невозможно удалить/обновить строки с ограничениями каскадного внешнего ключа, которые превышают максимальную глубину 250
    Пожалуйста, бросьте чрезмерные внешние ограничения и повторите попытку

У меня есть структура базы данных с основным ключом - внешним ключом с соответствующими действиями по обновлению/удалению, и мне нужно удалить данные дочерних таблиц, если данные в родительской таблице удалены приложением или вручную (бэкэнд).

У меня была проблема с Google, но я не нашел подходящего решения. Как я могу решить эту проблему?

4b9b3361

Ответ 1

Я согласен с исходными ответами @Devart и @Catcall здесь, но я хотел бы добавить несколько вещей после обмена несколькими комментариями с OP.

Во-первых, я уменьшил представление изображения схемы только на таблицы, на которые влияет запрос DELETE на tbl_indentmaster.

Из того, что я мог видеть, в этой диаграмме схемы нет круговых ссылок FK.

Кроме того, OP выполнил следующий запрос:

DELETE FROM tbl_indentmaster WHERE indentId IN (1,2,3,4,5,6,...,150,151,155,156,....)

Это удачное количество строк для удаления. При дальнейшем рассмотрении OP утверждает, что запрос работает для меньших подмножеств indentId.

Из этого я думаю, что мы можем использовать две возможности:

  • В MySQL существует ошибка (крайне маловероятная, но возможная), которая вызывает большие запросы с CASCADE DELETE как ваш. Примечание. Я предлагаю возможность появления новой ошибки, а не той [уже опубликованной] [2]. В идеале количество строк для удаления не должно иметь значения.
  • В tbl_indentmaster есть определенная запись indentId, которая вызывает сбой всего запроса.

Я бы предположил, что вы сначала попытаетесь диагностировать проблему, учитывая точку (2), которая является фактическим виновником. Вы можете разбить запрос DELETE на более мелкие куски и найти оскорбительные идентификаторы.

Если этот script - это то, что нужно периодически выполнять с помощью кода (в более крупном приложении), вам следует также рассмотреть возможность выполнения запроса в меньших фрагментах (вероятно, 15 id для запроса - это хороший запуск IMO). В дополнение к этому я предлагаю ошибки регистрации с оскорбительным идентификатором в файле журнала, чтобы вы точно знали, какие записи терпят неудачу.

Ответ 2

Посмотрите на эту ссылку - Cascade Удалите результаты в "Получил ошибку -1 из механизма хранения" . Есть предложение.

Кроме того, в качестве решения вы можете попробовать сделать это без опции DEL DELETE CASCADE, просто используйте DELETE выражение, которое удаляет записи из некоторых таблицы (синтаксис с несколькими таблицами).

Ответ 3

Изображение схемы не очень полезно, потому что оно не показывает каскадные объявления. Например, если удаленные объекты должны каскадироваться от tbl_indentmaster до tbl_tepdetails, но удаленные объекты не должны каскадироваться из tbl_tepdetails в tbl_tepnoting, тогда я ожидаю, что некоторые удаления будут сбой. (Но с другим сообщением об ошибке.)

Если существует круговое связанное ограничение, которое вызывает это, я ожидаю, что это будет частично вызвано каскадной ссылкой от tbl_indentmaster к tbl_tepdetails. Возможно, вы захотите попробовать сбросить ограничение внешнего ключа для тестирования. Сделайте это на sserver tset, а не на рабочем сервере.

Если это началось внезапно, и ваша база данных работала правильно раньше, я бы сначала подумал о

  • восстановление базы данных из резервной копии или
  • восстановление схемы из резервной копии и перезагрузка текущих данных или
  • проверка текущей версии и восстановление базы данных. (У вас есть схема базы данных в управлении версиями, не так ли?)

Я предполагаю, что у вас нет хорошей резервной копии и что у вас нет вашей схемы под контролем версий.

Вы начинаете с хорошей базы данных? Запустите mysqlcheck. Внимательно прочитайте эту документацию. Не выполняйте --repair перед тем, как вы проверите хорошую резервную копию.

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

  • установите MySQL 5.5 или 5.6 на тестовый сервер,
  • загрузите свою базу данных на этот тестовый сервер и
  • посмотреть, можете ли вы воспроизвести эту конкретную ошибку.

Чтобы загрузить свою базу данных на тестовый сервер, выгрузите содержимое, используя mysqldump. Не копируйте файлы на уровне файловой системы - один или несколько из них могут быть повреждены.

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