Làm thế nào để bạn loại bỏ phân mảnh từ các bảng InnoDB?


13

Tôi có một cơ sở dữ liệu có số lượng bảng.

Tôi muốn xóa một số bản ghi từ các bảng nói rằng không có bản ghi nào lớn hơn 20K hoặc 50K.

Tất cả các bảng là InnoDB. Và file_per_tableđược tắt .

Khi tôi sẽ xóa các bản ghi từ một số bảng sẽ có sự phân mảnh trong các bảng.

Có cách nào để loại bỏ sự phân mảnh.?

Cập nhật vào ngày 17 tháng 4

mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME      | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City            | world_innodb |   5242880 |
| City_Copy       | world_innodb |   5242880 |
| Country         | world_innodb |   5242880 |
| CountryLanguage | world_innodb |   5242880 |
| a               | world_innodb |   5242880 |
| t1              | world_innodb |   5242880 |
| t2              | world_innodb |   5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)

Vì vậy, bây giờ Câu hỏi của tôi là làm thế nào tôi sẽ quyết định rằng các bảng của tôi bị phân mảnh hay không.



1
Và một bài viết InnoDB: chăm sóc phân mảnh từ trang blog của Percona.
ypercubeᵀᴹ

Câu trả lời:


14

Tôi đã giải quyết vấn đề này trong StackOverflow vào tháng 10 năm 2010 .

Hãy ghi nhớ tệp bận rộn nhất trong cơ sở hạ tầng InnoDB: / var / lib / mysql / ibdata1

Tập tin này thường chứa bốn loại thông tin

  • Bảng dữ liệu
  • Bảng chỉ mục
  • Dữ liệu MVCC (Kiểm soát tương tranh đa biến)
  • Bảng siêu dữ liệu (Danh sách ID không gian bảng)

Chạy OPTIMIZE TABLEvới bảng InnoDB được lưu trữ trong ibdata1 thực hiện hai điều:

  • Làm cho dữ liệu và chỉ mục của bảng tiếp giáp bên trong ibdata1, do đó truy cập nhanh hơn
  • Nó làm cho ibdata1 phát triển vì các trang chỉ mục và dữ liệu liền kề được gắn vào ibdata1

Mặc dù bạn có thể tách riêng Dữ liệu bảng và Chỉ mục bảng khỏi ibdata1 và quản lý chúng một cách độc lập bằng innodb_file_per_table , toàn bộ không gian đĩa lớn trong ibdata1 đơn giản sẽ không bị từ chối và không thể lấy lại được. Bạn phải làm nhiều hơn nữa.

Để thu nhỏ ibdata1 một lần và mãi mãi, bạn phải làm như sau:

1) 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à /root/QueryData.sql)

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

3) Tắt máy tính

4) 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.

5) 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

6) Khởi động lại mysql

Điều này sẽ tạo lại ibdata1 ở mức 10 hoặc 18MB (tùy thuộc vào phiên bản tháng của MySQL), ib_logfile0 và ib_logfile1 ở mức 1G mỗi

7) Tải lại /root/QueryData.sql vào mysql

ibdata1 sẽ phát triển nhưng chỉ chứa siêu dữ liệu bảng. Trên thực tế, nó sẽ phát triển rất chậm trong những năm qua. Cách duy nhất để ibdata1 tăng trưởng nhanh chóng là nếu bạn có một hoặc nhiều điều sau đây:

  • Rất nhiều DDL ( CREATE TABLE, DROP TABLE, ALTER TABLE)
  • Rất nhiều giao dịch
  • Rất nhiều thay đổi để cam kết trên mỗi giao dịch

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 đi 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ẬP NHẬT 2012-04-19 09:23 EDT

Sau khi chạy các bước trên, làm thế nào bạn có thể xác định bảng nào cần được chống phân mảnh? Có thể tìm ra, nhưng bạn sẽ có kịch bản đó.

Đây là một ví dụ: Giả sử bạn có bảng mydb.mytable. Với innodb_file_per_table được bật, bạn có tệp /var/lib/mysql/mydb/mytable.ibd

Bạn sẽ phải lấy hai số

TẬP LÊN TỪ HĐH: Bạn có thể xác định kích thước tệp từ HĐH như thế này

ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'

LỌC TỪ THÔNG TIN_SCHema: Bạn có thể xác định kích thước tệp từ information_schema.tables như thế này:

SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';

Chỉ cần trừ giá trị Information_SCHema khỏi giá trị HĐH và chia chênh lệch cho giá trị Information_SCHema.

Từ đó bạn sẽ quyết định bao nhiêu phần trăm cho rằng cần thiết để chống phân mảnh bảng đó. Tất nhiên, bạn chống phân mảnh nó bằng một trong các lệnh sau:

OPTIMIZE TABLE mydb.mytable;

hoặc là

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Tôi không nghĩ / var / lib / mysql / ibdata1 rất bận nếu bạn đang sử dụng tùy chọn innodb_file_per_table = 1 được đề xuất
CrackerJack9

1
@ CrackerJack9 ibdata1 cực kỳ khó tin vì những gì đi vào nó: 1) Thông tin bộ đệm ghi đôi, 2) Chèn bộ đệm cho chỉ mục phụ, 3) Từ điển dữ liệu, 4) Phân đoạn rollback, 5) Hoàn tác không gian bảng. Vui lòng goto scribd.com/doc/31337494/XtraDB-InnoDB-iternals-in-drawing để thể hiện bằng hình ảnh của những điều này. Ngay cả khi xóa dữ liệu và trang chỉ mục cho các bảng InnoDB, ibdata1 vẫn có thể phát triển đáng kể trong môi trường giao dịch cao.
RolandoMySQLDBA

1
@ CrackerJack9 Tôi có một bài viết bổ sung thảo luận về hoạt động bổ sung xung quanh ibdata1: dba.stackexchange.com/a/23367/877
RolandoMyQueryDBA

Tôi đã không nhận ra nó vẫn còn được sử dụng rất nhiều. Rất cảm kích!
CrackerJack9

@RolandoMySQLDBA Bạn có thể bật tại Heap khi bạn có thời gian không?
ypercubeᵀᴹ

5

Nếu bạn thường xuyên xóa các hàng (hoặc cập nhật các hàng với các kiểu dữ liệu có độ dài thay đổi), bạn có thể sẽ có rất nhiều không gian bị lãng phí trong (các) tệp dữ liệu của mình, tương tự như phân mảnh hệ thống tệp.

Nếu bạn không sử dụng innodb_file_per_tabletùy chọn, điều duy nhất bạn có thể làm là xuất và nhập cơ sở dữ liệu, một quy trình tốn nhiều thời gian và đĩa.

Nhưng nếu bạn đang sử dụng innodb_file_per_table, bạn có thể xác định và lấy lại không gian này!

Trước 5.1.21, bộ đếm không gian trống có sẵn từ cột table_comment của information_schema.tables. Dưới đây là một số SQL để xác định các bảng có ít nhất 100M (thực tế là 97,65M) không gian trống:

CHỌN table_schema, table_name, table_comment TỪ
information_schema.tables WHERE Engine THÍCH 'InnoDB' VÀ table_comment RLIKE 'InnoDB miễn phí: ([0-9] {6,}). *';

Bắt đầu với 5.1.21, điều này đã được chuyển sang cột data_free (một nơi thích hợp hơn nhiều):

CHỌN table_schema, table_name, data_free / 1024/1024 AS data_free_MB TỪ information_schema.tables WHERE Engine THÍCH 'InnoDB' AND data_free> 100 * 1024 * 1024;

Bạn có thể lấy lại không gian bị mất bằng cách xây dựng lại bảng. Cách tốt nhất để làm điều này là sử dụng 'bảng thay đổi' mà không thực sự thay đổi bất cứ điều gì:

ALTER TABLE `TableName` ENGINE=InnoDB;

Đây là những gì MySQL thực hiện phía sau hậu trường nếu bạn chạy 'tối ưu hóa bảng' trên bảng InnoDB. Nó sẽ dẫn đến khóa đọc, nhưng không phải là khóa bảng đầy đủ. Mất bao lâu hoàn toàn phụ thuộc vào lượng dữ liệu trong bảng (chứ không phải kích thước của tệp dữ liệu). Nếu bạn có một bảng có khối lượng xóa hoặc cập nhật lớn, bạn có thể muốn chạy hàng tháng hoặc thậm chí hàng tuần.


Một điều nữa tôi không thể hiểu ý nghĩa của data_free> 100 * 1024 * 1024 ..? Và khi tôi thấy kết quả, tôi không thể quyết định rằng bảng có bị phân mảnh hay không .. ?? Có thể nói bảng bị phân mảnh hoặc không bị phân mảnh.?
Abdul Manaf

có một cái nhìn vào phần cập nhật của tôi
Abdul Manaf
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.