lobste.rs, MariaDB से SQLite पर स्विच
(lobste.rs)- lobste.rs ने MariaDB से SQLite पर स्विच करने के बाद सोमवार के ट्रैफ़िक स्पाइक को भी स्थिर रूप से संभाला, और CPU·मेमोरी उपयोग में कमी तथा तेज़ महसूस होने वाली responsiveness की पुष्टि की
- अलग MariaDB VPS को बंद करने पर VPS लागत आधी हो जाएगी, और 2019 में शुरू हुआ migration काम भी पूरा हो गया
- पहली deployment में केवल read-only ट्रैफ़िक से ही सभी CPU 100% तक पहुँच गए और rollback करना पड़ा, लेकिन बड़े tables पर हुए 2 full table scans और N+1 समस्या को ठीक करने के बाद दोबारा deployment सफल रही
- SQLite user-defined functions के ज़रिये
regexp·if·stddevको implement किया गया, वहीं unsigned bigint के non-support और केवल ASCII संभालने वालेNOCASEजैसी compatibility सीमाओं को भी हल करना पड़ा - production database तक पहुँच के बिना underlying DB बदलने के लिए वास्तविक आकार का test data, test suite, deployment·rollback checklist और करीबी सहयोग की ज़रूरत होती है
2019 की चर्चा से SQLite migration तक
- migration पर चर्चा 2019 में issue #539 से शुरू हुई
- उस समय MariaDB compatibility को देखते हुए MySQL को एक विकल्प के रूप में सुझाया गया था, लेकिन PostgreSQL migration पर चर्चा पहले से चल रही थी
- 2025 में Rahul ने K1 द्वारा MariaDB के अधिग्रहण का ज़िक्र किया, जिसके बाद PostgreSQL migration की details पर चर्चा आगे बढ़ी
- फ़रवरी में Rahul ने पूछा कि क्या lobsters को SQLite पर चलाया जा सकता है, और 2025 के जून से project में भागीदारी गंभीर रूप से शुरू हुई
- अगस्त 2025 का पहला PR काम रुक जाने के बाद GitHub द्वारा पुराने PR के रूप में बंद कर दिया गया, इसलिए उसे फिर से खोला नहीं जा सका
- दूसरे PR में performance testing, अपना DB-के-बीच migration script, और data integrity से जुड़ी debugging शामिल थी
- मौजूदा MariaDB/MySQL→SQLite conversion scripts में से कोई भी ज़रूरतें पूरी नहीं करता था, इसलिए अलग script लिखी गई
पहली deployment की विफलता और performance bottleneck में सुधार
- 21 फ़रवरी की पहली deployment deployment checklist तैयार करके की गई, लेकिन deployment के तुरंत बाद read-only स्थिति के ट्रैफ़िक से ही सभी CPU 100% तक पहुँच गए
- कारण का पता न लगने पर rollback किया गया
- production DB तक पहुँच न होने के कारण असली performance समस्या को पहले से reproduce करना मुश्किल था
- विफलता के दो दिन बाद तीसरा और अंतिम PR खोला गया, जिसमें search से जुड़ी समस्याएँ ठीक की गईं और असली lobsters data के लगभग आधे आकार का local dataset बनाने वाली bulk data generation script जोड़ी गई
- data generate करने में एक हफ़्ता लगा
- पहली deployment का bottleneck बड़े tables पर दो queries से हुए full table scans और अलग N+1 समस्या थी
- इसे ठीक करने वाले change 1, change 2, change 3 लागू किए गए
- अतिरिक्त performance समस्याओं को track करने के लिए deployment वाले दिन सुबह slow query log भी जोड़ा गया
दोबारा deployment के नतीजे और operating cost में कमी
- 11 जुलाई की दूसरी deployment में deployment·rollback checklist फिर से तैयार की गई, और switch के बाद भी साइट सामान्य रूप से चलती रही, साथ ही CPU और मेमोरी उपयोग भी स्थिर रहे
- साइट metrics और IRC की निगरानी करते हुए रिपोर्ट की गई समस्याओं को fix 1, fix 2 से तुरंत संभाला गया
- सोमवार के ट्रैफ़िक स्पाइक में भी कोई समस्या नहीं हुई, और CPU·मेमोरी उपयोग में कमी तथा तेज़ महसूस होने वाली responsiveness की पुष्टि हुई
- MariaDB VPS बंद करने पर VPS लागत आधी हो जाएगी, और migration issue भी बंद कर दिया गया
SQLite की वे सीमाएँ जो MariaDB से अलग थीं
- SQLite gem के user-defined function (UDF) support का उपयोग करके SQLite में मौजूद न रहने वाले
regexp,if,stddevimplement किए गए- इससे SQL migration के लिए बहुत ज़्यादा workaround जोड़ने की ज़रूरत नहीं पड़ी
- MariaDB में कुछ IDs के लिए इस्तेमाल होने वाले unsigned bigint को SQLite support नहीं करता, इसलिए उसे bigint में बदला गया
- sorting rules भी MariaDB की तुलना में अधिक सीमित हैं
- MariaDB में
utf8mb4_general_ciइस्तेमाल होता था, लेकिन SQLite मेंNOCASEलागू किया गया NOCASEपूरे UTF case folding को support नहीं करता और केवल ASCII characters संभालता है
- MariaDB में
- SQLite full-text search tables के लिए default की बजाय अनुशंसित तरीका Contentless-Delete Tables अधिक उपयुक्त है
- Rails की default PRAGMA settings lobsters में सही तरह काम करती हैं
- database migrations DB के अनुसार अलग होती हैं, इसलिए पुरानी migrations को old_migrations directory में ले जाया गया ताकि
db:migrateकाम करता रहे
- database migrations DB के अनुसार अलग होती हैं, इसलिए पुरानी migrations को old_migrations directory में ले जाया गया ताकि
testing और collaboration से मिली सीख
- lobsters codebase में search parser और rendering speed बढ़ाने वाले hack heinous_inline_partials की पहचान हुई
- test suite की वजह से बड़े पैमाने पर manual testing के बिना SQLite switch की correctness verify की जा सकी
- प्रतिभागियों के बीच smooth communication ने migration की सफलता में निर्णायक भूमिका निभाई
- production DB तक पहुँच न होने की स्थिति में underlying database बदलना बेहद मुश्किल था
- अगर यही काम फिर से करना हो, तो पहले से वास्तविक data scale तैयार रखना चाहिए
- अगर testing के दौरान full table scan होने पर failure सेट किया जा सकता, तो पहली deployment की performance समस्या पहले ही पकड़ी जा सकती थी
- production जैसी dataset को हाथ से लिखे बिना या एक-एक हफ़्ता इंतज़ार किए बिना आसानी से बनाने वाले tools की ज़रूरत है
1 टिप्पणियां
Lobste.rs की राय
@thomas0 ने बड़े migration को बहुत सावधानी से संभाला, @355E3B ने planning और operations में मदद की, और #539 से जुड़े contributors व #lobsters की वजह से read-only समय भी मज़ेदार तरीके से निकल गया
मूल रूप से #539 में PostgreSQL की योजना थी, लेकिन असल काम करने वाले volunteer ने SQLite इस्तेमाल किया, और अपेक्षित demand से बड़ी व जटिल solution से बचना चाहते थे, इसलिए SQLite चुना गया। PostgreSQL आम तौर पर default choice होता है, लेकिन एक अलग service को चलाने, tune करने और maintain करने का बोझ होता है
हैरानी की बात है कि migration के बाद CPU और RAM usage दोनों घट गए, और detailed charts #539 के आखिरी हिस्से में हैं
SQLite की default settings देखने पर हर बार हैरानी होती है। नए projects के लिए कोई mode हो तो अच्छा होगा जिसमें WAL, foreign keys,
synchronous=NORMALआदि default रूप से मिलें, और इनके अलावा भी सुधारने लायक default values शायद और होंSQLite database की backup strategy को लेकर जिज्ञासा है। क्या litestream जैसे tools इस्तेमाल किए जाते हैं, या कोई दूसरा तरीका है, यह जानना चाहूंगा
lobste.rs में update operations कैसे handle किए जाते हैं, यह जानना चाहूंगा
SQLite में पहले से iif function है, लेकिन उसी domain में user-defined functions चलाना अपने-आप में भी दिलचस्प है
मुझे लगता था कि SQLite, PostgreSQL या MySQL जैसी concurrency support नहीं कर पाता, लेकिन overview document को देखकर क्या अब यह समझना सही है कि इसे कई processes से इस्तेमाल किया जा सकता है, बस lobste.rs को single server पर चलना होगा?
यह भी जानना चाहूंगा कि क्या processes shared memory या
mmapजैसे तरीकों से SQLite के अंदर synchronize होकर केवल एक concurrent write और कई reads की अनुमति देते हैं, और क्या pending writes queue में अपनी बारी का इंतज़ार करते हैंwrite waiting के लिए explicit shared-memory queue नहीं, बल्कि थोड़ी देर wait करके retry करने का तरीका इस्तेमाल होता दिखता है। कई machines पर SQLite इस्तेमाल करना पूरी तरह असंभव है या नहीं, यह पक्का नहीं है, लेकिन NFS से file share करने वाला simple approach स्पष्ट रूप से recommend नहीं किया गया है, इसलिए इसे single server मानना एक उचित approximation है; और आजकल एक machine भी काफी scale handle कर सकती है
busy_timeoutकाम करे इसके लिए immediate transaction mode भी enable करना होता है संदर्भ सामग्री https://fractaledmind.github.io/2024/04/… और https://kerkour.com/sqlite-for-servers तथा https://www.sqlite.org/lang_transaction.html#immediate हैं; दूसरे link केSQLITE_BUSYहिस्से और तीसरे link में details देखी जा सकती हैंPR, issue और Gist में details बेहद अच्छी तरह व्यवस्थित हैं—यह एक impressive upgrade है। इस बदलाव से site search जैसी functional differences आई हैं या नहीं, और मौजूदा SQLite file का disk size कितना है, यह जानना चाहूंगा
SQLite file size के बारे में याद है कि कहीं 3.8GB बताया गया था