Проблема добавления внешнего ключа с помощью 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;