Câu chuyện xóa vật lý 300 triệu bản ghi trong MySQL

Giới thiệu

Xin chào. Tôi là ningenMe, nhà phát triển web.

Như tiêu đề đã nói, câu chuyện của tôi là câu chuyện xóa 300 triệu bản ghi trong MySQL.

Tôi bắt đầu quan tâm đến điều này nên quyết định làm một lời nhắc nhở (hướng dẫn).

Trang chủ - Cảnh báo

Máy chủ bó mà tôi sử dụng và bảo trì có quy trình thường xuyên thu thập dữ liệu của tháng trước từ MySQL mỗi ngày một lần.

Thông thường quá trình này được hoàn thành trong vòng khoảng 1 giờ, nhưng lần này nó không hoàn thành trong 7 hoặc 8 giờ và cảnh báo không ngừng xuất hiện...

Tìm kiếm lý do

Tôi đã cố gắng khởi động lại quá trình và xem nhật ký, nhưng tôi không thấy có gì sai.
Truy vấn đã được lập chỉ mục chính xác. Nhưng khi tôi nghĩ về điều gì đó đã xảy ra, tôi nhận ra rằng kích thước cơ sở dữ liệu khá lớn.

hoge_table | 350'000'000 |

350 triệu bản ghi. Việc lập chỉ mục dường như hoạt động chính xác, chỉ là rất chậm.

Việc thu thập dữ liệu cần thiết mỗi tháng là khoảng 12 bản ghi. Có vẻ như lệnh chọn mất nhiều thời gian và giao dịch không được thực hiện trong một thời gian dài.

DB

Về cơ bản, nó là một bảng tăng thêm khoảng 400 mục mỗi ngày. Cơ sở dữ liệu được cho là chỉ thu thập dữ liệu trong tháng trước, do đó, người ta hy vọng rằng nó sẽ chịu được chính xác lượng dữ liệu này, nhưng thật không may, thao tác xoay không được bao gồm.

Cơ sở dữ liệu này không phải do tôi phát triển. Tôi đã tiếp quản nó từ một nhà phát triển khác nên nó vẫn giống như một khoản nợ kỹ thuật.

Đã đến lúc khối lượng dữ liệu được chèn hàng ngày trở nên lớn và cuối cùng đã đạt đến giới hạn. Người ta cho rằng khi làm việc với một lượng lớn dữ liệu như vậy, cần phải tách chúng ra, nhưng thật không may, điều này đã không được thực hiện.

Và rồi tôi bắt tay vào hành động.

Điều chỉnh

Sẽ hợp lý hơn nếu giảm kích thước của cơ sở dữ liệu và giảm thời gian xử lý nó hơn là thay đổi logic.

Tình hình sẽ thay đổi đáng kể nếu bạn xóa 300 triệu bản ghi, vì vậy tôi quyết định làm như vậy... Ơ, tôi nghĩ cách này chắc chắn sẽ thành công.

Hành động 1

Sau khi chuẩn bị một bản sao lưu đáng tin cậy, cuối cùng tôi cũng bắt đầu gửi yêu cầu.

「Gửi yêu cầu」

DELETE FROM hoge_table WHERE create_time <= 'YYYY-MM-DD HH:MM:SS';

"…"

"…"

“Hmm... Không có câu trả lời. Có lẽ quá trình này sẽ mất nhiều thời gian?” — Tôi nghĩ vậy, nhưng để đề phòng, tôi nhìn vào grafana và thấy rằng tải đĩa đang tăng rất nhanh.
“Nguy hiểm,” tôi nghĩ lại và ngay lập tức dừng yêu cầu đó.

Hành động 2

Sau khi phân tích mọi thứ, tôi nhận ra rằng khối lượng dữ liệu quá lớn để có thể xóa mọi thứ cùng một lúc.

Tôi quyết định viết một đoạn script có thể xóa khoảng 1 bản ghi và khởi chạy nó.

「Tôi thực hiện kịch bản」

“Bây giờ điều này chắc chắn sẽ hiệu quả,” tôi nghĩ.

Hành động 3

Phương pháp thứ hai có hiệu quả nhưng hóa ra lại tốn rất nhiều công sức.
Để làm mọi thứ một cách cẩn thận, không cần lo lắng quá mức, sẽ mất khoảng hai tuần. Tuy nhiên, kịch bản này vẫn chưa đáp ứng được yêu cầu dịch vụ nên chúng tôi phải loại bỏ nó.

Vì vậy, đây là những gì tôi quyết định làm:

Sao chép bảng và đổi tên nó

Từ bước trước, tôi nhận ra rằng việc xóa một lượng lớn dữ liệu như vậy sẽ tạo ra một tải trọng lớn không kém. Vì vậy, tôi quyết định tạo một bảng mới từ đầu bằng cách chèn và di chuyển dữ liệu tôi định xóa vào đó.

| hoge_table     | 350'000'000|
| tmp_hoge_table |  50'000'000|

Nếu bạn tạo bảng mới có cùng kích thước như trên thì tốc độ xử lý dữ liệu cũng sẽ nhanh hơn 1/7.

Sau khi tạo bảng và đổi tên, tôi bắt đầu sử dụng nó làm bảng chính. Bây giờ nếu tôi bỏ bảng với 300 triệu bản ghi thì mọi thứ sẽ ổn.
Tôi phát hiện ra rằng việc cắt bớt hoặc bỏ bớt tốn ít chi phí hơn so với xóa và quyết định sử dụng phương pháp này.

Hiệu suất

「Gửi yêu cầu」

INSERT INTO tmp_hoge_table SELECT FROM hoge_table create_time > 'YYYY-MM-DD HH:MM:SS';

"…"
"…"
"Ừm...?"

Hành động 4

Tôi nghĩ ý tưởng trước đó sẽ hiệu quả nhưng sau khi gửi yêu cầu chèn, nhiều lỗi đã xuất hiện. MySQL không tha thứ.

Tôi đã quá mệt mỏi và bắt đầu nghĩ rằng mình không muốn làm việc này nữa.

Tôi ngồi suy nghĩ và nhận ra rằng có lẽ có quá nhiều truy vấn chèn trong một lần...
Tôi đã thử gửi yêu cầu chèn lượng dữ liệu mà cơ sở dữ liệu sẽ xử lý trong 1 ngày. Đã xảy ra!

Chà, sau đó chúng tôi tiếp tục gửi yêu cầu về cùng một lượng dữ liệu. Vì cần xóa dữ liệu của một tháng nên chúng tôi lặp lại thao tác này khoảng 35 lần.

Đổi tên một bảng

Ở đây may mắn đã đứng về phía tôi: mọi thứ diễn ra suôn sẻ.

Cảnh báo bị mất tích

Tốc độ xử lý hàng loạt đã tăng lên.

Trước đây quá trình này mất khoảng một giờ, bây giờ mất khoảng 2 phút.

Sau khi chắc chắn rằng mọi vấn đề đã được giải quyết, tôi đã bỏ 300 triệu bản ghi. Tôi xóa bảng và cảm thấy như được tái sinh.

Bản tóm tắt

Tôi nhận ra rằng quá trình xử lý xoay bị thiếu trong xử lý hàng loạt và đó là vấn đề chính. Loại lỗi kiến ​​trúc này dẫn đến lãng phí thời gian.

Bạn có nghĩ đến tải trọng trong quá trình sao chép dữ liệu khi xóa bản ghi khỏi cơ sở dữ liệu không? Chúng ta đừng làm quá tải MySQL.

Những người thành thạo cơ sở dữ liệu chắc chắn sẽ không gặp phải vấn đề như vậy. Đối với những người còn lại, tôi hy vọng bài viết này hữu ích.

Cảm ơn vì đã đọc!

Chúng tôi sẽ rất vui nếu bạn cho chúng tôi biết bạn có thích bài viết này không, bản dịch có rõ ràng không, nó có hữu ích cho bạn không?

Nguồn: www.habr.com

Thêm một lời nhận xét