2025, Oct 19 19:32

Django 3.2 में व्यू से बैकग्राउंड थ्रेड पर ORM चलाने पर MySQL server has gone away क्यों आता है और समाधान

जानें क्यों Django 3.2 में व्यू से बैकग्राउंड थ्रेड पर synchronous ORM चलाने से MySQL server has gone away त्रुटि आती है, और प्रोडक्शन का सुरक्षित समाधान क्या है.

Django 3.2 के किसी view से बैकग्राउंड थ्रेड में डेटाबेस लिखना उस समय आकर्षक लग सकता है जब आप HTTP प्रतिक्रियाएँ तुरंत लौटाना चाहते हैं। लेकिन synchronous ORM कॉल्स को ad‑hoc थ्रेड्स के साथ जोड़ना अक्सर MySQL के “server has gone away” जैसे एरर पर खत्म होता है। नीचे संक्षेप में बताया गया है कि ऐसा क्यों होता है और इस संदर्भ में सुरक्षित, प्रोडक्शन‑रेडी दिशा कैसी दिखती है।

समस्या दोहराने का तरीका

एप्लिकेशन स्टैक: Python 3 पर Django 3.2.x, MySQL, और सर्विंग uWSGI + Nginx के जरिए। व्यू तुरंत रिटर्न कर देता है, जबकि बैकग्राउंड थ्रेड मॉडल लेयर में ORM काम शुरू कर देता है।

from django.http import HttpResponse
from django.db import models
import threading
# सहायक
def extract_request_params(request):
    return {}
# मॉडल
class JobRecord(models.Model):
    create_username = models.CharField(max_length=50, default='system')
    update_username = models.CharField(max_length=50, default='system')
    @classmethod
    def perform(cls, params):
        # ORM लॉजिक
        pass
# व्यू
class OpsView:
    @classmethod
    def trigger_job(cls, request):
        payload = extract_request_params(request)
        payload['user'] = request.user
        worker = threading.Thread(target=JobRecord.perform, args=(payload,))
        worker.start()
        return HttpResponse("Task run success")

निष्पादन के दौरान यह लक्षण दिखता है:

(2006, 'MySQL server has gone away')

टास्क के भीतर कनेक्शन को मजबूती से स्थापित करने की कोशिश भी की गई:

from django.db import connection
class JobRecord(models.Model):
    create_username = models.CharField(max_length=50, default='system')
    update_username = models.CharField(max_length=50, default='system')
    @classmethod
    def perform(cls, params):
        connection.ensure_connection()
        # ORM लॉजिक
        # ...
        connection.close()

लेकिन त्रुटि फिर भी आती है।

यह क्यों विफल होता है

Django 3.2 का ORM synchronous है। यह किसी अनुरोध हैंडलर से सीधे शुरू किए गए async या अलग बैकग्राउंड टास्क के रूप में ORM कार्य चलाने का समर्थन नहीं करता। व्यू के अंदर स्वतंत्र थ्रेड्स या प्रोसेसेज़ शुरू करने से डेटाबेस ऑपरेशंस Django के अपेक्षित निष्पादन मॉडल से कट जाते हैं, जिससे कनेक्शन हैंडलिंग अस्थिर हो जाती है और वही त्रुटि मिलती है जो आप देख रहे हैं। उस थ्रेड के भीतर ensure_connection को मैन्युअल रूप से कॉल करना या कनेक्शन बंद करना इस बुनियादी असंगति को ठीक नहीं करता।

सही दिशा

यहाँ सुरक्षित तरीका सीधा है: किसी व्यू के भीतर स्वतंत्र थ्रेड्स या प्रोसेसेज़ शुरू न करें। डेटाबेस ऑपरेशंस को उसी सामान्य, synchronous अनुरोध‑प्रतिक्रिया प्रवाह में रखें जिसके लिए Django 3.2 डिज़ाइन किया गया है।

from django.http import HttpResponse
from django.db import models
# सहायक
def extract_request_params(request):
    return {}
# मॉडल
class JobRecord(models.Model):
    create_username = models.CharField(max_length=50, default='system')
    update_username = models.CharField(max_length=50, default='system')
    @classmethod
    def perform(cls, params):
        # ORM लॉजिक
        pass
# बैकग्राउंड थ्रेड के बिना व्यू
class OpsView:
    @classmethod
    def trigger_job(cls, request):
        payload = extract_request_params(request)
        payload['user'] = request.user
        JobRecord.perform(payload)
        return HttpResponse("Task run success")

यह अलग थ्रेड को हटा देता है और ORM ऑपरेशंस को समर्थित, synchronous मार्ग में चलाता है, जिससे थ्रेडिंग दृष्टिकोण के कारण होने वाली “MySQL server has gone away” वाली विफलताएँ समाप्त हो जाती हैं।

इसकी परवाह क्यों करें

इस सेटअप में व्यू से ट्रिगर किए गए बैकग्राउंड थ्रेड नाज़ुक होते हैं। ये Django के ORM और MySQL साथ इस्तेमाल करते समय मिलने वाली गारंटियों को तोड़ देते हैं और बीच‑बीच में कनेक्शन एरर और खोए हुए काम तक ले जाते हैं। ORM को synchronous मार्ग पर रखना प्रोडक्शन में uWSGI + Nginx के तहत विश्वसनीयता और पूर्वानुमेयता बनाए रखता है।

स्टैक पर नोट्स

Django 3.2 काफी पुराना संस्करण है। यह बात अपने आप में यहाँ बताई समस्या को हल नहीं करती, लेकिन जिस रिलीज़ को आप लक्षित कर रहे हैं उसकी उम्र से अवगत रहना उपयोगी है।

निष्कर्ष

यदि आपकी Django 3.2 ऐप किसी व्यू से शुरू किए गए बैकग्राउंड थ्रेड में डेटाबेस काम करते समय “(2006, 'MySQL server has gone away')” पर टकराती है, तो समाधान है: व्यू से थ्रेड्स या प्रोसेसेज़ शुरू करना बंद करें। ORM ऑपरेशंस को अनुरोध चक्र के भीतर synchronous रखें। यही भरोसेमंद तरीका है अस्थायी MySQL डिसकनेक्ट्स को रोकने और यह सुनिश्चित करने का कि आपकी डेटा लिखाइयाँ सही तरह निष्पादित हों।

यह लेख StackOverflow के एक प्रश्न (Dylan द्वारा) और Dylan के उत्तर पर आधारित है।