MySQL Ошибка 1005 (HY000): Foreign key constraint incorrectly formed (errno: 150)
Механизм связывания таблиц по внешним ключам (Foreign Key Integrity)
Реляционный движок InnoDB предъявляет жесткие требования к описанию связей внешних ключей (FOREIGN KEY ... REFERENCES). При попытке выполнения CREATE TABLE или ALTER TABLE ADD CONSTRAINT парсер проверяет полную идентичность структуры связываемых колонок в родительской и дочерней таблицах. Если обнаружено хотя бы малейшее расхождение в типах данных или свойствах индексов, операция отклоняется с системной ошибкой:
«ERROR 1005 (HY000): Can't create table 'database.child_table' (errno: 150 "Foreign key constraint is incorrectly formed")»
Бизнес-риски
Срыв развертывания миграций баз данных (Doctrine, Laravel Migrations, Django ORM), нарушение ссылочной целостности бизнес-сущностей в базе.
Диагностический чек-лист причин ошибки errno 150
| Параметр проверки | Родительская колонка (Parent) | Дочерняя колонка (Child / FK) | Результат при несовпадении |
|---|---|---|---|
| Знак числа (Sign) | INT UNSIGNED | INT (Signed) | Ошибка errno 150 |
| Тип данных | BIGINT | INT | Ошибка errno 150 |
| Кодировка и коллация | utf8mb4_unicode_ci | utf8mb4_general_ci | Ошибка errno 150 |
| Индекс на родительской таблице | Колонка НЕ проиндексирована | Определен Foreign Key | Ошибка errno 150 (родитель обязан иметь INDEX/PK) |
| Движок хранения (Engine) | InnoDB | MyISAM | Ошибка errno 150 (MyISAM не поддерживает FK) |
Регламент точной диагностики и формирования Foreign Key
Сценарий 1: Получение детального описания ошибки через LATEST FOREIGN KEY ERROR
MySQL сохраняет подробный отчет о последней ошибке создания внешнего ключа в системном мониторе:
SHOW ENGINE INNODB STATUS\GНайдите секцию ------------------------
LATEST FOREIGN KEY ERROR
------------------------. В ней будет точно написано, например: «Cannot find an index in the referenced table where the referenced columns appear as the first columns» или «You have defined two incompatible column types».
Сценарий 2: Приведение типов и свойств колонок к полному соответствию
-- 1. Структура родительской таблицы (таблица, НА которую ссылаемся):
CREATE TABLE `users` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(100) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- 2. ПРАВИЛЬНАЯ структура дочерней таблицы:
-- Поле user_id ОБЯЗАНО быть BIGINT UNSIGNED, как и в users.id!
CREATE TABLE `orders` (
`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` BIGINT UNSIGNED NOT NULL,
`amount` DECIMAL(10,2) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_orders_user_id` (`user_id`),
CONSTRAINT `fk_orders_user` FOREIGN KEY (`user_id`)
REFERENCES `users` (`id`)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;Сценарий 3: Временное отключение проверки внешних ключей для импорта схемы
Если таблицы создаются в произвольном порядке (дочерняя таблица пытается создаться раньше родительской):
-- Отключение проверки ограничений на время применения DDL-миграций:
SET FOREIGN_KEY_CHECKS = 0;
-- Выполнение запросов создания таблиц...
CREATE TABLE ...;
-- Обязательное включение проверки обратно:
SET FOREIGN_KEY_CHECKS = 1;Типовые ошибки администраторов
- Попытка сослаться на неиндексированное поле: Колонка в родительской таблице, на которую указывает
REFERENCES parent(col), ОБЯЗАНА быть объявлена какPRIMARY KEYили иметь явныйINDEX. - Разные кодировки таблиц: Если таблица
usersсоздана вutf8mb4, аordersвlatin1, внешний ключ для строковых колонок (например, связка по UUID/коду) упадет с ошибкой 150.
Инженеры ITSTM проведут аудит схемы данных, нормализуют типы колонок и настроят корректные каскадные ограничения.
Частые вопросы (FAQ)
Чем отличается errno 150 от errno 121?
Errno 150 указывает на структурное несовпадение колонок или отсутствие индексов. Errno 121 означает, что имя внешнего ключа (CONSTRAINT name) уже занято другой таблицей в базе.
Можно ли создать внешний ключ между таблицами в разных базах данных?
Да, если обе базы находятся на одном сервере MySQL и используют движок InnoDB (синтаксис: REFERENCES db2.parent_table(id)).
Поддерживает ли движок MyISAM внешние ключи?
Нет, MyISAM парсит синтаксис FOREIGN KEY, но полностью игнорирует его, не создавая реальных ограничений.
Почему нельзя использовать ON DELETE SET NULL для NOT NULL колонки?
Если колонка объявлена с атрибутом NOT NULL, движок не сможет записать в нее NULL при удалении родительской строки, что вызовет синтаксический отказ создания ключа.