Рейтинг:0

Как удалить потерянное ограничение внешнего ключа в MySQL?

флаг in

Использование MySQL 5.5. У меня есть таблица, для которой я не могу добавить внешний ключ:

ИЗМЕНИТЬ ТАБЛИЦУ `SOURCE_TABLE` 
    ДОБАВИТЬ ОГРАНИЧЕНИЕ `ConstraintFK`
        ВНЕШНИЙ КЛЮЧ ("otherTableID")
        ССЫЛКИ `OTHER_TABLE` (`id`)
        НА УДАЛИТЬ УСТАНОВИТЬ НУЛЕВОЕ
        НА КАСКАД ОБНОВЛЕНИЙ;

MySQL возвращает следующую ошибку:

Код ошибки: 1005. Не удается создать таблицу my_schema.#sql-4c0c_b6fc8ca (номер ошибки: 121)

Смотря на ПОКАЗАТЬ СТАТУС INNODB ДВИГАТЕЛЯ Я получил:

------------------------
ПОСЛЕДНЯЯ ОШИБКА ВНЕШНЕГО КЛЮЧА
------------------------
220523 16:34:36 Ошибка при создании ограничения внешнего ключа для таблицы `my_schema`.`#sql-4c0c_b6fc8ca`.
Ограничение внешнего ключа с именем `my_schema`.`ConstraintFK`
уже существует. (Обратите внимание, что внутренне InnoDB добавляет «имя базы данных»
перед определяемым пользователем именем ограничения.)
Обратите внимание, что системные таблицы FOREIGN KEY InnoDB хранят
имена ограничений нечувствительны к регистру, с
Стандартная сортировка MySQL latin1_swedish_ci. если ты
создавать таблицы или базы данных, имена которых отличаются только
регистр символов, затем коллизии в ограничении
имена могут встречаться. Обходной путь: назовите свои ограничения
явно с уникальными именами.

Конечно, в этой схеме не определено ограничение с именем ConstraintFK, я проверил как информационную схему, так и ПОКАЗАТЬ СОЗДАТЬ ТАБЛИЦУ SOURCE_TABLE вывод. Последнее показывает, что индекс для внешнего ключа существует, но ограничения внешнего ключа, похоже, нет:

-- показывается только релевантная информация
СОЗДАТЬ ТАБЛИЦУ `SOURCE_TABLE` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `otherTableID` int(11) ПО УМОЛЧАНИЮ NULL,
  ПЕРВИЧНЫЙ КЛЮЧ (`id`),
  KEY `ConstraintFK_idx` (`otherTableID`)
) ENGINE=InnoDB AUTO_INCREMENT=4089 НАБОР ШИМОВ ПО УМОЛЧАНИЮ=utf8;

СОЗДАТЬ ТАБЛИЦУ `OTHER_TABLE` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  ПЕРВИЧНЫЙ КЛЮЧ (`id`),
) ENGINE = InnoDB AUTO_INCREMENT = 58108 НАБОР ШИМОВ ПО УМОЛЧАНИЮ = utf8;

Действительно, если я попытаюсь снять это ограничение:

ИЗМЕНИТЬ ТАБЛИЦУ `SOURCE_TABLE`
   УДАЛИТЬ ВНЕШНИЙ КЛЮЧ `ConstraintFK`;

Я получил:

Код ошибки: 1025.Ошибка при переименовании «./my_schema/SOURCE_TABLE» в «./my_schema/#sql2-4c0c-b6fc8ca» (номер ошибки: 152)

Я посмотрел на файловую систему и не вижу причин, по которым переименование таблицы должно завершиться неудачей.

К сожалению, попытка запросить информационную схему не помогает:

SELECT * FROM information_schema.TABLE_CONSTRAINTS 
    ГДЕ information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'ВНЕШНИЙ КЛЮЧ' 
    AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_NAME = 'ConstraintFK';

возвращает пустой набор, а:

SELECT * FROM information_schema.TABLE_CONSTRAINTS 
    ГДЕ information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'ВНЕШНИЙ КЛЮЧ' 
    AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_SCHEMA = 'моя_схема';

возвращает все ограничения внешнего ключа в my_schema, которые я также могу получить из ПОКАЗАТЬ СОЗДАТЬ ТАБЛИЦУ заявления, но никаких признаков ConstraintFK...

Смотря на это и это, я подозреваю, что что-то произошло в прошлом, что привело к тому, что этот внешний ключ стал сиротой: действительно, эта SOURCE_TABLE была переименована некоторое время назад, и я почти уверен, что внешний ключ, который я пытаюсь добавить, был там в прошлом. Предлагаемый обходной путь — удалить схему и воссоздать ее из файла дампа. Есть ли что-нибудь еще, что я могу попробовать, что не связано с удалением этой схемы? Это довольно огромно, и время простоя будет иметь значение.

djdomi avatar
флаг za
Мауро, мне жаль вас, но dba — это сайт для вопросов по db. отметьте свой вопрос для перемещения по причине сообщества и выберите относится к другому сайту, там вы выбираете dba, и вскоре после этого ваш вопрос будет перемещен
флаг ua
Укажите `SHOW CREATE TABLE SOURCE_TABLE;` и `SHOW CREATE TABLE other_table;`
Mauro Molinari avatar
флаг in
@djdomi Я немного сбит с толку, если честно. Я нахожу много вопросов о MySQL здесь, о сбое сервера и даже о stackoverflow. Так почему же вместо этого мой вопрос должен быть адресован dba?
Mauro Molinari avatar
флаг in
@RickJames Я только что добавил соответствующий вывод для операторов SHOW CREATE TABLE. Если вы сомневались в типах столбцов, они совпадают.
флаг ua
`ВЫБЕРИТЕ имя_ограничения ИЗ information_schema.referential_constraits, ГДЕ ограничение_схема = "моя_схема";`
Рейтинг:0
флаг in

В конце концов, я был вынужден сбросить всю схему и восстановить ее с другим именем, а затем удалить схему со старым именем (и содержащую проблемные/поврежденные ИСТОЧНИК_ТАБЛИЦА).

Действительно, я нашел этот ответ с dba.stackexchange.com, в котором описывается способ, который, вероятно, мог бы решить эту проблему, и действительно, он работал... до определенного момента:

  • воссоздать таблицу ИСТОЧНИК_ТАБЛИЦА с ТОЧНОЙ ЖЕ структурой, но именем, которое она имела до переименования; обязательно укажите внешние ключи (иначе MySQL вернет ошибку 150), но с другим именем (иначе MySQL вернет ошибку 121). Также убедитесь, что имена индексов отражают новые имена ограничений внешнего ключа.Итак, в моем примере воссозданная таблица со старым именем должна иметь тот же внешний ключ (как описано выше), но с другим именем (например, КонстрФК вместо ОграничениеFK); также индекс должен быть назван ConstrFK_idx (иначе вы снова получите ошибку 121)
  • если все вышеперечисленное выполнено, MySQL должен позволить вам создать таблицу со старым именем
  • то вы можете удалить только что созданную таблицу
  • затем вернуться к ИСТОЧНИК_ТАБЛИЦА и повторите попытку создания ОграничениеFK как хотелось... теперь должно работать

Однако в моем случае с MySQL 5.5.62 (Percona Server) СУБД полностью зависла на последнем шаге, через несколько мгновений после того, как я увидел, что создание внешнего ключа действительно прошло успешно. При перезапуске (после завершения восстановления после сбоя) таблица находилась в несогласованном состоянии (это приводило к сбою MySQL Workbench, в то время как мои приложения жаловались, что ИСТОЧНИК_ТАБЛИЦА больше не существовало). Так что, чтобы выйти из этой ужасной ситуации, я действительно был вынужден сбросить всю схему (я работал на актуальной реплике, в которой ИСТОЧНИК_ТАБЛИЦА до сих пор цел), повторно импортировать как новую схему, затем сбросить схему с проблемной таблицей и избавиться от всей этой головной боли... Конечно, потребовалось как минимум пару часов простоя...

djdomi avatar
флаг za
вот почему я сказал, что dba будет вашим источником решения;)

Ответить или комментировать

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