SQLite در production روی VPS؛ مناسب چه برنامههایی است؟
برای اجرای SQLite در production روی یک VPS، WAL، busy_timeout و replication با Litestream را تنظیم کنید و محدودیت یک writer و یک فایل را بشناسید.
چه زمانی SQLite پایگاهداده مناسب برای production روی VPS است
اجرای SQLite در production روی VPS برای بیشتر برنامههای کوچک انتخاب مناسبی است. دلیل آن ساده است: فرایندی که روی یک ماشین، یک فایل را مینویسد، به database server نیاز ندارد. daemonی برای نظارت وجود ندارد، پورتی برای قراردادن پشت firewall وجود ندارد، passwordی برای تعویض وجود ندارد و ماشین دومی لازم نیست فعال نگه داشته شود. query بهجای یک رفتوبرگشت شبکه، یک فراخوانی تابع است. بنابراین صفحهای که چهل query اجرا میکند، برای شما هزینه چهل فراخوانی تابع را دارد.
این انتخاب محدودیتهای مشخص و واقعی دارد. SQLite در سراسر یک فایل database، در هر لحظه فقط یک writer را مجاز میداند و فایل را نمیتوان بین دو ماشین بهاشتراک گذاشت. هر دو محدودیت برای یک VPS که یک برنامه واحد را اجرا میکند، قابلقبول هستند. اما بهمحض اینکه از این الگو فراتر بروید، هر دو محدودیت مشکلساز میشوند. این راهنما تنظیماتی را پوشش میدهد که SQLite را روی یک server ایمن میکنند، پشتیبانگیری پیوسته با Litestream را توضیح میدهد و نقطهای را مشخص میکند که باید استفاده از آن را متوقف کنید.
ابتدا ابزار command line را نصب کنید. همه دستورهای زیر روی Ubuntu 24.04 اجرا شدهاند.
sudo apt update
sudo apt install -y sqlite3
sqlite3 --versionاین دستور نسخهای را نمایش میدهد که با 3. شروع میشود و پس از آن تاریخ build و یک source hash قرار دارد. Ubuntu 24.04 تا July 2026 نسخه SQLite 3.45.1 را ارائه میکند. احتمالاً برنامه شما از این binary استفاده نمیکند: بیشتر runtimeهای زبان، نسخه مخصوص خود را از SQLite library همراه دارند که اغلب جدیدتر است. بنابراین پیش از اتکا به یک feature جدید، نسخهای را که database driver شما گزارش میکند بررسی کنید.
چرا حالت WAL اولین تغییری است که اعمال میکنید
بهصورت پیشفرض، SQLite از rollback journal استفاده میکند. پیش از تغییر یک page، نسخه اصلی آن را در یک فایل -journal کپی میکند و سپس پایگاهداده را در محل خود ویرایش میکند. برای انجام ایمن این کار، یک قفل انحصاری روی کل فایل میگیرد؛ بنابراین هنگام اجرای هر عملیات نوشتن، همه خوانندهها منتظر میمانند. در یک laptop کسی متوجه این تأخیر نمیشود. اما در یک web server، یک عملیات نوشتنِ کند، هر درخواستی را که به پایگاهداده دسترسی دارد متوقف میکند.
حالت WAL (write-ahead log) این ترتیب را معکوس میکند. نویسنده pageهای جدید را به یک فایل -wal جداگانه اضافه میکند و فایل پایگاهداده اصلی را بدون تغییر باقی میگذارد. خوانندهها همچنان فایل اصلی را در snapshotای که هنگام شروع ایجاد کردهاند میخوانند؛ بنابراین خوانندهها نویسنده را مسدود نمیکنند و نویسنده نیز خوانندهها را مسدود نمیکند. بعداً، یک checkpoint، pageهای انباشتهشده در WAL را به پایگاهداده اصلی کپی میکند. این تغییر، بخش عمدهای از چیزی است که SQLite را برای استفاده پشت یک web application مناسب میکند.
فعالسازی حالت WAL و تأیید پایدار ماندن آن
mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"این فرمان wal را چاپ میکند. این خروجی تزئینی نیست. PRAGMA journal_mode حالتی را برمیگرداند که پایگاهداده واقعاً در آن قرار دارد؛ بنابراین پاسخ delete یعنی تغییر ناموفق بوده و هنوز از journal بازگشت استفاده میکنید.
حالت WAL پایدار است. این حالت یک پرچم در header پایگاهداده است، نه یک تنظیم اتصال. بنابراین آن را برای هر فایل پایگاهداده فقط یکبار اجرا میکنید و همه اتصالهای بعدی، حتی پس از راهاندازی مجدد، آن را به ارث میبرند. این موضوع را با یک اتصال جدید اثبات کنید.
sqlite3 ~/app/app.db "PRAGMA journal_mode;"اکنون یک جدول ایجاد کنید و ببینید روی دیسک چه چیزی ایجاد میشود.
sqlite3 ~/app/app.db <<'SQL'
CREATE TABLE IF NOT EXISTS notes (id INTEGER PRIMARY KEY, body TEXT NOT NULL);
INSERT INTO notes (body) VALUES ('first row');
SQL
ls -l ~/app/اکنون سه فایل وجود دارد: app.db، app.db-wal و app.db-shm. فایل -wal صفحاتی را نگه میدارد که commit شدهاند اما هنوز checkpoint نشدهاند. فایل -shm یک index حافظه مشترک است که همه اتصالها آن را map میکنند تا درباره محتوای WAL توافق داشته باشند. هر دو فایل متعلق به پایگاهداده هستند و فایل موقت محسوب نمیشوند. اگر هنگام اجرای برنامه فقط app.db را کپی کنید، فایلی به دست میآورید که همه commitهای اخیر را ندارد. اگر app.db را حذف کنید و دو فایل دیگر را باقی بگذارید، SQLite صفحات قدیمی WAL را روی هر فایل جدیدی که با آن نام ایجاد شود اعمال میکند. به این ترتیب، هنگام تلاش برای بازنشانی پایگاهداده، یک پایگاهداده تازه را خراب میکنند.
تنظیمات اتصال موردنیاز هر برنامه در محیط production
فقط journal_mode در پایگاه داده ذخیره میشود. همه تنظیمات دیگر در ادامه، برای هر اتصال جداگانه هستند. بنابراین برنامه شما باید آنها را روی هر اتصالی که باز میکند اجرا کند؛ این مورد شامل هر اتصالی نیز میشود که یک pool در پسزمینه ایجاد میکند.
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;busy_timeout = 5000 به SQLite میگوید تا پیش از بازگرداندن database is locked، حداکثر بهمدت 5000 میلیثانیه تلاش برای دسترسی به پایگاه داده قفلشده را ادامه دهد. مقدار پیشفرض 0 است. بنابراین SQLite بهطور پیشفرض، نخستین بار که دو عملیات نوشتن با هم همپوشانی پیدا میکنند، بلافاصله خطا میدهد. تنظیم همین یک مقدار، بیشتر خطاهای قفلشدن را که معمولاً به خود SQLite نسبت داده میشوند برطرف میکند.
synchronous = NORMAL تنظیم مناسب در حالت WAL است و باید پیامد آن را درک کنید. در FULL، SQLite در هر commit، روی WAL عملیات fsync را اجرا میکند. در NORMAL، همگامسازی در زمان checkpoint انجام میشود. مستندات SQLite درباره چیزی که از دست میدهید صریح هستند: پس از قطع برق یا reset سختافزاری، تراکنشها دیگر پایدار نیستند. قطع برق نمیتواند پایگاه داده را خراب کند؛ فقط commitهای آخری را از دست میدهید که هنوز روی دیسک نوشته نشدهاند. در یک VPS، این معمولاً انتخاب مناسبی است، زیرا اجرای fsync را از مسیر هر عملیات نوشتن حذف میکند.
foreign_keys = ON برای سازگاری با نسخههای قبلی، بهطور پیشفرض خاموش است و برای هر اتصال جداگانه اعمال میشود. یک schema که مملو از عبارتهای REFERENCES باشد، تا زمانی که هر اتصال این گزینه را فعال نکند، هیچ الزامی را اعمال نمیکند.
یک تنظیم دیگر فقط در ادامه اهمیت پیدا میکند. SQLite هنگامی که اندازه WAL از 1000 page بیشتر شود، بهطور خودکار checkpoint اجرا میکند. این کار را اتصالی انجام میدهد که در همان لحظه، بهطور تصادفی یک تراکنش را به پایان میرساند. این وضعیت بهخودیخود مشکلی ندارد. اما هنگام اجرای Litestream، موضوع اهمیت پیدا میکند، زیرا Litestream میخواهد زمان اجرای checkpointها را کنترل کند.
چرا database is locked پس از تنظیم busy_timeout همچنان رخ میدهد
این همان خطایی است که کاربران را دوباره به Postgres برمیگرداند و یک علت مشخص دارد.
تنظیم busy timeout یک busy handler نصب میکند، اما SQLite تضمین نمیکند که آن را فراخوانی کند.
اگر SQLite تشخیص دهد که فراخوانی busy handler ممکن است باعث بنبست شود، بهجای فراخوانی busy handler، مستقیماً SQLITE_BUSY را به برنامه برمیگرداند.
بنبستی که SQLite از آن جلوگیری میکند، هنگام ارتقای تراکنش رخ میدهد. یک BEGIN ساده در SQLite به معنای BEGIN DEFERRED است. اگر نخستین دستور پس از آن یک SELECT باشد، در یک تراکنش خواندن قرار دارید. اگر یک UPDATE بعدی در همان تراکنش نیاز داشته باشد به تراکنش نوشتن تبدیل شود، و اتصال دیگری پس از آغاز خواندن شما دادهای نوشته باشد، SQLite نمیتواند شما را منتظر نگه دارد؛ زیرا snapshot شما دیگر بهروز نیست و انتظار کشیدن فقط باعث میشود دو اتصال در برابر یکدیگر دچار بنبست شوند. مستندات نتیجه را مستقیماً بیان میکنند:
دستورهای نوشتن بعدی، در صورت امکان، تراکنش را به تراکنش نوشتن ارتقا میدهند؛ در غیر این صورت SQLITE_BUSY را برمیگردانند.
timeout شما که روی 5000 میلیثانیه تنظیم شده است، هرگز بررسی نمیشود. خطا فوراً برمیگردد و به همین دلیل به نظر میرسد تنظیم انجامشده بیاثر بوده است.
راهحل فقط یک کلمه است.
BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;BEGIN IMMEDIATE قفل نوشتن را در ابتدای کار و پیش از هرگونه خواندن میگیرد. بنابراین ارتقایی وجود ندارد، بنبستی برای جلوگیری وجود ندارد و busy handler اعمال میشود. در نتیجه اتصال بهجای شکستخوردن، نوبت خود را منتظر میماند. تراکنشهای فقطخواندنی را deferred نگه دارید. هر تراکنشی که شامل نوشتن است باید immediate باشد.
دومین علت خطاهای قفل دشوارتر شناسایی میشود: باز نگهداشتن تراکنش نوشتن هنگام انجام کارهای کند. SQLite عملیات نوشتن را سریالی میکند. بنابراین تراکنشی که باز میشود، از طریق شبکه یک API خارجی را فراخوانی میکند و سپس commit میشود، تمام نویسندههای دیگر را برای مدت آن فراخوانی مسدود میکند. دادههای موردنیاز را بخوانید، تراکنش را ببندید، کار کند را انجام دهید، سپس یک تراکنش نوشتن کوتاه باز کنید و نتیجه را ذخیره کنید.
پشتیبانگیری پیوسته با Litestream
یک کپی شبانه میتواند حداکثر یک روز از عملیات نوشتن را از دست بدهد. اجرای cp روی یک پایگاهداده SQLite فعال نیز ممکن است کپیای ایجاد کند که باز نمیشود. دو روش ایمن وجود دارد. sqlite3 app.db ".backup /path/to/backup.db" از رابط پشتیبانگیری آنلاین SQLite استفاده میکند و روی پایگاهدادهای که در حال استفاده است کار میکند. Litestream یک گام فراتر میرود: WAL را پایش میکند و تغییرات را بهطور پیوسته به فضای ذخیرهسازی اشیاء ارسال میکند. در نتیجه، بیشترین میزان از دست رفتن داده از یک روز به حدود یک ثانیه کاهش مییابد.
Litestream یک باینری Go است که در کنار برنامه شما اجرا میشود. بین برنامه و پایگاهداده قرار نمیگیرد. برنامه شما مانند قبل در SQLite مینویسد و Litestream، WAL را میخواند و تغییرات را بارگذاری میکند.
cd /tmp
curl -fsSL -O https://github.com/benbjohnson/litestream/releases/download/v0.5.14/litestream-0.5.14-linux-x86_64.deb
sudo dpkg -i litestream-0.5.14-linux-x86_64.deb
litestream versionنسخه v0.5.14 همان نسخهای است که صفحه رسمی نصب Linux تا ژوئیه 2026 مستند کرده است. نسخه v0.5.15 نیز در 21 ژوئیه 2026 منتشر شد. نسخه را در هر دو خط با برچسب فعلی در صفحه انتشارها مطابقت دهید. اگر VPS شما arm64 است، بسته arm64 متناظر را انتخاب کنید.
فایل پیکربندی در مسیر /etc/litestream.yml قرار دارد. کار را با یک replica محلی آغاز کنید، زیرا این کار کل چرخه را بدون نیاز به اعتبارنامههای ابری آزمایش میکند.
dbs:
- path: /home/appuser/app/app.db
replica:
type: file
path: /var/backups/litestream/appتوجه کنید که فیلد replica مفرد است. Litestream 0.5 آرایه replicas را که در سری 0.3 استفاده میشد، با یک بلوک replica واحد جایگزین کرد. اکنون پیکربندیای که دو ورودی داشته باشد، هنگام راهاندازی با خطا مواجه میشود. بسیاری از راهنماهای شخص ثالث هنوز آرایه قدیمی را نشان میدهند. بنابراین بهجای نخستین نمونهای که در جستوجو پیدا میکنید، از ساختار بالا استفاده کنید. سری 0.5 همچنین زیرفرمان litestream wal را به litestream ltx تغییر نام داد، زیرا قالب پشتیبان ذخیرهشده روی دیسک تغییر کرده است.
پیش از فعالسازی هر قابلیت، بررسی کنید که پیکربندی تجزیه میشود.
sudo litestream databases -config /etc/litestream.ymlسپس رفتوبرگشت داده را بهصورت دستی آزمایش کنید. این شکل، فایل پیکربندی را نادیده میگیرد و یک پایگاهداده را در یک مسیر مشخص replica میکند.
mkdir -p /tmp/replica
litestream replicate ~/app/app.db file:///tmp/replica/appاین فرمان در پیشزمینه اجرا میشود و به اجرای خود ادامه میدهد. در یک shell دوم، یک ردیف بنویسید و replica را در فایلی جدید بازیابی کنید.
sqlite3 ~/app/app.db "INSERT INTO notes (body) VALUES ('written after replication started');"
litestream restore -o /tmp/restored.db file:///tmp/replica/app
sqlite3 /tmp/restored.db "SELECT count(*) FROM notes;"این شمارش شامل ردیف جدید است. اگر چنین نیست، تغییر هنوز همگامسازی نشده است. Litestream در یک sync-interval ارسال را انجام میدهد که مقدار پیشفرض آن 1 ثانیه است. بنابراین کمی صبر کنید و دوباره بازیابی را انجام دهید. این 1 ثانیه، نقطه بازیابی شما نیز محسوب میشود. در صورت خرابی، حداکثر نوشتنهای مربوط به آخرین بازه همگامسازی از دست میروند و هیچ پیکربندیای این مقدار را به صفر نمیرساند.
برای ذخیرهسازی واقعی، بلوک replica را با یک URL مربوط به S3 جایگزین کنید. این روش با Amazon S3 و همچنین با فضای ذخیرهسازی اشیای سازگار با S3 از ارائهدهندگان دیگر کار میکند.
dbs:
- path: /home/appuser/app/app.db
replica:
url: s3://your-bucket-name/app
region: us-east-1
snapshot:
interval: 24h
retention: 24hاعتبارنامهها را در این فایل قرار ندهید. Litestream متغیرهای LITESTREAM_ACCESS_KEY_ID و LITESTREAM_SECRET_ACCESS_KEY را از محیط میخواند. بنابراین آنها را در یک systemd drop-in قرار دهید که مالک آن root باشد و mode آن 600 تنظیم شود.
مقادیر snapshot بالا پیشفرض هستند، اما مقدار پیشفرض retention ممکن است شگفتآور باشد. Retention مدتزمانی است که Litestream snapshotها و فایلهای متعلق به آنها را نگه میدارد. بنابراین مشخص میکند تا چه زمانی در گذشته امکان بازیابی دارید. 24 ساعت یعنی اگر یک migration معیوب را صبح چهارشنبه متوجه شوید، دیگر امکان بازیابی وضعیت دوشنبه از این منبع وجود ندارد. retention: 168h را روی یک هفته تنظیم کنید و هزینه فضای ذخیرهسازی اضافی را بپذیرید.
پیش از نیاز، بازیابی را آزمایش کنید
litestream restore -o /tmp/check.db /home/appuser/app/app.db
sqlite3 /tmp/check.db "PRAGMA integrity_check;"
sqlite3 /tmp/check.db "SELECT count(*) FROM notes;"با دریافت مسیر پایگاه داده، litestream restore نسخه همسان را در /etc/litestream.yml پیدا میکند و آن را دریافت میکند. PRAGMA integrity_check در صورت سالم بودن فایل، ok را چاپ میکند و هر خروجی دیگری به این معناست که نسخه بازیابیشده قابل استفاده نیست. این کار را طبق یک زمانبندی و با استفاده از یک سرویس و زمانسنج systemd اجرا کنید و خروجی را بخوانید. تا زمانی که یکبار نسخه پشتیبان را بازیابی نکرده باشید، نمیدانید که کار میکند.
اجرای Litestream تحت systemd
بسته Debian یک واحد litestream نصب میکند که /etc/litestream.yml را میخواند.
sudo systemctl enable litestream
sudo systemctl start litestream
sudo journalctl -u litestream -fدر خروجی سالم، نام هر پایگاهداده از پیکربندی نمایش داده میشود و سپس، بهجز خطوط همگامسازی دورهای، خروجی دیگری تولید نمیشود. خطای no such file or directory درباره مسیر پایگاهداده شما یعنی مسیر موجود در پیکربندی نادرست است یا فرایند اجازه خواندن آن را ندارد. واحد بهطور پیشفرض با حساب root اجرا میشود، اما این کار به چنین سطح دسترسیای نیاز ندارد. Litestream باید بتواند هم پایگاهداده و هم پوشه حاوی آن را بخواند و در آن بنویسد، زیرا با فایلهای -wal و -shm کنار پایگاهداده شما کار میکند. بنابراین، حسابی را به آن اختصاص دهید که برنامه شما از قبل استفاده میکند.
# /etc/systemd/system/litestream.service.d/override.conf
[Service]
User=appuser
Group=appuserآن را با sudo systemctl daemon-reload و sudo systemctl restart litestream اعمال کنید. راهاندازی یک حساب سرویس اختصاصی با حداقل سطح دسترسی فقط چند دقیقه زمان میبرد و تفاوت میان یک عامل پشتیبانگیری و یک فرایند root دیگر روی سرور است.
اگر زمانی ماشین را از ابتدا بازسازی کنید، ترتیب اجرای کارها اهمیت دارد. باید پایگاهداده پیش از شروع برنامه بازیابی شود. litestream restore گزینه -if-db-not-exists را میپذیرد؛ این گزینه زمانی که فایل از قبل وجود داشته باشد با کد خروجی 0 خارج میشود، بنابراین اجرای آن در هر بار راهاندازی امن است. آن را در خط ExecStartPre واحد برنامه خود قرار دهید تا یک VPS تازه پایگاهداده را دریافت کند و یک نمونه موجود هیچ کاری انجام ندهد. اگر ترجیح میدهید این تنظیم را در یک مکان نگه دارید، litestream replicate پرچم متناظر -restore-if-db-not-exists را نیز دارد.
مواردی که SQLite روی VPS دچار محدودیت میشود
فایلسیستمهای شبکهای. این محدودیتی است که نمیتوانید با پیکربندی از آن عبور کنید. حالت WAL به این نیاز دارد که هر فرایند استفادهکننده از پایگاهداده، یک ناحیه کوچک از حافظه را بهصورت مشترک استفاده کند؛ فایل -shm این ناحیه را فراهم میکند. مستندات SQLite این قانون را بدون استثنا بیان میکند:
همه فرایندهایی که از یک پایگاهداده استفاده میکنند باید روی یک رایانه میزبان باشند؛ WAL روی فایلسیستم شبکهای کار نمیکند.
بنابراین پایگاهدادهای که روی یک NFS (network file system) یا اشتراک SMB نصب شده است ممکن است دچار خرابی شود و هیچ pragmaای از آن جلوگیری نمیکند. در اینجا تفاوتی وجود دارد که معمولاً نادیده گرفته میشود. یک دستگاه بلوک شبکهای، که بیشتر ارائهدهندگان VPS آن را بهعنوان فضای ذخیرهسازی اضافی متصل میکنند، برای Linux مانند یک دیسک معمولی با یک فایلسیستم معمولی دیده میشود و مشکلی ندارد. اما یک اشتراک فایل نصبشده چنین وضعیتی ندارد.
یک سرور application دوم. هیچ تنظیمی این وضعیت را قابلاجرا نمیکند. وقتی به 2 ماشین برای ارائه همان داده نیاز دارید، باید از پایگاهدادهای استفاده کنید که از طریق شبکه ارتباط برقرار میکند. این انتقال را زمانی تصمیمگیری کنید که هنوز برای برنامهریزی فرصت دارید.
بارهای کاری با نوشتن سنگین. وجود تنها 1 نویسنده در هر لحظه، ویژگی قالب فایل است و قابل تنظیم نیست. نوشتنهای کوتاه کمهزینه هستند، زیرا هر commit به انتهای WAL اضافه میشود؛ بنابراین توان عملیاتی بیشتر از CPU به تأخیر نوشتنهای کوچک دیسک وابسته است. برای مشاهده تفاوت آن، به مقایسه NVMe با فضای ذخیرهسازی SATA SSD در VPS مراجعه کنید. مشکل اصلی، تراکنشهای طولانی هستند، زیرا همه نویسندههای دیگر را پشت سر خود در صف قرار میدهند.
پرسوجوهای تحلیلی. SQLite یک row store است که برای تراکنشها ساخته شده است. داشبوردی که 100 میلیون ردیف را پیمایش میکند، کار متفاوتی است و به ابزار متفاوتی نیاز دارد. مقاله مقایسه DuckDB با SQLite برای کارهای سروری مشخص میکند این مرز کجا قرار دارد.
VACUUM هنگام replication. یک VACUUM کامل، کل فایل پایگاهداده را بازنویسی میکند؛ بنابراین Litestream باید دوباره تمام آن را upload کند. مستندات Litestream نیز توصیه میکند هنگام فعال بودن replication، این عملیات را در همان محل اجرا نکنید. replicator را متوقف کنید، vacuum را اجرا کنید، سپس آن را دوباره شروع کنید و انتظار یک snapshot کامل جدید را داشته باشید.
2 replicator روی یک پایگاهداده. هرگز 2 فرایند Litestream را روی یک پایگاهداده یا یک مقصد replica یکسان اجرا نکنید. مستندات صراحتاً بیان میکند که جلوگیری از این وضعیت بر عهده شماست و نتیجه آن replicaای است که نمیتوانید restore کنید.
Litestream چه مواردی را پوشش نمیدهد
Litestream از فایل پایگاهداده محافظت میکند و هیچ مورد دیگری را پوشش نمیدهد. فایلهای بارگذاریشده، پیکربندی برنامه، گواهیهای TLS (امنیت لایه انتقال) و فایلهای unit همگی همچنان بر عهده شما هستند. آن را طبق یک برنامه زمانبندیشده با پشتیبانگیریهای رمزگذاریشده خارج از سرور با restic ترکیب کنید تا هر دو بخش پوشش داده شوند. اگر ماشین جدید است، ده دقیقه نخست در یک VPS جدید ایجاد حساب کاربری و پیکربندی firewall را پوشش میدهد؛ این راهنما فرض میکند این کارها از قبل انجام شدهاند.
FAQ
آیا SQLite برای یک برنامه عملیاتی کافی است؟
برای یک برنامه روی یک سرور، بله؛ مشروط بر اینکه حالت WAL را فعال کنید، یک مهلت انتظار برای مشغولبودن تنظیم کنید و بهطور پیوسته نسخه پشتیبان بگیرید. محدودیتهای مهم، ساختاری هستند: در هر لحظه فقط یک نویسنده و فقط یک ماشین میزبان. برنامهای که در این محدودهها قرار بگیرد، پایگاهدادهای بدون پرش شبکه و بدون فرایند جداگانه برای پایش در اختیار خواهد داشت. برنامهای که در این محدودهها قرار نگیرد، به پایگاهداده client-server نیاز دارد و هیچ مقدار tuning این واقعیت را تغییر نمیدهد.
چرا بعد از تنظیم busy_timeout همچنان database is locked دریافت میکنم؟
زیرا SQLite زمانی که انتظار میتواند باعث بنبست شود، busy handler را اجرا نمیکند. تراکنشی که با یک BEGIN ساده آغاز میشود، deferred است: یک SELECT ابتدایی آن را وارد تراکنش خواندن میکند و یک نوشتن بعدی باید سطح تراکنش را ارتقا دهد. اگر اتصال دیگری در این فاصله نوشتن انجام داده باشد، SQLite بهجای فراخوانی busy handler شما، فوراً SQLITE_BUSY را برمیگرداند؛ زیرا snapshot خواندن شما دیگر تازه نیست. هر تراکنشی را که قرار است نوشتن انجام دهد با BEGIN IMMEDIATE آغاز کنید تا قفل نوشتن از ابتدا گرفته شود و timeout اعمال شود.
آیا میتوانم پایگاهداده SQLite را روی فضای ذخیرهسازی شبکه نگه دارم؟
روی فایلسیستم شبکهای مانند NFS یا SMB، خیر. حالت WAL به همه فرایندها نیاز دارد که از طریق فایل -shm حافظه را بهاشتراک بگذارند، و مستندات SQLite تصریح میکند که هر فرایندی که از پایگاهداده استفاده میکند باید روی همان رایانه میزبان باشد. یک دستگاه block شبکهای که ارائهدهنده شما به سیستم متصل میکند، موضوع متفاوتی است: Linux آن را بهصورت یک دیسک عادی با یک فایلسیستم عادی میبیند و SQLite در آنجا کار میکند.
اگر از قبل هر شب نسخه پشتیبان میگیرم، آیا به Litestream نیاز دارم؟
این موضوع به مقدار دادهای بستگی دارد که میتوانید از دست بدهید. یک کار زمانبندیشده شبانه به معنای از دست دادن حداکثر بیستوچهار ساعت نوشتنها است. Litestream تقریباً هر یک ثانیه همگامسازی میکند، بنابراین در صورت خرابی، تقریباً آخرین ثانیه را از دست میدهید. استفاده از آن همچنین از کپیکردن فایل پایگاهداده با cp ایمنتر است؛ زیرا این کار ممکن است پایگاهداده را در میانه نوشتن ثبت کند. Litestream فقط پایگاهداده را پوشش میدهد، بنابراین یک نسخه پشتیبان عمومی از فایلها را نیز در کنار آن اجرا کنید.