MsSQL

SQL’de Backup, Restore ve Güvenlik

Veritabanları, modern işletmelerin can damarıdır ve kritik verileri barındırır. Bu nedenle, SQL veritabanlarında veri kaybını önlemek, iş sürekliliğini sağlamak ve güvenlik açıklarını kapatmak hayati önem taşır. Yedekleme, geri yükleme ve güvenlik stratejileri, olası felaket senaryolarına karşı bir kalkan görevi görür. Bu üç unsur, verilerinizin bütünlüğünü, erişilebilirliğini ve gizliliğini korumak için ayrılmaz bir bütündür. Bu makale, SQL veritabanı yönetiminin bu temel taşlarını derinlemesine inceleyecektir.

Veritabanı Yedekleme (Database Backup)

Veritabanı yedeklemesi, bir veritabanının belirli bir zamandaki kopyasını oluşturma işlemidir. Bu işlem, donanım arızaları, yazılım hataları, insan kaynaklı hatalar, siber saldırılar veya doğal afetler gibi öngörülemeyen durumlar karşısında veri kaybını önlemek için kritik öneme sahiptir. Etkili bir yedekleme stratejisi, iş sürekliliğini garantileyen temel unsurdur.

Yedekleme Türleri

  • Tam Yedekleme (Full Backup): Tüm veritabanının, işlem günlükleri dahil olmak üzere eksiksiz bir kopyasını oluşturur. Geri yükleme için tek başına yeterlidir ancak boyutu büyük olabilir ve tamamlanması uzun sürebilir.
  • Diferansiyel Yedekleme (Differential Backup): Son tam yedeklemeden bu yana değişen tüm verileri içerir. Tam yedeklemeye göre daha küçüktür ve daha hızlı tamamlanır. Geri yükleme için son tam yedekleme ve son diferansiyel yedekleme gerekir.
  • İşlem Günlüğü Yedeklemesi (Transaction Log Backup): Sadece işlem günlüğünü yedekler, bu da veritabanının bir felaket anında belirli bir zamana (point-in-time) geri yüklenmesine olanak tanır. Genellikle tam veya diferansiyel yedeklemeler arasında sık aralıklarla alınır.
  • Dosya/Dosya Grubu Yedeklemesi (File/Filegroup Backup): Büyük veritabanlarında, veritabanının tamamı yerine belirli dosya veya dosya gruplarını yedeklemek için kullanılır.

Yedekleme Stratejileri ve En İyi Uygulamalar

  • Sıklık ve Saklama Politikası: Yedeklemelerin ne sıklıkla alınacağı ve ne kadar süreyle saklanacağı, verinin kritikliği ve kurtarma noktası hedefi (RPO – Recovery Point Objective) ile belirlenmelidir. Örneğin, kritik üretim veritabanları için her 15 dakikada bir işlem günlüğü yedeklemesi alınabilir.
  • Yedekleme Ortamları: Yedeklemeler, ana veritabanından farklı fiziksel konumlarda (ağ depolama, bulut depolama, manyetik bant vb.) saklanmalıdır. 3-2-1 kuralı (3 kopya, 2 farklı ortam, 1 offsite) iyi bir yaklaşımdır.
  • Yedeklemelerin Doğrulanması: Alınan yedeklemelerin gerçekten geçerli ve geri yüklenebilir olduğundan emin olmak için düzenli olarak test edilmesi zorunludur. Bozuk bir yedekleme, yedekleme olmamasından daha kötü olabilir.
  • Şifreleme ve Sıkıştırma: Yedekleme dosyalarını şifrelemek, hassas verilerin yetkisiz erişime karşı korunmasına yardımcı olur. Sıkıştırma ise depolama alanı gereksinimlerini azaltır.

SQL Server T-SQL Örneği

BACKUP DATABASE YourDatabaseName
TO DISK = 'C:\Backup\YourDatabaseName_Full.bak'
WITH FORMAT, NAME = 'YourDatabaseName Full Backup';

BACKUP LOG YourDatabaseName
TO DISK = 'C:\Backup\YourDatabaseName_Log.trn'
WITH NORECOVERY, NAME = 'YourDatabaseName Log Backup';

Veritabanı Geri Yükleme (Database Restore)

Yedeklemelerin asıl amacı, bir felaket durumunda veritabanını çalışır duruma geri getirmektir. Geri yükleme işlemi, doğru yedekleme serisini doğru sırayla uygulamayı gerektirir.

Geri Yükleme Süreci

  • Tam Geri Yükleme: Önce en son tam yedekleme geri yüklenir.
  • Diferansiyel Geri Yükleme (Opsiyonel): Tam yedeklemeden sonra alınmış en son diferansiyel yedekleme geri yüklenir.
  • İşlem Günlüğü Geri Yüklemesi (Opsiyonel): Diferansiyel yedeklemeden (veya tam yedeklemeden, diferansiyel yoksa) sonra alınmış işlem günlüğü yedeklemeleri, istenilen kurtarma noktasına kadar sırayla geri yüklenir.
  • Kurtarma Modu: Geri yükleme işlemi sırasında veritabanı “NORECOVERY” modunda bırakılarak daha fazla işlem günlüğü uygulanmasına olanak tanınır. En son işlem günlüğü uygulandıktan sonra “WITH RECOVERY” seçeneği ile veritabanı erişime açılır.

Önemli Hususlar

  • Zamana Yönelik Geri Yükleme (Point-in-Time Recovery): İşlem günlüğü yedeklemeleri sayesinde, veritabanını belirli bir saate veya dakikaya kadar geri yüklemek mümkündür. Bu, örneğin, yanlışlıkla silinen bir tablonun silinmeden önceki durumuna dönmek için çok değerlidir.
  • Test Etme: Geri yükleme işlemlerinin de tıpkı yedeklemeler gibi düzenli olarak test edilmesi gerekir. Bir felaket anında geri yükleme prosedürlerinin işe yaradığından emin olmak kritik öneme sahiptir.
  • Hedef Konum: Veritabanının farklı bir sunucuya veya farklı bir konuma geri yüklenmesi gerekebilir. Bu durumda dosya yolları ve adlandırmalar dikkatle yönetilmelidir.

SQL Server T-SQL Örneği

RESTORE DATABASE YourDatabaseName
FROM DISK = 'C:\Backup\YourDatabaseName_Full.bak'
WITH NORECOVERY; -- Tam yedeklemeyi NORECOVERY ile geri yükle

-- Eğer diferansiyel yedekleme varsa:
-- RESTORE DATABASE YourDatabaseName
-- FROM DISK = 'C:\Backup\YourDatabaseName_Diff.bak'
-- WITH NORECOVERY;

-- İşlem günlüğü yedeklemesini zamana yönelik geri yükleme örneği
RESTORE LOG YourDatabaseName
FROM DISK = 'C:\Backup\YourDatabaseName_Log.trn'
WITH RECOVERY, STOPAT = '2023-10-27 14:30:00'; -- Belirli bir zamana kadar geri yükle ve erişime aç

Veritabanı Güvenliği (Database Security)

Veritabanı güvenliği, verilerin gizliliğini (confidentiality), bütünlüğünü (integrity) ve erişilebilirliğini (availability) korumak için alınan önlemlerin bütünüdür. Bu, yetkisiz erişimi engellemeyi, veri manipülasyonunu önlemeyi ve veritabanı sistemlerinin sürekli çalışmasını sağlamayı kapsar.

Kimlik Doğrulama (Authentication)

  • Windows Kimlik Doğrulaması: Kullanıcıların Windows işletim sistemi kimlik bilgilerini kullanarak veritabanına erişmesine olanak tanır. Daha güvenli kabul edilir, çünkü parola politikaları merkezi olarak yönetilir.
  • SQL Server Kimlik Doğrulaması: SQL Server içinde kullanıcı adları ve parolaları tanımlanır. Parola karmaşıklığı ve sona erme politikaları uygulanmalıdır.
  • Çok Faktörlü Kimlik Doğrulama (MFA): Ek bir güvenlik katmanı olarak MFA uygulamak, yetkisiz erişimi önemli ölçüde zorlaştırır.

Yetkilendirme (Authorization)

  • Kullanıcılar ve Roller: Her kullanıcıya tek tek yetki vermek yerine, benzer yetkilere sahip kullanıcıları rollere atamak ve yetkileri rollere vermek yönetim kolaylığı sağlar.
  • Erişim İzinleri (Permissions): Kullanıcılara veya rollere belirli veritabanı nesneleri (tablolar, görünümler, saklı yordamlar) üzerinde yalnızca ihtiyaç duydukları minimum izinler (SELECT, INSERT, UPDATE, DELETE, EXECUTE vb.) verilmelidir. Bu, “en az ayrıcalık ilkesi” (principle of least privilege) olarak bilinir.
  • GRANT ve DENY Deyimleri: SQL’de izinleri vermek için GRANT, belirli bir izni açıkça reddetmek için DENY kullanılır. REVOKE ise daha önce verilmiş veya reddedilmiş bir izni geri alır.

SQL Server T-SQL Örneği

CREATE LOGIN [MyUser] WITH PASSWORD = 'StrongPassword123!', CHECK_POLICY = ON;
CREATE USER MyUser FOR LOGIN MyUser;
CREATE ROLE DataReaders;
GRANT SELECT ON SCHEMA::dbo TO DataReaders;
ALTER ROLE DataReaders ADD MEMBER MyUser;
GRANT EXECUTE ON OBJECT::dbo.MyStoredProcedure TO MyUser;

Veri Şifreleme (Data Encryption)

  • Saydam Veri Şifrelemesi (Transparent Data Encryption – TDE): Veritabanı dosyalarını diskte (at rest) şifreler. Uygulama katmanında herhangi bir değişiklik yapmadan verilerin depolandığı yerde korunmasını sağlar.
  • Her Zaman Şifrelenmiş (Always Encrypted): Hassas verilerin veritabanına gönderilmeden önce istemci uygulamasında şifrelenmesini ve veritabanı sunucusunda şifrelenmiş olarak depolanmasını sağlar. Veritabanı yöneticileri bile şifrelenmiş verilere erişemez.
  • İletişim Şifrelemesi (Encryption in Transit): SSL/TLS gibi protokoller kullanarak istemci ile sunucu arasındaki ağ trafiğini şifrelemek, Man-in-the-Middle saldırılarını önler.

Denetim (Auditing)

  • Veritabanı denetimi, belirli veritabanı olaylarının (giriş denemeleri, veri değişiklikleri, şema değişiklikleri vb.) izlenmesi ve kaydedilmesidir. Bu kayıtlar, güvenlik ihlallerinin tespiti, sorumluluk tespiti ve uyumluluk gereksinimlerinin karşılanması için hayati öneme sahiptir.
  • SQL Server Audit gibi araçlar bu amaçla kullanılır.

Ağ Güvenliği

  • Güvenlik Duvarları (Firewalls): Veritabanı sunucusuna sadece belirli IP adreslerinden veya uygulamalardan erişime izin vermek için güvenlik duvarları yapılandırılmalıdır.
  • Ağ Segmentasyonu: Veritabanı sunucuları, diğer sunuculardan ayrı, izole edilmiş ağ segmentlerinde (DMZ gibi) tutulmalıdır.

Diğer Güvenlik Uygulamaları

  • Düzenli Güncellemeler ve Yama Yönetimi: Veritabanı yazılımını ve işletim sistemini en son güvenlik yamalarıyla güncel tutmak, bilinen güvenlik açıklarının kapatılması için zorunludur.
  • Fiziksel Güvenlik: Veritabanı sunucularının bulunduğu veri merkezlerine yetkisiz fiziksel erişimin engellenmesi.
  • Hassas Veri Maskeleme/Anonimleştirme: Geliştirme veya test ortamlarında gerçek hassas veriler yerine maskelenmiş veya anonimleştirilmiş veri kullanmak.
  • Zafiyet Tarama ve Penetrasyon Testleri: Veritabanı sistemlerindeki potansiyel güvenlik açıklarını tespit etmek için düzenli taramalar ve testler yapılmalıdır.

SQL veritabanlarında yedekleme, geri yükleme ve güvenlik, sadece teknik gereklilikler değil, aynı zamanda iş sürekliliğinin ve veri korumanın temel direkleridir. Kapsamlı bir yedekleme stratejisi, düzenli geri yükleme testleri ve katı güvenlik önlemleri, veri kaybı riskini minimize ederken, olası tehditlere karşı güçlü bir savunma hattı oluşturur. Bu unsurların entegre ve proaktif bir şekilde yönetilmesi, işletmelerin verilerine güvenle sahip çıkmasını ve olası aksaklıklardan hızla kurtulmasını sağlar. Unutmayın, veri güvenliği sürekli bir çabadır.


SQL’de Normalization (Normalizasyon)

Veritabanı yönetim sistemlerinde verilerin etkin, tutarlı ve tekrarsız bir şekilde saklanması büyük önem taşır. SQL’de normalizasyon, ilişkisel veritabanı tasarımında veri tekrarını azaltmayı, veri bütünlüğünü artırmayı ve veritabanı anormalliklerini ortadan kaldırmayı amaçlayan yapısal bir süreçtir. Bu, veritabanı performansını ve güvenilirliğini önemli ölçüde etkileyen temel bir kavramdır. Doğru uygulandığında, daha yönetilebilir ve sürdürülebilir bir veritabanı sağlar.

Normalizasyon Nedir ve Neden Önemlidir?

Normalizasyon, bir ilişkisel veritabanı şemasını belirli kurallar setine göre düzenleme işlemidir. Bu kurallar, “Normal Formlar” olarak bilinir ve veritabanındaki veri tekrarını (redundancy) en aza indirmeyi, veri bütünlüğünü (data integrity) artırmayı ve anormallikleri (anomalies) ortadan kaldırmayı hedefler. Bir veritabanının anormalliklere sahip olması; veri ekleme (insertion), güncelleme (update) veya silme (deletion) işlemlerinde tutarsızlıklara yol açabilen durumlardır.

Normalizasyonun temel faydaları şunlardır:

  • Veri Tekrarının Azaltılması: Aynı verinin birden fazla yerde saklanmasını önleyerek depolama alanından tasarruf sağlar.
  • Veri Bütünlüğünün Artırılması: Tekrarlı verinin olmaması, bir veriyi güncellerken tüm kopyalarının güncellenmesini zorunlu kılmaz ve böylece tutarsızlık riskini azaltır.
  • Anormalliklerin Ortadan Kaldırılması: Ekleme, güncelleme ve silme anormalliklerinin önüne geçerek veritabanının daha güvenilir olmasını sağlar. Örneğin, bir müşterinin adresini birden fazla tabloda tutuyorsanız ve adres değiştiğinde tüm kopyaları güncellemeyi unutursanız, veri tutarsızlığı yaşanır.
  • Daha İyi Veri Yönetimi: Daha küçük, daha odaklanmış tablolar, veri yönetimini ve bakımı kolaylaştırır.
  • Daha Esnek Veritabanı Yapısı: Yeni gereksinimlere daha kolay adapte olabilen bir yapı sunar.

Normal Formlar (Normalization Forms)

Normalizasyon süreci, bir dizi “Normal Form” aracılığıyla ilerler. Her normal form, bir önceki formun gereksinimlerini karşılar ve ek kurallar getirir. En yaygın kullanılan normal formlar 1NF, 2NF ve 3NF’dir.

Birinci Normal Form (1NF – First Normal Form)

Bir tablonun 1NF’de olabilmesi için aşağıdaki koşulları sağlaması gerekir:

  • Her sütun atomik (bölünemez) değerler içermelidir. Yani, bir hücrede birden fazla değer veya virgülle ayrılmış listeler olmamalıdır.
  • Her satır benzersiz olmalıdır (yani birincil anahtara sahip olmalıdır).
  • Tekrarlayan sütun grupları içermemelidir.

Örnek: Bir Çalışanlar tablosunda TelefonNumaraları sütununda “555-1234, 555-5678” gibi birden fazla telefon numarası varsa, bu 1NF’e aykırıdır. Düzeltme için, her telefon numarası için ayrı bir satır oluşturulabilir veya ayrı bir ÇalışanTelefonları tablosu oluşturulup, ÇalışanID ile ilişkilendirilebilir.

İkinci Normal Form (2NF – Second Normal Form)

Bir tablonun 2NF’de olabilmesi için aşağıdaki koşulları sağlaması gerekir:

  • 1NF’de olmalıdır.
  • Birincil anahtar olmayan hiçbir sütun, birleşik (composite) birincil anahtarın sadece bir kısmına bağlı olmamalıdır (kısmi bağımlılık olmamalıdır). Tüm birincil anahtara tam işlevsel bağımlılık göstermelidir.

Örnek: Bir SiparişDetayları tablosunun birincil anahtarı (SiparişID, ÜrünID) olsun. Bu tabloda ÜrünAdı sütunu varsa ve ÜrünAdı sadece ÜrünID‘ye bağlıysa (SiparişID‘ye değil), bu bir kısmi bağımlılıktır ve 2NF’e aykırıdır. Düzeltme için, ÜrünID ve ÜrünAdı‘nı içeren ayrı bir Ürünler tablosu oluşturulmalıdır.

Üçüncü Normal Form (3NF – Third Normal Form)

Bir tablonun 3NF’de olabilmesi için aşağıdaki koşulları sağlaması gerekir:

  • 2NF’de olmalıdır.
  • Birincil anahtar olmayan hiçbir sütun, birincil anahtar olmayan başka bir sütuna bağlı olmamalıdır (geçişli bağımlılık olmamalıdır).

Örnek: Bir Personel tablosunda (PersonelID, Ad, Soyad, DepartmanAdı, DepartmanKodu) sütunları olsun ve PersonelID birincil anahtar olsun. Eğer DepartmanKodu, DepartmanAdı‘na bağlıysa ve DepartmanAdı da PersonelID‘ye bağlı olmayan bir nitelikse, bu bir geçişli bağımlılıktır (PersonelID -> DepartmanAdı -> DepartmanKodu). Düzeltme için, DepartmanKodu ve DepartmanAdı‘nı içeren ayrı bir Departmanlar tablosu oluşturulmalıdır.

Boyce-Codd Normal Form (BCNF)

BCNF, 3NF’nin daha güçlü bir versiyonudur. Bir tablo BCNF’de olabilmesi için:

  • 3NF’de olmalıdır.
  • Her bir belirleyici (determinant) bir aday anahtar (candidate key) olmalıdır. (Belirleyici, başka bir özniteliği veya öznitelik grubunu belirleyen bir öznitelik veya öznitelik grubudur.)

BCNF, özellikle tabloda birden fazla, örtüşen aday anahtar olduğunda ortaya çıkan belirli anormallikleri ele alır. Çoğu durumda, 3NF pratik uygulamalar için yeterli olsa da, BCNF daha yüksek düzeyde normalizasyon sağlar.

Denormalizasyon (Denormalization)

Normalizasyonun temel amacı veri bütünlüğünü ve depolama verimliliğini sağlamak olsa da, çok yüksek derecede normalleştirilmiş veritabanları karmaşık sorgular için performansı düşürebilir. Birden fazla tablonun birleştirilmesi (JOIN) gerektiren sorgular, özellikle büyük veri setlerinde zaman alıcı olabilir.

Denormalizasyon, bilerek veri tekrarı ekleyerek veya normalleştirilmiş tabloları birleştirerek veritabanının okunabilirlik ve sorgu performansını artırmayı amaçlayan bir stratejidir. Genellikle, raporlama, veri ambarı sistemleri veya yüksek okuma trafiğine sahip uygulamalar gibi belirli performans darboğazlarını çözmek için kullanılır.

Denormalizasyonun faydaları şunlardır:

  • Sorguların daha hızlı çalışması.
  • JOIN işlemlerine olan ihtiyacın azalması, sorgu karmaşıklığının azalması.
  • Raporlama ve analiz için daha kolay veri erişimi.

Ancak denormalizasyonun dezavantajları da vardır:

  • Veri tekrarının artması.
  • Veri tutarlılığını korumak için daha karmaşık güncelleme ve ekleme işlemleri gerekliliği.
  • Depolama maliyetlerinin artması.

Denormalizasyon, yalnızca performans iyileştirmesi kritik olduğunda ve potansiyel tutarsızlık riskleri dikkatlice yönetilebildiğinde düşünülmesi gereken bir tasarım kararıdır.

Sonuç

Özetle, SQL’de normalizasyon, ilişkisel veritabanlarının sağlam, tutarlı ve verimli olmasını sağlayan kritik bir süreçtir. Veri tekrarını en aza indirerek ve anormallikleri ortadan kaldırarak veritabanı bütünlüğünü artırır, depolama alanından tasarruf sağlar ve veri yönetimini kolaylaştırır. Ancak, performans gereksinimleri doğrultusunda denormalizasyon da stratejik bir seçenek olabilir. Doğru dengeyi bulmak, veritabanı tasarımında uzun vadeli başarı için hayati öneme sahiptir. Veritabanı tasarımcıları, uygulamanın ihtiyaçlarına en uygun normalizasyon seviyesini dikkatlice belirlemelidir.


SQL’de Constraint’ler ve Veri Bütünlüğü

Veritabanı yönetim sistemlerinde verilerin doğruluğu, tutarlılığı ve güvenilirliği kritik öneme sahiptir. SQL Constraint’ler, bu veri bütünlüğünü sağlamak ve istenmeyen veya geçersiz verilerin veritabanına girişini engellemek için kullanılan güçlü araçlardır. İlişkisel veritabanlarının temel taşlarından olan bu kısıtlamalar, veritabanı şemasının tanımlı kurallara uygun kalmasını garanti ederek uzun vadede veri kalitesini maksimize eder ve uygulama hatalarını minimize eder.

Veri Bütünlüğü: İlişkisel Veritabanlarının Temeli

Veri bütünlüğü, veritabanındaki bilgilerin doğruluğunu, tutarlılığını ve güvenilirliğini ifade eder. Bu, verilerin istenmeyen değişikliklerden veya bozulmalardan korunması anlamına gelir. İlişkisel veritabanlarında genellikle dört ana veri bütünlüğü türü bulunur:

  • Varlık Bütünlüğü (Entity Integrity): Her satırın bir tablonun içinde benzersiz bir şekilde tanımlanabilmesini sağlar. Genellikle PRIMARY KEY ile garanti edilir.
  • Referans Bütünlüğü (Referential Integrity): Bir tablodaki yabancı anahtar değerlerinin, ilişkili tablodaki birincil anahtar değerleriyle eşleşmesini veya NULL olmasını sağlar. FOREIGN KEY ile garanti edilir.
  • Alan Bütünlüğü (Domain Integrity): Bir sütundaki tüm değerlerin belirli bir tür, biçim ve aralık dahilinde olmasını sağlar. NOT NULL, CHECK ve DEFAULT ile desteklenir.
  • Kullanıcı Tanımlı Bütünlük (User-Defined Integrity): İş gereksinimlerine özgü ek kuralları ifade eder ve genellikle CHECK constraint’ler veya tetikleyiciler (trigger) aracılığıyla uygulanır.

SQL Constraint’ler, bu bütünlük kurallarını doğrudan veritabanı şeması düzeyinde uygulayarak, verilerin uygulamalardan bağımsız olarak tutarlı kalmasını sağlar.

SQL Constraint’ler Nelerdir ve Nasıl Çalışır?

SQL Constraint’ler, bir veritabanı tablosundaki sütunlara veya tüm tabloya uygulanan kurallar bütünüdür. Bu kurallar, veri ekleme (INSERT), güncelleme (UPDATE) veya silme (DELETE) işlemleri sırasında devreye girer ve tanımlı koşulların ihlal edilip edilmediğini kontrol eder. Eğer bir işlem bir kısıtlamayı ihlal ederse, veritabanı bu işlemi reddeder ve bir hata mesajı döndürür. Bu mekanizma, hatalı verilerin sisteme girişini engeller ve veritabanının sağlıklı yapısını korur.

Temel SQL Constraint Türleri ve Kullanımları

1. NOT NULL Constraint

NOT NULL constraint, bir sütundaki değerlerin boş (NULL) olamayacağını garanti eder. Bu, o sütun için mutlaka bir değer girilmesi gerektiğini belirtir. Özellikle kritik bilgiler içeren sütunlar (örneğin, kullanıcı adları, sipariş numaraları) için hayati öneme sahiptir.

CREATE TABLE Musteriler (
    MusteriID INT NOT NULL,
    Ad VARCHAR(50) NOT NULL,
    Soyad VARCHAR(50),
    Email VARCHAR(100)
);

2. UNIQUE Constraint

UNIQUE constraint, bir sütundaki veya sütun kümesindeki tüm değerlerin benzersiz olmasını garanti eder. İki satırın aynı değere sahip olmasını engeller. NULL değerlere izin verir, ancak her NULL değeri benzersiz kabul eder. Birden fazla UNIQUE constraint bir tabloya uygulanabilir.

CREATE TABLE Urunler (
    UrunID INT NOT NULL UNIQUE,
    UrunKodu VARCHAR(20) UNIQUE,
    UrunAdi VARCHAR(100) NOT NULL
);

3. PRIMARY KEY Constraint

PRIMARY KEY (Birincil Anahtar) constraint, bir tablodaki her satırı benzersiz bir şekilde tanımlayan bir sütun veya sütun kümesidir. PRIMARY KEY, hem NOT NULL hem de UNIQUE özelliklerini içerir. Bir tabloda yalnızca bir PRIMARY KEY olabilir ve bu, varlık bütünlüğünü sağlar.

CREATE TABLE Calisanlar (
    CalisanID INT PRIMARY KEY,
    Ad VARCHAR(50),
    Soyad VARCHAR(50),
    TCKimlikNo VARCHAR(11) UNIQUE -- T.C. Kimlik No da benzersiz olmalı, ama birincil anahtar değil
);

Birden fazla sütunlu bir birincil anahtar için (composite primary key):

CREATE TABLE SiparisDetay (
    SiparisID INT,
    UrunID INT,
    Miktar INT,
    PRIMARY KEY (SiparisID, UrunID)
);

4. FOREIGN KEY Constraint

FOREIGN KEY (Yabancı Anahtar) constraint, iki tablo arasındaki bağlantıyı kurar ve referans bütünlüğünü sağlar. Bir tablodaki yabancı anahtar, başka bir tablodaki (veya aynı tablodaki) birincil anahtara referans verir. Bu, yalnızca ilişkili tabloda mevcut olan değerlerin girilebileceği anlamına gelir.

CREATE TABLE Departmanlar (
    DepartmanID INT PRIMARY KEY,
    DepartmanAdi VARCHAR(50) NOT NULL
);

CREATE TABLE Personel (
    PersonelID INT PRIMARY KEY,
    Ad VARCHAR(50),
    Soyad VARCHAR(50),
    DepartmanID INT,
    FOREIGN KEY (DepartmanID) REFERENCES Departmanlar(DepartmanID)
);

Yabancı anahtarlar, ilişkili ana tablo üzerindeki silme (ON DELETE) ve güncelleme (ON UPDATE) işlemlerinin davranışını da kontrol edebilir:

  • ON DELETE CASCADE: Ana tablodan bir satır silindiğinde, ilgili yabancı anahtar içeren satırları da siler.
  • ON DELETE SET NULL: Ana tablodan bir satır silindiğinde, ilgili yabancı anahtar sütununu NULL yapar.
  • ON DELETE RESTRICT / NO ACTION: İlgili yabancı anahtar içeren satırlar varsa ana tablodan silme işlemine izin vermez. (Varsayılan davranış genellikle RESTRICT’tir.)

5. CHECK Constraint

CHECK constraint, bir sütundaki tüm değerlerin belirli bir koşulu karşılamasını garanti eder. Bu koşul, bir mantıksal ifade olarak tanımlanır ve her veri ekleme veya güncelleme işleminde kontrol edilir. Alan bütünlüğünü ve kullanıcı tanımlı bütünlüğü sağlamak için çok esnek bir yol sunar.

CREATE TABLE Ogrenciler (
    OgrenciID INT PRIMARY KEY,
    Ad VARCHAR(50) NOT NULL,
    Yas INT CHECK (Yas >= 18),
    NotOrtalamasi DECIMAL(3, 2) CHECK (NotOrtalamasi BETWEEN 0.00 AND 4.00),
    Cinsiyet CHAR(1) CHECK (Cinsiyet IN ('E', 'K'))
);

6. DEFAULT Tanımı

DEFAULT tanımı, bir sütuna hiçbir değer belirtilmediğinde otomatik olarak atanacak varsayılan bir değer belirler. Teknik olarak bir kısıtlama olmasa da, alan bütünlüğünü destekler ve veri girişi sırasında eksik değerlerin tutarlı bir şekilde yönetilmesini sağlar.

CREATE TABLE Ayarlar (
    AyarID INT PRIMARY KEY,
    AyarAdi VARCHAR(50) NOT NULL,
    AyarDegeri VARCHAR(100) DEFAULT 'Varsayılan Değer',
    OlusturmaTarihi DATETIME DEFAULT GETDATE() -- SQL Server için
);

Diğer veritabanlarında NOW() veya CURRENT_TIMESTAMP gibi fonksiyonlar kullanılabilir.

Constraint’lerin Yönetimi

Constraint’ler, tablo oluşturulurken tanımlanabileceği gibi, daha sonra ALTER TABLE komutu kullanılarak da eklenebilir veya silinebilir.

Constraint Ekleme:

ALTER TABLE Musteriler
ADD CONSTRAINT UQ_Email UNIQUE (Email);

ALTER TABLE Siparisler
ADD CONSTRAINT FK_MusteriSiparis FOREIGN KEY (MusteriID) REFERENCES Musteriler(MusteriID);

ALTER TABLE Urunler
ADD CONSTRAINT CK_FiyatPozitif CHECK (Fiyat > 0);

Constraint Silme:

Constraint silmek için, genellikle kısıtlamanın adını bilmek gerekir. Kısıtlama adları, tablo oluşturulurken veya ALTER TABLE ADD CONSTRAINT ile açıkça belirtilebilir. Belirtilmezse, veritabanı sistemi otomatik olarak bir ad atar.

ALTER TABLE Musteriler
DROP CONSTRAINT UQ_Email;

ALTER TABLE Personel
DROP CONSTRAINT FK_DepartmanID; -- Veritabanına göre otomatik atanan ad farklı olabilir

SQL Constraint’ler, veritabanlarında veri bütünlüğünü sağlamanın ve korumanın vazgeçilmez bir parçasıdır. NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY ve CHECK gibi kısıtlamalar, verilerin doğruluğunu ve tutarlılığını garantilerken, DEFAULT tanımları da eksik değerlerin tutarlı yönetimine yardımcı olur. Bu kısıtlamaları doğru bir şekilde uygulamak, hatalı veri girişlerini önler, uygulama geliştirme süreçlerini basitleştirir ve uzun vadede veritabanı performansını ve güvenilirliğini artırır. Güçlü bir veritabanı şeması, temelinde sağlam constraint tanımları yatar.


SQL’de Index ve Performans İyileştirme

Veritabanı performansı, modern uygulamaların hızı ve kullanıcı deneyimi için kritik bir faktördür. Veri hacmi arttıkça, veritabanı sorgularının yavaşlaması kaçınılmaz bir sorun haline gelir. SQL indeksleri, bu yavaşlamayı ortadan kaldırmak ve veri erişimini hızlandırmak için temel bir araçtır. Bu makalede, SQL indekslerinin ne olduğunu, nasıl çalıştıklarını, farklı türlerini ve performans iyileştirme stratejilerini derinlemesine inceleyeceğiz.

SQL İndeks Nedir ve Neden Önemlidir?

SQL indeksi, bir kitap dizinine benzer. Bir kitapta belirli bir konuyu bulmak için tüm sayfaları tek tek taramak yerine, dizine bakarak ilgili sayfa numarasına doğrudan gidersiniz. SQL veritabanlarında da indeksler, bir tablodaki belirli verilere çok daha hızlı erişim sağlamak için kullanılır. Tüm tabloyu taramak (tam tablo taraması – full table scan) yerine, veritabanı yönetim sistemi (DBMS), indeks yapısını kullanarak istenen verinin fiziksel konumuna doğrudan ulaşır.

Bu hızlandırma, özellikle büyük veri kümeleri üzerinde çalışan uygulamalar için hayati öneme sahiptir. İndeksler, SELECT sorgularının performansını artırırken, WHERE, JOIN, ORDER BY ve GROUP BY gibi koşulların işlem süresini önemli ölçüde azaltır. Ancak, indekslerin kendilerine özgü bir depolama alanı maliyeti vardır ve INSERT, UPDATE, DELETE gibi veri değiştirme (DML) işlemlerinde ek bir yük oluştururlar, çünkü her DML işleminde indekslerin de güncellenmesi gerekir. Bu nedenle, indeksleme stratejisi dikkatli bir şekilde planlanmalıdır.

İndeks Türleri

SQL veritabanlarında yaygın olarak kullanılan iki ana indeks türü vardır: Clustered Index ve Non-Clustered Index.

Clustered Index (Kümelenmiş İndeks)

Clustered index, bir tablodaki veri satırlarının fiziksel depolama sırasını belirler. Bir tabloya yalnızca bir adet clustered index eklenebilir, çünkü veriler fiziksel olarak sadece bir şekilde sıralanabilir. Genellikle, tablonun birincil anahtarı (Primary Key) otomatik olarak clustered index olarak tanımlanır. Clustered index oluşturulduğunda, tablonun tamamı indeksin sıralamasına göre yeniden düzenlenir. Bu, özellikle veri aralıkları üzerinde yapılan sorgular (WHERE id BETWEEN 100 AND 200) veya sıralama gerektiren sorgular (ORDER BY id) için mükemmel performans sağlar. Verilere doğrudan erişildiği için, “key lookup” ihtiyacı yoktur.

Non-Clustered Index (Kümelenmemiş İndeks)

Non-clustered index, verilerin fiziksel depolama sırasını değiştirmez. Bunun yerine, ayrı bir yapı oluşturur ve bu yapı, indekslenen sütun değerlerini ve bu değerlere karşılık gelen veri satırlarının fiziksel adreslerini (veya clustered index anahtarını) içerir. Bir tabloda birden fazla non-clustered index oluşturulabilir. Bir non-clustered index, bir telefon rehberine benzer; isimlere göre sıralanmıştır ancak numaraların fiziksel konumuyla ilgili değildir, sadece hangi sayfada olduğunu gösterir. Non-clustered indexler, belirli sütunlarda yapılan WHERE koşulları veya JOIN işlemleri için idealdir. Sorgu, indeksi kullanarak istenen veri satırlarına daha hızlı ulaşır.

Covering Indexes (Kapsayan İndeksler)

Bir non-clustered indeks, yalnızca indekslenen sütunları değil, aynı zamanda sorguda ihtiyaç duyulan diğer sütunları da içeriyorsa, buna covering index denir. Yani, sorgu için gerekli tüm veriler sadece indeksin kendisinden okunabilir ve tablonun ana veri sayfalarına gitmeye gerek kalmaz. Bu, ek disk I/O’sunu ortadan kaldırarak performansı önemli ölçüde artırır. Örneğin, bir indeks email sütunu üzerinde oluşturulmuş ve ad ile soyad sütunlarını “included columns” olarak içeriyorsa, SELECT ad, soyad FROM Users WHERE email = '...' sorgusu için index zaten tüm bilgiyi barındırdığı için ana tabloya uğramaz.

İndeksleme Stratejileri ve Ne Zaman İndeks Kullanmalıyız?

Etkili bir indeksleme stratejisi geliştirmek, veritabanı performansını optimize etmenin anahtarıdır. İşte indeks oluşturmayı düşünmeniz gereken durumlar ve stratejiler:

  • `WHERE` Koşullarında Sık Kullanılan Sütunlar: Sorguların `WHERE` ifadesinde sıklıkla filtrelenen sütunlara indeks eklemek, veritabanının arama alanını daraltmasına yardımcı olur.
  • `JOIN` Koşullarında Kullanılan Sütunlar: Tablolar arası ilişkilerde (`JOIN` clause) kullanılan sütunlara indeks eklemek, birleştirme işlemlerini hızlandırır. Genellikle foreign key sütunları bu kategoriye girer.
  • `ORDER BY`, `GROUP BY` ve `DISTINCT` İçin Kullanılan Sütunlar: Verilerin sıralanması veya gruplanması gereken durumlarda ilgili sütunlara indeks eklemek, ek bir sıralama maliyetini (sort operation) ortadan kaldırabilir.
  • Yüksek Kardinaliteye Sahip Sütunlar: Bir sütunun kardinalitesi, o sütundaki benzersiz değerlerin sayısını ifade eder. Yüksek kardinaliteye sahip sütunlar (örn: e-posta adresi, TC kimlik numarası), indeksleme için daha iyi adaydır çünkü indeks, sorguyu çok daha spesifik bir veri alt kümesine yönlendirebilir. Düşük kardinaliteye sahip sütunlar (örn: cinsiyet, doğru/yanlış), indekslendiğinde daha az etki yaratır.
  • Küçük Tablolardan Kaçının: Çok az satıra sahip tablolarda indeksleme genellikle gereksizdir ve hatta performansı kötüleştirebilir, çünkü veritabanı için indeks yapısını okumak, tüm tabloyu taramaktan daha maliyetli olabilir.
  • Sıkça Güncellenmeyen Sütunlar: İndeksler, her veri değişikliğinde güncellenmeleri gerektiği için DML işlemlerine (INSERT, UPDATE, DELETE) ek yük bindirir. Bu nedenle, sıkça güncellenen sütunlara indeks eklerken dikkatli olunmalıdır. En iyi performans, sıkça okunan ancak nadiren yazılan sütunlarda elde edilir.
  • Execution Plan Analizi: Her zaman yavaş çalışan sorguların “Execution Plan”ını analiz edin. Bu planlar, sorgunun nasıl çalıştığını, hangi indeksleri kullandığını veya hangi operasyonların maliyetli olduğunu gösterir. Bu analiz, eksik veya yanlış indeksleri tespit etmenin en güvenilir yoludur.

İndekslemeyi Aşırıya Kaçmaktan Sakınmak

Her sütuna indeks eklemek cazip görünse de, bu genellikle performansı düşüren bir hatadır. Aşırı indeksleme şu sorunlara yol açar:

  • Artan Disk Alanı Kullanımı: Her indeks, disk üzerinde ek yer kaplar.
  • DML İşlemlerinde Performans Düşüşü: Yeni veri eklendiğinde, güncellendiğinde veya silindiğinde, veritabanının ilgili tüm indeksleri de güncellemesi gerekir. Çok sayıda indeks varsa, bu işlemler önemli ölçüde yavaşlayabilir.
  • Optimizatörün Karmaşıklığı: Çok sayıda indeks, veritabanı sorgu optimizatörünün en iyi yürütme planını seçmesini zorlaştırabilir ve hatta yanlış bir plan seçmesine neden olabilir.

Doğru dengeyi bulmak için, uygulamanızın tipik iş yükünü (okuma yoğun mu, yazma yoğun mu?) anlamak ve sorgularınızı sürekli olarak izlemek önemlidir.

İndeks Dışında Performans İyileştirme Yöntemleri

İndeksleme, performans iyileştirmenin önemli bir parçası olsa da, tek çözüm değildir. Bir veritabanının genel performansını artırmak için bütünsel bir yaklaşım benimsemek gerekir:

  • Sorgu Optimizasyonu:
    • `SELECT *` yerine sadece gerekli sütunları seçin.
    • Karmaşık `JOIN`’leri basitleştirin veya alt sorgular yerine uygun `JOIN` türlerini kullanın.
    • `WHERE` koşullarında fonksiyon kullanımından kaçının (`WHERE YEAR(tarih) = 2023` yerine `WHERE tarih BETWEEN ‘2023-01-01’ AND ‘2023-12-31’`). Fonksiyonlar indeks kullanımını engeller.
    • `LIKE ‘%keyword’` gibi baştan joker karakter içeren aramalar indeksleri kullanamaz; mümkünse `LIKE ‘keyword%’` veya full-text search kullanın.
    • Gereksiz `DISTINCT` veya `ORDER BY` kullanımlarından kaçının.
  • Veritabanı Şeması Optimizasyonu:
    • Doğru veri tiplerini kullanın (örn: `INT` yerine gereksiz yere `BIGINT` kullanmaktan kaçının).
    • Normalizasyon ve denormalizasyon kararlarını iş yüküne göre verin.
    • Büyük tablolar için bölümleme (Partitioning) kullanmayı düşünün.
  • Donanım İyileştirmeleri: Daha hızlı CPU’lar, daha fazla RAM ve özellikle hızlı diskler (SSD’ler), veritabanı performansını doğrudan etkiler.
  • Veritabanı Ayarları: Veritabanı yönetim sisteminin (SQL Server, MySQL, PostgreSQL vb.) konfigürasyon ayarları (örn: bellek önbelleği boyutları, bağlantı havuzları) dikkatlice optimize edilmelidir.
  • Saklı Prosedürler ve Fonksiyonlar: Sık kullanılan karmaşık sorguları saklı prosedürler veya fonksiyonlar halinde derlemek, önbelleğe alınmış yürütme planları sayesinde performansı artırabilir.

İndeksler, SQL veritabanı performansını artırmanın temel taşıdır ancak dikkatli bir planlama gerektirir. Doğru indeksleme stratejisi, sorgu hızlarını önemli ölçüde iyileştirirken, aşırı indeksleme DML işlemlerini yavaşlatabilir ve kaynak tüketimini artırabilir. En iyi performansı elde etmek için indekslemeyi, sorgu optimizasyonu, veritabanı şeması tasarımı ve donanım iyileştirmeleri gibi diğer performans teknikleriyle birleştirmek önemlidir. Sürekli izleme ve analiz, veritabanınızın zaman içinde değişen ihtiyaçlarına göre optimum performansını sürdürmenin anahtarıdır.


SQL’de Transaction ve Veri Tutarlılığı

Veritabanı yönetim sistemlerinin temel taşlarından biri olan transactionlar, SQL dünyasında veri bütünlüğünü ve güvenilirliğini sağlayan kritik mekanizmalardır. Karmaşık işlemleri mantıksal bir birim altında toplayarak, olası hatalara veya sistem kesintilerine karşı veritabanının tutarlı bir durumda kalmasını garanti ederler. Bu sayede, aynı anda birden fazla kullanıcının veritabanı üzerinde güvenle işlem yapabilmesi mümkün olur ve kritik iş süreçleri kesintisiz devam eder.

Transaction (İşlem) Nedir?

Veritabanı bağlamında bir transaction, mantıksal olarak tek bir iş birimi olarak kabul edilen bir dizi SQL ifadesidir. Bu ifadelerin tümü ya başarılı bir şekilde tamamlanır (commit edilir) ya da hiçbiri tamamlanmaz (rollback edilir). Transactionların temel amacı, çok adımlı bir işlem sırasında veritabanının her zaman tutarlı bir durumda kalmasını sağlamaktır. Örneğin, bir banka uygulamasında bir hesaptan başka bir hesaba para transferi işlemi, hem kaynak hesaptan paranın çekilmesi hem de hedef hesaba paranın yatırılması adımlarını içerir. Bu iki adımın da birlikte başarılı olması veya herhangi bir sorun durumunda her iki adımın da geri alınması gerekliliği, transactionların önemini vurgular.

Veri Tutarlılığı ve ACID Özellikleri

Veri tutarlılığı, bir veritabanındaki verilerin belirli kurallar ve kısıtlamalar dahilinde doğru ve güncel kalması durumudur. SQL transactionları, bu tutarlılığı sağlamak için ACID adı verilen dört temel özelliğe uymak zorundadır:

1. Atomicity (Bütünlük)

Atomicity, bir transaction’daki tüm işlemlerin tek bir bütün olarak kabul edildiği anlamına gelir. Yani, bir transaction ya tamamen başarıyla tamamlanır (commit) ya da hiçbir etkisi kalmayacak şekilde tamamen geri alınır (rollback). Kısmi bir tamamlanma söz konusu değildir. Yukarıdaki banka transferi örneğinde, para bir hesaptan çekilip diğerine yatırılmadan önce sistem çökerse, Atomicity özelliği sayesinde işlem tamamen geri alınır ve her iki hesap da önceki durumlarına döner. SQL’de `BEGIN TRANSACTION` ile başlayan ve `COMMIT` veya `ROLLBACK` ile biten bloklar Atomicity prensibini uygular.


BEGIN TRANSACTION;

UPDATE Hesaplar SET Bakiye = Bakiye - 100 WHERE HesapNo = 'TR123';
-- Eğer burada bir hata olursa veya sistem çökerse
UPDATE Hesaplar SET Bakiye = Bakiye + 100 WHERE HesapNo = 'TR456';

COMMIT; -- Eğer her iki işlem de başarılı ise değişiklikler kalıcı olur.
-- ROLLBACK; -- Eğer herhangi bir hata olursa tüm işlemler geri alınır.

2. Consistency (Tutarlılık)

Consistency, bir transaction’ın veritabanını bir tutarlı durumdan alıp başka bir tutarlı duruma bırakması gerektiğini belirtir. Yani, transaction’ın başlangıcında ve sonunda veritabanında tanımlanan tüm kurallar, kısıtlamalar (primary key, foreign key, unique, check kısıtlamaları) ve tetikleyiciler geçerli olmalıdır. Örneğin, bir kullanıcının bakiyesi asla eksi bir değere düşmemelidir kuralı varsa, bir para çekme işlemi bu kuralı ihlal edemez. Consistency, Atomicity ve Isolation ile birlikte çalışarak veritabanının doğru ve güvenilir kalmasını sağlar.

3. Isolation (İzolasyon)

Isolation, eş zamanlı olarak çalışan transactionların birbirini etkilememesi gerektiği anlamına gelir. Bir transaction sanki veritabanında tek başına çalışıyormuş gibi görünmelidir. Başka bir deyişle, bir transaction devam ederken yaptığı değişiklikler, commit edilmeden önce diğer transactionlar tarafından görülemez. Bu, özellikle yüksek eş zamanlılık gerektiren sistemlerde veri tutarsızlıklarını (kirli okuma, tekrarlanamayan okuma, hayalet okuma gibi) önlemek için kritik öneme sahiptir. SQL Server, MySQL gibi veritabanları farklı izolasyon seviyeleri sunarak geliştiricilere esneklik sağlar.


-- Transaction A
BEGIN TRANSACTION;
UPDATE Urunler SET Stok = Stok - 1 WHERE UrunID = 1;
-- Transaction A henüz commit etmedi.

-- Transaction B (Aynı anda çalışıyor)
SELECT Stok FROM Urunler WHERE UrunID = 1; -- Bu sorgu, Transaction A'nın yaptığı değişikliği görmemelidir.

4. Durability (Kalıcılık)

Durability, bir transaction başarılı bir şekilde commit edildikten sonra, yapılan değişikliklerin kalıcı olacağını garanti eder. Sistem çökmesi, güç kesintisi veya başka bir donanım/yazılım hatası bile bu değişiklikleri ortadan kaldıramaz. Veritabanı sistemi, commit edilen verileri kalıcı depolama birimine (sabit disk) yazarak veya günlük kayıtları (transaction log) tutarak bu özelliği sağlar. Sistem yeniden başlatıldığında, commit edilmiş tüm işlemlerin uygulandığı bir durum restore edilir.

Transaction Kontrol Komutları (TCL)

SQL’de transactionları yönetmek için kullanılan temel komutlar şunlardır:

  • BEGIN TRANSACTION veya START TRANSACTION: Yeni bir transaction başlatır.
  • COMMIT: Transaction içindeki tüm değişiklikleri kalıcı hale getirir ve transaction’ı sonlandırır.
  • ROLLBACK: Transaction içindeki tüm değişiklikleri geri alır ve veritabanını transaction’ın başladığı duruma döndürür.
  • SAVEPOINT (isteğe bağlı): Bir transaction içinde belirli bir noktayı işaretlemek için kullanılır. Daha sonra bu noktaya geri dönülebilir.

Neden Transaction Kullanmalıyız?

Transactionlar, veritabanı uygulamaları için vazgeçilmezdir çünkü:

  • Veri Bütünlüğü: ACID özellikleri sayesinde verilerin her zaman doğru ve tutarlı kalmasını sağlarlar.
  • Hata Yönetimi: İşlemler sırasında oluşan hatalarda kolayca önceki duruma dönülmesini (rollback) mümkün kılarak veri bozulmasını önlerler.
  • Eş Zamanlılık Kontrolü: Birden fazla kullanıcının aynı verilere aynı anda erişmesi durumunda tutarsızlıkları önler.
  • İş Süreçleri Güvenliği: Kritik iş süreçlerinin (para transferi, envanter güncelleme, sipariş işleme vb.) güvenilir bir şekilde yürütülmesini garanti ederler.

SQL’de transactionlar ve ACID özellikleri, veritabanı yönetim sistemlerinin güvenilirliğini ve veri bütünlüğünü sağlayan temel yapı taşlarıdır. Atomicity, Consistency, Isolation ve Durability prensipleri sayesinde, karmaşık operasyonlar bile güvenle yürütülür ve sistem hatalarına karşı koruma sağlanır. Bu mekanizmalar, modern veritabanı uygulamalarında verinin doğru, tutarlı ve erişilebilir kalmasının vazgeçilmez bir garantisidir, böylece iş süreçlerinin kesintisiz ve hatasız ilerlemesi mümkün olur.


SQL’de Performans ve Optimizasyon Temelleri

Veritabanı tabanlı uygulamaların temelini oluşturan SQL sorguları, performansı doğrudan etkileyen kritik unsurlardır. Yavaş çalışan sorgular, kullanıcı deneyimini olumsuz etkilemekle kalmaz, aynı zamanda sunucu kaynaklarını da gereksiz yere tüketir. Bu nedenle SQL performans ve optimizasyon temellerini anlamak, herhangi bir yazılım geliştiricisi veya veritabanı yöneticisi için vazgeçilmez bir beceridir. Bu makale, sorgularınızı hızlandırmak ve sistem verimliliğini artırmak için gerekli temel stratejileri derinlemesine inceleyecektir.

Performans Neden Bu Kadar Önemlidir?

SQL sorgularının performansı, bir uygulamanın genel yanıt verme hızını ve kullanıcı memnuniyetini doğrudan etkiler. Yavaş sorgular, sadece kullanıcıların bekleme süresini artırmakla kalmaz, aynı zamanda sunucu üzerinde gereksiz CPU, bellek ve disk G/Ç (I/O) yükü oluşturarak sistem kaynaklarının verimsiz kullanılmasına yol açar. Bu durum, uygulamanın ölçeklenebilirliğini sınırlar, maliyetleri artırır ve hatta iş operasyonlarında aksaklıklara neden olabilir. Özellikle büyük veri kümeleriyle çalışan veya anlık raporlama gerektiren sistemlerde, milisaniyeler bile büyük fark yaratabilir.

Performans Darboğazlarını Belirleme

Optimizasyon sürecinin ilk adımı, performans sorunlarına neden olan sorguları ve alanları doğru bir şekilde tespit etmektir. Bunun için çeşitli araçlar ve yöntemler bulunmaktadır:

Veritabanı İzleme Araçları

Modern veritabanı yönetim sistemleri (DBMS), çalışan sorguları, kilitlenmeleri, bellek ve disk kullanımını izlemek için güçlü araçlar sunar. SQL Server’ın Activity Monitor’ü, MySQL’in Performance Schema’sı veya PostgreSQL’in pg_stat_activity görünümü, o anki veritabanı durumunu ve uzun süren sorguları görmek için kullanılabilir.

EXPLAIN (Execution Plan) Kullanımı

EXPLAIN komutu (veya eşdeğeri), bir SQL sorgusunun veritabanı tarafından nasıl yürütüleceğini gösteren bir “yürütme planı” sağlar. Bu plan, sorgu planlayıcının hangi indeksleri kullandığını, hangi tabloları hangi sırada taradığını veya birleştirdiğini (JOIN) ve tahmini maliyetini detaylandırır. Örneğin, bir sorgunun tam tablo taraması (full table scan) yaptığını görmek, potansiyel bir indeksleme sorununa işaret eder.

EXPLAIN SELECT Ad, Soyad FROM Musteriler WHERE Sehir = 'Ankara' AND Yas > 30;

Bu çıktıyı analiz ederek, sorgunun performansını düşüren adımları (örneğin, indeks kullanılmaması) belirleyebilirsiniz.

Yavaş Sorgu Günlükleri (Slow Query Logs)

Birçok veritabanı sistemi, belirli bir süreden daha uzun süren sorguları otomatik olarak bir günlüğe kaydetme özelliğine sahiptir. Bu günlükler, sürekli olarak en yavaş sorguları tespit etmek ve optimizasyon çalışmaları için birincil hedef belirlemek açısından oldukça değerlidir.

Etkili İndeksleme Stratejileri

İndeksler, veritabanı tablolarındaki verilere hızlı erişim sağlayan özel arama tablolarıdır, tıpkı bir kitabın sonundaki dizin gibi. Doğru kullanıldığında, sorgu performansını katlanarak artırabilirler.

İndeks Türleri

  • Kümelenmiş (Clustered) İndeks: Tablo verilerinin fiziksel depolama sırasını belirler. Bir tabloda yalnızca bir kümelenmiş indeks olabilir ve genellikle birincil anahtar (Primary Key) üzerinde oluşturulur. Veri doğrudan indeks yapısında depolanır.
  • Kümelenmemiş (Non-Clustered) İndeks: Verilerin fiziksel sırasından bağımsızdır. Ayrı bir yapı olarak saklanır ve verinin fiziksel konumuna işaret eder. Bir tabloda birden fazla kümelenmemiş indeks olabilir. Sorgular, indeks üzerinden hızlıca ilgili verilere ulaşır.
  • Bileşik (Composite) İndeks: Birden fazla sütun üzerinde oluşturulan indekslerdir. WHERE, ORDER BY veya GROUP BY yan tümcelerinde sıkça birlikte kullanılan sütunlar için idealdir. Sütunların sırası önemlidir. Örneğin, (Sehir, PostaKodu) indeksi, WHERE Sehir = 'X' veya WHERE Sehir = 'X' AND PostaKodu = 'Y' sorgularında kullanılabilir, ancak sadece WHERE PostaKodu = 'Y' için yeterince etkili olmayabilir.

İndeks Tasarımı İçin En İyi Uygulamalar

  • Sık Kullanılan Sütunlar: WHERE, JOIN ON, ORDER BY ve GROUP BY yan tümcelerinde sıkça kullanılan sütunlara indeks ekleyin.
  • Kardinalite (Cardinality): Yüksek kardinaliteli (benzersiz veya çok sayıda farklı değeri olan) sütunlarda indeksler daha etkili çalışır (örneğin, e-posta adresleri, TC kimlik numaraları). Düşük kardinaliteli (örneğin, cinsiyet, durum gibi az sayıda farklı değeri olan) sütunlarda indeksler genellikle daha az faydalıdır veya maliyeti faydasından ağır basabilir.
  • Gereksiz İndekslerden Kaçınma: Her indeks, veri ekleme, güncelleme ve silme (INSERT, UPDATE, DELETE) işlemlerinin maliyetini artırır çünkü verinin yanı sıra indeksin de güncellenmesi gerekir. Bu nedenle sadece gerçekten gerekli olan indeksleri oluşturun.
  • İndeks Boyutu: İndeks ne kadar küçük olursa, belleğe sığma olasılığı o kadar yüksek olur ve bu da daha hızlı erişim anlamına gelir. Mümkünse kısa ve uygun veri tipleri kullanın.

Sorgu Optimizasyon Teknikleri

İndeksleme kadar önemli olan bir diğer konu da sorguların kendisinin doğru ve etkili bir şekilde yazılmasıdır.

SELECT Deyimi Optimizasyonu

  • Yıldız Kullanımından Kaçınma (SELECT *): Sadece ihtiyaç duyulan sütunları seçin. Gereksiz sütunların alınması, hem ağ trafiğini artırır hem de veritabanı sunucusunun daha fazla veri okumasına neden olur.

    -- Kötü Uygulama
    SELECT * FROM Urunler;
    
    -- İyi Uygulama
    SELECT UrunAdi, Fiyat FROM Urunler;

WHERE Koşulları Optimizasyonu

  • SARGable (Search Argument Able) Koşullar: İndekslerin kullanılabilmesi için WHERE koşullarının SARGable olması gerekir. Bu, koşulun doğrudan bir sütunun değerine uygulanması ve sütun üzerinde fonksiyon kullanılmamasının tercih edilmesi anlamına gelir.

    -- Kötü Uygulama (İndeks kullanamayabilir)
    SELECT * FROM Siparisler WHERE YEAR(SiparisTarihi) = 2023;
    
    -- İyi Uygulama (İndeks kullanabilir)
    SELECT * FROM Siparisler WHERE SiparisTarihi BETWEEN '2023-01-01' AND '2023-12-31';
  • LIKE Operatörü: Wildcard karakteri (%) koşulun başında kullanıldığında indeksler genellikle kullanılamaz.

    -- İndeks kullanabilir
    SELECT * FROM Musteriler WHERE Ad LIKE 'A%';
    
    -- İndeks kullanamaz
    SELECT * FROM Musteriler WHERE Ad LIKE '%A%';
  • OR Koşulları: Bazı durumlarda, OR içeren karmaşık koşullar yerine UNION ALL kullanarak ayrı sorguları birleştirmek daha performanslı olabilir. Ancak bu, veritabanı optimizasyoncusunun yeteneğine ve sorgunun yapısına bağlıdır.

JOIN Optimizasyonu

  • Doğru JOIN Türünü Seçmek: INNER JOIN, LEFT JOIN, RIGHT JOIN gibi farklı JOIN türlerinin ne zaman kullanılacağını iyi anlamak önemlidir.
  • ON Clause’unda İndeksli Sütunlar: Birleştirme koşulunda kullanılan sütunlar üzerinde indeks bulunması JOIN işlemlerini hızlandırır.
  • Küçük Tabloyu Önce Birleştirmek: Bazı veritabanları, JOIN sıralamasını optimize edebilir ancak genel kural olarak, en küçük sonuç kümesini üreten tabloyu diğerleriyle birleştirmek daha verimli olabilir.

Alt Sorgular (Subqueries) ve EXISTS/IN

Çoğu durumda, alt sorgular yerine JOIN kullanmak daha performanslıdır çünkü JOIN’ler veritabanı motoru tarafından daha etkili bir şekilde optimize edilebilir. EXISTS operatörü, IN operatörüne göre genellikle daha verimlidir, özellikle alt sorgu büyük sonuç kümeleri döndürüyorsa. EXISTS, koşulu sağlayan ilk satırı bulduğunda taramayı durdurabilirken, IN tüm alt sorguyu çalıştırmak zorunda kalabilir.

-- IN Kullanımı
SELECT Ad FROM Musteriler WHERE MusteriID IN (SELECT MusteriID FROM Siparisler WHERE ToplamTutar > 1000);

-- EXISTS Kullanımı (Genellikle daha performanslı)
SELECT M.Ad FROM Musteriler M WHERE EXISTS (SELECT 1 FROM Siparisler S WHERE S.MusteriID = M.MusteriID AND S.ToplamTutar > 1000);

GROUP BY ve ORDER BY Optimizasyonu

Bu yan tümcelerde kullanılan sütunlarda indeks bulunması, sıralama veya gruplama işlemlerini hızlandırabilir. Büyük veri kümelerinde gereksiz sıralamalardan kaçınmak veya sonuçları mümkün olduğunca erken filtrelemek önemlidir.

LIMIT/TOP Kullanımı

Bir sorgunun döndürdüğü sonuç sayısını sınırlamak (örneğin, bir sayfalama işlemi için) ağ trafiğini ve bellek kullanımını önemli ölçüde azaltır. LIMIT (MySQL, PostgreSQL) veya TOP (SQL Server) komutları bu amaçla kullanılır.

SELECT UrunAdi, Fiyat FROM Urunler ORDER BY Fiyat DESC LIMIT 10;

Veritabanı Şema Tasarımı

Veritabanının temel yapısı, SQL sorgularının performansı üzerinde derin bir etkiye sahiptir.

Normalizasyon ve Denormalizasyon

  • Normalizasyon: Veri tekrarını en aza indirme ve veri tutarlılığını sağlama sürecidir. Genellikle daha fazla tablo ve JOIN işlemi gerektirdiğinden okuma performansını bir miktar düşürebilir.
  • Denormalizasyon: Performansı artırmak için kasıtlı olarak veri tekrarına izin verme veya tabloları birleştirme işlemidir. Özellikle yoğun okuma, az yazma olan raporlama veya analitik sistemlerde faydalı olabilir. Ancak veri tutarlılığını sağlamak için ek çaba gerektirir.

Doğru Veri Türleri

Her sütun için en uygun ve en küçük veri türünü seçmek, depolama alanını azaltır, disk G/Ç’yi düşürür ve indekslerin daha verimli çalışmasına olanak tanır. Örneğin, bir sayının INT yerine SMALLINT veya TINYINT olarak saklanması, hem bellekte hem de diskte daha az yer kaplar.

Referans Bütünlüğü (Foreign Keys)

Yabancı anahtarlar (Foreign Keys), tablolar arasındaki ilişkileri ve veri bütünlüğünü sağlar. Ayrıca, veritabanı sorgu planlayıcısına tablolar arası ilişkiler hakkında ipuçları vererek daha iyi optimizasyon kararları almasına yardımcı olabilir.

Sunucu ve Veritabanı Yapılandırması

Yazılımsal optimizasyonlar kadar, donanım ve veritabanı sunucusunun doğru yapılandırılması da kritik öneme sahiptir.

Donanım Kaynakları

  • CPU: Özellikle karmaşık sorgular ve paralel işlemler için yeterli işlem gücü.
  • Bellek (RAM): Veritabanı önbellekleri (buffer pool, shared buffers) için kritik. Daha fazla bellek, disk G/Ç’yi azaltarak verilere daha hızlı erişim sağlar.
  • Disk G/Ç (I/O): Veritabanı, büyük miktarda veri okuma ve yazma işlemi yapar. SSD’ler, geleneksel HDD’lere göre önemli ölçüde daha iyi G/Ç performansı sunarak veritabanı hızını artırır. RAID konfigürasyonları da performansı ve güvenilirliği etkiler.

Veritabanı Ayarları

Her veritabanı yönetim sisteminin performansı etkileyen kendine özgü yapılandırma parametreleri vardır. Bunlar arasında bellek önbellek boyutları, işlem günlüğü (transaction log) ayarları, bağlantı havuzu limitleri ve paralel sorgu yürütme limitleri bulunur. Bu ayarlar, sistemin donanım kapasitesine ve iş yüküne göre dikkatlice ayarlanmalıdır.

Düzenli Bakım ve İzleme

Performans optimizasyonu, tek seferlik bir görev değil, sürekli bir süreçtir.

İndeks Bakımı

Veritabanında sürekli veri ekleme, güncelleme ve silme işlemleri, indekslerin parçalanmasına (fragmentation) neden olabilir. Parçalanmış indeksler, veritabanının verilere erişimini yavaşlatır. İndeksleri düzenli olarak yeniden oluşturmak (REBUILD) veya yeniden düzenlemek (REORGANIZE), performanslarını korumak için önemlidir.

İstatistik Güncellemeleri

Veritabanı sorgu planlayıcısı, en iyi yürütme planını oluşturmak için tablolardaki verilerin dağılımı hakkındaki istatistiklere güvenir. Bu istatistikler güncel olmadığında, planlayıcı yanlış kararlar alabilir. Otomatik istatistik güncelleme mekanizmaları olsa da, büyük veri değişikliklerinden sonra veya periyodik olarak manuel olarak güncellemeler yapmak (örneğin, ANALYZE TABLE) faydalıdır.

Periyodik Performans Analizi

Veritabanı performansını düzenli olarak izlemek, yavaşlayan sorguları veya sistemdeki yeni darboğazları erken tespit etmeyi sağlar. Bu, proaktif bir yaklaşımla olası sorunların büyümeden çözülmesine yardımcı olur.

SQL performans optimizasyonu, tek seferlik bir işlemden ziyade sürekli bir çabadır. Doğru indeksleme, etkili sorgu yazımı, uygun veritabanı şeması tasarımı ve düzenli izleme, sistemlerinizin sürekli yüksek performansla çalışmasını sağlar. Bu temel prensipleri benimseyerek, veritabanı uygulamalarınızın hem hızlı hem de ölçeklenebilir olmasını garanti edebilirsiniz. Unutmayın, iyi optimize edilmiş bir veritabanı, daha iyi kullanıcı deneyimi ve daha düşük operasyonel maliyet anlamına gelir.


SQL’de Görünümler (Stored Procedure ve Trigger Temelleri)

SQL veritabanı yönetiminde, verimlilik, güvenlik ve veri bütünlüğü kritik öneme sahiptir. Bu bağlamda, Görünümler (Views), Saklı Yordamlar (Stored Procedures) ve Tetikleyiciler (Triggers) gibi yapısal elemanlar, geliştiricilere güçlü araçlar sunar. Bu makale, söz konusu bu temel SQL bileşenlerinin ne işe yaradığını, nasıl kullanıldığını ve veritabanı işlemlerini nasıl optimize ettiğini ayrıntılarıyla inceleyecektir.

SQL Görünümler (Views)

Görünümler, SQL’de fiziksel olarak veri depolamayan, ancak bir veya daha fazla temel tablonun verilerinden türetilmiş sanal tablolardır. Bir görünüm aslında kaydedilmiş bir sorgudan ibarettir ve her çağrıldığında bu sorgu çalıştırılır. Görünümler, kullanıcılar için veri erişimini basitleştirir ve veri soyutlama katmanı oluşturur.

Görünümlerin Kullanım Amaçları

  • Güvenlik ve Veri Gizliliği: Kullanıcılara tüm tabloyu göstermek yerine, sadece yetkili oldukları belirli sütun veya satırları içeren görünümler sunularak hassas veriler gizlenebilir. Bu, yetkilendirme katmanını veritabanı seviyesine taşır.
  • Sorgu Basitliği ve Veri Soyutlama: Karmaşık JOIN’ler ve filtrelemeler içeren uzun sorguları bir görünüm içinde saklayarak, son kullanıcıların bu karmaşıklığı anlamadan sadece basit SELECT * FROM view_adı; gibi ifadelerle verilere erişmesini sağlar.
  • Veri Bütünlüğü ve Tutarlılık: Farklı tablolardan birleştirilmiş veriyi tutarlı bir yapı altında sunarak, raporlama veya analiz süreçlerini kolaylaştırır.
  • Uyumluluk: Temel tablo yapısı değişse bile (örneğin sütun adları), görünüm tanımı güncellenerek uygulama katmanının etkilenmemesi sağlanabilir.

Görünüm Oluşturma ve Kullanımı

Bir görünüm, CREATE VIEW ifadesiyle oluşturulur. Örneğin, müşteri ve sipariş bilgilerini birleştiren bir görünüm:

CREATE VIEW MusteriSiparisDetay AS
SELECT
    m.MusteriID,
    m.Ad,
    m.Soyad,
    s.SiparisID,
    s.SiparisTarihi,
    s.ToplamTutar
FROM
    Musteriler m
JOIN
    Siparisler s ON m.MusteriID = s.MusteriID
WHERE
    s.SiparisTarihi > '2023-01-01';

Bu görünümü kullanmak tıpkı bir tablo kullanmak gibidir:

SELECT MusteriID, Ad, Soyad, SiparisTarihi FROM MusteriSiparisDetay WHERE ToplamTutar > 1000;

Mevcut bir görünümü değiştirmek için ALTER VIEW, silmek için ise DROP VIEW kullanılır.

Saklı Yordamlar (Stored Procedures)

Saklı yordamlar, bir veya daha fazla SQL ifadesinden oluşan, önceden derlenmiş ve veritabanında saklanan programatik bloklardır. Bu yordamlar, parametre alabilir, kontrol akışı ifadeleri (IF, WHILE) içerebilir ve geri değer döndürebilirler.

Saklı Yordamların Kullanım Amaçları

  • Performans İyileştirme: Saklı yordamlar ilk çağrıldığında derlenir ve veritabanı sunucusunda önbelleğe alınır. Sonraki çağrılarda tekrar derlenmeye gerek kalmadığından daha hızlı çalışır. Ayrıca, ağ trafiğini azaltır çünkü uygulama sadece yordam adını ve parametrelerini gönderir, tüm SQL kodunu değil.
  • Güvenlik: Kullanıcılara doğrudan tablolara erişim vermek yerine, belirli işlemleri gerçekleştiren saklı yordamlara erişim izni verilerek daha güvenli bir ortam sağlanır. Bu, veri manipülasyonunu ve yetkilendirmeyi merkezi hale getirir.
  • Modülerlik ve Yeniden Kullanılabilirlik: Sık kullanılan veya karmaşık iş mantığına sahip işlemleri tek bir yordamda toplayarak kodun tekrar yazılmasını önler ve bakım kolaylığı sağlar.
  • Veri Bütünlüğü ve Tutarlılık: Veritabanı seviyesinde iş kurallarını uygulayarak, veri girişi veya güncellemelerinde tutarlılığı garanti eder.

Saklı Yordam Oluşturma ve Kullanımı

Bir saklı yordam CREATE PROCEDURE ifadesiyle tanımlanır. Aşağıdaki örnek, yeni bir müşteri ekleyen bir yordamı gösterir:

CREATE PROCEDURE YeniMusteriEkle
    @Ad NVARCHAR(50),
    @Soyad NVARCHAR(50),
    @Email NVARCHAR(100)
AS
BEGIN
    INSERT INTO Musteriler (Ad, Soyad, Email)
    VALUES (@Ad, @Soyad, @Email);

    SELECT SCOPE_IDENTITY() AS YeniMusteriID; -- Eklenen müşterinin ID'sini döndürür
END;

Bu yordam EXEC veya EXECUTE komutuyla çağrılır:

EXEC YeniMusteriEkle 'Ayşe', 'Yılmaz', 'ayse.yilmaz@example.com';

Saklı yordamlar OUT parametreleri aracılığıyla da değer döndürebilir, bu da daha karmaşık işlevsellik sunar.

Tetikleyiciler (Triggers)

Tetikleyiciler, belirli bir tabloda INSERT, UPDATE veya DELETE gibi bir olay meydana geldiğinde otomatik olarak çalışan özel saklı yordam türleridir. Tetikleyiciler, veritabanı seviyesinde iş kurallarını zorlamak, denetim (auditing) kayıtları tutmak veya basamaklı değişiklikler yapmak için kullanılır.

Tetikleyicilerin Kullanım Amaçları

  • Otomatik İşlemler: Bir veri değişikliği olduğunda otomatik olarak başka bir işlemi tetikleyerek veritabanı düzeyinde iş mantığı uygular.
  • Denetim (Auditing): Bir tablodaki veri değişikliklerini (kimin, ne zaman, neyi değiştirdiğini) bir denetim tablosuna kaydetmek için idealdir.
  • Veri Doğrulama: Bir kayıt eklenmeden veya güncellenmeden önce verinin belirli kurallara uygunluğunu kontrol etmek ve gerekirse işlemi iptal etmek için kullanılabilir (BEFORE tetikleyiciler).
  • Basamaklı Değişiklikler (Cascading Changes): Bir tabloda yapılan değişikliğin, ilgili diğer tablolara otomatik olarak yansımasını sağlamak (örneğin, bir kullanıcının silinmesiyle ilişkili tüm yorumlarını da silmek).

Tetikleyici Türleri ve Oluşturma

Tetikleyiciler, olayın zamanlamasına göre farklı türlerde olabilir:

  • AFTER Tetikleyiciler: İlgili SQL olayı (INSERT, UPDATE, DELETE) gerçekleştikten sonra tetiklenir. Çoğunlukla denetim veya başka bir tabloda veri güncellemek için kullanılır.
  • BEFORE Tetikleyiciler: İlgili SQL olayı gerçekleşmeden önce tetiklenir (SQL Server’da INSTEAD OF tetikleyiciler bu senaryoların bir kısmını karşılar, diğer veritabanlarında BEFORE bulunur). Genellikle veri doğrulama ve veri üzerinde değişiklik yapma için kullanılır.
  • INSTEAD OF Tetikleyiciler: Olayın kendisi yerine tetiklenir. Genellikle doğrudan güncellenemeyen görünümleri (JOIN içeren görünümler gibi) güncellemek için kullanılır.

Aşağıdaki örnek, bir ürünün fiyatı güncellendiğinde, eski ve yeni fiyatı bir log tablosuna kaydeden bir AFTER UPDATE tetikleyiciyi gösterir:

CREATE TRIGGER trg_UrunFiyatGuncellemeLog
ON Urunler
AFTER UPDATE
AS
BEGIN
    IF UPDATE(Fiyat) -- Sadece Fiyat sütunu güncellendiğinde çalışır
    BEGIN
        INSERT INTO UrunFiyatLog (UrunID, EskiFiyat, YeniFiyat, GuncellemeTarihi, GuncelleyenKullanici)
        SELECT
            d.UrunID,
            d.Fiyat AS EskiFiyat,
            i.Fiyat AS YeniFiyat,
            GETDATE(),
            SUSER_SNAME() -- Güncelleyen kullanıcı adını alır
        FROM
            DELETED d
        INNER JOIN
            INSERTED i ON d.UrunID = i.UrunID;
    END;
END;

INSERTED ve DELETED sanal tabloları, tetikleyici içinde ilgili olayın eski ve yeni değerlerine erişmek için kullanılır. INSERTED tablosu yeni eklenen veya güncellenen satırları, DELETED tablosu ise silinen veya güncellenmeden önceki satırları içerir.

SQL’deki Görünümler, Saklı Yordamlar ve Tetikleyiciler, modern veritabanı yönetiminin temel taşlarıdır. Veri güvenliğini artırırken, karmaşık sorguları basitleştirir, performansı optimize eder ve iş mantığını veritabanı seviyesinde uygularlar. Bu araçları etkin bir şekilde kullanarak, geliştiriciler daha sağlam, bakımı kolay ve performanslı veritabanı uygulamaları oluşturabilir, böylece veri bütünlüğünü ve sistem verimliliğini garantileyebilirler.


SQL’de Fonksiyonlar (Functions)

SQL veritabanlarında veri manipülasyonu ve sorgulama işlemleri sırasında karşılaşılan karmaşık görevleri basitleştirmek için fonksiyonlar güçlü bir araçtır. Bu yapısal elemanlar, belirli bir işlevi yerine getiren önceden tanımlanmış veya kullanıcı tarafından oluşturulmuş kod bloklarıdır. Fonksiyonlar, sorguları daha okunabilir hale getirirken, kod tekrarını azaltır ve verimliliği artırır. Veritabanı yönetiminde etkin bir şekilde kullanıldığında, SQL fonksiyonları geliştirme süreçlerini hızlandırır ve veri işleme mantığını merkezi bir yerde toplar.

SQL Fonksiyon Türleri

SQL fonksiyonları temel olarak iki ana kategoriye ayrılır: Yerleşik (Built-in) Fonksiyonlar ve Kullanıcı Tanımlı (User-Defined) Fonksiyonlar (UDF).

Yerleşik (Built-in) Fonksiyonlar

Veritabanı sistemleri (örneğin SQL Server, MySQL, PostgreSQL, Oracle) tarafından doğrudan sağlanan ve kullanıma hazır fonksiyonlardır. Bu fonksiyonlar genellikle çeşitli veri tipleri üzerinde işlemler yapmak için tasarlanmıştır ve geniş bir yelpazede görevleri kapsar.

Metin (String) Fonksiyonları

Metinsel ifadeler üzerinde işlem yapmak için kullanılırlar.

  • LEN() veya LENGTH(): Bir metin dizisinin karakter sayısını döndürür.
    SELECT LEN('Merhaba Dünya'); -- Sonuç: 13
  • CONCAT(): Birden fazla metin dizisini birleştirir.
    SELECT CONCAT('Merhaba', ' ', 'Dünya'); -- Sonuç: Merhaba Dünya
  • UPPER() ve LOWER(): Metni sırasıyla büyük veya küçük harfe dönüştürür.
    SELECT UPPER('sql dersleri'); -- Sonuç: SQL DERSLERI
  • SUBSTRING() veya SUBSTR(): Bir metin dizisinin belirli bir bölümünü alır.
    SELECT SUBSTRING('Veritabanı', 1, 5); -- Sonuç: Verit
  • REPLACE(): Bir metin dizisindeki belirli bir alt diziyi başka bir alt diziyle değiştirir.
    SELECT REPLACE('Merhaba Dünya', 'Dünya', 'Evren'); -- Sonuç: Merhaba Evren

Sayısal (Numeric) Fonksiyonlar

Sayısal değerler üzerinde matematiksel işlemler yapmak için kullanılırlar.

  • ROUND(): Bir sayıyı belirtilen ondalık basamak sayısına yuvarlar.
    SELECT ROUND(123.456, 2); -- Sonuç: 123.46
  • FLOOR(): Bir sayıyı kendisinden küçük en büyük tam sayıya yuvarlar (aşağı yuvarlama).
    SELECT FLOOR(123.99); -- Sonuç: 123
  • CEIL() veya CEILING(): Bir sayıyı kendisinden büyük en küçük tam sayıya yuvarlar (yukarı yuvarlama).
    SELECT CEILING(123.01); -- Sonuç: 124
  • ABS(): Bir sayının mutlak değerini döndürür.
    SELECT ABS(-100); -- Sonuç: 100
  • SQRT(): Bir sayının karekökünü döndürür.
    SELECT SQRT(81); -- Sonuç: 9

Tarih ve Saat (Date and Time) Fonksiyonları

Tarih ve saat değerleri üzerinde işlem yapmak için kullanılırlar.

  • GETDATE() veya NOW(): Mevcut tarih ve saati döndürür.
    SELECT GETDATE(); -- Sonuç: 2023-10-27 10:30:45.123 (örnek)
  • DATEDIFF(): İki tarih arasındaki farkı belirtilen birim cinsinden döndürür.
    SELECT DATEDIFF(day, '2023-01-01', '2023-01-31'); -- Sonuç: 30
  • DATEADD(): Bir tarihe belirtilen birim cinsinden bir değer ekler.
    SELECT DATEADD(month, 1, '2023-01-15'); -- Sonuç: 2023-02-15 00:00:00.000
  • YEAR(), MONTH(), DAY(): Bir tarihin yıl, ay veya gün bileşenini döndürür.
    SELECT YEAR('2023-10-27'); -- Sonuç: 2023

Aggregate (Toplama) Fonksiyonları

Bir sütundaki birden fazla satırdaki veriyi özetleyen tek bir değer döndürmek için kullanılırlar. Genellikle GROUP BY ifadesiyle birlikte kullanılırlar.

  • COUNT(): Bir sütundaki (NULL olmayan) satır sayısını veya tüm satırların sayısını döndürür.
    SELECT COUNT(*) FROM Musteriler;
  • SUM(): Bir sayısal sütundaki tüm değerlerin toplamını döndürür.
    SELECT SUM(SatisMiktari) FROM Satislar;
  • AVG(): Bir sayısal sütundaki tüm değerlerin ortalamasını döndürür.
    SELECT AVG(Fiyat) FROM Urunler;
  • MIN() ve MAX(): Bir sütundaki en küçük ve en büyük değeri döndürür.
    SELECT MIN(StokAdedi), MAX(StokAdedi) FROM Stoklar;

Dönüşüm (Conversion) Fonksiyonları

Bir veri tipini başka bir veri tipine dönüştürmek için kullanılırlar.

  • CAST() ve CONVERT(): Bir ifadeyi veya sütunu belirli bir veri tipine dönüştürür.
    SELECT CAST('123' AS INT); -- Sonuç: 123 (integer)
    SELECT CONVERT(VARCHAR(10), GETDATE(), 103); -- Sonuç: 27/10/2023 (belirli formatta)

Kullanıcı Tanımlı (User-Defined) Fonksiyonlar (UDF’ler)

Yerleşik fonksiyonların yeterli olmadığı veya özel iş mantığının gerektiği durumlarda, geliştiriciler kendi fonksiyonlarını oluşturabilirler. UDF’ler, belirli bir mantığı kapsüllemek ve SQL sorgularında tekrar kullanılabilirliği sağlamak için tasarlanmıştır.

Scalar Fonksiyonlar

Tek bir değer döndüren fonksiyonlardır. Genellikle karmaşık hesaplamalar veya veri manipülasyonları için kullanılırlar.

CREATE FUNCTION dbo.CalculateTax (@price DECIMAL(10, 2), @taxRate DECIMAL(5, 2))
RETURNS DECIMAL(10, 2)
AS
BEGIN
    RETURN @price * @taxRate;
END;

-- Kullanım Örneği
SELECT dbo.CalculateTax(100.00, 0.18); -- Sonuç: 18.00

Tablo Değerli Fonksiyonlar (Table-Valued Functions – TVF’ler)

Sonuç olarak bir tablo döndüren fonksiyonlardır. Bu fonksiyonlar, karmaşık sorguları basitleştirmek ve view’ler gibi kullanılmak üzere tasarlanmıştır.

  • Inline TVF’ler: Tek bir SELECT ifadesinden oluşan ve view’lere benzer şekilde çalışan TVF’lerdir. Performans açısından genellikle tercih edilirler.
  • Multi-statement TVF’ler: Birden fazla T-SQL ifadesi içerebilen daha karmaşık TVF’lerdir. İçlerinde değişken tanımlayabilir, döngüler ve koşullu ifadeler kullanabilirler. Ancak performans açısından inline TVF’lere göre daha maliyetli olabilirler.
-- Inline Table-Valued Function Örneği
CREATE FUNCTION dbo.GetProductsByCategory (@categoryName NVARCHAR(50))
RETURNS TABLE
AS
RETURN
(
    SELECT ProductID, ProductName, Price
    FROM Products
    WHERE Category = @categoryName
);

-- Kullanım Örneği
SELECT ProductID, ProductName FROM dbo.GetProductsByCategory('Elektronik');

SQL Fonksiyonlarının Avantajları

  • Kod Tekrarını Azaltma: Tekrar eden iş mantığını bir fonksiyon içinde kapsülleyerek kod tekrarını önler ve bakım maliyetlerini düşürür.
  • Modülerlik ve Okunabilirlik: Sorguları daha modüler ve okunabilir hale getirir. Karmaşık hesaplamalar fonksiyonlara taşınarak ana sorgu basitleştirilir.
  • Performans İyileştirmeleri: Özellikle yerleşik fonksiyonlar ve iyi tasarlanmış inline TVF’ler sorgu performansını artırabilir. Veritabanı motorları bu fonksiyonları optimize edilmiş bir şekilde çalıştırır.
  • Veri Bütünlüğü ve Güvenlik: Hassas veri işlemleri veya iş kuralları fonksiyonlar aracılığıyla uygulanabilir, bu da veri bütünlüğünü ve güvenliğini artırır. Ayrıca kullanıcıların doğrudan tablolara erişimini kısıtlayıp sadece fonksiyonlar üzerinden işlem yapmalarına izin verilebilir.

Fonksiyon Kullanımına Dikkat Edilmesi Gerekenler

  • Performans Etkisi: Özellikle kullanıcı tanımlı fonksiyonlar (UDF’ler), sorguların performansını olumsuz etkileyebilir. Özellikle scalar UDF’ler her satır için ayrı ayrı çağrıldığında ciddi yavaşlamalara neden olabilir. Mümkün olduğunda yerleşik fonksiyonlar veya inline TVF’ler tercih edilmelidir.
  • Yan Etkiler (Side Effects): SQL Server’da UDF’ler, veritabanının durumunu değiştiren (INSERT, UPDATE, DELETE gibi DML işlemleri yapan) yan etkilere sahip olamazlar. Bu durum, fonksiyonların veri okuma amaçlı olmasını ve deterministik bir sonuç üretmesini sağlar.
  • Veritabanı Motoru Bağımlılığı: Bazı yerleşik fonksiyonlar veritabanı motoruna özgü olabilir. Bu, farklı veritabanı sistemleri arasında geçiş yaparken uyumluluk sorunlarına yol açabilir.
  • Karmaşıklık: Çok karmaşık UDF’ler oluşturmak, hata ayıklamayı zorlaştırabilir ve sistemin anlaşılırlığını azaltabilir. Fonksiyonlar genellikle tek bir görevi yerine getirecek şekilde basit tutulmalıdır.

SQL fonksiyonları, veritabanı işlemlerini optimize eden, kod tekrarını önleyen ve sorguların okunabilirliğini artıran vazgeçilmez araçlardır. Yerleşik ve kullanıcı tanımlı fonksiyonlar sayesinde, veri işleme mantığı modüler bir yapıda toplanabilir, geliştirme süreçleri hızlanabilir. Ancak, performans üzerindeki potansiyel etkileri göz önünde bulundurularak dikkatli kullanılmaları önemlidir. Fonksiyonları doğru anlamak ve etkin bir şekilde uygulamak, SQL geliştiricileri için veritabanı yönetiminde büyük faydalar sağlar ve daha sürdürülebilir sistemler inşa etmeye olanak tanır.


SQL’de Tablo İlişkileri ve JOIN Kavramı

Veritabanı yönetimi söz konusu olduğunda, verilerin düzenli, tutarlı ve erişilebilir olması kritik öneme sahiptir. İlişkisel veritabanları, bu amacı gerçekleştirmek için tablolar arası bağlantı mekanizmalarını kullanır. Bu bağlantılar, farklı veri parçacıklarını mantıksal olarak bir araya getirerek anlamlı bilgi kümeleri oluşturmamızı sağlar. SQL’deki JOIN kavramı ise, bu ilişkilerden faydalanarak birden fazla tablodaki verileri tek bir sorguda birleştirmemize olanak tanıyan temel bir araçtır.

SQL’de Tablo İlişkileri

İlişkisel veritabanı tasarımının kalbinde tablo ilişkileri yatar. Bu ilişkiler, veritabanını daha verimli hale getirmek, veri tekrarını (redüntasyon) azaltmak ve veri bütünlüğünü sağlamak amacıyla kullanılır. Birincil Anahtar (Primary Key – PK) ve Yabancı Anahtar (Foreign Key – FK) kavramları, bu ilişkilerin kurulmasında temel yapı taşlarıdır.

Birincil Anahtar (Primary Key – PK)

Bir tablodaki her satırı benzersiz bir şekilde tanımlayan bir veya daha fazla sütundur. Birincil anahtar null (boş) değer içeremez ve her zaman benzersiz olmalıdır. Örneğin, bir “Müşteriler” tablosundaki “MüşteriID” sütunu bir birincil anahtar olabilir.

Yabancı Anahtar (Foreign Key – FK)

Başka bir tablodaki birincil anahtara referans veren bir veya daha fazla sütundur. Yabancı anahtar, iki tablo arasında bir bağlantı kurar ve referans bütünlüğünü sağlar. Örneğin, “Siparişler” tablosundaki “MüşteriID” sütunu, “Müşteriler” tablosundaki “MüşteriID” birincil anahtarına referans veren bir yabancı anahtardır. Bu sayede, var olmayan bir müşteriye sipariş girilmesi engellenir.

İlişki Türleri

Tablolar arasındaki ilişkiler genellikle üç ana kategoriye ayrılır:

1. Bire Bir İlişki (One-to-One – 1:1)

Bir tablodaki her kaydın, diğer tablodaki yalnızca bir kayıtla eşleştiği ilişki türüdür. Bu tür ilişkiler genellikle, bir tablonun çok fazla sütunu olduğunda ve bazı sütunların sık kullanılmadığı durumlarda, veri bütünlüğünü veya güvenliğini artırmak amacıyla kullanılır. Örneğin, “Kullanıcılar” tablosu ile “KullanıcıDetayları” tablosu arasında bir 1:1 ilişki olabilir. Her kullanıcı sadece bir detay kaydına, her detay kaydı ise sadece bir kullanıcıya ait olabilir.


CREATE TABLE Kullanicilar (
    KullaniciID INT PRIMARY KEY,
    KullaniciAdi VARCHAR(50)
);

CREATE TABLE KullaniciDetaylari (
    KullaniciID INT PRIMARY KEY,
    Ad VARCHAR(50),
    Soyad VARCHAR(50),
    Email VARCHAR(100),
    FOREIGN KEY (KullaniciID) REFERENCES Kullanicilar(KullaniciID)
);

2. Bire Çok İlişki (One-to-Many – 1:N)

En yaygın ilişki türüdür. Bir tablodaki bir kaydın, diğer tablodaki birden çok kayıtla eşleştiği, ancak diğer tablodaki her kaydın ilk tablodaki yalnızca bir kayıtla eşleştiği ilişkidir. Örneğin, bir “Departmanlar” tablosundaki her departman, “Çalışanlar” tablosundaki birden çok çalışana sahip olabilir, ancak her çalışan yalnızca bir departmana aittir.


CREATE TABLE Departmanlar (
    DepartmanID INT PRIMARY KEY,
    DepartmanAdi VARCHAR(100)
);

CREATE TABLE Calisanlar (
    CalisanID INT PRIMARY KEY,
    Ad VARCHAR(50),
    Soyad VARCHAR(50),
    DepartmanID INT,
    FOREIGN KEY (DepartmanID) REFERENCES Departmanlar(DepartmanID)
);

3. Çoka Çok İlişki (Many-to-Many – N:N)

Bir tablodaki bir kaydın, diğer tablodaki birden çok kayıtla ve diğer tablodaki bir kaydın da ilk tablodaki birden çok kayıtla eşleştiği ilişki türüdür. Doğrudan iki tablo arasında kurulamaz; bu tür bir ilişkiyi yönetmek için genellikle bir ara (bağlantı/köprü) tablo kullanılır. Örneğin, “Öğrenciler” tablosu ile “Dersler” tablosu arasında çoka çok ilişki vardır. Bir öğrenci birden çok ders alabilir ve bir ders birden çok öğrenciye verilebilir. Bu ilişkiyi “ÖğrenciDersleri” adında bir ara tablo ile çözeriz.


CREATE TABLE Ogrenciler (
    OgrenciID INT PRIMARY KEY,
    OgrenciAdi VARCHAR(50)
);

CREATE TABLE Dersler (
    DersID INT PRIMARY KEY,
    DersAdi VARCHAR(100)
);

-- Ara tablo
CREATE TABLE OgrenciDersleri (
    OgrenciID INT,
    DersID INT,
    PRIMARY KEY (OgrenciID, DersID),
    FOREIGN KEY (OgrenciID) REFERENCES Ogrenciler(OgrenciID),
    FOREIGN KEY (DersID) REFERENCES Dersler(DersID)
);

SQL’de JOIN Kavramı

SQL’deki JOIN ifadesi, ilişkili sütunlardaki değerlere dayanarak iki veya daha fazla tablonun satırlarını birleştirmek için kullanılır. Bu, farklı tablolarda depolanan verileri tek bir sonuç kümesinde görmemizi sağlar.

JOIN Türleri

Farklı senaryolara uygun çeşitli JOIN türleri bulunur:

1. INNER JOIN (İç Birleştirme)

İki tablonun birleşim koşulunu karşılayan (yani her iki tabloda da eşleşen değeri olan) satırları döndürür. Eşleşme olmayan satırlar sonuç kümesine dahil edilmez.


SELECT Calisanlar.Ad, Calisanlar.Soyad, Departmanlar.DepartmanAdi
FROM Calisanlar
INNER JOIN Departmanlar ON Calisanlar.DepartmanID = Departmanlar.DepartmanID;

2. LEFT JOIN (LEFT OUTER JOIN) (Sol Dış Birleştirme)

Sol tablodaki (FROM anahtar kelimesinden sonra belirtilen ilk tablo) tüm satırları ve sağ tablodaki eşleşen satırları döndürür. Eğer sağ tabloda bir eşleşme bulunamazsa, sol tablodaki satırlar yine de döndürülür ve sağ tabloya ait sütunlar için NULL değerleri görüntülenir.


SELECT Calisanlar.Ad, Calisanlar.Soyad, Departmanlar.DepartmanAdi
FROM Calisanlar
LEFT JOIN Departmanlar ON Calisanlar.DepartmanID = Departmanlar.DepartmanID;

Bu sorgu, tüm çalışanları listeler; bir departmanı olmayan çalışanlar için `DepartmanAdi` sütunu NULL olacaktır.

3. RIGHT JOIN (RIGHT OUTER JOIN) (Sağ Dış Birleştirme)

Sağ tablodaki (JOIN anahtar kelimesinden sonra belirtilen tablo) tüm satırları ve sol tablodaki eşleşen satırları döndürür. Eğer sol tabloda bir eşleşme bulunamazsa, sağ tablodaki satırlar yine de döndürülür ve sol tabloya ait sütunlar için NULL değerleri görüntülenir.


SELECT Calisanlar.Ad, Calisanlar.Soyad, Departmanlar.DepartmanAdi
FROM Calisanlar
RIGHT JOIN Departmanlar ON Calisanlar.DepartmanID = Departmanlar.DepartmanID;

Bu sorgu, tüm departmanları listeler; bir çalışanı olmayan departmanlar için `Ad` ve `Soyad` sütunları NULL olacaktır. (LEFT JOIN ile tabloların yerini değiştirerek aynı sonucu elde etmek mümkündür).

4. FULL JOIN (FULL OUTER JOIN) (Tam Dış Birleştirme)

Her iki tablodaki tüm satırları döndürür. Bir tabloda eşleşme bulunamazsa, diğer tablonun sütunları için NULL değerleri görüntülenir. Hem LEFT JOIN hem de RIGHT JOIN’in birleşimi olarak düşünülebilir.


SELECT Calisanlar.Ad, Calisanlar.Soyad, Departmanlar.DepartmanAdi
FROM Calisanlar
FULL JOIN Departmanlar ON Calisanlar.DepartmanID = Departmanlar.DepartmanID;

Bu sorgu, departmanı olmayan çalışanları, çalışanı olmayan departmanları ve eşleşen tüm çalışan-departman kombinasyonlarını listeler.

5. CROSS JOIN (Çapraz Birleştirme)

Her iki tablonun tüm olası kombinasyonlarını (Kartezyen çarpımını) döndürür. Yani, ilk tablodaki her satır, ikinci tablodaki her satırla birleştirilir. Genellikle dikkatli kullanılmalıdır çünkü büyük tablolarda çok fazla sonuç üretebilir.


SELECT Calisanlar.Ad, Departmanlar.DepartmanAdi
FROM Calisanlar
CROSS JOIN Departmanlar;

6. SELF JOIN (Kendine Birleştirme)

Bir tabloyu kendi kendine birleştirmektir. Aynı tablo içinde hiyerarşik verileri sorgulamak veya bir tablodaki satırları kendi içindeki diğer satırlarla karşılaştırmak için kullanılır. Bu, genellikle tabloya takma ad (alias) verilerek yapılır.


SELECT
    C1.Ad AS CalisanAdi,
    C1.Soyad AS CalisanSoyadi,
    C2.Ad AS YoneticiAdi,
    C2.Soyad AS YoneticiSoyadi
FROM
    Calisanlar C1
INNER JOIN
    Calisanlar C2 ON C1.YoneticiID = C2.CalisanID;

Bu örnekte, `Calisanlar` tablosundaki çalışanları yöneticileriyle birlikte listelemek için kendi kendine birleştirme kullanılır. Her çalışanın bir `YoneticiID` sütunu olduğu varsayılmıştır.

JOIN Koşulları: ON ve USING

  • ON Anahtar Kelimesi: Genellikle birleştirilecek sütunlar farklı adlara sahip olduğunda veya daha karmaşık birleştirme koşulları gerektiğinde kullanılır.
  • USING Anahtar Kelimesi: Birleştirilecek sütunların her iki tabloda da aynı ada sahip olduğu durumlarda daha kısa ve okunaklı bir syntax sağlar.

-- ON kullanımı (genel ve esnek)
SELECT C.Ad, D.DepartmanAdi
FROM Calisanlar C
INNER JOIN Departmanlar D ON C.DepartmanID = D.DepartmanID;

-- USING kullanımı (sütun adları aynı ise)
-- Not: Her SQL veritabanı sistemi USING'i desteklemeyebilir (örn. SQL Server)
SELECT C.Ad, D.DepartmanAdi
FROM Calisanlar C
INNER JOIN Departmanlar D USING (DepartmanID);

Tablo ilişkileri, sağlam ve optimize edilmiş veritabanı tasarımlarının temelini oluştururken, JOIN ifadeleri bu tasarımlardan anlamlı ve birleştirilmiş verileri çekmek için vazgeçilmez bir araçtır. Doğru JOIN türünü seçmek, ihtiyacınız olan veriye etkin bir şekilde ulaşmanızı sağlar.

SQL’de tablo ilişkileri ve JOIN kavramı, ilişkisel veritabanı yönetim sistemlerinin gücünü ortaya koyan temel taşlardır. Doğru tasarlanmış tablo ilişkileri, veri bütünlüğünü sağlarken veri tekrarını en aza indirir. JOIN’ler ise bu ilişkileri kullanarak, farklı tablolara dağılmış verileri mantıksal bir bütünlük içinde bir araya getirip anlamlı sorgu sonuçları elde etmemizi mümkün kılar. Her bir JOIN türünün kendine özgü kullanım senaryoları bulunur ve ihtiyaç duyulan veriye ulaşmak için doğru JOIN tipini seçmek, verimlilik açısından kritik öneme sahiptir.


SQL’de Yedekleme, Güvenlik ve Yetkilendirme

Günümüzün veri odaklı dünyasında, SQL veritabanları birçok kritik uygulamanın bel kemiğini oluşturmaktadır. Bu değerli bilgilerin korunması, iş sürekliliği ve veri bütünlüğü için hayati öneme sahiptir. Veritabanı yönetimi, sadece veri depolamakla kalmaz, aynı zamanda olası felaketlere karşı yedekleme stratejileri geliştirmeyi, kötü niyetli saldırılardan korunmak için güvenlik önlemleri almayı ve kullanıcıların verilere erişimini hassas bir şekilde yetkilendirmeyi de gerektirir. Bu üç temel sütun, sağlam bir veritabanı altyapısının vazgeçilmezidir.

SQL’de Yedekleme: Veri Kaybına Karşı Sigorta

Veri kaybı, donanım arızaları, yazılım hataları, doğal afetler veya insan hatası gibi çeşitli nedenlerle meydana gelebilir. SQL veritabanlarında yedekleme, bu tür durumlar karşısında verilerinizi kurtarmanın tek güvenilir yoludur. Etkili bir yedekleme stratejisi, iş sürekliliğini sağlar ve felaket kurtarma (Disaster Recovery) planlarının temelini oluşturur.

Yedekleme Çeşitleri ve Stratejileri

  • Tam Yedekleme (Full Backup): Bir veritabanının veya belirli dosya gruplarının tümünü içerir. En kapsamlı yedekleme türüdür ancak en uzun süreyi alır ve en çok depolama alanı gerektirir. Felaket anında hızlı bir kurtarma noktası sunar.
  • Diferansiyel Yedekleme (Differential Backup): En son tam yedeklemeden bu yana değişen tüm verileri içerir. Tam yedeklemeye göre daha hızlıdır ve daha az yer kaplar. Geri yükleme için yalnızca en son tam yedeklemeye ve en son diferansiyel yedeklemeye ihtiyaç duyar.
  • İşlem Günlüğü Yedeklemesi (Transaction Log Backup): SQL Server gibi veritabanlarında, veritabanında yapılan tüm değişiklikleri kaydeder. Küçük ve sık yedeklemeler için idealdir, bu da veri kaybını minimuma indirir. Özellikle kritik sistemlerde Point-in-Time Recovery (belirli bir ana geri dönme) olanağı sunar. MySQL gibi sistemlerde benzer işlevselliği binary log’lar (binlog) aracılığıyla elde edebiliriz.

Yedekleme ve Geri Yükleme Süreçleri

Yedeklemeler, belirlenen sıklıkta otomatik olarak çalışacak şekilde planlanmalıdır. Yedeklerin depolanması, ana veritabanı sunucusundan fiziksel olarak ayrı ve güvenli bir konumda (örneğin, ağ depolama, bulut depolama veya farklı bir veri merkezi) yapılmalıdır. Yedekleme kadar önemli olan bir diğer adım ise geri yükleme (restore) işlemlerinin düzenli olarak test edilmesidir. Bir yedeklemenin çalışır durumda olduğundan emin olmak için düzenli aralıklarla test geri yüklemeleri yapılmalı ve kurtarma süreleri ölçülmelidir.

Örnek (SQL Server):

BACKUP DATABASE YourDatabase
TO DISK = 'C:\Backup\YourDatabase_Full.bak'
WITH FORMAT, COMPRESSION, STATS = 10;

RESTORE DATABASE YourDatabase
FROM DISK = 'C:\Backup\YourDatabase_Full.bak'
WITH REPLACE;

SQL’de Güvenlik: Verilerinizi Koruma Kalkanı

Veritabanı güvenliği, hassas verileri yetkisiz erişimden, kötü amaçlı saldırılardan, veri ihlallerinden ve bozulmalardan korumak için uygulanan önlemlerin bütünüdür. Bir SQL veritabanı için güvenlik katmanlı bir yaklaşım gereklidir.

Başlıca Güvenlik Tehditleri ve Önlemler

  • SQL Enjeksiyonu (SQL Injection): Kullanıcı girdileri aracılığıyla kötü amaçlı SQL kodlarının çalıştırılmasına izin veren bir güvenlik açığıdır.
    • Önlem: Parametreli sorgular (parameterized queries) veya hazırlanmış ifadeler (prepared statements) kullanmak. Kullanıcı girdilerini asla doğrudan SQL sorgusuna eklememek. Giriş doğrulama (input validation) yapmak.
  • Zayıf Parolalar ve Kimlik Doğrulama: Kolay tahmin edilebilir parolalar veya yetersiz kimlik doğrulama mekanizmaları, yetkisiz erişim riskini artırır.
    • Önlem: Karmaşık parolalar kullanmak, düzenli parola değiştirmeyi zorunlu kılmak, çok faktörlü kimlik doğrulama (MFA) uygulamak.
  • Yetkisiz Erişim ve Aşırı Yetkiler: Kullanıcılara veya uygulamalara gereğinden fazla yetki verilmesi, güvenlik ihlallerine zemin hazırlar.
    • Önlem: En az ayrıcalık (Least Privilege) ilkesini uygulamak. Her kullanıcının veya uygulamanın yalnızca işini yapmak için ihtiyaç duyduğu minimum yetkiye sahip olmasını sağlamak.
  • Veri Şifreleme (Data Encryption): Verilerin hem depoda (at rest) hem de iletimde (in transit) korunması.
    • Önlem: Veritabanı düzeyinde şeffaf veri şifreleme (TDE – Transparent Data Encryption) kullanmak (SQL Server). İletişimi SSL/TLS kullanarak şifrelemek.
  • Yamalar ve Güncellemeler: Veritabanı yönetim sistemindeki (DBMS) güvenlik açıklarının giderilmemesi.
    • Önlem: DBMS ve işletim sistemini düzenli olarak güncel tutmak, güvenlik yamalarını zamanında uygulamak.
  • Denetim (Auditing): Veritabanı etkinliklerini izlememek.
    • Önlem: Veritabanı denetim mekanizmalarını etkinleştirmek ve şüpheli etkinlikleri takip etmek.

SQL’de Yetkilendirme: Doğru Kişiye Doğru Erişim

Yetkilendirme, bir kullanıcının (veya bir uygulamanın) kimliği doğrulandıktan sonra veritabanında hangi eylemleri gerçekleştirebileceğini ve hangi verilere erişebileceğini belirleme sürecidir. Kimlik doğrulama “kimsiniz?” sorusunu yanıtlarken, yetkilendirme “ne yapabilirsiniz?” sorusunu yanıtlar.

Temel Yetkilendirme Mekanizmaları

  • Kullanıcılar ve Oturumlar (Logins/Users): Veritabanına erişmek için oluşturulan bireysel kimliklerdir. Genellikle bir sunucu oturumu (login) ve veritabanı kullanıcısı (user) olarak ayrılırlar.
  • Roller (Roles): Benzer yetkilere sahip kullanıcıları gruplamak için kullanılan mantıksal yapılardır. Roller, yetki yönetimini basitleştirir ve hata yapma olasılığını azaltır. Örneğin, ‘Veri Okuyucu’ rolü tüm tablolarda SELECT yetkisine sahipken, ‘Veri Yazıcı’ rolü SELECT, INSERT, UPDATE, DELETE yetkilerine sahip olabilir.
  • İzinler/Ayrıcalıklar (Permissions/Privileges): Kullanıcılara veya rollere belirli nesneler (tablolar, görünümler, saklı yordamlar) üzerinde veya sistem genelinde (örneğin, veritabanı oluşturma) verilen yetkilerdir. Başlıca izin komutları şunlardır:
    • GRANT: Bir kullanıcıya veya role izin vermek için kullanılır.
    • REVOKE: Verilmiş bir izni geri almak için kullanılır.
    • DENY: Bir kullanıcının veya rolün belirli bir eylemi gerçekleştirmesini açıkça yasaklar (REVOKE’dan daha güçlüdür ve çakışan GRANT izinlerini geçersiz kılar).

Yetkilendirme İçin En İyi Uygulamalar

  • En Az Ayrıcalık İlkesi: Kullanıcıların ve rollerin yalnızca işlerini yapmak için kesinlikle ihtiyaç duyduğu minimum ayrıcalıklara sahip olmasını sağlamak.
  • Rol Kullanımı: Bireysel kullanıcılara doğrudan izin vermek yerine rolleri kullanarak yetkileri yönetmek. Bu, kullanıcılar katıldığında veya ayrıldığında yönetimi kolaylaştırır.
  • Düzenli Denetim: Mevcut izinleri ve rolleri düzenli olarak gözden geçirmek, gereksiz veya eski yetkileri kaldırmak.
  • Şema Tabanlı Güvenlik: Veritabanı nesnelerini (tablolar, görünümler) şemalar altında düzenleyerek, şema düzeyinde izinler vermek, yönetimi daha modüler hale getirir.
  • Satır Düzeyi Güvenlik (RLS – Row-Level Security): Belirli bir kullanıcının veya rolün, bir tablodaki yalnızca kendiyle ilgili satırlara erişmesini sağlamak. Bu, özellikle çok kiracılı (multi-tenant) uygulamalarda veya hassas verilerin bulunduğu senaryolarda önemlidir.

Örnek (SQL Server):

CREATE LOGIN MyLogin WITH PASSWORD = 'StrongPassword123!';
CREATE USER MyUser FOR LOGIN MyLogin;
CREATE ROLE DataReaderRole;
GRANT SELECT ON SCHEMA::dbo TO DataReaderRole;
ALTER ROLE DataReaderRole ADD MEMBER MyUser;

SQL veritabanlarında yedekleme, güvenlik ve yetkilendirme, modern veri yönetiminin ayrılmaz bileşenleridir. Bu üç alan, veritabanı altyapısının sağlamlığını, verilerin bütünlüğünü ve gizliliğini temin etmek için birbiriyle sıkı bir şekilde ilişkilidir. Etkili yedekleme stratejileriyle olası felaketlere karşı hazırlıklı olmak, katmanlı güvenlik önlemleriyle dış tehditlere karşı bir kalkan oluşturmak ve hassas yetkilendirme mekanizmalarıyla erişimi doğru bir şekilde kontrol etmek, veri kaybını ve ihlallerini önlemenin anahtarıdır. Proaktif bir yaklaşımla bu unsurlara yatırım yapmak, uzun vadeli iş başarısı için kritik öneme sahiptir.


© 2002 kiziltas.com - Kamil KIZILTAŞ. Her hakkı saklıdır.