Buyukweb
SQLite Nedir ve Ne Zaman Kullanılır? Hafif Veritabanı Rehberi

SQLite Nedir ve Ne Zaman Kullanılır? Hafif Veritabanı Rehberi

SQLite nedir, nasıl kullanılır ve ne zaman tercih edilmeli? Dosya tabanlı veritabanının avantajları, kısıtlamaları ve yaygın kullanım senaryoları.

Büyükweb Editör EkibiHosting, Sunucu ve Sistem Yönetimi Editörü11 dakika okuma

SQLite Nedir ve Ne Zaman Kullanılır?

SQLite, sunucu gerektirmeyen, tek bir dosyada saklanan, kompakt ve hızlı bir ilişkisel veritabanı motorudur. Dünya üzerinde milyarlarca cihazda kullanılan en yaygın veritabanıdır.

SQLite'ın Benzersiz Özellikleri

  • Sunucusuz: Ayrı bir sunucu process çalıştırılmaz
  • Tek dosya: Tüm veritabanı tek .db dosyasında
  • Sıfır yapılandırma: Kurulum veya yönetim gerektirmez
  • ACID uyumlu: Transaction desteği tam
  • Taşınabilir: Dosyayı kopyalayın, taşıdınız
  • Gömülü: Uygulamanın içine dahil edilebilir

Kullanım Senaryoları

SQLite Uygun:

  • Mobil uygulamalar (iOS/Android)
  • Masaüstü uygulamalar
  • Küçük/orta web uygulamaları (< 100 eş zamanlı yazma)
  • Prototip ve geliştirme ortamları
  • Konfigürasyon dosyası yerine
  • Test veritabanı
  • Gömülü sistemler, IoT

SQLite Uygun Değil:

  • Yüksek eş zamanlı yazma operasyonları
  • Büyük ölçekli web uygulamaları
  • Çok kullanıcılı aynı anda yazma senaryoları
  • Ağ üzerinden erişim gereksinimleri

SQLite Locking Modeli — Concurrent Writes Sınırı

SQLite, "yüksek eş zamanlı yazma" senaryosunda neden zayıf? Cevap dosya seviyesi locking modelinde:

UNLOCKED  → Bağlantı açık ama I/O yok
   ↓
SHARED    → Birden fazla okuyucu okuyabilir
   ↓
RESERVED  → Bir yazar yazmaya hazırlanıyor (okuyucular hâlâ okuyabilir)
   ↓
PENDING   → Yazar tüm okuyucuların bitirmesini bekler
   ↓
EXCLUSIVE → Sadece yazar; başka hiç kimse erişemez

Sonuç: Aynı anda tek yazma yapılabilir. Yüksek concurrent write'ta SQLITE_BUSY döner.

busy_timeout — İlk Savunma Hattı

PRAGMA busy_timeout = 5000;  -- 5 saniye bekle, yine yer açılmazsa hata
import sqlite3
conn = sqlite3.connect('blog.db', timeout=5.0)  # Python eşdeğeri

BEGIN IMMEDIATE — Deadlock Önleme

İki yazar aynı anda BEGIN yaparsa deadlock olabilir. BEGIN IMMEDIATE baştan RESERVED lock alır:

BEGIN IMMEDIATE TRANSACTION;
INSERT ...;
UPDATE ...;
COMMIT;

Application-Level Retry Pattern

import sqlite3, time
def safe_write(query, params, retries=5):
    for i in range(retries):
        try:
            conn = sqlite3.connect('blog.db', timeout=5.0)
            conn.execute(query, params)
            conn.commit()
            return
        except sqlite3.OperationalError as e:
            if 'locked' in str(e):
                time.sleep(0.1 * (2 ** i))  # Exponential backoff
                continue
            raise
    raise Exception("DB still locked after retries")

WAL Modu — Detaylı Anlatım

WAL (Write-Ahead Logging) varsayılan rollback journal'a göre okuma + yazmayı paralel yapabilir:

PRAGMA journal_mode = WAL;       -- Aktif et
PRAGMA wal_autocheckpoint = 1000;  -- 1000 sayfa biriktiğinde otomatik flush

WAL Mode Dosyaları

WAL modu aktifken 3 dosya olur:

Dosya İçerik
blog.db Ana veritabanı
blog.db-wal Yazma günlüğü (henüz commit'lenmemiş)
blog.db-shm Paylaşılan bellek (multi-process koordinasyon)

⚠️ Yedekleme: WAL aktifken cp blog.db yetmez — blog.db-wal da kopyalanmalı veya sqlite3 blog.db ".backup yedek.db" kullanılmalı (atomik snapshot).

Manual Checkpoint

-- Tüm WAL içeriğini ana DB'ye flush et
PRAGMA wal_checkpoint(TRUNCATE);

-- veya pasif (mevcut yazarları engellemez)
PRAGMA wal_checkpoint(PASSIVE);

Pragma Optimizasyonu (Üretim Için)

-- Optimum üretim setup'ı
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;          -- Tam kayıp yerine cache flush; %5 hız artışı
PRAGMA cache_size = -64000;           -- 64 MB sayfa cache (negatif = KB)
PRAGMA temp_store = MEMORY;           -- Geçici tablo bellekte
PRAGMA mmap_size = 268435456;         -- 256 MB memory-map
PRAGMA foreign_keys = ON;             -- FK constraint aktif (default off!)
PRAGMA busy_timeout = 5000;

mmap ile read-heavy workload'da 3-5x hız artışı mümkün.

SQLite vs MySQL/PostgreSQL

Özellik SQLite MySQL PostgreSQL
Kurulum Yok Gerekli Gerekli
Eş zamanlı yazma Düşük Yüksek Yüksek
Ağ erişimi Hayır Evet Evet
Dosya boyutu Tek dosya Dizin Dizin
Kullanım kolaylığı Çok kolay Orta Orta
Ölçeklenebilirlik Düşük Yüksek Çok yüksek

SQLite Kurulumu

# Ubuntu/Debian
apt install sqlite3

# RHEL/Rocky Linux
dnf install sqlite

# macOS (genellikle kurulu)
sqlite3 --version

# Python ile kullanım (built-in)
python3 -c "import sqlite3; print('SQLite:', sqlite3.sqlite_version)"

sqlite3 CLI Kullanımı

# Veritabanı aç/oluştur
sqlite3 blog.db

# Yardım
.help

# Tablo listesi
.tables

# Tablo yapısı
.schema kullanicilar

# Çıktı formatı
.mode column
.headers on

# Dosyadan SQL çalıştır
.read init.sql

# Yedekle
.backup blog_backup.db

# Çıkış
.quit

SQL Operasyonları

-- Tablo oluştur
CREATE TABLE IF NOT EXISTS yazilar (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    baslik TEXT NOT NULL,
    icerik TEXT,
    tarih DATETIME DEFAULT CURRENT_TIMESTAMP,
    yazar TEXT,
    aktif INTEGER DEFAULT 1
);

-- Veri ekle
INSERT INTO yazilar (baslik, icerik, yazar)
VALUES ('Merhaba Dünya', 'İlk yazım...', 'Ahmet');

-- Sorgula
SELECT * FROM yazilar WHERE aktif = 1 ORDER BY tarih DESC LIMIT 10;

-- Güncelle
UPDATE yazilar SET aktif = 0 WHERE id = 5;

-- Sil
DELETE FROM yazilar WHERE id = 10;

-- Index
CREATE INDEX idx_yazar ON yazilar(yazar);

Python ile SQLite

import sqlite3
import os

# Bağlan (veya oluştur)
conn = sqlite3.connect('blog.db')
conn.row_factory = sqlite3.Row  # Dict benzeri erişim
c = conn.cursor()

# Tablo oluştur
c.execute('''CREATE TABLE IF NOT EXISTS yazilar
             (id INTEGER PRIMARY KEY, baslik TEXT, icerik TEXT)''')

# Veri ekle (parametre ile - SQL injection önlemi)
c.execute("INSERT INTO yazilar (baslik, icerik) VALUES (?, ?)",
          ("Başlık", "İçerik buraya"))
conn.commit()

# Sorgula
c.execute("SELECT * FROM yazilar")
yazilar = c.fetchall()
for yazi in yazilar:
    print(dict(yazi))

conn.close()

Node.js ile SQLite (better-sqlite3)

npm install better-sqlite3
const Database = require('better-sqlite3');
const db = new Database('blog.db');

// Tablo oluştur
db.exec(`CREATE TABLE IF NOT EXISTS yazilar (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    baslik TEXT NOT NULL,
    tarih TEXT DEFAULT CURRENT_TIMESTAMP
)`);

// Veri ekle
const insert = db.prepare('INSERT INTO yazilar (baslik) VALUES (?)');
insert.run('Yeni Yazı');

// Sorgula
const rows = db.prepare('SELECT * FROM yazilar').all();
console.log(rows);

// Transaction
const insertMany = db.transaction((yazilar) => {
    const stmt = db.prepare('INSERT INTO yazilar (baslik) VALUES (?)');
    for (const yazi of yazilar) {
        stmt.run(yazi.baslik);
    }
});
insertMany([{baslik: 'Yazı 1'}, {baslik: 'Yazı 2'}]);

PHP ile SQLite (PDO)

$pdo = new PDO('sqlite:/var/www/blog.db');
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$stmt = $pdo->prepare('SELECT * FROM yazilar WHERE aktif = ?');
$stmt->execute([1]);
$yazilar = $stmt->fetchAll(PDO::FETCH_ASSOC);

Yedekleme

# Dosya kopyası (en basit yedek)
cp blog.db blog_backup_$(date +%Y%m%d).db

# sqlite3 ile yedek
sqlite3 blog.db ".backup /backups/blog.db"

# SQL dump
sqlite3 blog.db ".dump" > blog_dump.sql

# Geri yükle
sqlite3 yeni_blog.db < blog_dump.sql

SQLite Modern Eklentileri — FTS5, JSON1, R-Tree

Mini Elasticsearch alternatifi. Türkçe tokenizer ile kullanım:

CREATE VIRTUAL TABLE yazilar_fts USING fts5(
    baslik, icerik, tokenize='unicode61'
);

-- Veri ekle
INSERT INTO yazilar_fts(baslik, icerik) VALUES
('SQLite Nedir', 'SQLite tek dosya veritabanı motorudur...');

-- Doğal arama
SELECT * FROM yazilar_fts WHERE yazilar_fts MATCH 'sqlite veritabanı';

-- BM25 ranking
SELECT *, bm25(yazilar_fts) as rank
FROM yazilar_fts WHERE yazilar_fts MATCH 'sqlite'
ORDER BY rank;

-- Highlight (snippet)
SELECT snippet(yazilar_fts, 1, '<b>', '</b>', '...', 30)
FROM yazilar_fts WHERE yazilar_fts MATCH 'sqlite';

Bu blog FTS5 ile çalışıyor — milisaniyenin altında 273 yazı arasında full-text arama.

JSON1 — Native JSON Desteği

-- JSON sütun
CREATE TABLE urunler (
    id INTEGER PRIMARY KEY,
    veri TEXT  -- JSON
);

INSERT INTO urunler(veri) VALUES
('{"isim": "Hosting", "fiyat": 199, "etiketler": ["cpanel", "linux"]}');

-- JSON içinden veri çek
SELECT json_extract(veri, '$.isim') FROM urunler;

-- JSON içinde filtre
SELECT * FROM urunler WHERE json_extract(veri, '$.fiyat') > 100;

-- JSON path index
CREATE INDEX idx_fiyat ON urunler(json_extract(veri, '$.fiyat'));

R-Tree — Coğrafi/Mesafe Sorgu

-- Nokta tabanlı R-Tree
CREATE VIRTUAL TABLE yerler_rtree USING rtree(
    id, lat_min, lat_max, lon_min, lon_max
);

-- 41.0,29.0 noktasına yakın yerler
SELECT * FROM yerler_rtree
WHERE lat_min <= 41.1 AND lat_max >= 40.9
  AND lon_min <= 29.1 AND lon_max >= 28.9;

GIS ihtiyaçı için bile SQLite kafi gelebilir; gerçek üretim ölçeğinde PostGIS daha uygun.

VACUUM, Bütünlük Kontrolü ve Üretim Yedekleme

VACUUM — Disk Fragmentasyonu

DELETE/UPDATE sonrası SQLite silinen sayfaları geri kullanmaz, sadece "boş" işaretler. VACUUM ana DB'yi yeniden inşa eder, sıkıştırır:

-- Manuel
VACUUM;

-- Otomatik (DELETE'lerde)
PRAGMA auto_vacuum = INCREMENTAL;
PRAGMA incremental_vacuum(100);

-- Belirli aralıkla VACUUM mantıklı (haftalık)

⚠️ VACUUM ana DB'nin tamamı kadar geçici disk ister. 10 GB veritabanı için 10 GB serbest disk gerek.

Bütünlük Kontrolü

PRAGMA integrity_check;        -- Tüm DB tarama
PRAGMA quick_check;            -- Hızlı (FK ve index sağlama)
PRAGMA foreign_key_check;      -- Sadece FK

Bozuk DB tespit edildiyse .dump ile SQL'e çevirip yeni dosyaya re-import.

Üretim Yedekleme — Online Backup API

# Atomic snapshot — uygulamayı durdurmadan yedek
sqlite3 blog.db ".backup /backups/blog-$(date +%F).db"

vs cp (yazma sırasında alındıysa bozuk yedek).

Cron Yedek

#!/bin/bash
# /usr/local/bin/sqlite-backup.sh
DB=/var/www/buyukweb/prisma/blog.db
DEST=/backups/sqlite
DATE=$(date +%F-%H%M)
mkdir -p $DEST
sqlite3 $DB ".backup $DEST/blog-$DATE.db"
gzip -9 $DEST/blog-$DATE.db
# 30 günden eski yedekleri sil
find $DEST -name "*.db.gz" -mtime +30 -delete
# Saatte bir
0 * * * * root /usr/local/bin/sqlite-backup.sh

Dağıtık SQLite — LiteFS, rqlite, Turso

SQLite'ın "tek node" sınırını çözen modern projeler:

Proje Yaklaşım Kullanım
LiteFS FUSE filesystem + replikasyon Fly.io edge deployment
rqlite Raft consensus + HTTP API High-availability cluster
Turso LibSQL + edge replication Globally distributed
Cloudflare D1 LibSQL + Cloudflare Workers Serverless edge DB
# rqlite — 3 node cluster
rqlited -node-id 1 -http-addr=:4001 -raft-addr=:4002 ./node1
rqlited -node-id 2 -http-addr=:4003 -raft-addr=:4004 -join 127.0.0.1:4002 ./node2
rqlited -node-id 3 -http-addr=:4005 -raft-addr=:4006 -join 127.0.0.1:4002 ./node3

# HTTP üzerinden sorgu
curl -G 'http://localhost:4001/db/query' --data-urlencode 'q=SELECT * FROM yazilar'

Bu çözümler SQLite'ı MySQL-class workload'a yaklaştırır ama kompleksite katar. Tek node yeterli olduğu sürece düz SQLite + iyi backup en sade yol.

WAL Modu (Performans)

-- WAL (Write-Ahead Logging) modu daha iyi eş zamanlı okuma sağlar
PRAGMA journal_mode=WAL;

-- Diğer önemli pragma'lar
PRAGMA synchronous=NORMAL;  -- Daha hızlı ama biraz daha az güvenli
PRAGMA cache_size=10000;    -- Önbellek sayfası sayısı
PRAGMA temp_store=MEMORY;   -- Geçici tabloları bellekte tut

Bu blog sitesi de SQLite kullanmaktadır. [Büyükweb hosting](MASK51) paketlerinde MySQL ile production-grade veritabanı çözümü sunuyoruz.


SQLite Sıkça Sorulan Sorular

SQLite ne zaman MySQL/Postgres'e geçmeli?

Eşik göstergeleri:

  1. Concurrent yazma > 100/saniye ve SQLITE_BUSY hataları artıyor
  2. DB boyutu > 50 GB ve VACUUM saatler sürüyor
  3. Multiple application server aynı DB'ye erişmeli (ağ üzerinden)
  4. Granular yetki (kullanıcı bazlı GRANT) gerek
  5. Hot standby / replication kritik

Büyükweb VDS üzerinde MySQL/MariaDB taşıma 1-2 saat sürer; manuel script + SQL dump ile risk az.

SQLite WordPress için uygun mu?

2024 sonrası WordPress 6.4+ resmi SQLite deneysel desteği sundu (SQLite Database Integration plugin). Düşük trafikli kişisel blog için tamam — ama eklenti ekosistemi MySQL bekleyebilir, edge case'ler çıkar. Üretim WP için MySQL hâlâ standart.

Tek dosya 281 TB'a kadar destekliyor mu?

Teorik tavan: 281 TB (PRAGMA page_size=65536 + max_page_count=4294967294). Pratik tavan: 100-200 GB sonrası VACUUM, backup, integrity check çok uzar. Bu noktadan önce MySQL/Postgres çoktan tercih edilmeli.

Bu blog gerçekten SQLite mi kullanıyor?

Evet — /blog/ sayfasındaki 273 yazının tamamı prisma/blog.db SQLite dosyasında. Üretimde read-heavy workload ile mükemmel çalışıyor; haftalık WAL checkpoint + günlük .backup cron + Prisma ORM ile tip güvenli sorgu.

Concurrent write performansını ne kadar artırabilirim?

PRAGMA journal_mode = WAL + busy_timeout + retry pattern ile dakikada birkaç bin yazma mümkün. Eşik 200-500 yazma/saniye geçince Postgres veya MySQL daha doğru.

SQLite encryption destekli mi?

Resmi sürümde yok. Üçüncü taraf opsiyonlar:

  • SQLCipher (open-source, AES-256, en yaygın)
  • SEE (SQLite Encryption Extension, ticari)
  • VFS-based encryption (custom implementation)

Veritabanı şifrelenecekse SQLCipher tercih.

Mobil uygulamalarda SQLite vs Realm?

SQLite: ACID-tam, SQL bilgisi gerek, daha küçük (~600 KB). Realm: ORM, daha modern API, encryption built-in, kütüphane daha büyük (~2 MB). Karmaşık veri ilişkileri için Realm daha rahat; tam SQL gücü gerekirse SQLite.

PRAGMA synchronous = OFF ne zaman güvenli?

Sadece "kaybetme önemli değil" sahte verilerde (test, geçici cache). OFF modunda power loss veya kernel crash → bozuk DB. Üretimde NORMAL (default WAL ile) en iyi denge.

Sıralanmak istediğim niş kelime için SQLite blog yeterli mi?

Sıralama açısından DB'nin SQLite ya da MySQL olması Google için fark etmez — render edilen HTML aynı. Önemli olan uptime + sayfa hızı + içerik kalıtesi. SQLite ile Türkiye lokasyonlu hosting kombinasyonu Core Web Vitals açısından LiteSpeed + MySQL'le rekabet eder.

İlgili Büyükweb Hizmetleri

Veritabanı performansı ve güvenilirliği için Türkiye lokasyonlu sunucu paketlerimiz:

Sorularınız için 0850 302 60 70 numaralı destek hattımıza veya iletişim sayfamıza yazabilirsiniz.

Veritabanı Yönetimi İlgili Hizmetlerimiz

Bu yazıda anlatılan teknik konuyu profesyonel altyapıyla deneyimleyin

Etiketler:

#sqlite#veritabanı#database#veri yönetimi

Bu yazıyı paylaş