SSD Nodes Learn Hosting plans →
מדריכים Matt Connorמאת Matt Connor · עודכן 2026-10-25

שימוש ב-SQLite בסביבת ייצור על גבי שרת VPS

האם SQLite מתאים ליישומים קטנים בשרת VPS יחיד? גלו כיצד להגדיר מצב WAL ו-busy_timeout, לבצע גיבוי רציף עם Litestream ולהבין מתי המגבלות של SQLite מחייבות מעבר לשרת אחר.

Verified Every command ran end-to-end on a fresh Ubuntu 24.04 server, July 30, 2026.

מתי SQLite הוא מסד הנתונים הנכון לייצור בשרת VPS

הרצת SQLite בסביבת ייצור על גבי VPS היא הבחירה הנכונה עבור רוב היישומים הקטנים, והסיבה לכך פשוטה: תהליך אחד על מכונה אחת הכותב לקובץ אחד אינו זקוק לשרת מסד נתונים. אין daemon שיש לנטר, אין פורט שיש להגדיר ב־firewall, אין סיסמה שיש להחליף, ואין מכונה שנייה שיש לשמור עליה פעילה. שאילתה היא קריאת פונקציה ולא סבב תקשורת ברשת, לכן דף שמריץ ארבעים שאילתות עולה לכם ארבעים קריאות פונקציה בלבד.

המחיר הוא מוגבל ומוחשי. 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 נכון לאוקטובר 2026. היישום שלכם כנראה אינו משתמש בבינארי הזה: רוב סביבות ההרצה של שפות תכנות כוללות עותק משלהן של ספריית SQLite, לעיתים קרובות גרסה חדשה יותר, לכן בדקו את הגרסה שמדווחת על ידי הדרייבר של מסד הנתונים שלכם לפני שאתם מסתמכים על תכונה חדשה.

מדוע מצב WAL הוא השינוי הראשון שצריך לבצע

כברירת מחדל, SQLite משתמש ב-rollback journal. לפני שינוי דף, הוא מעתיק את הדף המקורי לקובץ -journal, ולאחר מכן עורך את מסד הנתונים במקומו. כדי לעשות זאת בצורה בטוחה, הוא נועל את כל הקובץ בנעילה בלעדית, כך שכל הקוראים ממתינים בזמן שמתבצעת כתיבה כלשהי. במחשב נייד איש אינו מבחין בכך. בשרת אינטרנט, כתיבה איטית אחת מעכבת כל בקשה שניגשת למסד הנתונים.

מצב WAL (קיצור של write-ahead log) הופך את הסדר. הכותב מצרף את הדפים החדשים לקובץ -wal נפרד ומשאיר את מסד הנתונים הראשי ללא שינוי. קוראים ממשיכים לקרוא מהקובץ הראשי בנקודת הזמן (snapshot) שבה התחילו, כך שהקוראים אינם חוסמים את הכותב והכותב אינו חוסם את הקוראים. מאוחר יותר, פעולת checkpoint מעתיקה את דפי ה-WAL שנצברו בחזרה למסד הנתונים הראשי. שינוי יחיד זה הוא רוב מה שהופך את SQLite לשימושי מאחורי יישום אינטרנט.

הפעלת מצב WAL ואימות ההגדרה

mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"

הפקודה מדפיסה wal. פלט זה אינו קישוט. PRAGMA journal_mode מחזיר את המצב שבו מסד הנתונים נמצא בפועל, לכן תשובה של delete משמעותה שהשינוי נכשל ואתם עדיין משתמשים ב-rollback 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 הוא אינדקס זיכרון משותף שכל חיבור ממפה, כדי שכולם יסכימו על תוכנו של ה-WAL. שניהם שייכים למסד הנתונים ואינם קבצי עבודה זמניים. אם תעתיקו את app.db לבדו בזמן שהיישום רץ, תקבלו קובץ שחסרים בו כל ה-commits האחרונים. אם תמחקו את 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 להמשיך לנסות לגשת למסד נתונים נעול למשך עד 5000 מילי-שניות לפני שהוא מחזיר database is locked. ברירת המחדל היא 0, לכן כברירת מחדל SQLite נכשל מיידית בפעם הראשונה שבה שני תהליכי כתיבה מתנגשים. הגדרת ערך יחיד זה מסירה את רוב שגיאות הנעילה שנוטים לייחס בטעות ל-SQLite עצמו.

synchronous = NORMAL היא ההגדרה הנכונה במצב WAL, וכדאי להבין את הפשרה הכרוכה בכך. ב-FULL,‏ SQLite מבצע fsync ל-WAL בכל commit. ב-NORMAL, הוא מסנכרן רק בנקודות ביקורת (checkpoints). התיעוד של SQLite מבהיר היטב על מה מוותרים: טרנזקציות אינן נחשבות עוד ל-durable לאחר הפסקת חשמל או אתחול קשיח. מסד הנתונים לא ייפגם כתוצאה מאובדן החשמל, אתם פשוט תאבדו את ה-commits האחרונים שטרם הגיעו לדיסק. בשרת VPS זו בדרך כלל הפשרה הנכונה, כיוון שהיא מוציאה את פעולת ה-fsync מנתיב הכתיבה של כל פעולה בודדת.

foreign_keys = ON כבויה כברירת מחדל לצורך תאימות לאחור, והיא מוגדרת ברמת החיבור. סכימה מלאה ב-REFERENCES לא תאכוף דבר כל עוד כל חיבור לא מפעיל הגדרה זו.

הגדרה אחת נוספת חשובה רק בשלב מאוחר יותר. SQLite מבצע checkpoint באופן אוטומטי ברגע שקובץ ה-WAL גדל מעבר ל-1000 דפים, והעבודה מבוצעת על ידי החיבור שסיים טרנזקציה באותו רגע. זה תקין כשלעצמו. העניין הופך למורכב כאשר Litestream רץ, כיוון ש-Litestream דורש שליטה על מועד ביצוע ה-checkpoints.

מדוע database is locked עדיין מתרחשת לאחר הגדרת busy_timeout

זהו הכשל שגורם למשתמשים לחזור ל-Postgres, ויש לו סיבה אחת ספציפית.

הגדרת busy timeout מתקינה מטפל עסוק (busy handler), אך SQLite לא מתחייבת להפעיל אותו.

אם SQLite קובעת שהפעלת המטפל העסוק עלולה להוביל ל-deadlock, היא תמשיך ותחזיר SQLITE_BUSY ליישום במקום להפעיל את המטפל.

ה-deadlock שהיא מונעת מתרחש בעת שדרוג טרנזקציה. פקודת BEGIN פשוטה ב-SQLite משמעותה BEGIN DEFERRED. אם הפקודה הראשונה אחריה היא SELECT, אתם נמצאים בתוך טרנזקציית קריאה. כאשר פקודת UPDATE מאוחרת יותר באותה טרנזקציה צריכה להפוך לטרנזקציית כתיבה, וחיבור אחר ביצע כתיבה מאז תחילת הקריאה שלכם, SQLite לא יכולה לגרום לכם להמתין. זאת כיוון שה-snapshot שלכם כבר אינו מעודכן, והמתנה רק תוביל ל-deadlock בין שני החיבורים. התיעוד מציין את התוצאה במפורש:

פקודות כתיבה עוקבות ישדרגו את הטרנזקציה לטרנזקציית כתיבה אם הדבר אפשרי, או יחזירו SQLITE_BUSY.

ה-timeout של ה-5000 מילי-שניות שלכם לעולם לא נבדק. השגיאה מגיעה באופן מיידי, וזו הסיבה שנראה כאילו ההגדרה לא עשתה דבר.

התיקון הוא מילה אחת.

BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;

BEGIN IMMEDIATE תופסת את נעילת הכתיבה כבר בהתחלה, לפני קריאת דבר מה. אין שדרוג, לכן אין deadlock למנוע, ולכן המטפל העסוק אכן פועל והחיבור ממתין לתורו במקום להיכשל. השאירו טרנזקציות לקריאה בלבד כ-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, ו-v0.5.17, התג החדש ביותר, ב-31 באוגוסט 2026. שנו את הגרסה בשתי השורות כדי שתתאים לתג הנוכחי בדף ה-releases, וקחו את חבילת ה-arm64 המתאימה אם ה-VPS שלכם הוא בארכיטקטורת arm64.

קובץ התצורה נמצא ב-/etc/litestream.yml. התחילו עם העתק (replica) לקובץ מקומי, כיוון שזה מוכיח את כל הלולאה ללא צורך בפרטי גישה לענן.

dbs:
  - path: /home/appuser/app/app.db
    replica:
      type: file
      path: /var/backups/litestream/app

שימו לב שהשדה הוא replica, ביחיד. גרסה 0.5 של Litestream החליפה את המערך replicas מסדרת 0.3 בבלוק replica יחיד, ותצורה המכילה שתי כניסות תיכשל בעת העלייה. מדריכים רבים של צד שלישי עדיין מציגים את המערך הישן, לכן העתיקו את המבנה שלעיל במקום את הדוגמה הראשונה שחיפוש מעלה. סדרת 0.5 גם שינתה את שם תת-הפקודה litestream wal ל-litestream ltx, כיוון שפורמט הגיבוי על הדיסק השתנה.

בדקו שהתצורה עוברת ניתוח (parse) לפני שאתם מפעילים משהו.

sudo litestream databases -config /etc/litestream.yml

לאחר מכן הוכיחו את סבב הפעולה ידנית. טופס זה מדלג על קובץ התצורה ומשכפל מסד נתונים אחד לנתיב אחד.

mkdir -p /tmp/replica
litestream replicate ~/app/app.db file:///tmp/replica/app

זה רץ בחזית וממשיך לפעול. בטרמינל שני, כתבו שורה ושחזרו את ה-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 שנייה, לכן המתינו ושחזרו שוב. אותה שנייה אחת היא גם נקודת השחזור שלכם. קריסה תגרום לאובדן של לכל היותר הכתיבות ממרווח הסנכרון האחרון, ושום תצורה לא תהפוך זאת לאפס.

עבור אחסון אמיתי, החליפו את בלוק ה-replica בכתובת S3 URL. זה עובד מול 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 ועם הרשאות 600.

ערכי ה-snapshot שלעיל הם ברירות המחדל, וברירת המחדל של ה-retention מפתיעה אנשים. Retention הוא משך הזמן ש-Litestream שומר snapshots והקבצים השייכים להם, ולכן הוא גם קובע כמה זמן אחורה ניתן לשחזר. עשרים וארבע שעות אומרות שמיגרציה כושלת שתבחינו בה בבוקר יום רביעי כבר אינה ניתנת לשחזור ממצב של יום שני. ב-Litestream 0.5, ה-retention הוא הגדרה גלובלית בבלוק ה-root snapshot, ולא ברמת ה-replica. עבור שבוע, שנו את הבלוק ל-retention: 168h ושלמו על האחסון הנוסף. שורת retention: בתוך בלוק ה-replica היא התחביר של סדרת 0.3. Litestream 0.5 מתעלם ממנה ללא שגיאה ונשאר על ברירת המחדל של 24 שעות.

וודאו את תקינות השחזור לפני שתזדקקו לו

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 מאתר את ה-replica התואם ב-/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 הנמצאים לצד מסד הנתונים שלך. לכן, הגדירו את חשבון המשתמש שבו היישום שלכם כבר רץ, appuser בדוגמאות אלו.

# /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 ביחידת ה-systemd של היישום שלכם, כך ששרת VPS חדש ימשוך את מסד הנתונים, בעוד שרת קיים לא יבצע דבר. ל-litestream replicate יש דגל -restore-if-db-not-exists תואם אם אתם מעדיפים לרכז זאת במקום אחד.

מתי SQLite נכשל בשימוש על גבי VPS

מערכות קבצים מבוססות רשת. זוהי מגבלה שלא ניתן לעקוף באמצעות הגדרות. מצב WAL מחייב שכל תהליך המשתמש בבסיס הנתונים ישתף אזור זיכרון קטן, וזהו התפקיד של הקובץ -shm. התיעוד של SQLite מציב כלל זה ללא סייגים:

כל התהליכים המשתמשים בבסיס נתונים חייבים להיות על אותו מחשב מארח; WAL אינו פועל על גבי מערכת קבצים רשתית.

לכן, בסיס נתונים המאוחסן על גבי שיתוף NFS (מערכת קבצים רשתית) או SMB עלול להיפגם, ושום pragma לא ימנע זאת. יש כאן הבחנה שרבים מפספסים. התקן בלוקים רשתי (network block device), שזה מה שרוב ספקי ה-VPS מצרפים כאחסון נוסף, מופיע בלינוקס כדיסק רגיל עם מערכת קבצים רגילה, וזה תקין. שיתוף קבצים (file share) מותקן אינו כזה.

שרת יישומים שני. אין הגדרה שתגרום לזה לעבוד. ברגע שאתם זקוקים לשני מחשבים המשרתים את אותם הנתונים, אתם זקוקים לבסיס נתונים שמדבר על גבי הרשת. החליטו על המעבר הזה בעוד שיש לכם זמן לתכנן אותו.

עומסי עבודה כבדים בכתיבה. כותב אחד בכל פעם הוא מאפיין של פורמט הקובץ, לא פרמטר שניתן לכוונון. כתיבות קצרות הן זולות כי כל commit הוא הוספה ל-WAL, לכן ה-throughput עוקב מקרוב יותר אחרי ה-latency של כתיבות קטנות בדיסק שלכם מאשר אחרי ה-CPU. ראו NVMe לעומת אחסון SATA SSD ב-VPS כדי לראות איך ההבדל הזה נראה. טרנזקציות ארוכות הן הבעיה האמיתית, כי הן מעמידות בתור כל כותב אחר מאחוריהן.

שאילתות אנליטיות. SQLite הוא מאגר שורות (row store) שנבנה עבור טרנזקציות. לוח מחוונים הסורק מאה מיליון שורות הוא משימה שונה עבור כלי שונה, והמאמר DuckDB בהשוואה ל-SQLite לעבודה בשרת מכסה היכן עובר הגבול הזה.

VACUUM תחת שכפול. פעולת VACUUM מלאה כותבת מחדש את כל קובץ בסיס הנתונים, מה שמבטל את המעקב ברמת הדף שעליו מסתמך Litestream, והתיעוד של Litestream ממליץ לא להריץ זאת במקום בזמן שהשכפול פעיל. הוא ממליץ על VACUUM INTO, שכותב עותק דחוס לקובץ נפרד ומשאיר את המקור ללא שינוי. אם אתם חייבים לבצע vacuum במקום, הנוהל המתועד ארוך יותר מאתחול: עצרו את ה-replicator, בצעו vacuum, מחקו את ספריית המעקב הנסתרת של Litestream לצד בסיס הנתונים ואת נתוני ה-replica המרוחקים הקיימים, ואז הפעילו אותו שוב כדי שיתחיל מ-snapshot מלא וחדש. השלב האחרון הזה זורק לפח את היסטוריית השחזור שהייתה לכם.

שני משכפלים (replicators) על בסיס נתונים אחד. לעולם אל תריצו שני תהליכי Litestream מול אותו בסיס נתונים או מול אותו יעד שכפול. התיעוד מפורש בכך שמניעת מצב זה היא באחריותכם, והתוצאה היא replica שלא תוכלו לשחזר.

מה Litestream אינו מכסה

Litestream מגן על קובץ מסד הנתונים בלבד, ולא על שום דבר אחר. קבצים שהועלו, הגדרות היישום, תעודות TLS (אבטחת שכבת תעבורה) וקובצי ה-unit נותרים באחריותך. מומלץ לשלב אותו עם גיבויים מוצפנים מחוץ לשרת באמצעות restic לפי לוח זמנים, ובכך לכסות את שני החלקים. אם מדובר במכונה חדשה, המדריך עשר הדקות הראשונות ב-VPS חדש מכסה את הגדרת חשבון המשתמש וה-firewall, פעולות שמונחות במדריך זה ככאלו שכבר בוצעו.

FAQ

האם SQLite מתאים ליישום בסביבת production?

עבור יישום יחיד על שרת יחיד, כן, בתנאי שמפעילים מצב WAL, מגדירים busy timeout ומבצעים גיבוי רציף. המגבלות המשמעותיות הן מבניות: כותב אחד בלבד בכל רגע נתון, ומכונת מארח אחת. יישום שעומד במגבלות אלו נהנה ממסד נתונים ללא דילוגי רשת וללא תהליך נפרד לניטור. יישום שאינו עומד במגבלות אלו זקוק למסד נתונים בתצורת client-server, ושום כוונון לא ישנה זאת.

מדוע אני עדיין מקבל database is locked לאחר הגדרת busy_timeout?

מכיוון ש-SQLite מדלג על ה-busy handler כאשר המתנה עלולה לגרום ל-deadlock. טרנזקציה שמתחילה ב-BEGIN פשוט היא deferred: פקודת SELECT ראשונית מכניסה אותה לטרנזקציית קריאה, וכתיבה מאוחרת יותר מחייבת שדרוג. אם חיבור אחר ביצע כתיבה בפרק זמן זה, SQLite מחזיר SQLITE_BUSY באופן מיידי במקום להפעיל את ה-busy handler, כיוון שצילום הקריאה שלך כבר אינו עדכני. התחילו כל טרנזקציה שעתידה לכתוב עם BEGIN IMMEDIATE, כך שנעילת הכתיבה תתבצע מראש וה-timeout יחול.

האם ניתן לשמור את מסד הנתונים של SQLite על אחסון רשת?

לא על מערכת קבצים מבוססת רשת כמו NFS או SMB. מצב WAL מחייב את כל התהליכים לשתף זיכרון דרך קובץ ה--shm, והתיעוד של SQLite מציין שכל תהליך המשתמש במסד הנתונים חייב להימצא על אותו מחשב מארח. התקן בלוקים רשתי שמחובר על ידי ספק התשתית הוא עניין שונה: Linux מזהה דיסק רגיל עם מערכת קבצים רגילה עליו, ו-SQLite עובד שם כראוי.

האם אני זקוק ל-Litestream אם אני כבר מריץ גיבויים ליליים?

זה תלוי בכמות הנתונים שאתה יכול להרשות לעצמך לאבד. משימה לילית משמעותה אובדן של עד עשרים וארבע שעות של כתיבה. Litestream מסנכרן נתונים בערך פעם בשנייה, כך שקריסה תעלה לך בערך בשנייה האחרונה של עבודה. הוא גם בטוח יותר מהעתקת קובץ מסד הנתונים עם cp, פעולה שעלולה לתפוס את מסד הנתונים באמצע כתיבה. Litestream מכסה רק את מסד הנתונים, לכן הקפד להריץ גיבוי קבצים כללי לצדו.

האם המאמר הזה היה מועיל?

#sqlite#wal#litestream#backups#production