SQLite في الإنتاج على VPS: الإعداد والحدود
اكتشف لماذا تناسب SQLite معظم التطبيقات الصغيرة على VPS واحد، وكيف تضبط WAL وbusy_timeout وتستخدم Litestream، ومتى تصبح SQLite عنق زجاجة.
عندما تكون SQLite قاعدة بيانات الإنتاج المناسبة على VPS
يُعد تشغيل SQLite في بيئة الإنتاج على VPS الخيار الصحيح لمعظم التطبيقات الصغيرة، والسبب بسيط: لا تحتاج عملية واحدة على جهاز واحد تكتب في ملف واحد إلى خادم قاعدة بيانات. لا يوجد daemon للإشراف عليه، ولا منفذ يجب ضبط جدار ناري له، ولا كلمة مرور يجب تدويرها، ولا جهاز ثانٍ يجب إبقاؤه قيد التشغيل. الاستعلام هو استدعاء دالة بدلاً من رحلة ذهاب وإياب عبر الشبكة، لذلك فإن الصفحة التي تنفّذ أربعين استعلاماً تكلّفك أربعين استدعاء دالة.
التكلفة محدودة وحقيقية. تسمح SQLite بكاتب واحد في كل مرة على مستوى ملف قاعدة البيانات بأكمله، ولا يمكن مشاركة الملف بين جهازين. كلا القيدين مناسب لـVPS واحد يشغّل تطبيقاً واحداً. لكن كلاهما يصبح عائقاً حاسماً فور تجاوزك هذا النمط. يغطي هذا الدليل الإعدادات التي تجعل SQLite آمنة على الخادم، والنسخ الاحتياطي المستمر باستخدام Litestream، والنقطة التي ينبغي عندها التوقف عن استخدامها.
ثبّت أداة سطر الأوامر أولاً. نُفّذت جميع الخطوات أدناه على Ubuntu 24.04.
sudo apt update
sudo apt install -y sqlite3
sqlite3 --versionيعرض ذلك إصداراً يبدأ بـ3.، ثم تاريخ بناء وhash للمصدر. توفّر Ubuntu 24.04 الإصدار SQLite 3.45.1 اعتباراً من July 2026. من المحتمل أن تطبيقك لا يستخدم هذا الملف التنفيذي: إذ تجمع معظم بيئات تشغيل اللغات نسختها الخاصة من مكتبة SQLite، وغالباً ما تكون أحدث، لذا تحقّق من الإصدار الذي يعرضه مشغّل قاعدة البيانات لديك قبل الاعتماد على ميزة حديثة.
لماذا يكون وضع WAL أول ما تغيّره
يستخدم SQLite دفتر تراجع في الإعداد الافتراضي. قبل تغيير صفحة، ينسخ الصفحة الأصلية إلى ملف -journal، ثم يعدّل قاعدة البيانات في مكانها. ولتنفيذ ذلك بأمان، يحصل على قفل حصري للملف بأكمله، لذلك ينتظر كل قارئ أثناء تنفيذ أي عملية كتابة. لا يلاحظ أحد ذلك على حاسوب محمول. أما على خادم ويب، فتؤدي كتابة بطيئة واحدة إلى إيقاف كل طلب يتعامل مع قاعدة البيانات.
يعكس وضع WAL (سجل الكتابة المسبقة) هذا الترتيب. يضيف الكاتب الصفحات الجديدة إلى ملف -wal منفصل، ويترك قاعدة البيانات الرئيسية دون تغيير. يواصل القراء قراءة الملف الرئيسي وفق اللقطة التي بدأوا بها، لذلك لا يحجب القراء الكاتب، ولا يحجب الكاتب القراء. لاحقاً، تنسخ نقطة تحقق صفحات WAL المتراكمة إلى قاعدة البيانات الرئيسية. هذا التغيير وحده هو العامل الأكبر الذي يجعل SQLite قابلاً للاستخدام خلف تطبيق ويب.
فعّل وضع WAL وتحقق من بقائه
mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"يطبع الأمر wal. هذا الناتج ليس للزينة. يعرض PRAGMA journal_mode الوضع الفعلي لقاعدة البيانات، لذلك تعني الإجابة delete أن التغيير فشل وأنك ما زلت تستخدم سجل التراجع.
وضع WAL مستمر. فهو علامة في ترويسة قاعدة البيانات، وليس إعداداً للاتصال. لذلك تشغّله مرة واحدة لكل ملف قاعدة بيانات، وترثه جميع الاتصالات اللاحقة، بما في ذلك بعد إعادة التشغيل. أثبت ذلك باستخدام اتصال جديد.
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 على الصفحات التي تم اعتمادها ولم تُنفَّذ لها عملية checkpoint بعد. أما الملف -shm فهو فهرس للذاكرة المشتركة تربطه كل الاتصالات حتى تتفق جميعاً على محتوى WAL. ينتمي الملفان إلى قاعدة البيانات، وليسا ملفين مؤقتين. إذا نسخت app.db وحده أثناء تشغيل التطبيق، فستحصل على ملف يفتقد كل عمليات الاعتماد الأخيرة. وإذا حذفت app.db وتركت الملفين الآخرين، فسيطبّق SQLite صفحات WAL القديمة على أي ملف جديد يظهر بهذا الاسم. هكذا تتلف قواعد بيانات جديدة عند محاولة إعادة ضبط قاعدة بيانات.
إعدادات الاتصال التي يحتاجها كل تطبيق في بيئة الإنتاج
يُخزَّن journal_mode فقط في قاعدة البيانات. أما كل إعداد آخر أدناه فهو خاص بالاتصال، ما يعني أن على تطبيقك تنفيذه عند كل اتصال يفتحه، بما في ذلك كل اتصال ينشئه connection pool في الخلفية.
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;يخبر busy_timeout = 5000 SQLite بإعادة المحاولة عند قفل قاعدة البيانات لمدة تصل إلى 5000 ميلي ثانية قبل أن يعيد database is locked. القيمة الافتراضية هي 0، لذلك يفشل SQLite فوراً في المرة الأولى التي تتداخل فيها عمليتا كتابة. ويزيل ضبط هذه القيمة الوحيدة معظم أخطاء القفل التي تُنسب إلى SQLite نفسه.
يُعد synchronous = NORMAL الإعداد المناسب في وضع WAL، ومن المهم فهم المقابل لذلك. عند ضبط FULL، يستدعي SQLite fsync على WAL عند كل عملية commit. أما عند ضبط NORMAL، فيجري المزامنة عند نقاط checkpoint بدلاً من ذلك. توضح وثائق SQLite بصرامة ما تتخلى عنه: لا تعود المعاملات متينة بعد انقطاع الطاقة أو إعادة الضبط القسري. لا يمكن لانقطاع الطاقة هذا إفساد قاعدة البيانات، لكنك ستفقد آخر عمليات commit التي لم تصل إلى القرص. على VPS، يكون هذا المقابل مناسباً عادةً، لأنه يزيل fsync من مسار كل عملية كتابة.
يكون foreign_keys = ON معطلاً افتراضياً للحفاظ على التوافق مع الإصدارات السابقة، وهو خاص بكل اتصال. ولا يفرض مخطط يحتوي على عبارات REFERENCES أي شيء على الإطلاق إلى أن يفعّل كل اتصال هذا الإعداد.
هناك إعداد آخر لا تبرز أهميته إلا لاحقاً. ينفّذ SQLite checkpoint تلقائياً عندما يتجاوز حجم WAL 1000 صفحة، وتنفّذ العملَ أيُّ connection تنتهي مصادفةً من معاملة في تلك اللحظة. لا توجد مشكلة في ذلك بحد ذاته. لكنه يصبح موضعاً للنقاش عند تشغيل Litestream، لأن Litestream يريد التحكم في توقيت تنفيذ نقاط checkpoint.
لماذا لا يزال database is locked يحدث بعد ضبط busy_timeout
هذا هو الفشل الذي يعيد المستخدمين إلى Postgres، وله سبب محدد واحد.
يُثبّت مهلة الانشغال معالجاً للانشغال، لكن SQLite لا يضمن استدعاءه.
إذا حدّد SQLite أن استدعاء معالج الانشغال قد يؤدي إلى حالة جمود، فسيعيد SQLITE_BUSY إلى التطبيق مباشرة بدلاً من استدعاء معالج الانشغال.
يحدث الجمود الذي يتجنبه SQLite عند ترقية المعاملة. يعني BEGIN المجرد في SQLite: BEGIN DEFERRED. إذا كانت العبارة الأولى بعده هي SELECT، فأنت داخل معاملة قراءة. عندما تحتاج UPDATE لاحقة في المعاملة نفسها إلى التحول إلى معاملة كتابة، وتكون وصلة أخرى قد أجرت كتابة منذ بدء قراءتك، لا يستطيع SQLite أن يجعلك تنتظر، لأن اللقطة التي تقرؤها أصبحت قديمة، والانتظار سيؤدي فقط إلى إدخال الوصلتين في حالة جمود متبادل. يوضح التوثيق النتيجة مباشرة:
ستُرقي عبارات الكتابة اللاحقة المعاملة إلى معاملة كتابة إن أمكن، أو ستعيد SQLITE_BUSY.
لا تُستخدم مهلة 5000 ميلي ثانية مطلقاً. يصل الخطأ فوراً، ولذلك يبدو كأن الإعداد لم يفعل شيئاً.
الإصلاح يتكون من كلمة واحدة.
BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;تأخذ BEGIN 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 حتى July 2026، وقد تلاه الإصدار v0.5.15 في 21 July 2026. غيّر الإصدار في السطرين ليتوافق مع الوسم الحالي في صفحة الإصدارات، واختر حزمة arm64 المطابقة بدلاً من ذلك إذا كان VPS لديك يعمل بمعمارية arm64.
يوجد ملف الإعداد في /etc/litestream.yml. ابدأ بنسخة محلية، لأنها تثبت اكتمال الدورة من دون الحاجة إلى بيانات اعتماد سحابية.
dbs:
- path: /home/appuser/app/app.db
replica:
type: file
path: /var/backups/litestream/appلاحظ أن الحقل هو replica بصيغة المفرد. استبدل Litestream 0.5 مصفوفة replicas من السلسلة 0.3 بكتلة نسخة واحدة، وأصبح ملف الإعداد الذي يحتوي على إدخالين يفشل عند بدء التشغيل. ما زالت أدلة كثيرة تابعة لجهات خارجية تعرض المصفوفة القديمة، لذلك انسخ البنية أعلاه بدلاً من أول مثال يظهر في نتائج البحث. كما أعادت السلسلة 0.5 تسمية الأمر الفرعي litestream wal إلى litestream ltx، لأن تنسيق النسخة الاحتياطية على القرص تغيّر.
تحقق من أن ملف الإعداد قابل للتحليل قبل تفعيل أي شيء.
sudo litestream databases -config /etc/litestream.ymlثم اختبر دورة النسخ والاستعادة يدوياً. يتجاوز هذا الشكل ملف الإعداد، وينسخ قاعدة بيانات واحدة إلى مسار واحد.
mkdir -p /tmp/replica
litestream replicate ~/app/app.db file:///tmp/replica/appيعمل هذا الأمر في الواجهة الأمامية ويستمر في التشغيل. في جلسة طرفية ثانية، اكتب صفاً ثم استعد النسخة إلى ملف جديد.
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 second، لذلك انتظر ثم نفّذ الاستعادة مرة أخرى. وتمثل هذه الثانية أيضاً نقطة الاستعادة لديك. يفقد التعطل عمليات الكتابة التي حدثت خلال فترة المزامنة الأخيرة بحد أقصى، ولا يمكن لأي إعداد جعل هذا الفقد صفراً.
بالنسبة إلى التخزين الفعلي، استبدل كتلة النسخة بعنوان 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 من البيئة، لذلك ضعها في ملف drop-in لـsystemd يملكه root وبصلاحية mode 600.
القيم المتعلقة باللقطات أعلاه هي القيم الافتراضية، لكن الإعداد الافتراضي للاحتفاظ يفاجئ بعض المستخدمين. يحدد الاحتفاظ مدة إبقاء Litestream للقطات والملفات التابعة لها، ولذلك يحدد أيضاً المدة التي يمكنك الرجوع إليها عند الاستعادة. تعني مدة 24 hours أن عملية ترحيل سيئة تكتشفها صباح Wednesday تصبح غير قابلة للاستعادة من حالة Monday. اضبط 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 (نظام ملفات شبكي) أو SMB، ولا تمنعها أي pragma. هناك فرق يغفل عنه كثيرون. يظهر جهاز الكتل الشبكي، الذي يربطه معظم مزوّدي VPS كتخزين إضافي، في Linux كقرص عادي يحتوي على نظام ملفات عادي، وهذا مناسب. أما مشاركة الملفات المركّبة فليست كذلك.
خادم تطبيق ثانٍ. لا يوجد إعداد يجعل هذا ممكناً. عندما تحتاج إلى جهازين يقدّمان البيانات نفسها، فأنت تحتاج إلى قاعدة بيانات تتواصل عبر الشبكة. اتخذ هذا القرار بينما لا يزال لديك وقت للتخطيط له.
أحمال العمل الكثيفة بالكتابة. وجود كاتب واحد في كل مرة خاصية في تنسيق الملف، وليس إعداداً قابلاً للضبط. تكون عمليات الكتابة القصيرة منخفضة التكلفة لأن كل عملية commit تُضاف إلى WAL، لذلك يعتمد معدل النقل على زمن استجابة القرص للكتابات الصغيرة أكثر من اعتماده على CPU. راجع NVMe مقارنةً بتخزين SATA SSD على VPS لمعرفة أثر هذا الفرق. أما المشكلة الفعلية فهي المعاملات الطويلة، لأنها تضع كل كاتب آخر في قائمة انتظار خلفها.
الاستعلامات التحليلية. SQLite مخزن صفوف مصمم للمعاملات. أما لوحة المعلومات التي تفحص مئة مليون صف فهي مهمة مختلفة لأداة مختلفة، ويوضح مقارنة DuckDB مع SQLite لأعمال الخوادم موضع هذا الحد.
VACUUM أثناء النسخ المتماثل. تعيد عملية VACUUM كاملة كتابة ملف قاعدة البيانات بأكمله، ما يعني أن Litestream يجب أن يرفعه كله مرة أخرى. وتنصح وثائق Litestream بعدم تشغيلها في مكانها أثناء نشاط النسخ المتماثل. أوقف برنامج النسخ المتماثل، ونفّذ vacuum، ثم شغّله مرة أخرى، وتوقع إنشاء لقطة كاملة جديدة.
برنامجا نسخ متماثل لقاعدة بيانات واحدة. لا تشغّل عمليتي Litestream على قاعدة البيانات نفسها أو على وجهة النسخة المتماثلة نفسها. تنص الوثائق صراحةً على أن منع ذلك مسؤوليتك، وإلا ستحصل على نسخة متماثلة لا يمكنك استعادتها.
ما لا يغطيه Litestream
يحمي Litestream ملف قاعدة البيانات فقط، ولا يحمي أي شيء آخر. تظل الملفات المرفوعة وإعدادات التطبيق وشهادات TLS (أمان طبقة النقل) وملفات الوحدات ضمن مسؤوليتك. اقرنه بجدولة نسخ احتياطية مشفّرة خارج الخادم باستخدام restic، وبذلك يغطي الحل جانبي الحماية. إذا كان الخادم جديداً، يشرح الدقائق العشر الأولى على VPS جديد إعداد حساب المستخدم وجدار الحماية، ويفترض هذا الدليل أن كليهما أُنجز مسبقاً.
FAQ
هل SQLite كافية لتطبيق يعمل في بيئة الإنتاج؟
لتطبيق واحد على خادم واحد، نعم، بشرط تفعيل وضع WAL، وضبط مهلة انتظار الانشغال، وإجراء نسخ احتياطي مستمر. القيود المهمة هنا بنيوية: كاتب واحد في كل مرة، وجهاز مضيف واحد. إذا كان التطبيق يندرج ضمن هذه الحدود، فستحصل على قاعدة بيانات من دون قفزة شبكية ومن دون عملية منفصلة لمراقبتها. أما إذا تجاوز التطبيق هذه الحدود، فيحتاج إلى قاعدة بيانات بنموذج العميل-الخادم، ولا يمكن لأي قدر من الضبط تغيير ذلك.
لماذا ما زلت أحصل على database is locked بعد ضبط busy_timeout؟
لأن SQLite تتجاوز معالج الانشغال عندما قد يؤدي الانتظار إلى حالة تعارض متبادل. تكون المعاملة التي تبدأ بـ BEGIN مجردة من التأجيل: إذ يضعها SELECT الافتتاحي في معاملة قراءة، ثم يجب على عملية كتابة لاحقة ترقيتها. إذا أجرى اتصال آخر عملية كتابة في هذه الأثناء، تُرجع SQLite SQLITE_BUSY فوراً بدلاً من استدعاء معالج الانشغال، لأن لقطة القراءة لديك أصبحت قديمة. ابدأ أي معاملة ستجري عملية كتابة باستخدام BEGIN IMMEDIATE، حتى يُؤخذ قفل الكتابة مسبقاً وتُطبَّق المهلة.
هل يمكنني الاحتفاظ بقاعدة بيانات SQLite على وحدة تخزين شبكية؟
ليس على نظام ملفات شبكي مثل NFS أو SMB. يحتاج وضع WAL إلى أن تتشارك جميع العمليات الذاكرة عبر ملف -shm، وتنص وثائق SQLite على أن كل عملية تستخدم قاعدة البيانات يجب أن تكون على جهاز مضيف واحد. أما جهاز الكتل الشبكي الذي يرفقه موفّر الخدمة، فهو مختلف: يرى Linux قرصاً عادياً بنظام ملفات عادي، وتعمل SQLite عليه.
هل أحتاج إلى Litestream إذا كنت أجري نسخاً احتياطية ليلية بالفعل؟
يعتمد ذلك على مقدار البيانات الذي يمكنك تحمّل فقدانه. تعني المهمة الليلية فقدان ما يصل إلى أربع وعشرين ساعة من عمليات الكتابة. تزامن Litestream البيانات مرة واحدة تقريباً كل ثانية، لذلك يكلّفك التعطل فقدان الثانية الأخيرة تقريباً. وهو أكثر أماناً أيضاً من نسخ ملف قاعدة البيانات باستخدام cp، لأن ذلك قد يلتقط قاعدة البيانات أثناء عملية كتابة. يغطي Litestream قاعدة البيانات فقط، لذلك أبقِ مهمة نسخ احتياطي عامة للملفات قيد التشغيل إلى جانبه.