VPS-এ SQLite production database হিসেবে ব্যবহার করবেন?
একটি VPS-এ ছোট অ্যাপের জন্য SQLite কেন যথেষ্ট, তা জানুন। WAL mode, busy_timeout, Litestream replication এবং কোন সীমায় PostgreSQL দরকার, সেটিও দেখুন।
যখন VPS-এ SQLite production database হিসেবে সঠিক পছন্দ
বেশিরভাগ ছোট অ্যাপ্লিকেশনের জন্য VPS-এ production পরিবেশে SQLite ব্যবহার করাই সঠিক পছন্দ। কারণটি সরল: একটি মেশিনে চলা একটি process যদি একটি file-এ লিখে, তাহলে তার জন্য আলাদা database server দরকার হয় না। supervise করার মতো কোনো daemon থাকে না, firewall-এ খোলার মতো কোনো port থাকে না, rotate করার মতো কোনো password থাকে না, এবং সচল রাখার জন্য দ্বিতীয় কোনো মেশিনও লাগে না। Query network round trip-এর পরিবর্তে একটি function call হিসেবে চলে। তাই একটি page-এ চল্লিশটি query থাকলে খরচ হয় চল্লিশটি function call।
সীমাবদ্ধতাও স্পষ্ট এবং বাস্তব। পুরো database file জুড়ে SQLite একসঙ্গে মাত্র একজন writer-কে অনুমতি দেয়, এবং file-টি দুইটি মেশিনের মধ্যে share করা যায় না। একটি VPS-এ একটি application চললে এই দুই সীমাই সমস্যা নয়। কিন্তু সেই কাঠামো ছাড়িয়ে গেলেই উভয় সীমা গুরুতর বাধা হয়ে দাঁড়ায়। এই guide-এ server-এ SQLite নিরাপদ রাখার settings, Litestream দিয়ে continuous backup এবং কখন SQLite ব্যবহার বন্ধ করা উচিত—এসব দেখানো হয়েছে।
প্রথমে command line tool install করুন। নিচের সব command Ubuntu 24.04-এ চালানো হয়েছে।
sudo apt update
sudo apt install -y sqlite3
sqlite3 --versionএটি এমন একটি version print করে, যা 3. দিয়ে শুরু হয় এবং তার পরে build date ও source hash থাকে। July 2026 অনুযায়ী Ubuntu 24.04-এ SQLite 3.45.1 release করা হয়েছে। আপনার application সম্ভবত এই binary ব্যবহার করে না। বেশিরভাগ language runtime SQLite library-এর নিজস্ব copy bundle করে, যা প্রায়ই আরও নতুন হয়। তাই সাম্প্রতিক কোনো feature-এর ওপর নির্ভর করার আগে আপনার database driver যে version report করে, সেটি যাচাই করুন।
WAL mode কেন প্রথমেই পরিবর্তন করবেন
ডিফল্টভাবে SQLite rollback journal ব্যবহার করে। কোনো page পরিবর্তনের আগে এটি মূল page-টি একটি -journal file-এ কপি করে, তারপর database-এ সরাসরি পরিবর্তন করে। নিরাপদে এই কাজ করতে পুরো file-এ exclusive lock নিতে হয়। তাই কোনো write চলার সময় প্রতিটি reader-কে অপেক্ষা করতে হয়। Laptop-এ এটি সাধারণত বোঝা যায় না। Web server-এ database ব্যবহার করা প্রতিটি request-কে একটি ধীর write আটকে দিতে পারে।
WAL (write-ahead log) mode এই ক্রম উল্টে দেয়। একটি writer নতুন page-গুলো আলাদা -wal file-এ যুক্ত করে এবং মূল database অপরিবর্তিত রাখে। Reader-রা যে snapshot দিয়ে শুরু করেছিল, সেই snapshot অনুযায়ী মূল file পড়তে থাকে। তাই reader writer-কে block করে না, এবং writer-ও reader-দের block করে না। পরে একটি checkpoint জমা হওয়া WAL page-গুলো মূল database-এ কপি করে। এই একটি পরিবর্তনই web application-এর পেছনে SQLite ব্যবহারযোগ্য করার প্রধান কারণ।
WAL mode চালু করে পরিবর্তন স্থায়ী হয়েছে কি না নিশ্চিত করুন
mkdir -p ~/app
sqlite3 ~/app/app.db "PRAGMA journal_mode=WAL;"কমান্ডটি wal প্রিন্ট করে। এই আউটপুটের কোনো আলংকারিক উদ্দেশ্য নেই। PRAGMA journal_mode ডেটাবেস বর্তমানে যে mode-এ আছে সেটি ফেরত দেয়। তাই delete উত্তর পাওয়ার অর্থ হলো পরিবর্তন ব্যর্থ হয়েছে এবং আপনি এখনও rollback journal ব্যবহার করছেন।
WAL mode স্থায়ী থাকে। এটি connection setting নয়; ডেটাবেস header-এর একটি flag। তাই প্রতিটি database file-এর জন্য এটি একবার চালালেই হয়। এরপর reboot-এর পরও প্রতিটি connection এটি উত্তরাধিকারসূত্রে পায়। নতুন একটি 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/এখন তিনটি file আছে: app.db, app.db-wal এবং app.db-shm। -wal file-এ এখনও checkpoint না হওয়া committed page থাকে। -shm file হলো shared memory index। প্রতিটি connection এটিকে map করে, যাতে সব connection WAL-এ কী আছে সে বিষয়ে একমত থাকে। উভয় file-ই ডেটাবেসের অংশ; এগুলো অস্থায়ী scratch file নয়। অ্যাপ্লিকেশন চলার সময় শুধু app.db copy করলে এমন একটি file পাবেন, যাতে সাম্প্রতিক সব commit অনুপস্থিত। app.db মুছে ফেলে অন্য দুটি file রেখে দিলে SQLite সেই পুরোনো WAL page-গুলো ওই নামে তৈরি হওয়া নতুন file-এ প্রয়োগ করবে। একটি ডেটাবেস reset করার চেষ্টা করার সময় এভাবেই নতুন database নষ্ট হয়ে যেতে পারে।
উৎপাদন পরিবেশের প্রতিটি অ্যাপের প্রয়োজনীয় connection settings
শুধু journal_mode database-এ সংরক্ষিত থাকে। নিচের অন্য সব setting প্রতিটি connection-এর জন্য আলাদা। অর্থাৎ আপনার অ্যাপ যে প্রতিটি connection খোলে, এমনকি pool যে connection-গুলো পেছনে তৈরি করে, সেগুলোর প্রতিটিতে এই setting প্রয়োগ করতে হবে।
PRAGMA journal_mode = WAL;
PRAGMA busy_timeout = 5000;
PRAGMA synchronous = NORMAL;
PRAGMA foreign_keys = ON;busy_timeout = 5000 SQLite-কে database locked থাকলে সর্বোচ্চ 5000 milliseconds পর্যন্ত পুনরায় চেষ্টা করতে বলে। এরপর এটি database is locked ফেরত দেয়। ডিফল্ট মান 0। তাই ডিফল্টভাবে দুইটি writer-এর কাজ একই সময়ে হলে SQLite প্রথমবারেই তাৎক্ষণিকভাবে ব্যর্থ হয়। শুধু এই একটি মান নির্ধারণ করলেই SQLite-এর ওপর দায় চাপানো বেশিরভাগ lock error দূর হয়।
synchronous = NORMAL WAL mode-এর জন্য সঠিক setting। তবে এর বিনিময়ে কী ত্যাগ করতে হয়, তা বোঝা জরুরি। FULL অবস্থায় SQLite প্রতিটি commit-এর সময় WAL-এ fsync চালায়। NORMAL অবস্থায় এটি checkpoint-এর সময় sync করে। SQLite documentation-এ এর সীমাবদ্ধতা স্পষ্টভাবে বলা আছে: power failure বা hard reset-এর পরে transaction আর durable থাকে না। সেই power loss-এর কারণে database corrupted হয় না। শুধু যেসব শেষ commit disk-এ লেখা হয়নি, সেগুলো হারিয়ে যায়। VPS-এ সাধারণত এটি উপযুক্ত বিনিময়। কারণ এতে প্রতিটি write-এর পথ থেকে একটি fsync বাদ যায়।
foreign_keys = ON backward compatibility-এর জন্য ডিফল্টভাবে বন্ধ থাকে এবং এটি প্রতি connection-এ আলাদাভাবে প্রযোজ্য। Schema-তে REFERENCES clause থাকলেও প্রতিটি connection এই setting চালু না করা পর্যন্ত সেগুলো কোনো constraint কার্যকর করে না।
আরেকটি setting পরে গুরুত্বপূর্ণ হয়ে ওঠে। WAL 1000 pages-এর বেশি বড় হলে SQLite স্বয়ংক্রিয়ভাবে checkpoint চালায়। সেই মুহূর্তে যে connection কোনো transaction শেষ করে, সেই connection-ই checkpoint-এর কাজ করে। একা ব্যবহারে এতে সমস্যা নেই। তবে Litestream চললে বিষয়টি গুরুত্বপূর্ণ হয়। কারণ checkpoint কখন হবে, Litestream তা নিয়ন্ত্রণ করতে চায়।
busy_timeout সেট করার পরও database is locked কেন ঘটে
এটি এমন একটি ব্যর্থতা, যার কারণে অনেকে আবার Postgres-এ ফিরে যান। এর একটি নির্দিষ্ট কারণ আছে।
Busy timeout একটি busy handler ইনস্টল করে। তবে SQLite busy handler কল করার নিশ্চয়তা দেয় না।
SQLite যদি নির্ধারণ করে যে busy handler কল করলে deadlock হতে পারে, তাহলে busy handler কল না করে সরাসরি application-এ SQLITE_BUSY ফেরত দেয়।
এটি যে deadlock এড়ায়, তা transaction upgrade করার সময় ঘটে। SQLite-এ খালি BEGIN বলতে BEGIN DEFERRED বোঝায়। এর পরের প্রথম statement যদি SELECT হয়, তাহলে আপনি একটি read transaction-এ আছেন। একই transaction-এ পরে কোনো UPDATE-কে write transaction-এ পরিণত করতে হলে, এবং আপনার read শুরু হওয়ার পর অন্য কোনো connection লিখে থাকলে, SQLite আপনাকে অপেক্ষা করাতে পারে না। কারণ আপনার snapshot ইতিমধ্যে পুরোনো হয়ে গেছে, এবং অপেক্ষা করালে দুই connection পরস্পরের জন্য deadlock তৈরি করবে। Documentation-এ ফলাফলটি সরাসরি বলা হয়েছে:
পরবর্তী write statement-গুলো সম্ভব হলে transaction-কে write transaction-এ upgrade করবে। অন্যথায় SQLITE_BUSY ফেরত দেবে।
আপনার 5000 millisecond timeout একবারও বিবেচনা করা হয় না। Error সঙ্গে সঙ্গে আসে। তাই মনে হয় setting কাজ করেনি।
সমাধানটি এক শব্দের।
BEGIN IMMEDIATE;
UPDATE notes SET body = 'edited' WHERE id = 1;
COMMIT;BEGIN IMMEDIATE শুরুতেই write lock নেয়, কিছু পড়ার আগেই। কোনো upgrade হয় না। তাই এড়ানোর মতো deadlock-ও থাকে না। ফলে busy handler কার্যকর হয় এবং connection ব্যর্থ না হয়ে নিজের পালার জন্য অপেক্ষা করে। Read-only transaction-গুলো deferred রাখুন। যে transaction-এ write থাকে, সেটি immediate হওয়া উচিত।
Lock error-এর দ্বিতীয় কারণটি শনাক্ত করা কঠিন: ধীর কাজ চলাকালে write transaction খোলা রাখা। SQLite writer-দের serialise করে। তাই কোনো transaction শুরু হয়ে network-এর মাধ্যমে external API কল করে, তারপর commit করলে, সেই কল চলার পুরো সময় অন্য সব 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 পড়ে পরিবর্তিত অংশ upload করে।
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জুলাই 2026 অনুযায়ী official Linux install page-এ v0.5.14 release নথিভুক্ত আছে, এবং 21 July 2026-এ v0.5.15 প্রকাশিত হয়েছে। releases page-এর বর্তমান tag অনুযায়ী উভয় লাইনে version পরিবর্তন করুন। আপনার VPS যদি arm64 হয়, তার বদলে একই version-এর 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-টি singular replica। Litestream 0.5 সংস্করণে 0.3 series-এর replicas array-এর বদলে একটি single replica block ব্যবহার করা হয়েছে। এখন configuration-এ দুটি entry থাকলে startup ব্যর্থ হয়। অনেক third-party guide-এ এখনও পুরোনো array দেখানো হয়। তাই search-এ পাওয়া প্রথম উদাহরণটি না নিয়ে উপরের কাঠামোটি কপি করুন। 0.5 series-এ litestream wal subcommand-এর নাম পরিবর্তন করে litestream ltx করা হয়েছে, কারণ on-disk backup format পরিবর্তিত হয়েছে।
কোনো কিছু enable করার আগে configuration parse হচ্ছে কি না পরীক্ষা করুন।
sudo litestream databases -config /etc/litestream.ymlএরপর হাতে পুরো round trip যাচাই করুন। এই পদ্ধতিতে configuration 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-এর সময়ে লেখা data সর্বোচ্চ হারাতে পারেন। কোনো configuration-ই এই ক্ষতি শূন্য করতে পারে না।
বাস্তব storage ব্যবহারের জন্য replica block-এর বদলে একটি S3 URL দিন। এটি Amazon S3 এবং অন্যান্য provider-এর 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 environment থেকে LITESTREAM_ACCESS_KEY_ID এবং LITESTREAM_SECRET_ACCESS_KEY পড়ে। তাই এগুলো root-এর মালিকানাধীন, mode 600-সহ একটি systemd drop-in file-এ রাখুন।
উপরের snapshot value-গুলো default। Retention-এর default অনেককে অবাক করে। Retention নির্ধারণ করে Litestream কতদিন snapshot এবং সেগুলোর প্রয়োজনীয় file সংরক্ষণ করবে। তাই অতীতে কতদূর পর্যন্ত restore করতে পারবেন, সেটিও এটি নির্ধারণ করে। Twenty-four hours হলে বুধবার সকালে ধরা পড়া একটি খারাপ migration-এর ক্ষেত্রে Monday-এর state থেকে আর recovery করা যাবে না। এক সপ্তাহের জন্য retention: 168h সেট করুন এবং অতিরিক্ত storage-এর খরচ বহন করুন।
প্রয়োজনের আগে restore যাচাই করুন
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;"একটি database path দিলে litestream restore, /etc/litestream.yml-এ মিল থাকা replica খুঁজে সেটি ডাউনলোড করে। সুস্থ file হলে PRAGMA integrity_check, ok প্রদর্শন করে। অন্য যেকোনো output দেখালে restored copy ব্যবহারযোগ্য নয়। একটি systemd service ও timer ব্যবহার করে এটি নির্ধারিত সময়সূচিতে চালান এবং output পড়ুন। অন্তত একবার backup restore না করা পর্যন্ত এটি কাজ করে কি না আপনি নিশ্চিতভাবে জানতে পারবেন না।
systemd-এর অধীনে Litestream চালান
Debian package একটি litestream unit ইনস্টল করে, যা /etc/litestream.yml পড়ে।
sudo systemctl enable litestream
sudo systemctl start litestream
sudo journalctl -u litestream -fসফল output-এ config থেকে প্রতিটি database-এর নাম দেখায় এবং এরপর নিয়মিত sync line ছাড়া নীরব থাকে। আপনার database path-এর ক্ষেত্রে no such file or directory error দেখালে config-এর path ভুল, অথবা process সেটি পড়তে পারছে না। ডিফল্টভাবে unit-টি root হিসেবে চলে, যা এই কাজের প্রয়োজনের তুলনায় বেশি privilege। Litestream-কে database এবং সেটি থাকা directory—উভয়ই পড়তে ও লিখতে সক্ষম হতে হবে, কারণ এটি আপনার database-এর পাশে থাকা -wal এবং -shm file নিয়ে কাজ করে। তাই আপনার application ইতিমধ্যে যে account ব্যবহার করে, সেই account নির্ধারণ করুন।
# /etc/systemd/system/litestream.service.d/override.conf
[Service]
User=appuser
Group=appusersudo systemctl daemon-reload এবং sudo systemctl restart litestream দিয়ে এটি প্রয়োগ করুন। কম privilege-সহ একটি নির্দিষ্ট service account তৈরি করতে কয়েক মিনিট সময় লাগে। এর মাধ্যমে backup agent এবং server-এ চলা দ্বিতীয় root process-এর মধ্যে মৌলিক পার্থক্য তৈরি হয়।
আপনি যদি কখনও শূন্য থেকে machine পুনর্নির্মাণ করেন, একটি execution order গুরুত্বপূর্ণ। Application শুরু হওয়ার আগে database restore করতে হবে। litestream restore, -if-db-not-exists গ্রহণ করে। File আগে থেকেই থাকলে এটি 0 exit status দিয়ে শেষ হয়, তাই প্রতিটি boot-এ চালানো নিরাপদ। আপনার application-এর unit-এ একটি ExecStartPre line হিসেবে এটি যোগ করুন। তাহলে নতুন VPS database download করবে, আর আগে থেকেই থাকা VPS কিছু করবে না। এটি এক জায়গায় রাখতে চাইলে litestream replicate-এ একই কাজের -restore-if-db-not-exists flag আছে।
VPS-এ SQLite যেখানে কাজ করে না
Network filesystem। এটি এমন একটি সীমা, যা configuration পরিবর্তন করে এড়ানো যায় না। WAL mode-এর জন্য database ব্যবহারকারী প্রতিটি process-কে memory-এর একটি ছোট অংশ share করতে হয়। -shm file এই কাজটি করে। SQLite documentation-এ কোনো ব্যতিক্রম ছাড়াই নিয়মটি বলা আছে:
একটি database ব্যবহারকারী সব process-কে একই host computer-এ থাকতে হবে; network filesystem-এর ওপর WAL কাজ করে না।
তাই mounted NFS (network file system) বা SMB share-এ রাখা database corrupt হতে পারে। কোনো pragma এটি প্রতিরোধ করতে পারে না। এখানে একটি পার্থক্য আছে, যা অনেকেই উপেক্ষা করেন। Network block device, যা অধিকাংশ VPS provider অতিরিক্ত storage হিসেবে সংযুক্ত করে, Linux-এর কাছে সাধারণ disk এবং তার ওপর থাকা সাধারণ filesystem হিসেবে দেখা যায়। এটি সমস্যা নয়। কিন্তু mounted file share আলাদা।
দ্বিতীয় application server। কোনো setting দিয়ে এটি কাজ করানো যায় না। একই data পরিবেশন করার জন্য যখন দুটি machine প্রয়োজন হয়, তখন network-এর মাধ্যমে কাজ করতে পারে এমন database প্রয়োজন। পরিকল্পনা করার সময় থাকা অবস্থাতেই এই পরিবর্তনের সিদ্ধান্ত নিন।
Write-heavy workload। একবারে একজন writer কাজ করতে পারা file format-এর বৈশিষ্ট্য; এটি tunable নয়। Short write দ্রুত হয়, কারণ প্রতিটি commit WAL-এ append হয়। তাই throughput আপনার CPU-এর চেয়ে disk-এর small-write latency-এর সঙ্গে বেশি সম্পর্কিত। এই পার্থক্য কেমন হয়, তা দেখতে VPS-এ NVMe ও SATA SSD storage-এর তুলনা দেখুন। আসল সমস্যা long transaction, কারণ এগুলো শেষ না হওয়া পর্যন্ত অন্য সব writer queue-তে অপেক্ষা করে।
Analytical query। SQLite transaction-এর জন্য তৈরি একটি row store। একশো million row scan করা dashboard-এর কাজ ভিন্ন, এবং তার জন্য ভিন্ন tool দরকার। server কাজের জন্য DuckDB ও SQLite-এর তুলনা-এ এই সীমারেখা কোথায়, তা ব্যাখ্যা করা হয়েছে।
Replication-এর সময় VACUUM। একটি সম্পূর্ণ VACUUM পুরো database file নতুন করে লেখে। ফলে Litestream-কে file-টির সম্পূর্ণ অংশ আবার upload করতে হয়। Litestream documentation replication সক্রিয় থাকা অবস্থায় এটি চালাতে নিষেধ করে। Replicator বন্ধ করুন, vacuum চালান, আবার চালু করুন, এবং নতুন full snapshot তৈরি হবে বলে ধরে নিন।
একটি database-এ দুটি replicator। একই database বা একই replica destination-এর বিরুদ্ধে কখনো দুটি Litestream process চালাবেন না। Documentation-এ স্পষ্টভাবে বলা আছে, এটি প্রতিরোধ করা আপনার দায়িত্ব। অন্যথায় এমন replica তৈরি হতে পারে, যা restore করা যাবে না।
Litestream যা কভার করে না
Litestream শুধু database file সুরক্ষিত রাখে। এর বাইরে কিছু নয়। Uploaded file, application config, TLS (transport layer security) certificate এবং unit file আপনাকেই পরিচালনা করতে হবে। নির্ধারিত সময়সূচিতে restic ব্যবহার করে encrypted off-box backup-এর সঙ্গে এটি ব্যবহার করলে উভয় দিকই কভার হয়। মেশিনটি নতুন হলে নতুন VPS-এ প্রথম দশ মিনিট অংশে user account এবং firewall-এর কাজ দেখানো আছে, যা এই guide-এ আগে থেকেই সম্পন্ন ধরে নেওয়া হয়েছে।
FAQ
একটি production application-এর জন্য কি SQLite যথেষ্ট?
একটি সার্ভারে একটি application চালালে এটি যথেষ্ট, তবে আপনাকে WAL mode চালু করতে হবে, busy timeout সেট করতে হবে এবং নিয়মিত backup নিতে হবে। গুরুত্বপূর্ণ সীমাবদ্ধতাগুলো কাঠামোগত: একই সময়ে একজন writer এবং একটি host machine। যে application এই সীমার মধ্যে থাকে, সেটি network hop ছাড়া এবং আলাদা কোনো process monitor না করেই database ব্যবহার করতে পারে। যে application এই সীমার মধ্যে থাকে না, তার client-server database প্রয়োজন। কোনো tuning এই সীমাবদ্ধতা পরিবর্তন করতে পারে না।
busy_timeout সেট করার পরও কেন database is locked পাচ্ছি?
কারণ অপেক্ষা করলে deadlock হতে পারে—এমন ক্ষেত্রে SQLite busy handler চালায় না। bare BEGIN দিয়ে শুরু হওয়া transaction deferred থাকে: শুরুতে একটি SELECT এটিকে read transaction-এ রাখে, পরে write করতে হলে সেটিকে upgrade করতে হয়। এর মধ্যে অন্য কোনো connection write করলে SQLite আপনার busy handler চালানোর বদলে সঙ্গে সঙ্গে SQLITE_BUSY ফেরত দেয়, কারণ আপনার read snapshot ইতিমধ্যে stale হয়ে গেছে। যে transaction-এ write হবে, সেটি BEGIN IMMEDIATE দিয়ে শুরু করুন। এতে শুরুতেই write lock নেওয়া হয় এবং timeout কার্যকর হয়।
network storage-এ কি SQLite database রাখতে পারি?
NFS বা SMB-এর মতো network filesystem-এ নয়। WAL mode-এর জন্য সব process-কে -shm file-এর মাধ্যমে memory share করতে হয়। SQLite documentation অনুযায়ী, database ব্যবহার করা প্রতিটি process-কে একই host computer-এ থাকতে হবে। আপনার provider সংযুক্ত করে দেওয়া network block device আলাদা বিষয়। Linux সেখানে একটি সাধারণ filesystem-সহ সাধারণ disk দেখতে পায়, তাই SQLite সেখানে কাজ করে।
আমি যদি ইতিমধ্যে nightly backup চালাই, তাহলে কি Litestream প্রয়োজন?
আপনি কতটা data হারানো মেনে নিতে পারেন, তার ওপর এটি নির্ভর করে। একটি nightly job চালালে সর্বোচ্চ twenty-four hours-এর write হারাতে পারেন। Litestream প্রায় প্রতি second-এ sync করে, তাই crash হলে আনুমানিক শেষ second-এর data হারায়। cp দিয়ে database file copy করার চেয়েও এটি নিরাপদ, কারণ copy চলাকালে database write হলে database-এর অসম্পূর্ণ অবস্থা ধরা পড়তে পারে। Litestream শুধু database সুরক্ষিত করে। তাই এর পাশাপাশি সাধারণ file backup চালু রাখুন।