[CÂU TRẢ LỜI MỚI]
Cảm ơn @NeverEndingQueue đã đưa ra vấn đề này. Có vẻ như MySQL cuối cùng đã khắc phục sự cố này. Tôi không chắc sự cố này đã được khắc phục ở phiên bản nào đầu tiên, nhưng ngay bây giờ tôi đã thử nghiệm với phiên bản sau và sự cố không còn ở đó nữa:
mysql> SHOW VARIABLES LIKE "%version%";
+-------------------------+------------------------------+
| Variable_name | Value |
+-------------------------+------------------------------+
| innodb_version | 5.7.22 |
| protocol_version | 10 |
| slave_type_conversions | |
| tls_version | TLSv1,TLSv1.1 |
| version | 5.7.22 |
| version_comment | MySQL Community Server (GPL) |
| version_compile_machine | x86_64 |
| version_compile_os | Linux |
+-------------------------+------------------------------+
Để rõ ràng:
mysql> INSERT IGNORE INTO child -> VALUES -> (NULL, 1) -> , (NULL, 2) -> , (NULL, 3) -> , (NULL, 4) -> , (NULL, 5) -> , (NULL, 6); Query OK, 4 rows affected, 2 warnings (0.03 sec) Records: 6 Duplicates: 2 Warnings: 2
Để hiểu rõ hơn ý nghĩa của truy vấn cuối cùng này và tại sao nó cho thấy sự cố đã được khắc phục, vui lòng tiếp tục với câu trả lời cũ bên dưới.
[CÂU TRẢ LỜI CŨ]
Giải pháp của tôi là giải quyết vấn đề và giải pháp thực tế sẽ luôn khắc phục sự cố trong chính MySQL.
Các bước sau đã giải quyết được vấn đề của tôi:
a. Cân nhắc sử dụng các bảng và dữ liệu sau:
mysql>
CREATE TABLE parent (id INT AUTO_INCREMENT NOT NULL
, PRIMARY KEY (id)
) ENGINE=INNODB;
mysql>
CREATE TABLE child (id INT AUTO_INCREMENT
, parent_id INT
, INDEX par_ind (parent_id)
, PRIMARY KEY (id)
, FOREIGN KEY (parent_id) REFERENCES parent(id)
ON DELETE CASCADE
ON UPDATE CASCADE
) ENGINE=INNODB;
mysql>
INSERT INTO parent
VALUES (NULL), (NULL), (NULL), (NULL), (NULL), (NULL);
mysql>
SELECT * FROM parent;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
+----+
b. Bây giờ chúng ta cần xóa một số hàng để chứng minh vấn đề:
mysql>
DELETE FROM parent WHERE id IN (3, 5);
c á c. VẤN ĐỀ: Sự cố phát sinh khi bạn cố gắng chèn các hàng con sau:
mysql>
INSERT IGNORE INTO child
VALUES
(NULL, 1)
, (NULL, 2)
, (NULL, 3)
, (NULL, 4)
, (NULL, 5)
, (NULL, 6);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint f
ails (`test`.`child`, CONSTRAINT `child_ibfk_1` FOREIGN KEY (`parent_id`) REFERE
NCES `parent` (`id`) ON DELETE CASCADE ON UPDATE CASCADE)
mysql>
SELECT * FROM child;
Empty set (0.00 sec)
Mặc dù IGNORE
từ khóa được sử dụng, nhưng MySQL hủy hoạt động được yêu cầu vì lỗi đã tạo không được chuyển thành cảnh báo (như nó phải xảy ra). Bây giờ vấn đề đã rõ ràng, hãy xem làm cách nào chúng ta có thể thực thi câu lệnh insert into cuối cùng mà không gặp phải bất kỳ lỗi nào.
d. GIẢI PHÁP: Tôi sẽ kết thúc câu lệnh insert into bằng một số câu lệnh hằng số khác không phụ thuộc vào các bản ghi được chèn vào, cũng không phụ thuộc vào số của chúng.
mysql>
SET FOREIGN_KEY_CHECKS = 0;
mysql>
INSERT INTO child
VALUES
(NULL, 1)
, (NULL, 2)
, (NULL, 3)
, (NULL, 4)
, (NULL, 5)
, (NULL, 6);
mysql>
DELETE FROM child WHERE parent_id NOT IN (SELECT id FROM parent);
mysql>
SET FOREIGN_KEY_CHECKS = 1;
Tôi biết rằng điều này không phải là tối ưu nhưng miễn là MySQL vẫn chưa khắc phục được sự cố, thì đây là điều tốt nhất mà tôi biết. Đặc biệt là vì tất cả các câu lệnh có thể được thực thi trong một yêu cầu nếu bạn sử dụng thư viện mysqli trong PHP.