Saya menjalankan aplikasi Python Pyramid di server CentOS menggunakan uWSGI dan nginx. Saya menggunakan SQLAlchemy sebagai ORM, MySQLdb sebagai API, dan MySQL sebagai database. Situs ini belum ditayangkan, jadi satu-satunya lalu lintas adalah saya dan beberapa karyawan perusahaan lainnya. Kami membeli beberapa data untuk mengisi basis data, sehingga tabel terbesar (dan paling sering ditanyakan) adalah ~ 150.000 baris.
Kemarin saya membuka empat tab baru situs web secara berurutan, dan saya mendapatkan kembali beberapa 502 kesalahan Gateway Buruk. Saya mencari di log uWSGI, dan menemukan yang berikut:
sqlalchemy.exc.OperationalError: (OperationalError) (2006, 'MySQL server has gone away') 'SELECT ge...
Catatan penting: Kesalahan ini bukan karena wait_timeout MySQL. Pernah ke sana, melakukan itu.
Saya bertanya-tanya apakah masalah ini disebabkan oleh permintaan bersamaan yang dilayani secara bersamaan. Saya menjadikan diri saya seorang penguji beban orang miskin:
for i in {1..10}; do (curl -o /dev/null http://domain.com &); done;
Benar saja, dalam sepuluh permintaan itu setidaknya satu akan membuat kesalahan 2006, seringkali lebih. Terkadang kesalahan akan semakin asing, misalnya:
sqlalchemy.exc.NoSuchColumnError: "Could not locate column in row for column 'table.id'"
Ketika kolom paling pasti ada dan bekerja dengan baik pada semua permintaan identik lainnya. Atau yang ini:
sqlalchemy.exc.ResourceClosedError: This result object does not return rows. It has been closed automatically.
Ketika, sekali lagi, itu berfungsi dengan baik untuk semua permintaan lainnya.
Untuk lebih jauh memverifikasi bahwa masalahnya berasal dari koneksi database bersamaan, saya mengatur uWSGI menjadi pekerja tunggal dan multi-threading dinonaktifkan, memaksa permintaan untuk diproses satu per satu. Benar saja, masalahnya hilang.
Dalam upaya untuk menemukan masalah, saya membuat log kesalahan untuk MySQL. Dengan pengecualian beberapa pemberitahuan selama MySQL dimulai, tetap kosong.
Ini konfigurasi MySQL saya:
[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 berat tentang kesalahan itu hanya sedikit mengungkapkan, tetapi menyarankan agar saya meningkatkan max_allowed_packet. Saya meningkatkannya menjadi 100 juta dan memulai kembali MySQL, tetapi itu tidak membantu sama sekali.
Untuk meringkas: Koneksi bersamaan dengan MySQL menyebabkan 2006, 'MySQL server has gone away'
dan beberapa kesalahan aneh lainnya. Tidak ada relevansi dalam log kesalahan MySQL.
Saya telah bekerja di ini selama berjam-jam dan belum membuat kemajuan. Bisakah seseorang membantu saya?
Jawaban:
Saya juga mengalami ini dan menemukan alasan dan memperbaikinya.
Alasan ini terjadi adalah bahwa plugin python uwsgi (atau lebih mungkin semua plugin uwsgi) fork () pekerja baru setelah aplikasi dimuat di induk. Akibatnya, anak-anak mewarisi semua sumber daya (termasuk deskriptor file seperti koneksi db) dari orang tua.
Anda dapat membaca tentang ini secara singkat di uwsgi wiki :
Dan seperti yang Anda ketahui, koneksi mysqldb dan kursor Python bukan threadsafe kecuali Anda secara eksplisit melindunginya. Oleh karena itu banyak proses (seperti pekerja uwsgi) menggunakan koneksi mysql yang sama / kursor secara bersamaan akan merusaknya.
Dalam kasus saya (untuk API Emas Raja Arthur ) ini berfungsi dengan baik ketika saya membuat koneksi MySQL per-permintaan dalam ruang lingkup modul lain, tetapi ketika saya ingin koneksi terus-menerus untuk membantu dengan kinerja saya memindahkan koneksi database dan kursor ke lingkup global di modul induk. Akibatnya, koneksi saya saling menginjak seperti milik Anda.
Cara mengatasinya adalah dengan menambahkan kata kunci "lazy" (atau - baris perintah command) ke konfigurasi uwsgi Anda. Akibatnya, aplikasi akan bercabang lagi untuk setiap anak alih-alih bercabang dari orang tua dan berbagi koneksi (dan menginjaknya di beberapa titik, sehingga server MySQL memaksa itu ditutup karena permintaan yang korup di beberapa titik).
Terakhir, jika Anda menginginkan cara untuk melakukan ini tanpa mengubah konfigurasi uwsgi Anda, Anda mungkin dapat menggunakan dekorator @postfork untuk membuat koneksi database baru dengan benar segera setelah proses pekerja bercabang dua. Anda dapat membaca tentang itu di sini .
Saya melihat dari tindak lanjut Anda bahwa Anda sudah beralih ke pgsql, tetapi inilah jawabannya sehingga Anda dapat tidur lebih nyenyak di malam hari dan bagi siapa pun seperti Anda dan saya mencoba menemukan jawabannya!
PS Suatu ketika saya memiliki pemahaman tentang masalah (kursor rusak karena pekerja saling menginjak) tetapi tidak menyadari sedikit tentang garpu () dan - lazy, saya sedang mempertimbangkan menerapkan kolam saya sendiri di mana pekerja akan " periksa "koneksi mysql dari kumpulan pada lingkup global, lalu" periksa kembali "tepat sebelum keluar dari aplikasi (), namun sepertinya jauh lebih baik untuk menggunakan --lazy kecuali jika beban web / aplikasi Anda cukup bervariasi sehingga Anda selalu menciptakan pekerja baru. Bahkan kemudian saya mungkin lebih suka - lazy karena jauh lebih bersih daripada menerapkan kolam koneksi db Anda sendiri.
sunting: berikut ini adalah penyelesaian yang lebih menyeluruh dari solusi + masalah ini karena ada kekurangan informasi tentangnya untuk orang lain yang telah mengalaminya: http://tns.u13.net/?p=190
sumber
ping
danmysqladmin
permintaan lainnya . Itu mungkin karena saya mencoba untuk menjatuhkan database dari shell ... tetapi terus memberikan kesalahan "server telah hilang" untuk perintah itu. Bagaimanapun, terima kasih!