9

外部キーであるいくつかの列の名前を変更した運用データベースがあります。明らかに、私の経験では、mysql はこれを行うのが本当に面倒です。

私の解決策は、すべてのインデックスと外部キーを削除し、id 列の名前を変更してから、インデックスと外部キーを再度追加することでした。

これは、開発データベース用の Windows 上の mysql 5.1 でうまく機能します。

mysql 5.1も使用しているdebianサーバーで移行スクリプトを実行しようとしましたが、次のエラーが発生します。

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)

このテーブルには、追加しようとしている外部キーと競合する値はありません。データベースは変更されていません。外部キー DID は以前に存在していたので、データは問題ありません。サーバー上にあるのと同じデータベースを使用したことは言うまでもありませんが、それは 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 がデータベースを破損して破壊したことも付け加えたいと思います。再試行するには、バックアップからリロードする必要がありました。

ヘルプ?:/

4

6 に答える 6

9

両方のテーブルは InnoDB タイプですか?

company テーブルには company_id のインデックスがありますか?

テーブルは MyISAM (構成を変更していない場合のデフォルト) であり、MyISAM で外部キー制約を作成できないと思います。2 つのテーブルについては、CREATE TABLE の説明を参照してください。

両方のテーブルが空の場合は、それらを削除して再作成し、エンジンとして InnoDB を選択します。テーブル作成スクリプトに FOREIGN KEY 制約を追加することもできます。


MySQLリファレンスマニュアルから:

外部キーの定義には、次の条件が適用されます。

  • 両方のテーブルは InnoDBテーブルである必要があり、TEMPORARY テーブルであってはなりません。

  • 外部キーと参照されるキーの対応する列は、型変換なしで比較できるように、InnoDB 内で同様の内部データ型を持っている必要があります。整数型のサイズと符号は同じでなければなりません。文字列型の長さは同じである必要はありません。非バイナリ (文字) 文字列列の場合、文字セットと照合は同じである必要があります

  • InnoDB では、外部キーのチェックが高速になり、テーブル スキャンが不要になるように、外部キーと参照キーにインデックスが必要です。参照テーブルには、外部キー列が同じ順序で最初の列としてリストされているインデックスが必要です。このような索引が存在しない場合は、参照表に自動的に作成されます。(これは、インデックスを明示的に作成する必要があり、そうしないと外部キー制約の作成が失敗する一部の古いバージョンとは対照的です。) index_name が指定されている場合は、前述のように使用されます。

  • InnoDB では、外部キーが任意のインデックス列または列のグループを参照できます。ただし、参照されるテーブルには、参照される列が最初の列として同じ順序でリストされているインデックスが必要です。

  • 外部キー列のインデックス プレフィックスはサポートされていません。この結果の 1 つは、BLOB および TEXT 列を外部キーに含めることができないということ です。これらの列のインデックスには常にプレフィックス長が含まれている必要があるためです。

  • CONSTRAINT シンボル句が指定されている場合、シンボル値はデータベース内で一意である必要があります。句が指定されていない場合、 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;
于 2011-04-15T05:01:27.200 に答える
4

company_to_module.company_id と company.company_id がまったく同じデータ型であることを確認してください。これは、主キーが UNSIGNED INT として設定されていたが、外部キー フィールドが単なる INT であったときに発生しました。データ型に UNSIGNED を追加すると、問題が修正されました。

于 2011-04-15T04:54:30.623 に答える
1

Windows を使用してリファクタリングを適用し、データベースを Debian に再インポートしました。動作します。

Debian サーバー、または Linux バージョンの Mysql で何かが台無しになったと言っても過言ではありません - おそらく 5.1 ビルドのバグでしょうか?

とにかく、サーバーの RAM を 1GB から 2GB にアップグレードしたところ、これらの問題はなくなりました。

MySQL には、操作を完了するのに十分な RAM がなかったのかもしれません。もしそうなら (そしてそうであるように見えます)、MySQL はこれらのエラーを吐き出すのではなく、単純にそう言うべきだったと思います。

とにかく、助けようとした人々に感謝します。少なくとも、それができなかったすべてのものを分離するのに役立ちました.

于 2011-04-16T20:11:13.357 に答える
0

構文に関連するものではないように思われるので、InnoDBテーブルを作成するためのスペースが不足していると思います。

編集:InnoDB構成を貼り付けることができますか?

SHOW VARIABLES LIKE "inno%";
于 2011-04-15T08:33:00.657 に答える
0

手動でコピーを作成しようとするcompany_to_moduleと同じエラーが発生するため、にすでに存在するfk制約を注意深く確認する必要がありますcompany_to_module。それはまだ有効ですか、それともテーブルを変更しましたmoduleか?

MySQL-Docsから:

1005(ER_CANT_CREATE_TABLE)テーブルを作成できません。エラーメッセージがエラー150を参照している場合、外部キー制約が正しく形成されていないため、テーブルの作成に失敗しました。

于 2011-04-15T10:31:14.627 に答える
0

@egervari あなたが書いた - 私の解決策は、すべてのインデックスと外部キーを削除し、id 列の名前を変更してから、インデックスと外部キーを再度追加することでした。

あなたに同意。しかし、何かが間違っていた可能性があります。エラーを再現し、(私の場合は)修正しました。

列の名前が変更されたテーブルに対して OPTIMIZE TABLE コマンドを実行することをお勧めします。ドキュメントには、InnoDB テーブルの場合、OPTIMIZE TABLE が ALTER TABLE にマップされ、テーブルが再構築されてインデックス統計が更新され、クラスター化インデックスの未使用領域が解放されます。


もう1つの解決策:

参照されるテーブルに一意のキーをドロップします(外部キーで使用されるキー、この場合は主キーです)。次に、新しい外部キーを追加し、削除された一意のキーを再作成します。


もう1つの解決策:

参照されるテーブルに新しい列を追加および削除してから、外部キーを作成してみてください。

ALTER TABLE company ADD COLUMN column1 VARCHAR(255) DEFAULT NULL;
ALTER TABLE company DROP COLUMN column1;
于 2011-04-15T10:45:15.917 に答える