Lỗi 2006: Máy chủ MySQL đã biến mất


8

Tôi đang chạy ứng dụng Python Pyramid trên máy chủ CentOS bằng uWSGI và nginx. Tôi đang sử dụng SQLAlchemy làm ORM, MySQLdb làm API và MySQL làm cơ sở dữ liệu. Trang web chưa hoạt động, vì vậy lưu lượng truy cập duy nhất là tôi và một số nhân viên khác của công ty. Chúng tôi đã mua một số dữ liệu để điền vào cơ sở dữ liệu, vì vậy bảng lớn nhất (và thường xuyên được truy vấn nhất) là ~ 150.000 hàng.

Hôm qua tôi đã mở bốn tab mới của trang web liên tiếp và tôi đã nhận được một vài lỗi 502 Bad Gateway. Tôi đã xem nhật ký uWSGI và tìm thấy như sau:

sqlalchemy.exc.OperationalError: (OperationalError) (2006, 'MySQL server has gone away') 'SELECT ge...

Lưu ý quan trọng: Lỗi này không phải do Wait_timeout của MySQL. Đã từng trải qua rồi.

Tôi tự hỏi nếu vấn đề được gây ra bởi các yêu cầu đồng thời được phục vụ đồng thời. Tôi tự biến mình thành người kiểm tra tải trọng của người nghèo:

for i in {1..10}; do (curl -o /dev/null http://domain.com &); done;

Chắc chắn, trong mười yêu cầu đó, ít nhất một yêu cầu sẽ gây ra lỗi năm 2006, đôi khi còn nhiều hơn thế. Đôi khi các lỗi thậm chí còn trở nên xa lạ, ví dụ:

sqlalchemy.exc.NoSuchColumnError: "Could not locate column in row for column 'table.id'"

Khi cột chắc chắn tồn tại và hoạt động tốt trên tất cả các yêu cầu giống hệt khác. Hoặc, cái này:

sqlalchemy.exc.ResourceClosedError: This result object does not return rows. It has been closed automatically.

Khi, một lần nữa, nó hoạt động tốt cho tất cả các yêu cầu khác.

Để xác minh thêm rằng sự cố xuất phát từ các kết nối cơ sở dữ liệu đồng thời, tôi đã đặt uWSGI thành một công nhân duy nhất và đa luồng bị vô hiệu hóa, buộc các yêu cầu phải được xử lý cùng một lúc. Chắc chắn, các vấn đề biến mất.

Trong nỗ lực tìm kiếm sự cố, tôi đã thiết lập một nhật ký lỗi cho MySQL. Ngoại trừ một số thông báo trong khi khởi động MySQL, nó vẫn trống.

Đây là cấu hình MySQL của tôi:

[mysqld]
default-storage-engine = myisam
key_buffer = 1M
query_cache_size = 1M
query_cache_limit = 128k
max_connections=25
thread_cache=1
skip-innodb
query_cache_min_res_unit=0
tmp_table_size = 1M
max_heap_table_size = 1M
table_cache=256
concurrent_insert=2
max_allowed_packet = 1M
sort_buffer_size = 64K
read_buffer_size = 256K
read_rnd_buffer_size = 256K
net_buffer_length = 2K
thread_stack = 64K
innodb_file_per_table=1
log-error=/var/log/mysql/error.log

Googling nặng về lỗi ít tiết lộ, nhưng đề nghị tôi tăng max_allowed_packet. Tôi đã tăng nó lên 100 triệu và khởi động lại MySQL, nhưng điều đó không giúp ích gì cả.

Tóm lại: Kết nối đồng thời với nguyên nhân MySQL 2006, 'MySQL server has gone away'và một số lỗi lạ khác. Không có gì liên quan trong nhật ký lỗi của MySQL.

Tôi đã làm việc trong nhiều giờ và không có tiến triển gì. có ai giúp tôi ra ngoài không?


Khi bạn đang xử lý các yêu cầu đồng thời, mỗi luồng (hoặc quá trình hoặc bất cứ điều gì) có kết nối riêng với cơ sở dữ liệu không?
DerfK

Mỗi quy trình có một nhóm kết nối được quản lý bởi SQLAlchemy, vì vậy mỗi yêu cầu nên có kết nối riêng.
Theron Luhn

Một lưu ý khác: Việc kiểm tra tải không gây ra bất kỳ vấn đề nào trên máy chủ phát triển cục bộ của tôi, đó là Waitress cho máy chủ và MySQL cho cơ sở dữ liệu.
Theron Luhn

Câu trả lời:


18

Tôi cũng đã gặp phải điều này và tìm thấy lý do và khắc phục.

Lý do điều này xảy ra là plugin uwsgi python (hoặc nhiều khả năng là tất cả các plugin uwsgi) fork () công nhân mới sau khi ứng dụng được tải trong cha mẹ. Kết quả là, con cái thừa hưởng tất cả các tài nguyên (bao gồm các mô tả tệp như kết nối db) từ cha mẹ.

Bạn có thể đọc về điều này một cách ngắn gọn trên wiki uwsgi :

uWSGI cố gắng lạm dụng bản sao fork () khi viết bất cứ khi nào có thể. Theo mặc định, nó sẽ rẽ nhánh sau khi đã tải ứng dụng của bạn. Nếu bạn không muốn hành vi đó sử dụng tùy chọn --lazy. Kích hoạt nó, sẽ hướng dẫn uWSGI tải các ứng dụng sau mỗi ngã ba của công nhân ()

Và như bạn có thể biết, các kết nối và con trỏ mysqldb của Python không phải là chủ đề an toàn trừ khi bạn bảo vệ chúng một cách rõ ràng. Do đó, nhiều quá trình (chẳng hạn như các nhân viên uwsgi) sử dụng cùng một kết nối / con trỏ mysql sẽ làm hỏng nó.

Trong trường hợp của tôi (đối với API vàng của King Arthur ), nó hoạt động tốt khi tôi tạo kết nối theo yêu cầu của MySQL trong phạm vi của mô-đun khác, nhưng khi tôi muốn kết nối liên tục để giúp thực hiện, tôi đã chuyển kết nối cơ sở dữ liệu và con trỏ sang phạm vi toàn cầu trong mô đun mẹ. Kết quả là, các kết nối của tôi đã từng bước giống nhau như của bạn.

Cách khắc phục là thêm từ khóa "lười biếng" (hoặc tùy chọn dòng lệnh --lazy) vào cấu hình uwsgi của bạn. Do đó, ứng dụng sẽ được chia rẽ một lần nữa cho mỗi đứa trẻ thay vì từ cha mẹ và chia sẻ kết nối (và bước vào đó tại một số điểm, do đó máy chủ MySQL buộc phải đóng do yêu cầu bị hỏng tại một số điểm).

Cuối cùng, nếu bạn muốn có một cách để làm điều này mà không sửa đổi cấu hình uwsgi của mình, bạn có thể sử dụng trình trang trí @postfork để tạo kết nối cơ sở dữ liệu mới ngay lập tức sau khi xử lý rẽ nhánh. Bạn có thể đọc về điều đó ở đây .

Tôi thấy từ theo dõi của bạn rằng bạn đã chuyển sang pssql, nhưng đây là câu trả lời để bạn có thể ngủ ngon hơn vào ban đêm và cho bất cứ ai như bạn và tôi đang cố gắng tìm câu trả lời cho điều này!

PS Một khi tôi đã hiểu vấn đề (con trỏ bị hỏng do các công nhân giẫm đạp lên nhau) nhưng không nhận ra chút gì về fork () và --lazy, tôi đã xem xét triển khai nhóm của riêng mình, nơi các công nhân sẽ " kiểm tra "kết nối mysql từ một nhóm ở phạm vi toàn cầu, sau đó" kiểm tra lại "ngay trước khi thoát ứng dụng (), tuy nhiên có thể sử dụng --lazy tốt hơn trừ khi tải web / ứng dụng của bạn đủ thay đổi mà bạn liên tục tạo công nhân mới. Thậm chí sau đó tôi có thể thích --lazy vì nó sạch hơn đáng kể so với việc thực hiện nhóm kết nối db của riêng bạn.

chỉnh sửa: đây là một bài viết kỹ lưỡng hơn về vấn đề này + giải pháp vì thiếu thông tin về nó cho những người khác đã gặp phải: http://tns.u13.net/?p=190


Thật tuyệt khi biết điều gì đã gây ra điều này. Cảm ơn bạn!
Theron Luhn

Chỉ cần ném ra rằng bài đăng này là cùng một vấn đề chính xác tôi đã gặp phải và giải pháp của bạn đã khắc phục nó :) Cảm ơn!
MasterGberry

"Do đó, nhiều quá trình (chẳng hạn như các công nhân uwsgi) sử dụng cùng một kết nối / con trỏ mysql sẽ làm hỏng nó." Điều này rất hướng dẫn. Tôi đã có hai kết nối mở tới cùng một cơ sở dữ liệu trên máy cục bộ của tôi (một từ vỏ, một từ ứng dụng wsgi của tôi) và đã gặp lỗi này. Cơ sở dữ liệu đã báo cáo chính nó còn sống pingvà các mysqladminyêu cầu khác . Có lẽ là do tôi đã cố gắng bỏ cơ sở dữ liệu khỏi shell ... nhưng nó vẫn liên tục đưa ra lỗi "máy chủ đã biến mất" cho lệnh đó. Dù sao cũng cảm ơn!
Brian Peterson

bạn đã cứu mạng tôi.
con đỉa
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.