MySql - thay đổi innodb_file_per_table cho db trực tiếp


18

Tôi có một MySql DB lớn (150GB) và chỉ bây giờ tôi mới nhận thấy rằng nó innodb_file_per_tableđược đặt thành offnguyên nhân khiến toàn bộ DB được lưu trữ trên một tệp duy nhất ( ibdata1). Tôi muốn kích hoạt innodb_file_per_tablevà để nó phân tách hồi tố DB thành nhiều tệp, cách tốt nhất để làm điều này là gì?

Câu trả lời:


32

Thực sự chỉ có một cách để kéo cái này ra. Bạn sẽ phải xuất dữ liệu bằng mysqldumps, bỏ tất cả cơ sở dữ liệu, tắt mysqld, xóa ib_logfile0, xóa ib_logfile1, xóa ibdata1, thêm vào innodb_file_per_tabledưới [mysqld]tiêu đề, bắt đầu mysql.

Tôi đã đăng câu trả lời này trong StackOverflow vào tháng 10 năm 2010

Dưới đây là các bước được liệt kê theo chiều dọc:

Bước 01) MySQLDump tất cả các cơ sở dữ liệu vào một tệp văn bản SQL (gọi nó là SQLData.sql)

Bước 02) Bỏ tất cả các cơ sở dữ liệu (trừ lược đồ mysql)

Bước 03) Tắt máy mysql

CAVEAT : Để xóa hoàn toàn các giao dịch không được cam kết khỏi Tệp InnoDB, hãy chạy nó

mysql -uroot -p... -Ae"SET GLOBAL innodb_fast_shutdown = 0;"
service mysql stop

Bước 04) Thêm các dòng sau vào /etc/my.cnf

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

Sidenote: Bất kể thiết lập của bạn cho innodb_buffer_pool_size, hãy đảm bảo innodb_log_file_size là 25% của innodb_buffer_pool_size.

Bước 05) Xóa ibdata1, ib_logfile0 và ib_logfile1

Tại thời điểm này, chỉ nên có lược đồ mysql trong / var / lib / mysql

Bước 06) Khởi động lại mysql

Điều này sẽ tạo lại ibdata1 ở mức 10MB, ib_logfile0 và ib_logfile1 ở mức 1G mỗi

Bước 07) Tải lại SQLData.sql vào mysql

ibdata1 sẽ phát triển nhưng chỉ chứa siêu dữ liệu bảng

Mỗi bảng InnoDB sẽ tồn tại bên ngoài ibdata1

Giả sử bạn có một bảng InnoDB có tên mydb.mytable. Nếu bạn truy cập vào / var / lib / mysql / mydb, bạn sẽ thấy hai tệp đại diện cho bảng

  • mytable.frm (Tiêu đề công cụ lưu trữ)
  • mytable.ibd (Trang chủ của dữ liệu bảng và chỉ mục bảng cho mydb.mytable)

ibdata1 sẽ không bao giờ chứa dữ liệu và chỉ mục InnoDB nữa.

Với tùy chọn innodb_file_per_table trong /etc/my.cnf, bạn có thể chạy OPTIMIZE TABLE mydb.mytable và tệp /var/lib/mysql/mydb/mytable.ibd sẽ thực sự co lại.

Tôi đã làm điều này nhiều lần trong sự nghiệp là một DBA của MySQL

Trên thực tế, lần đầu tiên tôi làm điều này, tôi đã thu gọn tệp ibdata1 50GB thành 500MB.

Hãy thử một lần. Nếu bạn có thêm câu hỏi về điều này, gửi email cho tôi. Tin tôi đi Điều này sẽ làm việc trong ngắn hạn và trên đường dài. !!!

Có một cách khác sẽ trích xuất bảng InnoDB mà không thu hẹp ibdata1.

Bước 01) Thêm các dòng sau vào /etc/my.cnf

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

Bước 02) service mysql restart

Bước 03) Để trích xuất một bảng InnoDB có tên mydb.mytable, hãy làm điều này:

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Điều này sẽ tạo ra một tập tin pleus giữ tập tin cấu trúc ban đầu

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

Bạn có thể làm điều này cho mọi bảng InnoDB. Thật không may, ibdata1 sẽ ở lại 150GB.


Trong khi chạy tải lại từ các tập tin .sql tôi có lỗi ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesnào sau đây không?
Ran

@Ran xin vui lòng gửi đó là một câu hỏi riêng biệt.
RolandoMySQLDBA


Nếu bạn đặt innodb_file_per_tablevà sau đó thực hiện ALTER TABLEtrên mỗi bảng, bạn có thể xóa tệp ibdata1 để lấy lại không gian mà không phải khôi phục không?
SystemParadox

1
@SystemParadox TUYỆT ĐỐI KHÔNG !!!!!!!! Bạn sẽ mất từ ​​điển dữ liệu.
RolandoMySQLDBA 10/03/2015

5

Nếu bạn muốn lấy lại không gian của ibdata, kết xuất / khôi phục là lựa chọn duy nhất của bạn, như Rolando chỉ ra. Nó cũng có thể là tốt nhất cho hiệu suất để làm điều này.

Tuy nhiên, nếu bạn chỉ muốn cắt lỗ và 'mất' 150GB đó trên ổ cứng, bạn chỉ cần kích hoạt innodb_file_per_tabletrong my.cnf và khởi động lại máy chủ của mình.

Sau đó, cho mỗi bảng, vấn đề:

ALTER TABLE x DISABLE KEYS;
ALTER TABLE x ENGINE=InnoDB;
ALTER TABLE x ENABLE KEYS; 

Vấn đề ở đây là không gian bàn lớn sẽ mất một lúc.

Những gì tôi muốn đề xuất là thiết lập một nô lệ của db trực tiếp của bạn, chạy chuyển đổi trên nô lệ, sau đó tắt chủ / nô lệ và sao chép bảng dữ liệu mới cho chủ hoặc quảng bá nô lệ thành chủ sau khi nó bắt kịp .

Bạn sẽ gặp khó khăn khi thực hiện thay đổi này mà không có thời gian chết nào cả.


+1 vì trung thực một cách tàn nhẫn và nói 'cắt lỗ của bạn'. Bạn có thể nói 'cắn viên đạn' quá.
RolandoMySQLDBA

Bạn có thể sử dụng pt-online-lược đồ-thay đổi để tránh thời gian chết trong khi chạy bảng thay đổi.
cornernote
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.