Neden SQL geliştiricisini ilgilendirir?
6698 sayılı Kişisel Verilerin Korunması Kanunu (KVKK) ve AB'deki GDPR, kişisel verinin işlenmesine, saklanmasına ve silinmesine kurallar getirir. Kuralları hukuk ekibi yorumlar ama uygulama çoğu zaman veritabanında yapılır: kimin hangi sütunu gördüğü, test ortamına ne kopyalandığı, verinin ne zaman imha edildiği.
Temel ilkeler ve SQL karşılıkları
| İlke | Veritabanında |
|---|---|
| Amaçla sınırlı ve ölçülü işleme | Raporlara yalnızca gereken sütunlar; SELECT * ile kişisel veriyi gereksiz taşımama |
| Erişimin sınırlanması | Rol bazlı yetki, görünüm üzerinden erişim, satır düzeyinde güvenlik, dinamik veri maskeleme |
| Veri güvenliği | Şifreleme (diskte ve iletimde), denetim kayıtları |
| Saklama süresi ve imha | Süresi dolan verinin silinmesi, anonimleştirilmesi; imha kayıtları |
| İlgili kişinin hakları | Kişinin verilerini bulup raporlayabilmek, düzeltebilmek, silebilmek |
Maskeleme
Raporu veya test verisini hazırlarken değerin bir kısmını gizlemek:
SELECT customer_id,
SUBSTR(first_name, 1, 1) || '***' AS ad,
SUBSTR(last_name, 1, 1) || '.' AS soyad,
SUBSTR(email, 1, 2) || '***' || SUBSTR(email, INSTR(email, '@')) AS email_maskeli,
2024 - birth_year - (2024 - birth_year) % 10 AS yas_grubu
FROM customers
WHERE email IS NOT NULL
ORDER BY customer_id
LIMIT 5;
-- SQL Server: dinamik veri maskeleme (veri değişmez, yetkisiz kullanıcı maskeli görür) ALTER TABLE dbo.customers ALTER COLUMN email ADD MASKED WITH (FUNCTION = 'email()'); ALTER TABLE dbo.customers ALTER COLUMN last_name ADD MASKED WITH (FUNCTION = 'partial(1, "***", 0)'); GRANT UNMASK TO rapor_yoneticisi; -- PostgreSQL: maskeli görünüm ve yetki CREATE VIEW rapor.v_musteri AS SELECT customer_id, left(first_name, 1) || '***' AS ad, city, segment FROM customers; REVOKE ALL ON customers FROM analist; GRANT SELECT ON rapor.v_musteri TO analist;
Takma adlandırma (pseudonymization)
Kimlik bilgisini, geri döndürülmesi zor bir anahtarla değiştirmek: e-posta yerine e-postanın tuzlu özeti (hash). Analizde aynı kişiyi takip edebilirsin ama kim olduğunu doğrudan göremezsin. Tuz (salt) ayrı ve güvenli saklanmalı.
-- SQL Server
SELECT CONVERT(VARCHAR(64), HASHBYTES('SHA2_256', CONCAT(@tuz, LOWER(email))), 2) AS kisi_anahtari FROM dbo.customers;
-- PostgreSQL (pgcrypto)
SELECT encode(digest(:tuz || lower(email), 'sha256'), 'hex') AS kisi_anahtari FROM customers;
-- BigQuery
SELECT TO_HEX(SHA256(CONCAT(@tuz, LOWER(email)))) AS kisi_anahtari FROM anadolu.customers;
Yeniden tanınma riski: k-anonimlik
Ad soyad silinse bile “şehir + doğum yılı + cinsiyet” birleşimi tek bir kişiye işaret edebilir. Bir veri setinde bu tür yarı tanımlayıcıların her birleşiminin en az k kişide görünmesi istenir. SQL ile kontrol:
SELECT city, birth_year, gender, COUNT(*) AS kisi FROM customers WHERE city IS NOT NULL GROUP BY city, birth_year, gender HAVING COUNT(*) < 3 ORDER BY kisi, city LIMIT 8;
Çözüm genellikle genelleştirmedir: doğum yılı yerine 10'luk yaş grubu, şehir yerine bölge.
Saklama süresi ve imha
-- 10 yılı dolmuş, ilişkisi bitmiş müşterilerin kişisel alanlarını anonimleştir
UPDATE customers
SET first_name = 'Anonim', last_name = 'Anonim', email = NULL, birth_year = NULL
WHERE iliski_bitis < DATEADD(year, -10, GETDATE());
-- İmha kaydı
INSERT INTO imha_kaydi (tablo, kayit_sayisi, yontem, tarih)
VALUES ('customers', @@ROWCOUNT, 'anonimleştirme', SYSDATETIME());
İlgili kişinin talebi
“Hakkımda hangi verileri tutuyorsunuz?” sorusuna yanıt verebilmek için kişiye bağlı tüm tabloları bilmek gerekir (veri envanteri). Yabancı anahtarlar ve iyi adlandırılmış sütunlar bu işi kolaylaştırır.