Làm cách nào tôi có thể định cấu hình MySQL Innodb để xử lý 1000 lần chèn mỗi giờ?


10

Tôi có một trang web có lưu lượng truy cập rất cao, nơi có thể có 1000 bản ghi mới được chèn mỗi giờ.

Đây là một lỗi làm tê liệt trang web:

PDOException: SQLSTATE[40001]: Serialization failure: 1213 
Deadlock found when trying to get lock; 
try restarting transaction: INSERT INTO {location_instance} 
(nid, vid, uid, genid, lid) VALUES (:db_insert_placeholder_0, 
:db_insert_placeholder_1, :db_insert_placeholder_2, 
:db_insert_placeholder_3, :db_insert_placeholder_4); 
Array ( [:db_insert_placeholder_0] => 1059 [:db_insert_placeholder_1] => 
1059 [:db_insert_placeholder_2] => 0 [:db_insert_placeholder_3] => 
cck:field_item_location:1059 [:db_insert_placeholder_4] => 1000 )

Tôi sẽ rất ngạc nhiên nếu MySQL không thể xử lý loại tải này. Vì vậy, câu hỏi của tôi là, đây có phải là vấn đề về cơ sở dữ liệu không và làm cách nào tôi có thể định cấu hình MySQL để có thể xử lý nhiều lưu lượng truy cập này?

Tôi có một bản sao trang web của mình được thiết lập trên một máy chủ phát triển với các tập lệnh mô phỏng tải nội dung được thêm vào trang web. Tôi đang chạy Ubuntu, LAMP stack, với 16GB RAM.

Phải thừa nhận rằng, tôi không am hiểu lắm về cơ sở dữ liệu. Trên thực tế, tôi đang bắt đầu với my.cnf mặc định đi kèm với nó sau khi 'apt-get install' kết thúc. Bàn là tất cả Innodb. Những gì bắt đầu cài đặt cấu hình và cách tiếp cận bạn muốn giới thiệu để bắt đầu giải quyết vấn đề này?

Hãy cho tôi biết những gì bạn có thể cần thêm thông tin.

Cảm ơn


Bạn đang bắt đầu với my.cnf mặc định cho sản xuất? Man, bạn phải tối ưu hóa nó nhiều hơn. Sẽ chi tiết cho bạn nhiều hơn trong câu trả lời của tôi. :-)

Câu trả lời:


11

Bạn đang đối phó với bế tắc, không phải là vấn đề tắc nghẽn hiệu suất.

Nếu bạn có một nghìn hồ sơ mới mỗi giờ, bạn sẽ còn rất xa để đạt đến giới hạn MySQL. MySQL có thể xử lý ít nhất 50 lần tải của bạn.

Bế tắc là do mã ứng dụng và không phải là lỗi của máy chủ cơ sở dữ liệu. Bế tắc không thể được sửa chữa ở phía máy chủ MySQL, ngoại trừ trong một số tình huống cụ thể.

InnoDBcó thể hiển thị cho bạn thông tin khóa chết chi tiết bằng cách chạy SHOW ENGINE INNODB STATUStại dấu nhắc của MySQL hoặc với mysql -uroot -p... -e "SHOW ENGINE INNODB STATUS".

Tuy nhiên, điều này chỉ cho thấy sự bế tắc cuối cùng xảy ra, không có nhật ký bế tắc.

Rất may, có một công cụ pt-deadlock-logger xử lý vấn đề đó, nó xử lý InnoDBtrạng thái bỏ phiếu và lưu tất cả thông tin bế tắc chi tiết trước khi nó được làm mới với một bế tắc mới.


Tốt để biết! Tôi thấy trong lệnh hiển thị trạng thái thông tin về khóa và bảng và truy vấn có liên quan. Cho rằng đây là trong mã của tôi, làm thế nào tôi có thể sử dụng thông tin này từ lệnh trạng thái để bắt đầu gỡ lỗi vấn đề? Truy vấn PDO của PHP khá dễ dàng - kết nối, chuẩn bị, thực hiện, lặp lại. Tôi rất vui lòng gửi bất kỳ mã hoặc thông báo trạng thái nếu điều đó sẽ giúp.
dùng658182

@ user658182 kiểm tra bài đăng này trên stackoverflow về cách xử lý các bế tắc: cách tránh bế tắc mysql được tìm thấy khi cố gắng khóa
Valor

1
@ max-vernon cảm ơn vì đã chỉnh sửa cú pháp, rõ ràng tiếng Anh không phải là ngôn ngữ mẹ đẻ của tôi :-).
Valor

1
-e "SHOW Engine INNODB STATUS"
glyph

8

Điều này có thể đơn giản như một phần mã của bạn đang chạy giao dịch:

insert into t1...
insert into t2...
commit;

trong khi một phần khác của mã của bạn sửa đổi các bảng giống nhau theo một thứ tự khác nhau:

delete from t2 where...
delete from t1 where...
commit;

Nếu cả hai giao dịch đó chạy cùng một lúc, một điều kiện cuộc đua có thể xảy ra: giao dịch đầu tiên không thể sửa đổi t2vì nó bị khóa bởi giao dịch thứ hai; trong khi giao dịch thứ hai bị chặn tương tự vì t1bị khóa bởi giao dịch đầu tiên. MySQL chọn một giao dịch là "nạn nhân" trong đó XÁC NHẬN / CẬP NHẬT / XÓA không thành công. Ứng dụng cần bắt lỗi đó và thử lại câu lệnh - có thể sau khi tạm dừng để giao dịch khác có thời gian kết thúc. Không có gì để làm với giới hạn dung lượng, chỉ là thời gian không may có thể bị làm trầm trọng hơn bởi cách sắp xếp mã. Chuyển đổi xung quanh XÓA trong giao dịch số 2 hoặc INSERT trong giao dịch số 1 và sau đó không có xung đột - mỗi giao dịch sẽ chờ truy cập vào (các) bảng mà nó cần.

Trong MySQL 5.6, bạn có thể chạy với tùy chọn innodb_print_all_deadlocks được bật để thu thập thông tin về tất cả các khóa chết (không chỉ là lỗi gần đây nhất) trong nhật ký lỗi của MySQL.

[Tuyên bố miễn trừ trách nhiệm: Tôi là nhân viên của Oracle. Trên đây là quan điểm cá nhân của tôi không phải là một tuyên bố chính thức.]

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.