Hiểu về Lỗi 'Table is Full'
Gặp phải lỗi ERROR 1114 (HY000): The table 'session_cache' is full là một khoảnh khắc "hết nhiên liệu" kinh điển cho cơ sở dữ liệu của bạn. Không giống như lỗi cú pháp hay vấn đề phân quyền, đây là một giới hạn cứng về tài nguyên. MySQL đang thông báo rằng nó đã chạm trần—hoặc trên phần cứng vật lý hoặc trong một tệp cấu hình cụ thể.
Điều này thường xảy ra trong các hoạt động INSERT lớn hoặc khi các truy vấn phức tạp tạo ra các bảng tạm thời nội bộ khổng lồ. Cách khắc phục hoàn toàn phụ thuộc vào engine nào đang vận hành bảng của bạn: InnoDB hoặc MEMORY.
Xác định Storage Engine của Bảng
Trước khi thay đổi bất kỳ cài đặt nào, hãy xác nhận storage engine bạn đang xử lý là gì. Chạy lệnh này trong MySQL shell:
SHOW TABLE STATUS WHERE Name = 'session_cache';
Kiểm tra cột Engine. Nếu là InnoDB, có khả năng bạn đã hết dung lượng đĩa hoặc chạm giới hạn tablespace. Nếu là MEMORY, bạn đã cạn kiệt lượng RAM được cấp phát.
Kịch bản 1: Khắc phục cho Bảng InnoDB
Khi InnoDB chạm phải bức tường này, điều đó gần như luôn có nghĩa là cơ sở dữ liệu không thể ghi thêm bất kỳ byte nào vào ổ đĩa lưu trữ.
Bước 1: Kiểm tra Dung lượng Lưu trữ Vật lý
Ổ cứng đầy là nguyên nhân phổ biến nhất. Hãy kiểm tra mức sử dụng đĩa ngay lập tức từ terminal Linux:
df -h
Nếu phân vùng dữ liệu của bạn (thường là /var/lib/mysql) đang ở mức 98% hoặc 100%, bạn cần dọn dẹp các tệp tin. Hãy tìm các tệp log truy vấn chậm khổng lồ hoặc các bản sao lưu bị bỏ quên đang chiếm dụng không gian. Ví dụ, một tệp slow_query.log dung lượng 50GB có thể dễ dàng làm sập một máy chủ nhỏ:
sudo du -sh /var/log/*
sudo find /var/lib/mysql -name "*.log" -size +100M
Bước 2: Mở rộng Giới hạn InnoDB Tablespace
Điều gì xảy ra nếu bạn có 200GB dung lượng trống nhưng vẫn gặp lỗi? Tệp my.cnf (hoặc my.ini) của bạn có thể có giới hạn cứng về kích thước tệp dữ liệu. Hãy tìm chỉ thị innodb_data_file_path.
Bạn có thể tìm thấy một dòng giới hạn sự tăng trưởng ở một kích thước cụ thể, chẳng hạn như 2GB:
innodb_data_file_path = ibdata1:10M:autoextend:max:2000M
Khi ibdata1 đạt đến 2000MB, MySQL sẽ ngừng ghi. Để khắc phục, hãy tăng giới hạn lên mức lớn hơn (như 10G) hoặc loại bỏ hoàn toàn giới hạn tối đa để nó có thể tăng trưởng cùng với ổ đĩa của bạn:
# Loại bỏ hậu tố :max:2000M để cho phép tăng trưởng không giới hạn
innodb_data_file_path = ibdata1:10M:autoextend
Lưu ý: Bạn phải khởi động lại dịch vụ MySQL để áp dụng các thay đổi này.
Bước 3: Dọn dẹp Thư mục Tạm thời
MySQL thường sử dụng /tmp cho các hoạt động sắp xếp lớn. Nếu /tmp được gắn trên một phân vùng nhỏ chỉ 512MB, các truy vấn phức tạp sẽ thất bại với Lỗi 1114. Bạn có thể chuyển hướng các tệp tạm thời này sang một phân vùng lớn hơn bằng cách chỉnh sửa cấu hình:
[mysqld]
tmpdir = /home/mysql_tmp
Kịch bản 2: Khắc phục cho Bảng MEMORY
Các bảng MEMORY nằm hoàn toàn trong RAM. Chúng không quan tâm bạn có bao nhiêu dung lượng SSD; chúng chỉ quan tâm đến ngân sách bộ nhớ đã được cấp phát trước đó.
Bước 1: Kiểm tra Giới hạn RAM
Truy vấn các giới hạn bảng heap và bảng tạm thời hiện tại của bạn:
SHOW VARIABLES LIKE 'max_heap_table_size';
SHOW VARIABLES LIKE 'tmp_table_size';
Bước 2: Tăng Ngân sách Bộ nhớ
Nếu bảng session_cache của bạn đã phát triển quá lớn so với mặc định 16MB, bạn có thể tăng nó lên 512MB hoặc 1GB một cách linh hoạt:
SET GLOBAL tmp_table_size = 536870912; -- 512MB
SET GLOBAL max_heap_table_size = 536870912; -- 512MB
Để duy trì thiết lập này sau khi khởi động lại, hãy thêm các dòng sau vào phần [mysqld] của tệp my.cnf:
[mysqld]
tmp_table_size = 512M
max_heap_table_size = 512M
Quan trọng: Các bảng MEMORY hiện có không tự động thay đổi kích thước khi bạn thay đổi các biến này. Bạn phải "làm mới" bảng để giới hạn mới có hiệu lực:
ALTER TABLE session_cache ENGINE=MEMORY;
Xác minh Giải pháp
Sau khi áp dụng các thay đổi, hãy xác minh việc khắc phục bằng ba bước kiểm tra sau:
- Thử ghi lại: Thực hiện lại lệnh
INSERThoặcUPDATEđã thất bại trước đó. - Theo dõi sự tăng trưởng: Sử dụng lệnh
SHOW TABLE STATUS LIKE 'session_cache';để đảm bảoData_lengthhiện đang tăng vượt quá giới hạn cũ. - Giám sát sức khỏe hệ thống: Chạy
htopđể đảm bảo bạn không làm hệ điều hành bị thiếu hụt RAM sau khi tăng giới hạn heap của MySQL.
Chiến lược Phòng ngừa
- Sử dụng File-Per-Table: Bật
innodb_file_per_table. Điều này giúp ngănibdata1trở thành một tệp dữ liệu khổng lồ, khó kiểm soát. - Tự động hóa Cảnh báo: Thiết lập một cron job hoặc công cụ giám sát (như Zabbix) để thông báo cho bạn khi mức sử dụng đĩa đạt 85%.
- Dọn dẹp Session: Đối với các bảng như
session_cache, hãy chạy tập lệnh dọn dẹp hàng ngày:DELETE FROM session_cache WHERE expires_at < NOW();. - Chuyển sang InnoDB: Nếu một bảng MEMORY thường xuyên vượt quá RAM của bạn, hãy chuyển đổi nó sang InnoDB. Với các ổ SSD NVMe hiện đại, tác động đến hiệu suất là không đáng kể so với sự ổn định của việc lưu trữ trên đĩa.

