VPS پر SQLite کو production میں کب چلائیں؟
ایک VPS پر چھوٹی apps کے لیے SQLite کیوں مناسب ہے، WAL mode، busy_timeout اور Litestream replication کیسے لگائیں، اور ایک writer کی حد کب رکاوٹ بنتی ہے۔
VPS پر SQLite کب درست پیداواری database ہے
VPS پر زیادہ تر چھوٹی applications کے لیے SQLite کو production میں چلانا درست انتخاب ہے، اور وجہ سادہ ہے: ایک machine پر ایک process اگر ایک file میں لکھ رہا ہو تو اسے database server کی ضرورت نہیں ہوتی۔ نگرانی کے لیے کوئی daemon نہیں ہوتا، firewall میں کھولنے کے لیے کوئی port نہیں ہوتا، تبدیل کرنے کے لیے کوئی password نہیں ہوتا، اور فعال رکھنے کے لیے دوسری machine نہیں ہوتی۔ Query network round trip کے بجائے function call ہوتی ہے، اس لیے چالیس queries چلانے والا page آپ سے چالیس function calls کی لاگت لیتا ہے۔
اس کی حد واضح اور حقیقی ہے۔ SQLite پوری database file میں ایک وقت میں صرف ایک writer کی اجازت دیتا ہے، اور file کو دو machines کے درمیان share نہیں کیا جا سکتا۔ ایک VPS پر ایک application چلانے کے لیے دونوں حدود قابل قبول ہیں۔ جیسے ہی آپ اس ساخت سے آگے بڑھتے ہیں، دونوں حدود فیصلہ کن رکاوٹ بن جاتی ہیں۔ اس guide میں وہ settings شامل ہیں جو server پر SQLite کو محفوظ بناتی ہیں، Litestream کے ساتھ مسلسل backup، اور وہ مرحلہ بھی جہاں آپ کو رک جانا چاہیے۔
پہلے command line tool install کریں۔ ذیل کے تمام اقدامات Ubuntu 24.04 پر کیے گئے ہیں۔
sudo apt update
sudo apt install -y sqlite3
sqlite3 --versionیہ 3. سے شروع ہونے والا version، اس کے بعد build date اور source hash دکھاتا ہے۔ July 2026 تک Ubuntu 24.04 کے ساتھ SQLite 3.45.1 جاری کیا گیا ہے۔ ممکن ہے آپ کی application اس binary کو استعمال نہ کرتی ہو: زیادہ تر language runtimes اپنی SQLite library کی copy شامل کرتے ہیں، جو اکثر اس سے نئی ہوتی ہے۔ اس لیے کسی حالیہ feature پر انحصار کرنے سے پہلے اپنے database driver کی بتائی ہوئی version چیک کریں۔
WAL موڈ میں تبدیلی سب سے پہلے کیوں کی جاتی ہے
بطور ڈیفالٹ SQLite، rollback journal استعمال کرتا ہے۔ کسی page کو تبدیل کرنے سے پہلے یہ اصل page کو -journal فائل میں نقل کرتا ہے، پھر database کو اسی جگہ ترمیم کرتا ہے۔ یہ عمل محفوظ طریقے سے انجام دینے کے لیے پوری فائل پر exclusive lock لگایا جاتا ہے، اس لیے جب بھی write جاری ہو، ہر reader انتظار کرتا ہے۔ Laptop پر اس کا عموماً پتا نہیں چلتا۔ Web server پر ایک سست write، database کو استعمال کرنے والی ہر request کو روک دیتی ہے۔
WAL (write-ahead log) موڈ اس ترتیب کو الٹ دیتا ہے۔ Writer نئے pages کو الگ -wal فائل میں شامل کرتا ہے اور main database کو تبدیل نہیں کرتا۔ Readers، شروع میں حاصل کیے گئے snapshot کے مطابق main file سے reading جاری رکھتے ہیں، اس لیے readers، writer کو block نہیں کرتے اور writer، readers کو block نہیں کرتا۔ بعد میں checkpoint، جمع شدہ WAL pages کو main database میں واپس نقل کرتا ہے۔ یہ ایک تبدیلی زیادہ تر اس بات کی وجہ بنتی ہے کہ SQLite کو web application کے پیچھے مؤثر طور پر استعمال کیا جا سکتا ہے۔
WAL موڈ فعال کریں اور تصدیق کریں کہ یہ برقرار ہے
mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"کمانڈ wal پرنٹ کرتی ہے۔ یہ آؤٹ پٹ محض ظاہری معلومات نہیں ہے۔ PRAGMA journal_mode وہ موڈ واپس کرتا ہے جس میں database فی الحال موجود ہے، اس لیے delete کا جواب ظاہر کرتا ہے کہ تبدیلی ناکام ہو گئی ہے اور آپ اب بھی rollback journal استعمال کر رہے ہیں۔
WAL موڈ مستقل ہوتا ہے۔ یہ connection کی setting کے بجائے database header میں موجود ایک flag ہے۔ اس لیے اسے ہر database file کے لیے صرف ایک بار چلائیں۔ اس کے بعد ہر connection اسے خود اختیار کر لیتا ہے، reboot کے بعد بھی۔ نئی connection سے اس کی تصدیق کریں۔
sqlite3 ~/app/app.db "PRAGMA journal_mode;"اب ایک table بنائیں اور دیکھیں کہ disk پر کیا ظاہر ہوتا ہے۔
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/اب تین files موجود ہیں: app.db، app.db-wal اور app.db-shm۔ -wal file ان committed pages کو محفوظ رکھتی ہے جن کا ابھی checkpoint نہیں بنایا گیا۔ -shm file ایک shared memory index ہے جسے ہر connection map کرتا ہے، تاکہ سب connections WAL کے مواد پر متفق رہیں۔ دونوں files database کا حصہ ہیں، scratch files نہیں۔ Application کے چلتے ہوئے صرف app.db کو copy کرنے سے ایسی file حاصل ہوتی ہے جس میں ہر حالیہ commit غائب ہوتا ہے۔ app.db کو حذف کر کے باقی دونوں files برقرار رکھیں تو SQLite ان پرانے WAL pages کو اس نام سے بننے والی نئی file پر لاگو کرے گا۔ اسی طرح لوگ database reset کرنے کی کوشش میں نیا database خراب کر دیتے ہیں۔
ہر پروڈکشن ایپلیکیشن کے لیے ضروری کنکشن کی ترتیبات
صرف journal_mode ڈیٹابیس میں محفوظ ہوتی ہے۔ ذیل کی ہر دوسری ترتیب فی کنکشن ہوتی ہے۔ اس کا مطلب ہے کہ آپ کی ایپلیکیشن کو ہر کھولے گئے کنکشن پر اسے چلانا ہوگا، بشمول ہر وہ کنکشن جو connection pool پس منظر میں بناتا ہے۔
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;busy_timeout = 5000، لاک شدہ ڈیٹابیس کے لیے زیادہ سے زیادہ 5000 milliseconds تک دوبارہ کوشش جاری رکھنے کو کہتا ہے، اس کے بعد یہ database is locked واپس کرتا ہے۔ پہلے سے طے شدہ قدر 0 ہے۔ اس لیے پہلے سے طے شدہ صورت میں، دو writers کے بیک وقت کام کرنے پر SQLite پہلی ہی بار فوراً ناکام ہوجاتا ہے۔ صرف یہ ایک قدر مقرر کرنے سے lock errors کی زیادہ تر وجوہ ختم ہوجاتی ہیں جن کا الزام SQLite پر لگایا جاتا ہے۔
synchronous = NORMAL، WAL mode میں درست ترتیب ہے، اور اس کے تبادلے کو سمجھنا ضروری ہے۔ FULL پر SQLite ہر commit کے وقت WAL پر fsync چلاتا ہے۔ NORMAL پر یہ checkpoints کے وقت sync کرتا ہے۔ SQLite کی دستاویزات واضح طور پر بتاتی ہیں کہ اس کے بدلے آپ کیا کھوتے ہیں: power failure یا hard reset کے بعد transactions پائیدار نہیں رہتیں۔ اس power loss سے ڈیٹابیس خراب نہیں ہوسکتا؛ آپ صرف وہ آخری commits کھوتے ہیں جو disk تک نہیں پہنچے تھے۔ VPS پر عموماً یہ مناسب تبادلہ ہے، کیونکہ اس سے ہر write کے راستے سے ایک fsync ہٹ جاتا ہے۔
foreign_keys = ON، backwards compatibility کے لیے پہلے سے بند ہوتی ہے، اور یہ فی کنکشن ہوتی ہے۔ REFERENCES clauses سے بھرپور schema اس وقت تک کچھ بھی نافذ نہیں کرتا جب تک ہر کنکشن اسے فعال نہ کردے۔
ایک اور ترتیب بعد میں اہم ہوتی ہے۔ WAL کے 1000 pages سے بڑا ہوجانے پر SQLite خودکار طور پر checkpoint کرتا ہے، اور یہ کام وہ کنکشن انجام دیتا ہے جو اس لمحے transaction مکمل کرتا ہے۔ اپنے طور پر یہ ٹھیک ہے۔ Litestream چل رہا ہو تو یہ معاملہ بن جاتا ہے، کیونکہ Litestream یہ کنٹرول کرنا چاہتا ہے کہ checkpoints کب ہوں۔
database is locked مقرر کرنے کے بعد بھی کیوں ہوتا رہتا ہے
یہ وہ خرابی ہے جو لوگوں کو دوبارہ Postgres کی طرف لے جاتی ہے، اور اس کی ایک مخصوص وجہ ہے۔
مصروفیت کا timeout ایک busy handler نصب کرتا ہے، لیکن SQLite یہ ضمانت نہیں دیتا کہ وہ اسے ضرور کال کرے گا۔
اگر SQLite یہ طے کرے کہ busy handler کو کال کرنے سے deadlock پیدا ہو سکتا ہے، تو وہ busy handler کو کال کرنے کے بجائے application کو SQLITE_BUSY واپس کر دیتا ہے۔
جس deadlock سے SQLite بچ رہا ہوتا ہے، وہ transaction کے upgrade کے وقت پیدا ہوتا ہے۔ SQLite میں سادہ BEGIN کا مطلب BEGIN DEFERRED ہے۔ اگر اس کے فوراً بعد پہلا statement SELECT ہو، تو آپ read transaction میں ہیں۔ جب اسی transaction میں بعد کا UPDATE write transaction میں تبدیل ہونے کی ضرورت محسوس کرے، اور آپ کے read شروع ہونے کے بعد کسی دوسرے connection نے لکھا ہو، تو SQLite آپ کو انتظار نہیں کرا سکتا، کیونکہ آپ کا snapshot پہلے ہی پرانا ہو چکا ہے۔ انتظار کرنے سے دونوں connections ایک دوسرے کے خلاف deadlock میں پھنس جائیں گے۔ documentation نتیجہ براہ راست بیان کرتی ہے:
بعد کے write statements ممکن ہونے کی صورت میں transaction کو write transaction میں upgrade کریں گے، ورنہ SQLITE_BUSY واپس کریں گے۔
آپ کا 5000 millisecond کا timeout کبھی استعمال ہی نہیں ہوتا۔ خرابی فوراً آ جاتی ہے، اسی لیے ایسا لگتا ہے کہ setting نے کوئی کام نہیں کیا۔
حل ایک لفظ ہے۔
BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;BEGIN IMMEDIATE شروع ہی میں، کچھ پڑھنے سے پہلے، write lock حاصل کرتا ہے۔ اس میں کوئی upgrade نہیں ہوتا، اس لیے جس deadlock سے بچنا ہو وہ بھی نہیں ہوتا۔ چنانچہ busy handler مؤثر ہوتا ہے اور connection ناکام ہونے کے بجائے اپنی باری کا انتظار کرتا ہے۔ صرف read والی transactions کو deferred رکھیں۔ جس transaction میں write شامل ہو، اسے immediate ہونا چاہیے۔
lock errors کی دوسری وجہ تلاش کرنا زیادہ مشکل ہے: write transaction کو سست کام کے دوران کھلا رکھنا۔ SQLite writers کو باری باری چلاتا ہے، اس لیے جو transaction شروع ہو، network پر کسی external API کو call کرے، اور پھر commit کرے، وہ اس call کے پورے دورانیے تک ہر دوسرے writer کو روک دے گا۔ جو کچھ درکار ہو اسے پڑھیں، transaction بند کریں، سست کام مکمل کریں، پھر نتیجہ محفوظ کرنے کے لیے مختصر write transaction شروع کریں۔
Litestream کے ساتھ مسلسل بیک اپ
رات کو بنائی گئی نقل میں ایک دن تک کی تحریری تبدیلیاں ضائع ہو سکتی ہیں، اور فعال SQLite database پر cp چلانے سے ایسی نقل بن سکتی ہے جو کھلے ہی نہ۔ دو طریقے محفوظ ہیں۔ sqlite3 app.db ".backup /path/to/backup.db"، SQLite کے online backup interface کو استعمال کرتا ہے اور استعمال میں موجود database پر کام کرتا ہے۔ Litestream اس سے آگے جاتا ہے: یہ WAL کی نگرانی کرتا ہے اور تبدیلیاں مسلسل object storage میں اپ لوڈ کرتا ہے۔ اس سے بدترین صورت میں data loss ایک دن سے کم ہو کر تقریباً ایک سیکنڈ رہ جاتا ہے۔
Litestream ایک Go binary ہے جو آپ کی application کے ساتھ چلتی ہے۔ یہ application اور database کے درمیان نہیں بیٹھتا۔ آپ کی application پہلے کی طرح 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 versionv0.5.14 وہ release ہے جسے جولائی 2026 تک سرکاری Linux install page دستاویز کرتی ہے، اور v0.5.15 اس کے بعد 21 July 2026 کو جاری ہوا۔ دونوں lines میں version کو releases page پر موجود موجودہ tag کے مطابق تبدیل کریں۔ اگر آپ کا VPS arm64 ہے تو اس کے بجائے متعلقہ arm64 package لیں۔
Configuration file /etc/litestream.yml میں موجود ہوتی ہے۔ ابتدا local file replica سے کریں، کیونکہ اس سے cloud credentials کے بغیر پورا عمل ثابت ہو جاتا ہے۔
dbs:
- path: /home/appuser/app/app.db
replica:
type: file
path: /var/backups/litestream/appیاد رکھیں کہ field replica واحد ہے۔ Litestream 0.5 نے 0.3 series کے replicas array کو ایک single replica block سے تبدیل کر دیا ہے۔ اب دو entries والی config startup پر fail ہو جاتی ہے۔ بہت سی third-party guides اب بھی پرانا array دکھاتی ہیں، اس لیے اوپر دی گئی structure نقل کریں، نہ کہ search میں ملنے والی پہلی example۔
0.5 series نے litestream wal subcommand کا نام بھی litestream ltx کر دیا، کیونکہ on-disk backup format تبدیل ہو گیا تھا۔
کسی بھی چیز کو enable کرنے سے پہلے تصدیق کریں کہ config parse ہو رہی ہے۔
sudo litestream databases -config /etc/litestream.ymlاس کے بعد round trip کو دستی طور پر ثابت کریں۔ یہ form config file کو نظرانداز کرتا ہے اور ایک database کو ایک path پر replicate کرتا ہے۔
mkdir -p /tmp/replica
litestream replicate ~/app/app.db file:///tmp/replica/appیہ foreground میں چلتا ہے اور چلتا رہتا ہے۔ دوسرے shell میں ایک row لکھیں اور replica کو نئی file میں restore کریں۔
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;"Count میں نئی row شامل ہونی چاہیے۔ اگر ایسا نہ ہو تو تبدیلی ابھی sync نہیں ہوئی۔ Litestream ایک sync-interval پر push کرتا ہے، جو default طور پر 1 second ہے، اس لیے انتظار کریں اور دوبارہ restore کریں۔ یہی ایک سیکنڈ آپ کا recovery point بھی ہے۔ crash کی صورت میں زیادہ سے زیادہ آخری sync interval کی تحریری تبدیلیاں ضائع ہو سکتی ہیں، اور کوئی configuration اس مدت کو صفر نہیں کر سکتی۔
حقیقی storage کے لیے replica block کو S3 URL سے تبدیل کریں۔ یہ Amazon S3 اور دیگر providers کے S3-compatible object storage، دونوں کے ساتھ کام کرتا ہے۔
dbs:
- path: /home/appuser/app/app.db
replica:
url: s3://your-bucket-name/app
region: us-east-1
snapshot:
interval: 24h
retention: 24hCredentials کو اس file میں نہ رکھیں۔ Litestream LITESTREAM_ACCESS_KEY_ID اور LITESTREAM_SECRET_ACCESS_KEY کو environment سے پڑھتا ہے، اس لیے انہیں root کی ملکیت والے mode 600 کے systemd drop-in میں رکھیں۔
اوپر دی گئی snapshot values defaults ہیں، جبکہ retention کا default اکثر لوگوں کے لیے حیران کن ہوتا ہے۔ Retention سے مراد وہ مدت ہے جس تک Litestream snapshots اور ان سے متعلق files محفوظ رکھتا ہے۔ اسی سے یہ بھی طے ہوتا ہے کہ آپ ماضی میں کتنی دور تک restore کر سکتے ہیں۔ چوبیس گھنٹے کا مطلب ہے کہ Wednesday morning کو معلوم ہونے والی خراب migration کو Monday کی state سے restore نہیں کیا جا سکے گا۔ retention: 168h کو ایک ہفتے کے لیے مقرر کریں اور اضافی storage کے اخراجات قبول کریں۔
ضرورت سے پہلے بحالی کی تصدیق کریں
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 میں متعلقہ replica تلاش کرتا ہے اور اسے ڈاؤن لوڈ کرتا ہے۔ صحت مند فائل پر PRAGMA integrity_check، ok دکھاتا ہے۔ کوئی بھی دوسری آؤٹ پٹ اس بات کی نشاندہی کرتی ہے کہ بحال شدہ کاپی قابلِ استعمال نہیں ہے۔ اسے systemd سروس اور ٹائمر کے ذریعے مقررہ شیڈول پر چلائیں اور آؤٹ پٹ پڑھیں۔ جب تک آپ ایک بار backup بحال نہیں کر لیتے، آپ کو معلوم نہیں ہوگا کہ یہ کام کرتا ہے۔
systemd کے تحت Litestream چلائیں
Debian پیکیج ایک litestream یونٹ انسٹال کرتا ہے جو /etc/litestream.yml کو پڑھتا ہے۔
sudo systemctl enable litestream
sudo systemctl start litestream
sudo journalctl -u litestream -fصحت مند آؤٹ پٹ کنفیگریشن میں موجود ہر ڈیٹابیس کا نام دکھاتا ہے، پھر وقفے وقفے سے آنے والی sync لائنوں کے علاوہ خاموش رہتا ہے۔ آپ کے ڈیٹابیس کے path کے لیے no such file or directory کی خرابی کا مطلب ہے کہ کنفیگریشن میں path غلط ہے یا process اسے پڑھ نہیں سکتا۔ یہ یونٹ بطور ڈیفالٹ root کے تحت چلتا ہے، جو اس کام کے لیے ضرورت سے زیادہ مراعات ہیں۔ Litestream کو ڈیٹابیس اور اسے رکھنے والی directory، دونوں کو پڑھنے اور لکھنے کی اجازت ہونی چاہیے، کیونکہ یہ آپ کے ڈیٹابیس کے ساتھ موجود -wal اور -shm فائلوں کے ساتھ کام کرتا ہے۔ اس لیے وہ account استعمال کریں جسے آپ کی application پہلے ہی استعمال کرتی ہے۔
# /etc/systemd/system/litestream.service.d/override.conf
[Service]
User=appuser
Group=appuserاسے sudo systemctl daemon-reload اور sudo systemctl restart litestream کے ذریعے نافذ کریں۔ کم سے کم مراعات والے dedicated service account کی تشکیل میں چند منٹ لگتے ہیں۔ یہی چیز backup agent اور machine پر چلنے والے دوسرے root process کے درمیان فرق پیدا کرتی ہے۔
اگر آپ کبھی machine کو مکمل طور پر دوبارہ بنائیں تو ترتیب کی ایک تفصیل اہم ہے۔ آپ چاہتے ہیں کہ application شروع ہونے سے پہلے ڈیٹابیس بحال ہو جائے۔ litestream restore، -if-db-not-exists قبول کرتا ہے، جو فائل پہلے سے موجود ہونے کی صورت میں 0 کے ساتھ ختم ہوتا ہے، اس لیے اسے ہر boot پر چلانا محفوظ ہے۔ اسے اپنی application کے unit میں ExecStartPre لائن کے طور پر شامل کریں۔ اس طرح نیا VPS ڈیٹابیس ڈاؤن لوڈ کر لے گا، جبکہ موجودہ VPS کچھ نہیں کرے گا۔ اگر آپ اسے ایک ہی جگہ رکھنا چاہیں تو litestream replicate میں اس کے مطابق -restore-if-db-not-exists flag موجود ہے۔
VPS پر SQLite کہاں ناکام ہوتا ہے
نیٹ ورک فائل سسٹمز۔ یہ وہ حد ہے جس کے گرد آپ configuration نہیں کر سکتے۔ WAL mode کے لیے ضروری ہے کہ database استعمال کرنے والے تمام processes memory کے ایک چھوٹے حصے کو مشترک طور پر استعمال کریں۔ یہ حصہ -shm file فراہم کرتی ہے۔ SQLite documentation میں یہ اصول بلا استثنا بیان کیا گیا ہے:
Database استعمال کرنے والے تمام processes ایک ہی host computer پر ہونے چاہئیں؛ WAL، network filesystem کے ذریعے کام نہیں کرتا۔
اس لیے mounted NFS (network file system) یا SMB share پر موجود database خراب ہو سکتا ہے، اور کوئی pragma اسے نہیں روک سکتا۔ یہاں ایک فرق ہے جسے لوگ نظر انداز کر دیتے ہیں۔ Network block device، جسے زیادہ تر VPS providers اضافی storage کے طور پر attach کرتے ہیں، Linux کو ایک عام disk کے طور پر نظر آتا ہے جس پر عام filesystem ہوتا ہے، اور یہ درست ہے۔ Mounted file share ایسا نہیں ہے۔
دوسرا application server۔ کوئی setting اسے کام نہیں کروا سکتی۔ جب ایک ہی data فراہم کرنے کے لیے دو machines درکار ہوں، تو آپ کو ایسے database کی ضرورت ہے جو network کے ذریعے کام کرے۔ اس منتقلی کا فیصلہ اس وقت کریں جب آپ کے پاس planning کے لیے ابھی وقت موجود ہو۔
Write-heavy workloads۔ ایک وقت میں صرف ایک writer کی اجازت file format کی خصوصیت ہے، tunable setting نہیں۔ مختصر writes کم لاگت ہوتی ہیں کیونکہ ہر commit، WAL میں append ہوتا ہے۔ اس لیے throughput، CPU کے مقابلے میں disk کی small-write latency سے زیادہ متاثر ہوتا ہے۔ دیکھیں VPS پر NVMe اور SATA SSD storage کا موازنہ تاکہ اس فرق کی عملی صورت معلوم ہو۔ اصل مسئلہ طویل transactions ہیں، کیونکہ وہ ہر دوسرے writer کو اپنی قطار میں انتظار کرواتی ہیں۔
Analytical queries۔ SQLite ایک row store ہے جسے transactions کے لیے بنایا گیا ہے۔ ایک سو million rows scan کرنے والا dashboard ایک مختلف tool کے لیے مختلف کام ہے، اور server کے کام کے لیے DuckDB اور SQLite کا موازنہ بتاتا ہے کہ یہ حد کہاں آتی ہے۔
Replication کے دوران VACUUM۔ مکمل VACUUM پورے database file کو دوبارہ لکھتا ہے۔ اس کا مطلب ہے کہ Litestream کو اسے دوبارہ مکمل طور پر upload کرنا پڑتا ہے، اور Litestream documentation replication فعال ہونے کے دوران اسے براہ راست چلانے کے خلاف مشورہ دیتی ہے۔ Replicator روکیں، vacuum چلائیں، اسے دوبارہ شروع کریں، اور نئے مکمل snapshot کی توقع رکھیں۔
ایک database پر دو replicators۔ ایک ہی database یا اسی replica destination کے خلاف کبھی بھی دو Litestream processes نہ چلائیں۔ Documentation واضح طور پر کہتی ہے کہ اس صورت حال کو روکنا آپ کی ذمہ داری ہے، اور اس کا نتیجہ ایسا replica ہوتا ہے جسے آپ restore نہیں کر سکتے۔
Litestream کا احاطہ کن چیزوں پر نہیں ہوتا
Litestream صرف database file کو محفوظ کرتا ہے، اس کے علاوہ کسی چیز کو نہیں۔ Uploaded files، application config، TLS (transport layer security) certificates اور unit files کی دیکھ بھال اب بھی آپ کی ذمہ داری ہے۔ مقررہ شیڈول کے مطابق اسے restic کے ذریعے encrypted off-box backups کے ساتھ استعمال کریں، تو دونوں پہلوؤں کا احاطہ ہو جاتا ہے۔ اگر machine نئی ہے، تو نئے VPS پر پہلے دس منٹ میں وہ user account اور firewall کا کام شامل ہے جسے یہ guide پہلے سے مکمل فرض کرتی ہے۔
FAQ
کیا پیداواری application کے لیے SQLite کافی ہے؟
ایک server پر ایک application کے لیے ہاں، بشرطیکہ آپ WAL mode فعال کریں، busy timeout مقرر کریں، اور مسلسل backup لیتے رہیں۔ اہم حدود ساختی ہیں: ایک وقت میں صرف ایک writer، اور صرف ایک host machine۔ جو application ان حدود کے اندر ہو، اسے network hop کے بغیر اور نگرانی کے لیے الگ process کے بغیر database ملتا ہے۔ جو application ان حدود میں نہ آئے، اسے client-server database درکار ہے، اور tuning کی کوئی مقدار اس بنیادی مسئلے کو تبدیل نہیں کر سکتی۔
busy_timeout مقرر کرنے کے بعد بھی database is locked کیوں ملتا ہے؟
کیونکہ انتظار کرنے سے deadlock پیدا ہونے کا امکان ہو تو SQLite busy handler کو نظرانداز کرتا ہے۔ جو transaction سادہ BEGIN سے شروع ہو، وہ deferred ہوتا ہے: ابتدائی SELECT اسے read transaction میں رکھتا ہے، اور بعد میں ہونے والی write کو upgrade کرنا پڑتا ہے۔ اگر اس دوران کسی دوسرے connection نے write کی ہو تو SQLite فوراً SQLITE_BUSY واپس کرتا ہے، busy handler کو کال نہیں کرتا، کیونکہ آپ کا read snapshot پہلے ہی پرانا ہو چکا ہوتا ہے۔ ایسی ہر transaction کو BEGIN IMMEDIATE سے شروع کریں جس میں write ہونی ہو، تاکہ write lock ابتدا ہی میں حاصل ہو جائے اور timeout نافذ ہو سکے۔
کیا میں اپنا SQLite database network storage پر رکھ سکتا ہوں؟
NFS یا SMB جیسے network filesystem پر نہیں۔ WAL mode کے لیے تمام processes کو -shm file کے ذریعے memory شیئر کرنا ضروری ہے، اور SQLite documentation کے مطابق database استعمال کرنے والا ہر process ایک ہی host computer پر ہونا چاہیے۔ آپ کے provider کا منسلک کردہ network block device مختلف چیز ہے: Linux اسے عام filesystem والے عام disk کے طور پر دیکھتا ہے، اور SQLite وہاں کام کرتا ہے۔
اگر میں پہلے ہی nightly backups چلا رہا ہوں تو کیا Litestream کی ضرورت ہے؟
یہ اس بات پر منحصر ہے کہ آپ کتنا data ضائع ہونے کے قابل ہیں۔ nightly job کا مطلب ہے کہ زیادہ سے زیادہ چوبیس گھنٹے کی writes ضائع ہو سکتی ہیں۔ Litestream تقریباً ہر second sync کرتا ہے، اس لیے crash کی صورت میں عموماً آخری second کا data ضائع ہوتا ہے۔ یہ cp کے ذریعے database file copy کرنے سے بھی زیادہ محفوظ ہے، کیونکہ اس طرح database کی write کے دوران بنائی گئی copy حاصل ہو سکتی ہے۔ Litestream صرف database کا احاطہ کرتا ہے، اس لیے اس کے ساتھ عمومی file backup بھی چلاتے رہیں۔