Ana içeriğe geç
Kesit SQL
İleri · Modern SQL

KVKK ve kişisel veri: maskeleme, takma adlandırma, saklama ve silme

Veri sorumlusu olarak SQL tarafında yapılacaklar: en az veri, maskeleme, k-anonimlik, imha.

Uygulamada aç, 6 alıştırmayı çözÜcretsiz, hesap gerekmez, kurulum yok.

Bu sayfa dersin okuma sürümüdür. Metin bir kutuyu çalıştırmanı ya da adıma geçmeni söylüyorsa dersi uygulamada aç.

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.

Hukuki notBu ders teknik uygulamaları anlatır; hukuki danışmanlık değildir. Kurumunun KVKK politikası ve veri envanteri esas alınmalıdır.

Temel ilkeler ve SQL karşılıkları

İlkeVeritabanında
Amaçla sınırlı ve ölçülü işlemeRaporlara 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 imhaSü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;
Takma ad ≠ anonimTakma adlandırılmış veri hâlâ kişisel veridir; anahtar ve başka bilgilerle kişiye ulaşılabilir. Anonim veri için kişiyi tekrar tanımlamak makul yollarla mümkün olmamalıdır.

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.

Alıştırmalara geç (6)