Veritabanları (Databases)

Bir yazılım projesinde, verileri organize bir şekilde saklayarak gerektiğinde bu verilere ulaşmak için veritabanları kullanılır. Veritabanları, verilerin güvenilir bir şekilde tutulmasını sağlarken veri erişimini hızlandırır ve verilerin güvenliğini sağlar. Peki, veritabanları nasıl çalışır ve hangi türleri vardır?

Veritabanı Türleri#

Veritabanları genel olarak SQL (yapısal) ve NoSQL (yapısal olmayan) olmak üzere iki ana türe ayrılır. Bu iki tür arasındaki temel farklar, veri organizasyonu ve sorgulama şekillerinde görülür.

1. SQL Veritabanları#

SQL veritabanları, verilerin tablo yapısında saklandığı ve Structured Query Language (SQL) ile sorgulandığı ilişkisel veritabanlarıdır. Veriler, satırlar ve sütunlar halinde düzenlenir ve tablolar arasında güçlü ilişkiler kurulur.

SQL Veritabanı Şema ve Sorgu Örneği Örneğin, bir e-ticaret sitesi için ürünler ve siparişler tablolarını içeren bir şema:

-- Ürünler tablosu
CREATE TABLE products (
    product_id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    price DECIMAL(10, 2),
    stock INT
);

-- Siparişler tablosu
CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    product_id INT REFERENCES products(product_id),
    quantity INT,
    order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Bu şema ile örnek bir sorgu:

-- Fiyatı 50’den büyük ürünleri getirme
SELECT name, price 
FROM products 
WHERE price > 50;

-- Siparişlerin detaylarını ürün bilgileriyle birlikte getirme
SELECT o.order_id, p.name AS product_name, o.quantity, o.order_date
FROM orders o
JOIN products p ON o.product_id = p.product_id;

SQL veritabanları, güçlü veri bütünlüğü ve ilişkisel yapı gerektiren durumlarda kullanılır.

2. NoSQL Veritabanları#

NoSQL veritabanları, yapısal olmayan veya esnek veri organizasyonuna sahip veritabanlarıdır. Belge tabanlı, anahtar-değer çiftleri, grafik veya geniş sütunlu veritabanları olarak sınıflandırılabilir. Bu veritabanları esnek yapısı nedeniyle büyük ve çeşitli verilerle çalışmak için uygundur.

NoSQL Veritabanı Şema ve Sorgu Örneği

Bir NoSQL örneği olarak MongoDB’de bir ürün koleksiyonu ve buna bağlı bir sorgu:

[{
  "_id": "1",
  "name": "Laptop",
  "price": 1200,
  "stock": 30,
  "category": "electronics"
},
{
  "_id": "1",
  "name": "Laptop",
  "price": 1200,
  "stock": 30,
}]

Her döküman her anahtara sahip olmak zorunda değil, ilişkisel veritabanlarında tablolar ve sütunlar sabit ve her satır tüm sütunlar için bir bilgi alanına sahiptir. Bu alanlar boş olsa bile ilişkisel veritabanları veriyi aynı yapıda saklar. Ancak burada durum değişebilir, örneğin category alanı sadece belirli ürünlerde olabilir.

// Fiyatı 1000’den büyük olan ürünleri getir
db.products.find({ price: { $gt: 1000 } });

NoSQL veritabanları, hızlı erişim ve yatay ölçeklenebilirlik gerektiren büyük verilerle çalışmak için idealdir.

Veritabanına Erişim#

Veritabanlarına erişim, sunucu yapılandırmasına ve veritabanı türüne göre farklı şekillerde yapılabilir. Genel olarak iki ana veritabanı erişim türü vardır: lokal veritabanları ve ağa bağlı (networked) veritabanları.

Lokal Veritabanları#

Lokal veritabanları, doğrudan cihaz üzerinde çalışan ve bir ağ aracılığıyla erişimi olmayan veritabanlarıdır. Bu tür veritabanları, özellikle mobil uygulamalarda veya küçük çaplı projelerde, veriye çevrimdışı erişim sağlamak için kullanılır. Uygulamanın bir internet erişimi olsa bile kısa süreli senkronizasyon işlemleri için anlık veritabanları oluşturulup işlem tamamlandıktan sonra kaldırılabilmektedir. Örneğin, SQLite tek bir dosya üzerinde işlem yaparak çalışan hızlı ve oldukça kapasiteli bir veritabanı uygulamasıdır. Mobil uygulamanızda kullanmak için cihaz üzerinde bir sqlite veritabanı oluşturup uygulama verilerinizi kontrol edebilirsiniz.

Ağa Bağlı Veritabanları#

Ağa bağlı veritabanları, istemcilerin uzaktaki bir sunucu üzerinden veritabanına erişmesini sağlar. Bu tür veritabanları, web uygulamaları ve daha büyük projelerde yaygındır. İstemciler veritabanı sunucusuna API’ler veya doğrudan bağlantılar aracılığıyla erişerek verilere ulaşır veya veri ekler. Örneğin PostgreSQL ve MySQL gibi çok bilinen veritabanları varsayılan olarak kuruldukları bilgisayar üstünde bir port üzerinden erişilebilir hale geliyorlar. Bunu lokal olarak veya ağ üzerinde kullanmak tabi ki sizin tercihinizde.

Veritabanı Ölçekleme#

Bir veritabanına erişim sayısı veya veri miktarı arttığında, veritabanının performansını korumak için ölçekleme yöntemlerine başvurulması gerekir. Bu tür durumlarda genellikle iki tip ölçeklemeden bahsedebiliriz, aslında bu ölçeklemeler sadece veritabanları için değil tüm sunucu tipleri için düşünülebilir.

1. Dikey Ölçekleme (Vertical Scaling)#

Dikey ölçekleme, veritabanı sunucusunun daha güçlü bir donanımla güncellenmesini içerir. CPU, RAM veya depolama kapasitesi arttırılarak mevcut sunucunun performansı yükseltilir. Ancak, dikey ölçeklemenin bir sınırı vardır; belirli bir donanım seviyesinin üzerine çıkmak maliyetli veya mümkün olmayabilir.

2. Yatay Ölçekleme (Horizontal Scaling)#

Yatay ölçekleme, veritabanını birden çok sunucuya dağıtarak yapılır. Veritabanı, veri parçaları halinde farklı sunucularda tutulur. Bu sayede daha fazla bağlantı ve veri yükü dağıtılabilir. Yatay ölçekleme, NoSQL veritabanlarında daha yaygındır çünkü veri kolayca parçalanabilir.


Her ölçekleme yönteminin getirdiği avantajlar ve dezavantajlar vardır. Örneğin dikine ölçekleme fiziki olarak mümkün olmayabilir, anakart üzerinde yeterli slot olmayabilir diğer donanım aygıtlarının limitleri size engel teşkil edebilir. Dikey ölçekleme fiziksel olarak mümkün iken sunucuyu yeniden başlatma gibi bir zorunluluk olabilir, hizmet kesintisinin mümkün olmadığı durumlarda bu problem çıkaracaktır.

Yatay ölçeklemede fiziki olarak bir sınır olmasa da yükü dağıtmak yeni problemlere yol açacaktır. Örneğin veritabanını iki farklı sunucuda çalıştırdığınızda verinizi senkronize etmek için yöntemler bulmak zorundasınız. Veya iki sunucuya yükü dağıtmak için bir başka sunucuya da ihtiyacınız olacak. Üstelik birden fazla sunucunun aynı anda çalıştığı durumlarda bir yada birden fazla sunucunun servis dışı kalması yine uygulamanızda problemlere yol açabilir.

Veritabanlarında ACID Prensipleri#

ACID prensipleri, veritabanı sistemlerinde veri bütünlüğünü sağlamak için kullanılan dört temel ilkeden oluşur: Atomiklik, Tutarlılık, Yalıtım ve Dayanıklılık. Bu prensipler, özellikle SQL veritabanlarında veri güvenilirliğini korumak için yaygın olarak uygulanır; ancak bazı SQL veritabanları, performans veya esneklik gereksinimleri nedeniyle bu prensiplerin tamamını tam olarak desteklemeyebilir.

Her bir prensibi ve örneklerini inceleyelim:

1. Atomiklik (Atomicity)#

Atomiklik, bir işlemdeki tüm adımların ya tamamen başarılı olması ya da hiç yapılmamış olması gerektiğini ifade eder. Örneğin, bir banka işleminde bir hesaptan para çekilip diğer hesaba yatırılıyorsa, her iki adımın da başarılı olması gerekir. Aksi takdirde, işlem geri alınarak her iki hesabın bakiyesi de ilk durumuna döndürülür.

Örnek: Bir SQL işlemi, Alice’in hesabından 100 TL çekip Bob’un hesabına yatırıyorsa, işlem sırasında hata olursa 100 TL’nin Alice’in hesabından çıkıp Bob’a ulaşmaması sağlanır:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE user = 'Alice';
UPDATE accounts SET balance = balance + 100 WHERE user = 'Bob';
COMMIT;

Eğer herhangi bir adım başarısız olursa, ROLLBACK komutuyla işlem geri alınır ve veritabanı eski haline döner.

2. Tutarlılık (Consistency)#

Tutarlılık, bir işlem tamamlandığında veritabanının belirli kurallar çerçevesinde kalması gerektiğini ifade eder. Bu prensip, işlem öncesi ve sonrası veritabanının tanımlanan kısıtlamalara uygun olmasını sağlar. Örneğin, negatif bir bakiye değeri veya yanlış bir referans içeren veri eklenemez.

Örnek: Bir sipariş tablosunda, quantity alanı her zaman sıfırdan büyük olmalıdır. Bu tür bir kısıtlama varsa, tutarlılık prensibi veritabanını hatalı verilerden korur.

ALTER TABLE orders ADD CONSTRAINT positive_quantity CHECK (quantity > 0);

Bu kısıtlama sayesinde, eğer bir işlem negatif miktarda sipariş eklemeye çalışırsa, veritabanı bunu engelleyerek tutarlılığı korur.

3. Yalıtım (Isolation)#

Yalıtım, aynı anda çalışan işlemlerin birbirini etkilememesini sağlar. Bir işlem tamamlanmadan diğer işlemler tarafından görülmemelidir. Bu prensip sayesinde, eşzamanlı işlemler veritabanının tutarlılığını bozmaz. Yalıtım seviyesi, veritabanı tarafından belirlenen farklı düzeylerde uygulanabilir (örneğin, read uncommitted, read committed, repeatable read, serializable).

Örnek: Aynı anda iki kullanıcı bir ürünün stok bilgisini güncelliyorsa, bir kullanıcı işlemi tamamlamadan diğer kullanıcı işlemi görmemelidir.

BEGIN TRANSACTION;
UPDATE inventory SET stock = stock - 1 WHERE product_id = 123;
-- Başka işlemler bu güncellemeyi görmez
COMMIT;

Burada, işlem tamamlanmadan diğer kullanıcılar stoktaki güncellemeyi göremez.

4. Dayanıklılık (Durability)#

Dayanıklılık, bir işlem başarıyla tamamlandıktan sonra sonuçların kalıcı olması gerektiğini ifade eder. Sistemde bir arıza veya güç kesintisi olsa bile, başarıyla tamamlanmış işlemler veritabanında saklanır.

Örnek: Kullanıcıya başarı mesajı gösterildikten sonra, işlem kalıcı olarak diske yazılır ve sistem kapanıp tekrar açıldığında veri kaybı yaşanmaz.

BEGIN;
INSERT INTO orders (user_id, product_id, quantity) VALUES (1, 123, 2);
COMMIT;
-- İşlem tamamlandıktan sonra veriler kalıcıdır

Bir güç kesintisi veya sistem çökmesi olsa bile, COMMIT işleminden sonra bu sipariş kaydı veritabanında kalıcı olarak saklanır.

ACID Prensiplerinin Uygulanması#

ACID prensipleri, veritabanının güvenilir ve tutarlı çalışmasını sağlasa da her veritabanı bu prensiplerin tamamını sağlamak zorunda değildir. Örneğin, SQLite gibi hafif veritabanları belirli durumlarda dayanıklılık konusunda esneklik gösterebilir. MySQL’de ise kullanılan depolama motoruna göre (InnoDB veya MyISAM gibi) ACID uyumluluğu değişebilir.

Sonuç olarak, ACID prensipleri özellikle veri güvenliği ve tutarlılığın kritik olduğu projeler için tercih edilirken, performans veya esneklik öncelikli durumlarda bazı prensiplerden ödün verilebilir.