lobste.rs, MariaDB'den SQLite'a geçti
(lobste.rs)- lobste.rs, MariaDB'den SQLite'a geçtikten sonra pazartesi günkü trafik sıçramasını da stabil biçimde karşıladı; CPU ve bellek kullanımında düşüş ile daha hızlı hissedilen yanıt süreleri gözlemlendi
- Ayrı MariaDB VPS'i kapatınca VPS maliyeti yarıya inecek ve 2019'da başlayan migrasyon görevi de tamamlanmış olacak
- İlk dağıtımda yalnızca salt okunur trafikle bile tüm CPU'lar %100'e ulaştığı için rollback yapıldı; ancak büyük tablolardaki 2 tam tablo taraması ve N+1 sorunu düzeltildikten sonra yeniden dağıtım başarıyla gerçekleşti
- SQLite kullanıcı tanımlı fonksiyonlarıyla
regexp,ifvestddevuygulanırken, unsigned bigint desteğinin olmaması ve yalnızca ASCII işleyenNOCASEgibi uyumluluk kısıtlarının da çözülmesi gerekti - Üretim veritabanına erişmeden temel DB'yi değiştirmek için gerçekçi boyutta test verisi, test suite'i, dağıtım/rollback kontrol listeleri ve yakın iş birliği gerekiyor
2019'daki tartışmadan SQLite geçişine
- Migrasyon tartışması 2019'da issue #539 ile başladı
- O dönemde MariaDB ile uyumluluk göz önüne alınarak alternatif olarak MySQL önerilmişti, ancak PostgreSQL'e geçiş tartışmaları zaten sürüyordu
- 2025'te Rahul, K1'in MariaDB'yi satın almasını gündeme getirince PostgreSQL migrasyonunun ayrıntılarına dair tartışma devam etti
- Şubat ayında Rahul, lobsters'ın SQLite üzerinde çalışıp çalışamayacağını sordu ve Haziran 2025'ten itibaren projeye katılım ciddi biçimde başladı
- Ağustos 2025'teki ilk PR, çalışma durduktan sonra GitHub tarafından eski PR olarak kapatıldı ve yeniden açılamadı
- İkinci PR performans testlerini, özel bir DB'ler arası migrasyon script'ini ve veri bütünlüğüyle ilgili hata ayıklamayı içeriyordu
- Mevcut MariaDB/MySQL→SQLite dönüştürme script'leri içinde gereksinimleri karşılayan olmadığı için ayrı bir script yazıldı
İlk dağıtım hatası ve performans darboğazlarının düzeltilmesi
- 21 Şubat'taki ilk dağıtım, bir dağıtım kontrol listesi hazırlanarak yapıldı; ancak dağıtımın hemen ardından salt okunur durumdaki trafik bile tüm CPU'ları %100 seviyesine çıkardı
- Neden bulunamadığı için rollback yapıldı
- Üretim DB'sine erişilemediğinden gerçek performans sorunlarını önceden yeniden üretmek zordu
- Başarısızlıktan iki gün sonra üçüncü ve nihai PR açılarak aramayla ilgili sorunlar düzeltildi ve gerçek lobsters verisinin yarısı büyüklüğünde veriyi yerelde oluşturan bir toplu veri üretme script'i eklendi
- Veriyi üretmek bir hafta sürdü
- İlk dağıtımdaki darboğaz, büyük tablolarda iki sorgunun neden olduğu tam tablo taramaları ve ayrı bir N+1 sorunuydu
- Bunları çözen değişiklik 1, değişiklik 2, değişiklik 3 dahil edildi
- Ek performans sorunlarını izleyebilmek için dağıtım sabahı yavaş sorgu log'u eklendi
Yeniden dağıtım sonucu ve operasyon maliyetlerinde düşüş
- 11 Temmuz'daki ikinci dağıtımda dağıtım ve rollback kontrol listeleri yeniden hazırlandı; geçişten sonra da site normal çalıştı, CPU ve bellek kullanımı stabil kaldı
- Site metrikleri ve IRC izlenirken bildirilen sorunlar düzeltme 1, düzeltme 2 ile hemen ele alındı
- Pazartesi günkü trafik sıçramasında da sorun yaşanmadı; CPU ve bellek kullanımının düştüğü ve yanıtların daha hızlı hissedildiği doğrulandı
- MariaDB VPS kapatıldığında VPS maliyeti yarıya inecek ve migrasyon issue'su da kapanacak
SQLite'ın MariaDB'den farklı kısıtları
- SQLite gem'inin kullanıcı tanımlı fonksiyon (UDF) desteği kullanılarak SQLite'ta bulunmayan
regexp,if,stddevuygulandı- SQL migrasyonu için aşırı miktarda workaround eklemeye gerek kalmadı
- MariaDB'de bazı ID'ler için kullanılan unsigned bigint SQLite tarafından desteklenmediğinden bigint'e değiştirildi
- Sıralama kuralları da MariaDB'ye göre daha sınırlı
- MariaDB'de
utf8mb4_general_cikullanılıyordu, SQLite'ta iseNOCASEuygulandı NOCASE, tüm UTF büyük/küçük harf katlamasını desteklemez ve yalnızca ASCII karakterleri işler
- MariaDB'de
- SQLite tam metin arama tabloları için varsayılan olmayan ama önerilen yaklaşım olan Contentless-Delete Tables uygundur
- Rails'in varsayılan PRAGMA ayarları lobsters'ta sorunsuz çalıştı
- Veritabanı migrasyonları DB'ye göre değiştiğinden mevcut migrasyonlar old_migrations dizinine taşındı ve
db:migrate'in çalışmaya devam etmesi sağlandı
- Veritabanı migrasyonları DB'ye göre değiştiğinden mevcut migrasyonlar old_migrations dizinine taşındı ve
Test ve iş birliğinden çıkarılan dersler
- lobsters kod tabanında arama parser'ı ve render hızını artıran bir hack olan heinous_inline_partials görüldü
- Test suite'i sayesinde, geniş kapsamlı manuel test olmadan SQLite geçişinin doğruluğu doğrulanabildi
- Katılımcılar arasındaki sorunsuz iletişim migrasyonun başarısını belirledi
- Üretim DB'sine erişim olmadan temel veritabanını değiştirmek çok zordu
- Aynı iş yeniden yapılacak olsa önceden gerçekçi veri ölçeği hazırlanmalı
- Test sırasında tam tablo taraması oluştuğunda başarısız olacak şekilde ayar yapılabilseydi, ilk dağıtımdaki performans sorunu önceden yakalanabilirdi
- Üretime benzer veri setlerini doğrudan yazmadan veya birer hafta beklemeden kolayca oluşturabilecek araçlara ihtiyaç var
1 yorum
Lobste.rs görüşleri
@thomas0 büyük ölçekli migrasyonu titizlikle üstlendi, @355E3B planlama ve operasyon tarafında yardımcı oldu; ayrıca #539 ile ilgili katkı sunanlara ve #lobsters sayesinde salt okunur dönemi de keyifle atlatabildiler
Aslında #539'da PostgreSQL planlanmıştı, ancak işi fiilen üstlenen gönüllü SQLite kullandı ve beklenen ihtiyaçtan daha büyük ve karmaşık bir çözümden kaçınmak istedikleri için SQLite seçildi. PostgreSQL normalde varsayılan tercihleri olsa da ayrı bir servisi çalıştırma, ayarlama ve bakım yükü getiriyor
Şaşırtıcı biçimde migrasyondan sonra CPU ve RAM kullanımı da azaldı; ayrıntılı grafikler #539'un son kısmında yer alıyor
SQLite'ın varsayılan ayarlarına her baktığımda şaşırıyorum. WAL, foreign key,
synchronous=NORMALgibi ayarları varsayılan sunan yeni proje modu olsa iyi olurdu; bunun dışında da iyileştirilebilecek başka varsayılanlar var gibi görünüyorSQLite veritabanı için yedekleme stratejisinin ne olduğunu merak ediyorum. litestream gibi bir araç mı kullanılıyor, yoksa başka bir yöntem mi var bilmek isterim
lobste.rs'te güncelleme işleri nasıl ele alınıyor, merak ediyorum
SQLite'ta zaten iif fonksiyonu var, ama aynı alanda kullanıcı tanımlı fonksiyonlar çalıştırma fikri de başlı başına ilginç
SQLite'ın PostgreSQL ya da MySQL düzeyinde eşzamanlılık desteklemediğini sanıyordum, ancak genel bakış belgesine bakınca artık birden fazla proses tarafından kullanılabildiğini görüyorum; bunu lobste.rs'in yine de tek sunucuda çalışması gerektiği şeklinde mi anlamalıyım
Prosesler paylaşımlı bellek veya
mmapbenzeri bir mekanizmayla SQLite içinde senkronize olup aynı anda yalnızca tek yazmaya mı izin veriyor ve birden çok okumayı mı destekliyor; bekleyen yazma işleri de sırayla kuyrukta mı bekliyor, onu da merak ediyorumYazma bekleme tarafında açık bir paylaşımlı bellek kuyruğu yerine kısa süre bekleyip yeniden deneme yaklaşımı kullanılıyor gibi görünüyor. SQLite'ı birden fazla makinede kullanmanın tamamen imkansız olup olmadığından emin değilim, ancak dosyayı NFS ile paylaşma gibi basit yaklaşım açıkça önerilmediği için tek sunucu diye düşünmek makul bir yaklaşık olur; zaten günümüzde tek makineyle de oldukça büyük ölçekler taşınabiliyor
busy_timeout'un çalışması için immediate transaction mode da etkinleştirilmeli Başvuru için https://fractaledmind.github.io/2024/04/… ile https://kerkour.com/sqlite-for-servers ve https://www.sqlite.org/lang_transaction.html#immediate bağlantılarına bakılabilir; ayrıntılar özellikle ikinci bağlantıdakiSQLITE_BUSYbölümünde ve üçüncü bağlantıda yer alıyorPR, issue ve Gist'te ayrıntıları çok iyi belgelenmiş, etkileyici bir yükseltme olmuş. Bu değişiklikle site içi arama gibi işlevsel farklar ortaya çıktı mı ve şu anki SQLite dosyasının diskteki boyutu ne kadar, merak ediyorum
SQLite dosya boyutunun bir yerde 3.8GB olarak söylendiğini hatırlıyorum