Làm thế nào: Làm sạch một công cụ lưu trữ mysql InnoDB?


132

Có thể làm sạch một công cụ lưu trữ innodb mysql để nó không lưu trữ dữ liệu từ các bảng đã xóa?

Hay tôi phải xây dựng lại một cơ sở dữ liệu mới mỗi lần?


Điều gì khiến bạn nghĩ rằng MySQL đang lưu trữ dữ liệu từ các bảng bị xóa?
Robert Munteanu

1
Nếu tôi thả cả đống bảng lớn, các tệp lưu trữ InnoDB của tôi sẽ không co lại
Bryan Field

2
@RobertMunteanu: xem bug.mysql.com/orms.php?id=1341
Tối đa

Câu trả lời:


350

Đây là một câu trả lời đầy đủ hơn liên quan đến InnoDB. Đó là một chút của một quá trình dài, nhưng có thể đáng nỗ lực.

Hãy nhớ rằng đó /var/lib/mysql/ibdata1là tệp bận rộn nhất trong cơ sở hạ tầng InnoDB. Nó thường chứa sáu 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)
    • Phân đoạn rollback
    • Hoàn tác không gian
  • Bảng siêu dữ liệu (Từ điển dữ liệu)
  • Double Write Buffer (viết nền để ngăn chặn sự phụ thuộc vào bộ đệm của hệ điều hành)
  • Chèn bộ đệm (quản lý các thay đổi đối với các chỉ mục phụ không duy nhất)
  • Xem Pictorial Representation of ibdata1

Kiến trúc InnoDB

Kiến trúc InnoDB

Nhiều người tạo ra nhiều ibdatatệp với hy vọng quản lý và hiệu suất không gian đĩa tốt hơn, tuy nhiên niềm tin đó bị nhầm lẫn.

Tôi có thể chạy OPTIMIZE TABLEkhông

Thật không may, chạy OPTIMIZE TABLEvới bảng InnoDB được lưu trữ trong tệp không gian bảng chia sẻ ibdata1có 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
  • Làm cho ibdata1tăng trưởng vì dữ liệu và chỉ số trang liền kề được nối tớiibdata1

Tuy nhiên, bạn có thể tách riêng Dữ liệu Bảng và Chỉ mục Bảng khỏi ibdata1và quản lý chúng một cách độc lập.

Tôi có thể chạy OPTIMIZE TABLEvới innodb_file_per_table?

Giả sử bạn đã thêm innodb_file_per_tablevào /etc/my.cnf (my.ini). Bạn có thể chạy OPTIMIZE TABLEtrên tất cả các Bảng InnoDB không?

Tin tốt : Khi bạn chạy OPTIMIZE TABLEvới innodb_file_per_tablekích hoạt, điều này sẽ tạo ra một .ibdtệp cho bảng đó. Ví dụ: nếu bạn có bảng với một mydb.mytabledatadir của /var/lib/mysqlnó, nó sẽ tạo ra các mục sau:

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

Các .ibdsẽ chứa các trang dữ liệu và Trang Index cho bảng đó. Tuyệt quá.

Tin xấu : Tất cả những gì bạn đã làm là trích xuất các Trang dữ liệu và Trang chỉ mục mydb.mytabletừ khi sống ibdata. Mục nhập từ điển dữ liệu cho mọi bảng, bao gồm mydb.mytable, vẫn còn trong từ điển dữ liệu (Xem phần Đại diện hình ảnh của ibdata1 ). BẠN KHÔNG THỂ CHỈ CẦN XÓA ibdata1ĐƠN GIẢN TẠI ĐIỂM NÀY !!! Xin lưu ý rằng ibdata1đã không thu hẹp chút nào.

Dọn dẹp cơ sở hạ tầng InnoDB

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

  1. Kết xuất (ví dụ: với mysqldump) tất cả các cơ sở dữ liệu vào một .sqltệp văn bản ( SQLData.sqlđược sử dụng bên dưới)

  2. Bỏ tất cả các cơ sở dữ liệu (ngoại trừ mysqlinformation_schema) CAVEAT : Để phòng ngừa, vui lòng chạy tập lệnh này để đảm bảo chắc chắn rằng bạn có tất cả các khoản trợ cấp của người dùng:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. Đăng nhập vào mysql và chạy SET GLOBAL innodb_fast_shutdown = 0;(Điều này sẽ xóa hoàn toàn tất cả các thay đổi giao dịch còn lại từ ib_logfile0ib_logfile1)

  4. Tắt máy MySQL

  5. Thêm các dòng sau vào /etc/my.cnf(hoặc my.initrên Windows)

    [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 là gì innodb_buffer_pool_size, hãy đảm bảo innodb_log_file_sizelà 25% innodb_buffer_pool_size.

    Ngoài ra: innodb_flush_method=O_DIRECTkhông có sẵn trên Windows)

  6. Xóa ibdata*ib_logfile*, Tùy chọn, bạn có thể xóa tất cả các thư mục trong /var/lib/mysql, ngoại trừ /var/lib/mysql/mysql.

  7. Bắt đầu MySQL (Điều này sẽ tạo lại ibdata1[10MB theo mặc định] ib_logfile0ib_logfile1ở mức 1G mỗi cái).

  8. Nhập khẩu SQLData.sql

Bây giờ, ibdata1vẫn sẽ phát triển nhưng chỉ chứa siêu dữ liệu bảng vì mỗi bảng InnoDB sẽ tồn tại bên ngoài ibdata1. ibdata1sẽ không còn chứa dữ liệu và chỉ mục của InnoDB cho các bảng khác.

Ví dụ: giả sử bạn có bảng InnoDB được đặt tên mydb.mytable. Nếu bạn nhìn 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 (Bảng dữ liệu và chỉ mục)

Với innodb_file_per_tabletùy chọn trong /etc/my.cnf, bạn có thể chạy OPTIMIZE TABLE mydb.mytablevà tệp /var/lib/mysql/mydb/mytable.ibdsẽ 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 nhỏ một tệp 50 GB ibdata1 xuống chỉ còn 500 MB!

Hãy thử một lần. Nếu bạn có thêm câu hỏi về điều này, chỉ cần hỏi. Tin tôi đi; điều này sẽ làm việc trong thời gian ngắn cũng như trên đường dài.

CAUPAT

Ở Bước 6, nếu mysql không thể khởi động lại do mysqllược đồ bắt đầu bị hủy, hãy nhìn lại Bước 2. Bạn đã tạo bản sao vật lý của mysqllược đồ. Bạn có thể khôi phục nó như sau:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Quay trở lại Bước 6 và tiếp tục

CẬP NHẬT 2013-06-04 11:13 EDT

Liên quan đến việc đặt innodb_log_file_size thành 25% innodb_buffer_pool_size trong Bước 5, quy tắc chăn đó là trường học khá cũ.

Quay lại July 03, 2006, Percona đã có một bài viết hay tại sao để chọn một innodb_log_file_size thích hợp . Sau đó, Nov 21, 2008Percona tiếp tục với một bài viết khác về cách tính kích thước phù hợp dựa trên khối lượng công việc cao nhất giữ cho giá trị thay đổi trong một giờ .

Kể từ khi tôi viết bài đăng trong DBA StackExchange về việc tính toán kích thước nhật ký và nơi tôi đã tham chiếu hai bài báo Percona đó.

Cá nhân, tôi vẫn sẽ sử dụng quy tắc 25% cho thiết lập ban đầu. Sau đó, khi khối lượng công việc có thể được xác định chính xác hơn theo thời gian trong sản xuất, bạn có thể thay đổi kích thước các bản ghi trong một chu kỳ bảo trì chỉ trong vài phút.


9
Tôi cũng đã sử dụng tùy chọn innodb_file_per_table để có hiệu quả tuyệt vời, có 200 cơ sở dữ liệu với 200 bảng trên mỗi máy chủ, tôi có thể liên kết các cơ sở dữ liệu khác nhau trên các phân vùng khác nhau, do đó sử dụng nhiều bộ đệm IO và trục chính có thể có sẵn :)
Dave Rix

2
@SeanDowney BTW nhớ tăng innodb_open_tablesnếu cần thiết. Mặc định là 300.
RolandoMySQLDBA

2
@ giorgio79 bạn cần đặt chèn số lượng lớn của mình thành giá trị lớn hơn. đây là một quan điểm tốt. Tôi sẽ thêm bản chất câu hỏi của bạn vào câu trả lời của tôi.
RolandoMySQLDBA

3
Trong các hệ thống 32 bit, giá trị 4Gb cho innodb_buffer_pool_size không được phép. Mysql sẽ âm thầm bắt đầu với innodb bị vô hiệu hóa và các bảng được khôi phục sẽ được đổi thành myisam. Sử dụng một giá trị nhỏ hơn một chút để sửa nó.
David

5
Trời đất ơi. Tôi chỉ muốn nói rằng đây có lẽ là một trong những câu trả lời hay nhất tôi từng thấy trong công việc tốt quá, thưa ngài. Đã giúp tôi tìm ra giải pháp cho vấn đề của mình khi tôi nhận được ERROR 2013 (HY000) khi nhập một db 154g. Cảm ơn câu trả lời tuyệt vời!
Josh Brown

4

Công cụ InnoDB không lưu trữ dữ liệu đã xóa. Khi bạn chèn và xóa các hàng, không gian chưa sử dụng sẽ được phân bổ trong các tệp lưu trữ InnoDB. Theo thời gian, không gian tổng thể sẽ không giảm, nhưng theo thời gian, không gian 'bị xóa và giải phóng' sẽ được máy chủ DB sử dụng lại tự động.

Bạn có thể điều chỉnh và quản lý thêm không gian được sử dụng bởi động cơ thông qua việc tái lập thủ công các bảng. Để thực hiện việc này, kết xuất dữ liệu trong các bảng bị ảnh hưởng bằng mysqldump, thả các bảng, khởi động lại dịch vụ mysql và sau đó tạo lại các bảng từ các tệp kết xuấ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.