Sửa lỗi MySQL ERROR 1813: Tablespace for table exists. Please DISCARD the tablespace before IMPORT

intermediate🗄️ MySQL2026-05-08| MySQL 5.7 / 8.0+, InnoDB storage engine, Linux/Windows/macOS

Error Message

ERROR 1813 (HY000): Tablespace for table '`mydb`.`mytable`' exists. Please DISCARD the tablespace before IMPORT.
#mysql#innodb#tablespace#khôi phục#import#ibd

Lỗi Gặp Phải

Bạn đang khôi phục một bảng InnoDB bằng cách sao chép thủ công các file .ibd, và MySQL chặn lại ngay:

ERROR 1813 (HY000): Tablespace for table '`mydb`.`mytable`' exists. Please DISCARD the tablespace before IMPORT.

Lỗi này xảy ra khi bạn dùng phương pháp transportable tablespace — thả file .ibd từ bản backup vào thư mục dữ liệu MySQL đang chạy. Nguyên nhân: InnoDB đã có một tablespace đang hoạt động được đăng ký cho bảng đó trong từ điển nội bộ của nó.

MySQL từ chối ghi đè lên tablespace đang được theo dõi. Bạn phải giải phóng tablespace hiện tại một cách tường minh trước khi import tablespace thay thế.

Nguyên Nhân

InnoDB duy trì từ điển dữ liệu riêng, độc lập với hệ thống file. Khi bạn chạy ALTER TABLE ... IMPORT TABLESPACE, MySQL kiểm tra xem tablespace cho bảng đó đã được đăng ký chưa. Nếu đã tồn tại — dù file .ibd trên đĩa đã là file backup của bạn — thì ERROR 1813 sẽ bắn ra.

Ba tình huống thường dẫn đến lỗi này:

  • Khôi phục một bảng đơn lẻ từ backup bằng cách sao chép trực tiếp file .ibd vào thư mục dữ liệu
  • Import lại sau một lần khôi phục thất bại khiến tablespace cũ vẫn còn được đăng ký
  • Di chuyển bảng giữa các server bằng FLUSH TABLES ... FOR EXPORT / IMPORT TABLESPACE

Cách Sửa Từng Bước

Bốn bước: tạo lại cấu trúc bảng → discard tablespace → đặt file .ibd backup vào → import.

Bước 1: Lấy cấu trúc bảng từ bản backup

Bạn cần câu lệnh CREATE TABLE khớp chính xác với file .ibd đang khôi phục. Lấy từ server nguồn nếu nó vẫn đang chạy:

-- Trên server nguồn
SHOW CREATE TABLE mydb.mytable\G

Sao chép kết quả đó ra chỗ nào đó — bạn sẽ cần dùng ở bước tiếp theo.

Bước 2: Xóa và tạo lại bảng trên server đích

Trên MySQL đích, tạo lại bảng với cùng cấu trúc. Điều này cho InnoDB một mục tablespace mới để làm việc.

USE mydb;

DROP TABLE IF EXISTS mytable;

CREATE TABLE mytable (
  id INT NOT NULL AUTO_INCREMENT,
  name VARCHAR(255) NOT NULL,
  -- ... các cột còn lại của bạn
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

MySQL lúc này tạo một file mytable.ibd hoàn toàn mới. Bạn sắp bỏ file đó đi và thay bằng bản backup.

Bước 3: Discard tablespace

ALTER TABLE mydb.mytable DISCARD TABLESPACE;

Lệnh này xóa file .ibd MySQL vừa tạo và hủy đăng ký tablespace khỏi từ điển InnoDB. Định nghĩa bảng vẫn còn — chỉ có file dữ liệu bị xóa.

Bước 4: Sao chép file .ibd backup vào đúng chỗ

Trước tiên tìm thư mục dữ liệu MySQL:

mysql -u root -p -e "SELECT @@datadir;"

Trên Linux cài đặt chuẩn thường là /var/lib/mysql/. Giờ sao chép các file backup. MySQL 8.0+ yêu cầu cả .ibd lẫn .cfg (file .cfg được tạo bởi FLUSH TABLES ... FOR EXPORT):

# MySQL 5.7 — chỉ cần .ibd
cp /path/to/backup/mytable.ibd /var/lib/mysql/mydb/

# MySQL 8.0+ — cần cả hai file
cp /path/to/backup/mytable.ibd /var/lib/mysql/mydb/
cp /path/to/backup/mytable.cfg /var/lib/mysql/mydb/

Sửa quyền sở hữu, nếu không import sẽ thất bại âm thầm:

chown mysql:mysql /var/lib/mysql/mydb/mytable.ibd
chown mysql:mysql /var/lib/mysql/mydb/mytable.cfg  # MySQL 8.0+ only

Bước 5: Import tablespace

ALTER TABLE mydb.mytable IMPORT TABLESPACE;

Chạy thành công sẽ trả về Query OK, 0 rows affected. Không có thông báo nghĩa là có gì đó sai — kiểm tra error log.

Kiểm Tra Sau Khi Sửa

Đừng tin vào một lần import thành công cho đến khi bạn đã kiểm tra dữ liệu sơ bộ:

SELECT COUNT(*) FROM mydb.mytable;
SELECT * FROM mydb.mytable LIMIT 5;

Ngay cả khi import sạch vẫn có thể có cảnh báo corruption ẩn trong error log của MySQL. Kiểm tra ngay:

# Đường dẫn mặc định trên Linux
tail -50 /var/log/mysql/error.log

# Hoặc tìm vị trí log của bạn
mysql -u root -p -e "SHOW VARIABLES LIKE 'log_error';"

Sau đó chạy kiểm tra toàn vẹn đầy đủ:

CHECK TABLE mydb.mytable;

Nếu Lỗi Vẫn Xuất Hiện Sau Khi DISCARD

Đôi khi chính lệnh DISCARD TABLESPACE cũng từ chối chạy. Flush bảng trước để xóa mọi transaction đang hoạt động:

FLUSH TABLES mydb.mytable;

ALTER TABLE mydb.mytable DISCARD TABLESPACE;

Vẫn bị chặn? Ràng buộc khóa ngoại thường là thủ phạm. Chúng âm thầm ngăn các thao tác tablespace. Tắt kiểm tra FK trong thời gian thực hiện:

SET foreign_key_checks = 0;
ALTER TABLE mydb.mytable DISCARD TABLESPACE;
-- sao chép file .ibd (và .cfg) vào đây
ALTER TABLE mydb.mytable IMPORT TABLESPACE;
SET foreign_key_checks = 1;

Cách Export Đúng (Cho Lần Sau)

Nếu bạn kiểm soát được server nguồn, hãy làm điều này trước khi sao chép file. FLUSH TABLES ... FOR EXPORT tạo ra file metadata .cfg giúp import đáng tin cậy hơn — đặc biệt trên 8.0+:

-- Trên server nguồn
FLUSH TABLES mydb.mytable FOR EXPORT;

-- Sao chép cả hai file từ thư mục dữ liệu:
-- /var/lib/mysql/mydb/mytable.ibd
-- /var/lib/mysql/mydb/mytable.cfg

-- Giải phóng lock khi xong
UNLOCK TABLES;

Bỏ qua .cfg trên MySQL 8.0 thì import vẫn chạy — nhưng MySQL ghi một cảnh báo rằng tính năng phát hiện schema mismatch đã bị bỏ qua. Nên tránh điều này.

Mẹo Nhanh

  • Row format phải khớp: ROW_FORMAT của bản backup (COMPACT, DYNAMIC, COMPRESSED) phải giống hệt với CREATE TABLE trên server đích. Kiểm tra bằng SHOW TABLE STATUS LIKE 'mytable'\G.
  • Tương thích phiên bản: file .ibd từ MySQL 8.0 không thể import vào 5.7. Định dạng trang nội bộ đã thay đổi giữa các phiên bản.
  • innodb_file_per_table phải bật: phương pháp này chỉ hoạt động khi mỗi bảng có file .ibd riêng. Xác nhận bằng SHOW VARIABLES LIKE 'innodb_file_per_table'.
  • Bảng phân vùng: mỗi partition có file riêng (mytable#p#p0.ibd, mytable#p#p1.ibd, v.v.). Chạy DISCARD và IMPORT riêng cho từng partition.

Related Error Notes