MySQL InnoDB không giải phóng không gian đĩa sau khi xóa các hàng dữ liệu khỏi bảng


140

Tôi có một bảng MySQL sử dụng công cụ lưu trữ InnoDB; nó chứa khoảng 2M hàng dữ liệu. Khi tôi xóa các hàng dữ liệu khỏi bảng, nó không giải phóng không gian đĩa được phân bổ. Kích thước của tệp ibdata1 cũng không giảm sau khi chạy optimize tablelệnh.

Có cách nào để lấy lại không gian đĩa từ MySQL không?

Tôi đang ở trong một tình huống xấu; ứng dụng này đang chạy ở khoảng 50 địa điểm khác nhau và hiện tại vấn đề về không gian đĩa thấp đang xuất hiện ở hầu hết tất cả chúng.


sau khi chạy lệnh tối ưu hóa, kích thước của tệp ibdata1 không giảm.
Sumit Deo

4
Tôi nghĩ rằng nhận xét đó sẽ được chỉnh sửa tốt hơn vào câu trả lời của bạn và sau đó bị xóa
Ben Millwood

bản sao có thể có của stackoverflow.com/q/11751792/82114 (nhưng cái này đã ở đây đầu tiên)
FlipMcF

1
"Kích thước của tệp ibdata1 cũng không giảm sau khi chạy lệnh tối ưu hóa bảng" đó là do bạn innodb_file_per_tableđã tắt. Tin tốt là tùy chọn này ontheo mặc định trong các phiên bản gần đây của MySQL.
Kế toán م

Tôi chạy "tối ưu hóa bảng xxxx" và nhận được thông báo "Bảng không hỗ trợ tối ưu hóa, thực hiện tái tạo + phân tích thay thế." Sau khi chạy "du -h / var / lib / mysql" trên shell, tôi có thể thấy cơ sở dữ liệu đã bị thu hẹp.
dùng1097111

Câu trả lời:


137

MySQL không làm giảm kích thước của ibdata1. Không bao giờ. Ngay cả khi bạn sử dụng optimize tableđể giải phóng không gian được sử dụng từ các bản ghi bị xóa, nó sẽ sử dụng lại sau.

Một cách khác là cấu hình máy chủ để sử dụng innodb_file_per_table, nhưng điều này sẽ yêu cầu sao lưu, bỏ cơ sở dữ liệu và khôi phục. Mặt tích cực là tệp .ibd cho bảng bị giảm sau một optimize table.


4
Tài liệu MySQL 5.5 về trạng thái chế độ tệp trên mỗi bảng của InnoDB "Để tận dụng các tính năng [InnoDB tệp trên mỗi bảng] cho một bảng hiện có, bạn có thể bật cài đặt tệp trên mỗi bảng và chạy ALTER TABLE t ENGINE=INNODBtrên bảng hiện có. " Điều này ngụ ý rằng bạn có thể bật tính năng này, "chuyển đổi" các bảng hiện có để sử dụng tệp InnoDB riêng với lệnh ALTER TABLE, sau đó TỐI ƯU bảng để thu nhỏ kích thước của nó. Tuy nhiên, khi bạn đã hoàn tất, bạn phải tìm cách xóa tệp InnoDB nguồn (rất lớn) ...
Josh

9
Tôi đoán điều này về mặt kỹ thuật trả lời câu hỏi, nhưng tôi hy vọng phần lớn những người tìm kiếm chủ đề này đang tìm kiếm quy trình thực tế để thu nhỏ / lấy lại không gian, mà câu trả lời này không cung cấp.
Manachi

@Manachi Quá trình này là "cấu hình máy chủ để sử dụng innodb_file_per_table", "sao lưu" máy chủ, "thả cơ sở dữ liệu", dừng mysql, xóa .ibd, khởi động máy chủ và khôi phục (các) cơ sở dữ liệu. Với MySQL 5.5+, bạn có thể sử dụng những gì Josh đã nói và sau khi thay đổi tất cả các bảng, hãy dừng máy chủ, xóa .ibd khổng lồ và bắt đầu lại.
Leonel Martins

39

Chỉ có vấn đề tương tự bản thân mình.

Điều gì xảy ra là, ngay cả khi bạn bỏ cơ sở dữ liệu, innodb vẫn sẽ không giải phóng không gian đĩa. Tôi đã phải xuất, dừng mysql, xóa các tệp theo cách thủ công, khởi động mysql, tạo cơ sở dữ liệu và người dùng, sau đó nhập. Cảm ơn chúa tôi chỉ có hàng trị giá 200 MB, nhưng nó đã tiêu tốn 250GB tệp innodb.

Thất bại do thiết kế.


10
Vâng, đó chắc chắn là một thất bại.
trusktr

1
MySql 5.5 có cùng một vấn đề: Tôi đã chạy "tối ưu hóa bảng" để giảm mức sử dụng đĩa của bảng 28 GB. Hoạt động có thể đã cố gắng tạo một bản sao được tối ưu hóa của bản gốc và làm như vậy đã sử dụng hết tất cả không gian trên phân vùng. Bây giờ "tối ưu hóa bảng" không thành công và tôi không còn chỗ trống trên phân vùng ngay cả khi tôi đã bỏ toàn bộ db ... rất đáng thất vọng.
basilikode

1
Và hơn 4 năm sau tôi gặp vấn đề tương tự với MySQL. MS SQL cũng tương tự: dba.stackexchange.com/questions/47 310/ trên
Csaba Toth

24

Nếu bạn không sử dụng innodb_file_per_table , việc lấy lại dung lượng đĩa là có thể, nhưng khá tẻ nhạt và đòi hỏi một lượng thời gian chết đáng kể.

Các Làm thế nào để là khá sâu - nhưng tôi dán phần có liên quan dưới đây.

Hãy chắc chắn cũng giữ lại một bản sao của lược đồ của bạn trong bãi chứa của bạn.

Hiện tại, bạn không thể xóa tệp dữ liệu khỏi vùng bảng hệ thống. Để giảm kích thước vùng bảng hệ thống, hãy sử dụng quy trình này:

Sử dụng mysqldump để kết xuất tất cả các bảng InnoDB của bạn.

Dừng máy chủ.

Xóa tất cả các tệp vùng bảng hiện có, bao gồm các tệp ibdata và ib_log. Nếu bạn muốn giữ một bản sao dự phòng thông tin, sau đó sao chép tất cả các tệp ib * sang một vị trí khác trước khi xóa các tệp trong cài đặt MySQL của bạn.

Xóa mọi tệp .frm cho các bảng InnoDB.

Cấu hình một không gian bảng mới.

Khởi động lại máy chủ.

Nhập các tệp kết xuất.


Cảm ơn bạn đã bao gồm các bước - mô tả liên kết 'làm thế nào để' không chứa thông tin này nữa
aland

3

Mười năm sau và tôi đã có cùng một vấn đề. Tôi đã giải quyết nó theo cách sau:

  • Tôi tối ưu hóa tất cả các cơ sở dữ liệu vẫn còn.
  • Tôi đã khởi động lại máy tính và MySQL trên các dịch vụ (Windows + r -> services.msc)

Đó là tất cả :)


1

Một cách khác để giải quyết vấn đề đòi lại không gian là, Tạo nhiều phân vùng trong bảng - Phân vùng dựa trên phạm vi, Giá trị và chỉ cần thả / cắt bớt phân vùng để lấy lại không gian, sẽ giải phóng không gian được sử dụng bởi toàn bộ dữ liệu được lưu trữ trong phân vùng cụ thể.

Sẽ có một số thay đổi cần thiết trong lược đồ bảng khi bạn giới thiệu phân vùng cho bảng của mình như - Khóa duy nhất, Chỉ mục để bao gồm cột phân vùng, v.v.


0

Năm trở lại tôi cũng gặp phải vấn đề tương tự trên phiên bản mysql5.7 và ibdata1 chiếm 150 Gb. vì vậy tôi đã thêm hoàn tác không gian bảng

Thực hiện sao lưu Mysqldump
Dừng dịch vụ mysql
Xóa tất cả dữ liệu khỏi dữ liệu dir
Thêm bên dưới hoàn tác tham số không gian bảng trong my.cnf hiện tại

 #undo tablespace
  innodb_undo_directory =  /var/lib/mysql/
  innodb_rollback_segments = 128 
  innodb_undo_tablespaces = 3
  innodb_undo_logs = 128  
  innodb_max_undo_log_size=1G
  innodb_undo_log_truncate = ON

Bắt đầu
sao lưu dịch vụ mysq cửa hàng mysqldump

Giải quyết vấn đề !!


-1

Có một số cách để lấy lại không gian đĩa sau khi xóa dữ liệu khỏi bảng cho công cụ MySQL Inodb

Nếu bạn không sử dụng innodb_file_per_table ngay từ đầu, việc hủy tất cả dữ liệu, xóa tất cả tệp, tạo lại cơ sở dữ liệu và nhập lại dữ liệu chỉ là cách (kiểm tra câu trả lời của FlipMcF ở trên)

Nếu bạn đang sử dụng innodb_file_per_table, bạn có thể thử

  1. Nếu bạn có thể xóa tất cả lệnh cắt dữ liệu sẽ xóa dữ liệu và lấy lại không gian đĩa cho bạn.
  2. Lệnh bảng thay đổi sẽ thả và tạo lại bảng để nó có thể lấy lại không gian đĩa. Do đó, sau khi xóa dữ liệu, hãy chạy bảng thay đổi không thay đổi gì để giải phóng hardisk (ví dụ: bảng TBL_A có bảng mã uf8, sau khi xóa dữ liệu chạy ALTER TABLE TBL_A charset utf8 -> lệnh này không thay đổi gì từ bảng của bạn nhưng nó làm cho mysql tạo lại bảng của bạn và lấy lại không gian đĩa
  3. Tạo TBL_B như TBL_A. Chèn dữ liệu chọn bạn muốn giữ từ TBL_A vào TBL_B. Thả TBL_A và đổi tên TBL_B thành TBL_A. Cách này rất hiệu quả nếu TBL_A và dữ liệu cần xóa là lớn (lệnh xóa trong MySQL innodb là hiệu năng rất tệ)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.