محتوای آموزشی وبلاگ نتآرام
سایت جنگو گاهی هنگام ذخیره فرم یا اجرای یک کار زمانبندیشده خطای
database is locked میدهد. SQLite اطلاعات را در فایل نگه میدارد و برای نوشتن از قفل استفاده میکند. اگر یک کار نوشتن را برای مدت طولانی نگه دارد یا چند کار همزمان بخواهند بنویسند، درخواست دیگری ممکن است تا پایان زمان انتظار موفق نشود.این خطا به معنی ضرورت حذف فایل دیتابیس یا ایجاد دوباره آن نیست. ابتدا مطمئن میشویم برنامه واقعاً از SQLite استفاده میکند، از داده نسخه قابل بازیابی میگیریم و زمان و علت تداخل را پیدا میکنیم. بعد بسته به شرایط، مدت تراکنش، زمان اجرای کارها یا نوع دیتابیس را اصلاح میکنیم.
۱. زمان خطا و دیتابیس فعال را مشخص کنید
در پنل برنامه، گزارش خطای همان برنامه را برای زمان مشکل ببینید. ثبت کنید خطا هنگام ورود، ذخیره فرم، کار دورهای یا چند درخواست همزمان رخ داده است. اگر خطای اصلی
Permission denied یا پرشدن فضاست، راه آن با قفل SQLite فرق دارد. اطلاعات کاربران و رمزها را در گزارش عمومی منتشر نکنید.در Terminal یا SSH حساب، محیط مجازی همان برنامه را با فرمانی که پنل Setup Python App نمایش میدهد فعال کنید. سپس به پوشه دارای
کد / دستورmanage.py بروید؛ مسیر زیر نمونه است:cd ~/myproject
pwd
ls -la manage.py
برای مشاهده موتور و نام تنظیمشده دیتابیس پیشفرض، در همان محیط:
کد / دستورpython manage.py shell -c 'from django.conf import settings; d=settings.DATABASES["default"]; print("engine:", d["ENGINE"]); print("name:", d["NAME"])'
اگر موتور به
django.db.backends.sqlite3 اشاره میکند، این راهنما مرتبط است. مسیر یا نام دیتابیس میتواند خصوصی باشد؛ آن را بیدلیل منتشر نکنید. متغیرهای محیطی ترمینال و برنامه وب ممکن است متفاوت باشند؛ نام تنظیمات فعال را با پنل تطبیق دهید. اگر برنامه MySQL یا PostgreSQL استفاده میکند، قفل آنها قواعد دیگری دارد.۲. پیش از تغییر، پشتیبان قابل بازیابی تهیه کنید
فایل SQLite و داده سایت را حذف نکنید و فایلهای جانبی آن را هنگام اجرای برنامه کورکورانه پاک نکنید. کپی ساده یک فایل در زمان نوشتن فعال، بسته به حالت journal و زمان کپی، ممکن است نسخه سازگار موردنیاز شما را ندهد. از روش پشتیبان آنلاین SQLite یا روش پشتیبان تأییدشده سرویس استفاده کنید و نتیجه را در محیط جداگانه آزمایش کنید.
اگر ابزار
کد / دستورsqlite3 روی محیط آزمایشی در دسترس و مسیر فایل واقعی تأیید شده است، قابلیت .backup میتواند یک نسخه سازگار بسازد. برای روشنشدن شکل دستور، مسیرهای زیر فقط نمونهاند:test -f /home/USER/myproject/db.sqlite3 && \
sqlite3 /home/USER/myproject/db.sqlite3 '.backup /home/USER/private-backups/db-before.sqlite3'
نام کاربر و مسیرها را با مقادیر واقعی، بدون اطلاعات عمومی، جایگزین کنید. پوشه مقصد باید خصوصی، موجود، قابل نوشتن و دارای فضای کافی باشد و نام فایل مقصد نباید روی تنها نسخه پشتیبان قبلی بیفتد. اگر فایل مبدأ را با مسیر اشتباه باز کنید، ابزارها ممکن است یک پایگاه داده تازه بسازند؛ قبل از فرمان دوم وجود و هویت فایل را حتماً تأیید کنید. اگر ابزار یا روش مناسب را نمیشناسید، از پنل یا پشتیبانی برای تهیه پشتیبان سازگار کمک بگیرید.
۳. نوشتنهای همزمان و تراکنش طولانی را پیدا کنید
زمان خطا را با اجرای Cron، واردکردن داده، ارسال گزارش و درخواستهای کاربران مقایسه کنید. اگر دو کار مشابه همزمان اجرا میشوند، برنامه زمانبندی را طوری اصلاح کنید که کار جدید پس از پایان قبلی آغاز شود؛ فقط همان کار مشخص را پس از شناخت اثر آن تغییر دهید. خاموشکردن همه Cronهای حساب میتواند کارهای ضروری دیگر را متوقف کند.
در کد، به بخشهایی که با
کد / دستورtransaction.atomic() کار میکنند توجه کنید. نگهداشتن تراکنش حین یک تماس شبکه کند یا پردازش طولانی میتواند زمان قفل را زیاد کند. یک الگوی قابل بررسی این است که کار کندی که واقعاً وابسته به تراکنش نیست پیش از بخش کوتاه نوشتن انجام شود:result = get_external_result() # زمان انتظار و خطا برای این تابع لازم است
with transaction.atomic():
save_result(result)
این قطعه فقط شکل ایده را نشان میدهد؛ نام توابع و کنترل خطا باید مطابق برنامه شما پیادهسازی شوند. اگر عملیات بیرونی و ذخیره داده باید با هم تضمین خاصی داشته باشند، جابهجایی آنها بدون طراحی میتواند ناسازگاری ایجاد کند. پس تغییر را ابتدا در نسخه آزمایشی و با سناریوی واقعی بررسی کنید.
۴. زمان انتظار را فقط بهعنوان کمک موقت تنظیم کنید
اگر نوشتنها معمولاً سریع تمام میشوند و تداخل کوتاه است، Django برای SQLite امکان تعیین زمان انتظار اتصال را دارد. نمونه تنظیم:
کد / دستورDATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
"OPTIONS": {"timeout": 20},
}
}
این نمونه را جایگزین بیفکر کل تنظیمات پروژه نکنید؛ مسیر و گزینههای موجود خودتان را حفظ کنید. مقدار
20 ثانیه یک مثال است. انتظار بیشتر میتواند به قفل کوتاه فرصت پایان بدهد، اما علت تراکنش طولانی یا حجم زیاد نوشتن همزمان را درمان نمیکند و ممکن است پاسخ کاربر را کندتر کند. در نسخه آزمایشی، زمان پاسخ و نرخ خطا را قبل و بعد مقایسه کنید.پس از تغییر تأییدشده، برنامه مربوط را از پنل Restart و همان فرم یا کار آزمایشی را دوباره اجرا کنید. داده واقعی را چند بار ثبت نکنید؛ آزمون باید با حساب و رکورد آزمایشی قابل کنترل باشد.
۵. اگر بار نوشتن از توان SQLite بیشتر است
برای برنامهای با نوشتن همزمان زیاد، یک پایگاه داده سروری مانند PostgreSQL یا MySQL ممکن است مناسبتر باشد. این یک تغییر معماری و مهاجرت داده است، نه یک گزینه فوری برای پاککردن خطا. قبل از انتقال، نسخه پشتیبان قابل بازیابی بگیرید، موتور و نسخه مقصد و افزونههای پروژه را بررسی کنید و فرآیند انتقال را روی یک پایگاه داده آزمایشی تمرین کنید. تعداد رکوردها، کاراکترهای فارسی، کلیدها، ورود کاربران و عملیات واقعی را پس از انتقال بسنجید. تا زمان تأیید، دیتابیس قبلی و مسیر بازگشت را نگه دارید.
گزینههایی مانند تغییر journal mode یا فعالکردن WAL هم باید با محل ذخیره فایل، محدودیت محیط و مستندات نسخه SQLite بررسی شوند؛ بهویژه برخی فایلسیستمهای شبکه برای این طراحی مناسب نیستند. حذف فایل WAL یا خاموشکردن قفل برای ساکتکردن خطا میتواند به داده آسیب بزند.
برای انتخاب محیط مناسب، صفحه هاست پایتون نتآرام و راهنمای نیازهای Worker برنامه را ببینید. توضیح محدودیت همزمانی و گزینه timeout در مستندات پایگاه داده Django و روش پشتیبان در مستند SQLite آمده است.
اشتراکگذاری:
لینکدینتلگرامایکس
مقاله قبلی
مقاله بعدی
دیدگاهها (۰)
دیدگاههای تاییدشده و پاسخهای تیم نتآرام
