Điểm:0

How to remove orphaned foreign key constraint in MySQL?

lá cờ in

Using MySQL 5.5. I have a table for which I can't add a foreign key:

ALTER TABLE `SOURCE_TABLE` 
    ADD CONSTRAINT `ConstraintFK`
        FOREIGN KEY (`otherTableID`)
        REFERENCES `OTHER_TABLE` (`id`)
        ON DELETE SET NULL
        ON UPDATE CASCADE;

MySQL returns the following error:

Error Code: 1005. Can't create table 'my_schema.#sql-4c0c_b6fc8ca' (errno: 121)

Looking at SHOW ENGINE INNODB STATUS I get:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
220523 16:34:36 Error in foreign key constraint creation for table `my_schema`.`#sql-4c0c_b6fc8ca`.
A foreign key constraint of name `my_schema`.`ConstraintFK`
already exists. (Note that internally InnoDB adds 'databasename'
in front of the user-defined constraint name.)
Note that InnoDB's FOREIGN KEY system tables store
constraint names as case-insensitive, with the
MySQL standard latin1_swedish_ci collation. If you
create tables or databases whose names differ only in
the character case, then collisions in constraint
names can occur. Workaround: name your constraints
explicitly with unique names.

Of course, there's no constraint named ConstraintFK defined in this schema, I checked both the information schema and the SHOW CREATE TABLE SOURCE_TABLE output. The latter shows that the index for the foreign key exists, but the foreign key constraint seems not to be there:

-- only relevant info shown
CREATE TABLE `SOURCE_TABLE` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `otherTableID` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `ConstraintFK_idx` (`otherTableID`)
) ENGINE=InnoDB AUTO_INCREMENT=4089 DEFAULT CHARSET=utf8;

CREATE TABLE `OTHER_TABLE` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`),
) ENGINE=InnoDB AUTO_INCREMENT=58108 DEFAULT CHARSET=utf8;

Indeed, if I try to drop that constraint:

ALTER TABLE `SOURCE_TABLE`
   DROP FOREIGN KEY `ConstraintFK`;

I get:

Error Code: 1025. Error on rename of './my_schema/SOURCE_TABLE' to './my_schema/#sql2-4c0c-b6fc8ca' (errno: 152)

I looked at the file system and I see no reasons for which renaming of the table should fail.

Unfortunately, trying to query the information schema does not help:

SELECT * FROM information_schema.TABLE_CONSTRAINTS 
    WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY' 
    AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_NAME = 'ConstraintFK';

returns an empty set, while:

SELECT * FROM information_schema.TABLE_CONSTRAINTS 
    WHERE information_schema.TABLE_CONSTRAINTS.CONSTRAINT_TYPE = 'FOREIGN KEY' 
    AND information_schema.TABLE_CONSTRAINTS.CONSTRAINT_SCHEMA = 'my_schema';

returns all the foreign key constraints in my_schema that I can also get from SHOW CREATE TABLE statements, but no sign of ConstraintFK...

Looking at this and this, I suspect that something occurred in the past that caused that foreign key to be orphaned: indeed, this SOURCE_TABLE was renamed some time ago and I'm pretty sure the foreign key I'm trying to add was there in the past. The suggested workaround is to drop the schema and re-create from a dump file. Is there anything else I can try which does not involve dropping this schema? It's quite huge and the downtime would be relevant.

djdomi avatar
lá cờ za
Mauro, tôi xin lỗi bạn nhưng dba là trang web dành cho các câu hỏi về Db. gắn cờ câu hỏi của bạn để di chuyển thông qua lý do cộng đồng và chọn thuộc về một trang web khác, ở đó bạn chọn dba và câu hỏi của bạn sẽ được di chuyển ngay sau đó
lá cờ ua
Vui lòng cung cấp `SHOW CREATE TABLE SOURCE_TABLE;` và `SHOW CREATE TABLE other_table;`
Mauro Molinari avatar
lá cờ in
@djdomi Thành thật mà nói, tôi hơi bối rối. Tôi tìm thấy nhiều câu hỏi liên quan đến MySQL ở đây trên serverfault và thậm chí trên stackoverflow. Vậy tại sao câu hỏi của tôi nên chuyển sang dba?
Mauro Molinari avatar
lá cờ in
@RickJames Tôi vừa thêm đầu ra có liên quan cho các câu lệnh SHOW CREATE TABLE. Nếu nghi ngờ của bạn về các loại cột, thì chúng phù hợp.
lá cờ ua
`CHỌN constraint_name TỪ information_schema.referential_constraits WHERE constraint_schema = "my_schema";`
Điểm:0
lá cờ in

Cuối cùng, tôi buộc phải kết xuất toàn bộ lược đồ và khôi phục nó bằng một tên khác, sau đó bỏ lược đồ có tên cũ (và chứa tệp có vấn đề/bị hỏng NGUỒN_TABLE).

Thật vậy, tôi tìm thấy câu trả lời này từ dba.stackexchange.com mô tả một cách có thể giải quyết vấn đề này và thực sự nó dường như hoạt động ... cho đến một thời điểm nhất định:

  • tạo lại bảng NGUỒN_TABLE với cấu trúc CHÍNH XÁC CÙNG nhưng tên nó có trước khi đổi tên; đảm bảo cũng chỉ định các khóa ngoại (nếu không thì MySQL sẽ trả về lỗi 150) nhưng với một tên khác (nếu không thì MySQL sẽ trả về lỗi 121). Ngoài ra, hãy đảm bảo rằng tên chỉ mục phản ánh tên mới của các ràng buộc khóa ngoại.Vì vậy, trong ví dụ của tôi, bảng được tạo lại với tên cũ phải có cùng khóa ngoại (như mô tả ở trên) nhưng có tên khác (giả sử ConstrFK thay vì ràng buộcFK); cũng chỉ mục phải được đặt tên ConstrFK_idx (nếu không bạn sẽ gặp lại lỗi 121)
  • nếu tất cả những điều trên được thỏa mãn, MySQL sẽ cho phép bạn tạo bảng với tên cũ
  • sau đó bạn có thể thả bảng vừa tạo
  • sau đó quay trở lại NGUỒN_TABLE và thử lại để tạo ràng buộcFK như mong muốn ... bây giờ nó sẽ hoạt động

Tuy nhiên, trong trường hợp của tôi, với MySQL 5.5.62 (Máy chủ Percona), DBMS đã bị lỗi hoàn toàn ở bước cuối cùng, một số khoảnh khắc sau khi tôi thấy rằng việc tạo khóa ngoại đã thực sự thành công. Khi khởi động lại (sau khi khôi phục sự cố hoàn tất), bảng ở trạng thái không nhất quán (nó khiến MySQL Workbench gặp sự cố, trong khi các ứng dụng của tôi dường như phàn nàn rằng NGUỒN_TABLE không còn tồn tại nữa). Vì vậy, để thoát khỏi tình huống khủng khiếp đó, tôi thực sự buộc phải bỏ toàn bộ lược đồ (tôi đã làm việc trên một bản sao cập nhật, có NGUỒN_TABLE vẫn còn nguyên vẹn), nhập lại dưới dạng lược đồ mới, sau đó loại bỏ lược đồ với bảng có vấn đề và loại bỏ tất cả vấn đề đau đầu này... Tất nhiên là cần ít nhất vài giờ ngừng hoạt động...

djdomi avatar
lá cờ za
đó là lý do tại sao tôi đã nói, dba sẽ là nguồn giải pháp của bạn;)

Đăng câu trả lời

Hầu hết mọi người không hiểu rằng việc đặt nhiều câu hỏi sẽ mở ra cơ hội học hỏi và cải thiện mối quan hệ giữa các cá nhân. Ví dụ, trong các nghiên cứu của Alison, mặc dù mọi người có thể nhớ chính xác có bao nhiêu câu hỏi đã được đặt ra trong các cuộc trò chuyện của họ, nhưng họ không trực giác nhận ra mối liên hệ giữa câu hỏi và sự yêu thích. Qua bốn nghiên cứu, trong đó những người tham gia tự tham gia vào các cuộc trò chuyện hoặc đọc bản ghi lại các cuộc trò chuyện của người khác, mọi người có xu hướng không nhận ra rằng việc đặt câu hỏi sẽ ảnh hưởng—hoặc đã ảnh hưởng—mức độ thân thiện giữa những người đối thoại.