Проблема добавления внешнего ключа с помощью Alter Table с существующей базой данных MYSQL - не могу добавить его! Помогите!
у меня есть производственная база, где я переименовал несколько столбцов, которые являются внешними ключами. Очевидно, что mysql делает это настоящей болью в моем опыте.
моим решением было удалить все индексы и внешние ключи, переименовать столбцы id, а затем повторно добавить индексы и внешние ключи.
это отлично работает на mysql 5.1 в windows для базы данных разработки.
Я пошел, чтобы запустить мой сценарий миграции на моем сервере debian, который также использует mysql 5.1, и он дает следующую ошибку:
mysql> ALTER TABLE `company_to_module`
-> ADD CONSTRAINT `FK82977604FE40A062` FOREIGN KEY (`company_id`) REFERENCES `company` (`company_id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ERROR 1005 (HY000): Can't create table 'jobprep_production.#sql-44a5_76' (errno: 150)
в этой таблице нет значений, которые противоречили бы внешнему ключу, который я пытаюсь добавить. База данных не изменилась. Внешний ключ существовал и раньше... так что данные в порядке. Не будем упоминать, что я взял ту же базу данных, что и на сервере, и она отлично переносится на Windows. Но эти же миграции внешнего ключа не принимают Debian.
столбцы используют один и тот же тип-BIGINT (20)
имена на самом деле существуют в их соответствующих таблицах.
таблицы innodb. У них уже есть внешние ключи в других столбцах, как это. Это не новая база данных.
Я не могу удалить таблицы, потому что это производственная база данных.
таблицы "как есть" в моей базе:
CREATE TABLE `company_to_module` (
`company_id` bigint(20) NOT NULL,
`module_id` bigint(20) NOT NULL,
KEY `FK8297760442C8F876` (`module_id`),
KEY `FK82977604FE40A062` (`company_id`) USING BTREE,
CONSTRAINT `FK8297760442C8F876` FOREIGN KEY (`module_id`) REFERENCES `module` (`module_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
и
Create Table: CREATE TABLE `company` (
`company_id` bigint(20) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`address` varchar(255) DEFAULT NULL,
`postal_code` varchar(255) DEFAULT NULL,
`province_id` bigint(20) DEFAULT NULL,
`phone_number` varchar(255) DEFAULT NULL,
`is_enabled` bit(1) DEFAULT NULL,
`director_id` bigint(20) DEFAULT NULL,
`homepage_viewable` bit(1) NOT NULL DEFAULT b'1',
`courses_created` int(10) NOT NULL DEFAULT '0',
`header_background` varchar(25) DEFAULT '#172636',
`display_name` varchar(25) DEFAULT '#ffffff',
`tab_background` varchar(25) DEFAULT '#284767',
`tab_text` varchar(25) DEFAULT '#ffffff',
`hover_tab_background` varchar(25) DEFAULT '#284767',
`hover_tab_text` varchar(25) DEFAULT '#f2e0bd',
`selected_tab_background` varchar(25) DEFAULT '#f5f5f5',
`selected_tab_text` varchar(25) DEFAULT '#172636',
`hover_table_row_background` varchar(25) DEFAULT '#c0d2e4',
`link` varchar(25) DEFAULT '#4e6c92',
PRIMARY KEY (`company_id`),
KEY `FK61AE555A71DF3E03` (`province_id`),
KEY `FK61AE555AAC50C977` (`director_id`),
CONSTRAINT `company_ibfk_1` FOREIGN KEY (`director_id`) REFERENCES `user_account` (`user_account_id`),
CONSTRAINT `FK61AE555A71DF3E03` FOREIGN KEY (`province_id`) REFERENCES `province` (`province_id`)
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8
вот статус innodb:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
110415 3:14:34 Error in foreign key constraint of table jobprep_production/#sql-44a5_1bc:
FOREIGN KEY (`company_id`) REFERENCES `company` (`company_id`) ON DELETE RESTRICT ON UPDATE RESTRICT:
Cannot resolve column name close to:
) ON DELETE RESTRICT ON UPDATE RESTRICT
если я попытаюсь удалить индекс из 'company_to_module', Я получаю эту ошибку:
#1025 - Error on rename of './jobprep_production/#sql-44a5_23a' to './jobprep_production/company_to_module' (errno: 150)
вот мои переменные innodb:
+---------------------------------+------------------------+
| Variable_name | Value |
+---------------------------------+------------------------+
| innodb_adaptive_hash_index | ON |
| innodb_additional_mem_pool_size | 1048576 |
| innodb_autoextend_increment | 8 |
| innodb_autoinc_lock_mode | 1 |
| innodb_buffer_pool_size | 8388608 |
| innodb_checksums | ON |
| innodb_commit_concurrency | 0 |
| innodb_concurrency_tickets | 500 |
| innodb_data_file_path | ibdata1:10M:autoextend |
| innodb_data_home_dir | |
| innodb_doublewrite | ON |
| innodb_fast_shutdown | 1 |
| innodb_file_io_threads | 4 |
| innodb_file_per_table | OFF |
| innodb_flush_log_at_trx_commit | 1 |
| innodb_flush_method | |
| innodb_force_recovery | 0 |
| innodb_lock_wait_timeout | 50 |
| innodb_locks_unsafe_for_binlog | OFF |
| innodb_log_buffer_size | 1048576 |
| innodb_log_file_size | 5242880 |
| innodb_log_files_in_group | 2 |
| innodb_log_group_home_dir | ./ |
| innodb_max_dirty_pages_pct | 90 |
| innodb_max_purge_lag | 0 |
| innodb_mirrored_log_groups | 1 |
| innodb_open_files | 300 |
| innodb_rollback_on_timeout | OFF |
| innodb_stats_on_metadata | ON |
| innodb_support_xa | ON |
| innodb_sync_spin_loops | 20 |
| innodb_table_locks | ON |
| innodb_thread_concurrency | 8 |
| innodb_thread_sleep_delay | 10000 |
+---------------------------------+------------------------+
Я также хочу добавить, что, пока я играл с добавлением внешних ключей, mysql повредил мою базу данных и уничтожил ее. Мне пришлось перезагрузить резервную копию, чтобы попробовать еще раз.
помочь? :/
6 ответов
являются ли обе таблицы InnoDB типом?
имеет ли таблица компании индекс company_id ?
Я думаю, что ваша таблица MyISAM (по умолчанию, если вы не изменили конфигурацию), и вы не можете создавать ограничения внешнего ключа в MyISAM. См. Описание таблицы CREATE для двух таблиц yout.
Если обе таблицы пусты, отбросьте их и создайте заново, выбрав InnoDB в качестве движка. Вы также можете добавить ограничения внешнего ключа в создание таблиц скрипт(ы).
Из MySQL Справочник:
определения внешних ключей подчиняются следующим условиям:
обе таблицы должны быть InnoDB столы и это не должны быть временные таблицы.
соответствующие столбцы в иностранных ключ и ссылочный ключ должно быть похожие типы внутренних данных внутри InnoDB, чтобы их можно было сравнить без преобразования типов. размер и знак целочисленных типов должен быть же. Длина типов строк должна не быть прежним. для недвоичных (символьные) строковые столбцы, набор символов и параметры сортировки должны быть то же самое.
InnoDB требует индексов на зарубежных ключи!--22--> и ссылочные ключи, так что проверки внешнего ключа могут быть быстрыми и не требуется таблица сканирование. В таблица ссылок, должна быть индекс, где столбцы внешнего ключа перечислены как первые столбцы в тот же порядок. такой индекс создано в таблице ссылок автоматически, если он не существует. (Это в отличие от некоторых старых версии, в которых индексы должны быть создано явно или создание ограничения внешнего ключа не удастся.) index_name, если задано, используется как описано ранее.
InnoDB разрешает внешний ключ ссылка на любой столбец или группу индекса из колонны. Однако в ссылочная таблица, должно быть индекс, в котором указаны столбцы перечислены как первые столбцы в тот же порядок.
префиксы индекса на столбцах внешнего ключа не поддерживаются. Одно из следствий это то, что BLOB и текстовые столбцы невозможно включить во внешний ключ поскольку индексы на этих столбцах должны всегда включайте длину префикса.
если предложение символа ограничения учитывая, значение символа должно быть уникальным в базе данных. Если предложение не дано, InnoDB создает имя автоматически.
@egervari: что произойдет, если вы запустите это:
CREATE TABLE `test` (
`company_id` bigint(20) NOT NULL,
`module_id` bigint(20) NOT NULL,
KEY (`module_id`),
KEY (`company_id`),
CONSTRAINT `test_fk_module`
FOREIGN KEY (`module_id`)
REFERENCES `module` (`module_id`),
CONSTRAINT `test_fk_company`
FOREIGN KEY (`company_id`)
REFERENCES `company` (`company_id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
и если вы запустите:
ALTER TABLE `company_to_module`
ADD CONSTRAINT `company_to_module_fk_company`
FOREIGN KEY (`company_id`)
REFERENCES `company` (`company_id`)
ON DELETE RESTRICT
ON UPDATE RESTRICT;
убедитесь, что company_to_module.company_id и компании.company_id-это тот же самый тип данных. Это произошло, когда первичный ключ был настроен как UNSIGNED INT, но поле внешнего ключа было просто INT. Добавление UNSIGNED к типу данных исправило проблему.
Я просто применил рефакторинг с использованием Windows и затем импортировать базу данных в Debian - это работает.
Я думаю, можно с уверенностью сказать, что что - то было испорчено на сервере Debian или с linux-версией Mysql-возможно, ошибка в сборке 5.1?
в любом случае, я также обновил ОЗУ на сервере с 1gb до 2gb, и эти проблемы ушли.
Я думаю, что MySQL, возможно, просто не хватило ОЗУ для завершения операции. Если это было так (и, похоже, так), я думаю, MySQL должен был просто сказать так, а не выплевывать эти ошибки - заставляя меня и всех здесь думать, что это проблема синтаксиса или схемы.
в любом случае, спасибо за тех, кто пытался помочь. По крайней мере, это помогло мне изолировать все то, чего не могло быть.
поскольку это, похоже, не связано с синтаксисом, я бы предположил, что у вас заканчивается пространство для создания таблиц InnoDB.
EDIT: можете ли вы вставить конфигурацию InnoDB:
SHOW VARIABLES LIKE "inno%";
С момента попытки создать копию company_to_module
вручную дает вам ту же ошибку, вы должны тщательно проверить ограничение fk, уже присутствующее в company_to_module
. Он по-прежнему действителен или вы изменили таблицу module
?
С MySQL-Docs:
1005 (ER_CANT_CREATE_TABLE) не удается создать таблицу. Если сообщение об ошибке ссылается на ошибку 150, создание таблицы не удалось из-за неправильного формирования ограничения внешнего ключа.
@egervari вы написали-мое решение состояло в том, чтобы удалить все индексы и внешние ключи, переименовать столбцы id, а затем повторно добавить индексы и внешние ключи.
согласен с вами. Но, возможно, что-то пошло не так. Я воспроизвел ошибку, и (в моем случае) исправил.
Я бы предложил вам запустить команду OPTIMIZE TABLE для таблицы, в которой столбец был переименован. Документация говорит -для таблиц InnoDB таблица OPTIMIZE сопоставляется с ALTER TABLE, которая перестраивает таблицу обновить статистику индекса и освободить неиспользуемое пространство в кластеризованном индексе.
еще одно решение:
Drop уникальный ключ в ссылочной таблице (ключ, который используется внешним ключом, в вашем случае это первичный ключ). Затем добавьте новый внешний ключ и заново создайте уникальный ключ.
еще одно решение:
попробуйте добавить и удалить новый столбец в ссылочную таблицу, затем попробуйте создать внешний ключ.
ALTER TABLE company ADD COLUMN column1 VARCHAR(255) DEFAULT NULL;
ALTER TABLE company DROP COLUMN column1;