Mengutip "Bagaimana cara menggunakan mesin/koneksi/sesi dengan multiprosesor Python, atau os.fork()?" dengan penekanan tambahan:
Objek SQLAlchemy Engine mengacu pada kumpulan koneksi koneksi database yang ada. Jadi saat objek ini direplikasi ke proses anak, tujuannya adalah memastikan bahwa tidak ada koneksi database yang dibawa .
dan
Namun, untuk kasus Sesi atau Koneksi aktif-transaksi yang dibagikan, tidak ada perbaikan otomatis untuk ini; aplikasi perlu memastikan proses anak baru hanya memulai objek dan transaksi Koneksi baru, serta objek Sesi ORM.
Masalah ini berasal dari proses turunan bercabang yang mewarisi session
global langsung , yang memegang Connection
. Ketika target
memanggil init
, itu menimpa referensi global ke engine
dan session
, sehingga mengurangi penghitungan ulang mereka menjadi 0 pada anak, memaksa mereka untuk menyelesaikan. Jika Anda misalnya dengan satu atau lain cara membuat referensi lain ke sesi yang diwarisi pada anak, Anda mencegahnya dibersihkan – tetapi jangan lakukan itu. Setelah main
telah bergabung dan kembali ke bisnis seperti biasa mencoba menggunakan koneksi yang sekarang berpotensi diselesaikan - atau tidak sinkron. Saya tidak yakin mengapa ini menyebabkan kesalahan hanya setelah sejumlah iterasi.
Satu-satunya cara untuk menangani situasi ini menggunakan global seperti yang Anda lakukan adalah dengan
- Tutup semua sesi
- Panggil
engine.dispose()
sebelum garpu. Ini akan mencegah koneksi bocor ke anak. Misalnya:
def main():
global session
init()
try:
dummy = Dummy(value=1)
session.add(dummy)
session.commit()
dummy_id = dummy.id
# Return the Connection to the pool
session.close()
# Dispose of it!
engine.dispose()
# ...or call your cleanup() function, which does the same
p = multiprocessing.Process(target=target, args=(dummy_id,))
p.start()
p.join()
# Start a new session
session = Session()
dummy = session.query(Dummy).get(dummy_id)
assert dummy.value == 2
finally:
cleanup()
Contoh kedua Anda tidak memicu finalisasi pada anak, dan sepertinya itu hanya berfungsi, meskipun mungkin rusak seperti yang pertama, karena masih mewarisi salinan sesi dan koneksi yang ditentukan secara lokal di main
.