Tại sao DROP DATABASE mất nhiều thời gian như vậy? (MySQL)


46

Cài đặt CentOS mới.

Tôi đang chạy một DB lớn (tệp 2 GB) và gặp sự cố. Máy khách SSH dường như mất kết nối và quá trình nhập dường như bị đóng băng. Tôi đã sử dụng một cửa sổ khác để đăng nhập vào mysql và quá trình nhập dường như đã chết, bị kẹt trên một bảng hàng 3M cụ thể.

Vì vậy, tôi đã cố gắng

DROP DATABASE huge_db;

15-20 phút sau, không có gì. Trong một cửa sổ khác, tôi đã làm:

/etc/init.d/mysqld restart

Cửa sổ DROP DB bị rối: SERVER SHUTDOWN. Sau đó, tôi thực sự khởi động lại máy chủ vật lý.

Đăng nhập lại vào mysql, kiểm tra và db vẫn ở đó, chạy

DROP DATABASE huge_db;

một lần nữa và một lần nữa tôi đã đợi khoảng 5 phút.

Một lần nữa, đó là cài đặt mới. Đây huge_dblà db duy nhất (trừ dbs hệ thống). Tôi thề rằng tôi đã bỏ db lớn như vậy trước đây và nhanh chóng, nhưng có lẽ tôi đã sai.

Tôi đã bỏ thành công cơ sở dữ liệu. Phải mất khoảng 30 phút. Cũng lưu ý rằng tôi nghĩ rằng tôi đã nhầm khi tôi nghĩ rằng việc nhập mysqldump đã chết. Kết nối đầu cuối bị mất, nhưng tôi nghĩ rằng quá trình vẫn đang chạy. Tôi rất có thể đã giết bảng giữa nhập (bảng hàng 3M) và có thể là 3/4 chặng đường qua toàn bộ db. Thật sai lầm khi "top" cho thấy mysql chỉ sử dụng 3% bộ nhớ, khi có vẻ như nó nên được sử dụng nhiều hơn.

Mất DB cuối cùng mất 30 phút, vì vậy, một lần nữa, tôi có thể không phải khởi động lại máy chủ và có thể chỉ cần đợi DROP kết thúc, nhưng tôi không biết mysql sẽ phản ứng thế nào khi nhận được truy vấn DROP cho cùng một db mà nó đang nhập thông qua mysqldump.

Tuy nhiên, câu hỏi vẫn còn đó, tại sao phải mất 30 phút + để DROP cơ sở dữ liệu 2GB khi tất cả những gì cần làm là xóa tất cả các tệp db và xóa tất cả các tham chiếu đến DB khỏi information_schema? Vấn đề lớn là gì?

Câu trả lời:


73

Thay vì giết quá trình, sẽ an toàn hơn nếu bạn thực hiện trong MySQL:

$ mysqladmin processlist -u root -p
Enter password: 
+-----+------+-----------+-------------------+---------+------+-------+------------------+
| Id  | User | Host      | db                | Command | Time | State | Info             |
+-----+------+-----------+-------------------+---------+------+-------+------------------+
| 174 | root | localhost | example           | Sleep   | 297  |       |                  |
| 407 | root | localhost |                   | Query   | 0    |       | show processlist |
+-----+------+-----------+-------------------+---------+------+-------+------------------+

Truy vấn với id 174 là một lần xóa cơ sở dữ liệu 'ví dụ', vì vậy trước khi bạn hủy bất kỳ quy trình nào trước tiên, hãy để MySQL thử chấm dứt truy vấn:

$ mysqladmin kill 174

Chạy processlistlệnh trên một lần nữa để xác nhận rằng nó đã bị giết.

Nếu điều này không hiệu quả, thì có lẽ bạn có thể xem xét việc tiêu diệt quá trình sai lầm, nhưng trước đó bạn có thể thử khởi động lại máy chủ MySQL.

Bạn cũng có thể chạy các lệnh như 'SHOW FULL PROCESSLIST' và 'KILL 174' trong shell MySQL, ví dụ nếu bạn chỉ cài đặt máy khách MySQL. Điểm chính là để tránh giết quá trình sử dụng 'kill' trong vỏ trừ khi thực sự cần thiết.

Nói chung, bạn có thể sử dụng mysqlhoặc mysqladmin. Bạn không cần phải chạy các lệnh như thế này thường xuyên; một khi bạn bắt đầu giết các truy vấn thường xuyên, một cái gì đó chắc chắn là sai và tốt hơn hết là bạn nên khắc phục vấn đề đó (giết quá trình truy vấn chỉ là xử lý triệu chứng).


1
@BugsBuggy Một cách phổ biến trong đó điều này có thể xảy ra là nếu một quy trình khác (ví dụ: máy chủ web hoặc trong trường hợp này là quy trình nhập) đang chạy và được kết nối với cơ sở dữ liệu. Khi bạn phát DROP DATABASElệnh, máy chủ sẽ không tiến hành cho đến khi tất cả các kết nối đã bị đóng.
Stefan Magnuson

11

Mặc dù tôi nghĩ rằng quá trình nhập khẩu đã chết, nhưng nó có thể vẫn đang chạy.

Các DROP DATABASElệnh lẽ chờ cơ sở dữ liệu để kết thúc nhập khẩu trước khi nó chạy.

Vì vậy, thay vì DROP DATABASEmất nhiều thời gian, nó có lẽ chỉ là nhập khẩu.

Nếu bất cứ ai khác đọc được điều này và đang cố gắng hủy bỏ việc nhập cơ sở dữ liệu và hủy cơ sở dữ liệu, tôi khuyên bạn trước tiên nên tìm PID (id quy trình) để nhập và chạy nó từ một thiết bị đầu cuối khác:

$ kill [PID]

... Trong đó [PID] sẽ là PID thực tế cho quá trình.

Bạn sẽ thấy dừng nhập ngay lập tức nếu thiết bị đầu cuối khác vẫn được kết nối.

Bạn cũng có thể chạy SHOW PROCESSLISTtrong tab phpMyAdmin SQL. Bảng kết quả hiển thị các quy trình đang chạy và nhấp vào 'x' bên cạnh hàng bạn muốn giết sẽ thực hiện thủ thuật.

Sau đó chạy

DROP DATABASE `database_name`;

Và mọi thứ nên sạch sẽ.


Một câu trả lời khác cho rằng việc giết quá trình trong mysql tốt hơn là thực hiện nó từ bên ngoài. Tôi chưa kiểm tra câu trả lời đó, nhưng nghe có vẻ rất hợp lý. Vì vậy, tôi đã đánh dấu nó là "câu trả lời được chấp nhận" thay vì câu trả lời này.


3

Cố gắng cắt bớt các bảng lớn nhất trong cơ sở dữ liệu youra trước khi bạn thả nó. Tôi đã thấy hành vi rất giống nhau khi làm việc với kho lưu trữ tường lửa của MySQL và điều này giúp ích rất nhiều.


Theo tài liệu của MySQL, "Thao tác cắt xén thả và tạo lại bảng, nhanh hơn nhiều so với xóa từng hàng một", vì vậy không có điểm nào trong việc cắt xén để thả - dev.mysql.com/doc/refman/8.0/en/ truncate-table.html
ejoubaud


3

Tôi phải đối mặt với cùng một vấn đề. Nhưng lần này tôi đã kiểm tra danh sách quy trình; Nó cho biết kiểm tra cho phép trong thời gian dài hơn. Sau đó, tôi thấy rằng mysqld_safe đang chạy bằng root trong khi quyền cấp thư mục chỉ dành cho người dùng mysql. Do đó tôi đã giết truy vấn, tất nhiên phải mất một thời gian dài để nói nó ở trạng thái bị giết nhưng tôi đợi nó phản ứng rồi nó giết truy vấn và thay đổi quyền cấp thư mục thành root bằng cách thêm nó vào nhóm và chmod thành 770. Sau đó, tôi đã thực thi cùng cơ sở dữ liệu thả blah; nó đã làm việc với tôi trong 2 giây cho cơ sở dữ liệu 20GB.

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.