Üretimde WHERE’siz bir UPDATE ya da DELETE’i, ifadeyi yazan kişinin fark
etmesini umarak değil, ifadeyi veritabanına ulaşmadan reddederek durdurursunuz.
Bunun için üç katman gerekir, çünkü her biri farklı biçimde başarısız olur: ifadeyi
reddeden bir parse adımı, geriye kalanı okuyan bir insan ve ilk ikisi kaçırdığında
hasarı sınırlayan veritabanı yetkileri.
Kaza neye benzer?
DELETE FROM orders;
Bir veritabanı istemcisindeki editör bunu, WHERE id = 42 olan ifadeyi
gönderdiği gibi gönderir. Veritabanı, doğru yetkiye sahip bir kullanıcıdan gelen
geçerli bir ifade görür ve çalıştırır. DELETE yetkisi olan bir rol, dikkatle
yapılmış tek satırlık bir değişiklikle tüm tabloyu etkileyen değişikliği
ayırt edemez; veritabanı erişim denetiminin ne olduğunu
anlatan yazıda geçen “kim işlem yapabilir” ile “ifade ne yapar” arasındaki
boşluk budur.
MySQL safe updates sorunu çözer mi?
Kısmen. MySQL 8.4 kılavuzu,
--safe-updates’i
“WHERE koşulunu unutarak bir UPDATE ya da DELETE ifadesi vermiş olabileceğiniz”
durumlarda yararlı olarak tanımlar. sql_safe_updates açıkken bu tür ifadeler
“WHERE koşulunda bir anahtar kısıtı belirtmezse ya da bir LIMIT koşulu
sağlamazsa, ya da ikisini birden” hata üretir. (2026-10-13’te okundu.)
Üretimde üç sınır önemlidir:
- Oturum bazında bir ayardır. Oturumunda açık olan kişiyi korur; bir betiğin ya da başka bir aracın onsuz açtığı bağlantıyı korumaz.
- Bir
LIMITonu tatmin eder.DELETE FROM orders LIMIT 100000kuralı geçer ve yine de yüz bin satırı siler. - Kılavuz,
WHEREkoşulunda anahtar olsa bile optimizer indeksi kullanmamaya karar verirse ifadenin hata verebileceğini belirtir. Doğru ifadelerde tetiklenen bir kural kapatılır.
Terminalde çalışan kişiler için kullanın. Tek denetiminiz bu olmasın. Aynısı GUI istemcilerindeki üretim ayarları için de geçerlidir; DBeaver ve DataGrip karşılaştırması bunların neyi koruyup neyi açık bıraktığını ele alır.
İfadeyi parse etmek ne katar?
Bağlantının önünde duran bir guard, kuralı hangi araç yazmış olursa olsun her
ifadeye uygulayabilir. QueryProxy her gönderimi, onay kuyruğuna girmeden önce
parse eder. SQL korumaları referansının ifadesiyle,
WHERE’siz bir UPDATE ya da DELETE gönderim anında reddedilir ve statik
olarak her zaman doğru olan bir WHERE koşulu eksik sayılır:
DELETE FROM users; -- rejected
DELETE FROM users WHERE 1 = 1; -- rejected
DELETE FROM users WHERE true; -- rejected
DELETE FROM users WHERE id = 1 OR 1 = 1; -- rejected
DELETE FROM users WHERE id = 42; -- allowed, still needs approval
Kural transaction’ların, CTE gövdelerinin, EXPLAIN ANALYZE’ın ve MariaDB
ANALYZE’ın içinde de geçerlidir. Geçersiz kılma imkânı yoktur: WHERE’siz ya
da her zaman doğru olan bir ifade bir gözden geçirene asla ulaşmaz (aşağıdaki
PostgreSQL DO blokları istisnadır).
Buna güvenmeden önce bilmeye değer iki ayrıntı var:
- Birden fazla ifade açık bir transaction ister. Bir istekteki iki çıplak
UPDATEifadesi reddedilir.BEGIN … COMMITiçinde atomik çalışırlar ve herhangi bir ifade başarısız olursa her şey geri alınır. - Kontrol statiktir. Literalleri, karşılaştırmaları,
AND,OR,NOTve parantezleri değerlendirir. Bir kolon ya da fonksiyon gibi değerlendiremediği bir işlenen asla doğru sayılmaz. PostgreSQLDOblokları da bu kuraldan muaftır: yazma olarak sınıflandırılır ve her zaman, gövdenin tamamını gören bir DBA’ya gider.
Guard neden yetmez?
Çünkü yasak listesi doğası gereği eksiktir. Aynı referans, listenin “yapısal olarak eksik” olduğunu ve bir ifadeyi yetkilendirenin DBA onayı olduğunu söyler: hazırlanmış SQL’i gören ve çalışıp çalışmaması gerektiğine karar veren bir kişi. İkinci katman budur. Bir isteğin nasıl ilerlediğini SQL sorgu onay akışında okuyabilirsiniz.
Üçüncü katman veritabanının kendisidir. QueryProxy’nin
üretim güvenliği rehberi, yalnızca okuyanlar için
yalnızca SELECT yetkili ayrı bir bağlantıyı önerir ve salt okunur çalıştırmanın
henüz mevcut olmadığını belirtir (v0.3.0 için planlı).
SQL korumaları kapsam tablosu, veritabanı
tarafındaki bir ifade zaman aşımını da henüz kapsanmamış olarak listeler; o da
v0.3.0 için planlıdır. O zamana kadar veritabanı tarafındaki sınırınız
yetkilerdir. Motora özgü ayrıntılar
PostgreSQL erişim denetiminde ve
MySQL ve MariaDB erişim denetiminde.
Yine de olursa?
O zaman bir kurtarma sorunudur. PostgreSQL 18.6, sürekli arşivleme ve point-in-time recovery’yi belgeler: “temel yedeğiniz alındığından bu yana herhangi bir andaki duruma veritabanını geri yüklemek mümkündür.” Bu, yalnızca arşivleme hatadan önce kurulmuşsa işe yarar. (2026-10-13’te okundu.)
Bu ne zaman fazla gelir?
Küçük bir veritabanının tek sahibi varsa ve her değişiklik gözden geçirilmiş
migration’lardan geçiyorsa, bağlantının önündeki bir parse adımı pek bir şey
katmaz. Asıl gerekçesi, üretime erişimi olan çok sayıda kişi ve elle yazılan
ifadelerdir. Başlamak için hızlı başlangıç,
QueryProxy’yi tek bir docker run ile çalıştırır.
Sık sorulanlar
- Birinin üretimde WHERE'siz DELETE çalıştırmasını nasıl engellerim?
- İfadeyi veritabanına ulaşmadan reddedin. Gönderilen her ifadeyi parse edin, WHERE koşulu olmayan UPDATE ve DELETE'leri geri çevirin, geriye kalanı ikinci bir kişinin onayına bağlayın. QueryProxy ilk ikisini gönderim anında, geçersiz kılma imkânı olmadan yapar.
- WHERE 1=1 yakalanır mı?
- QueryProxy'de evet. Statik olarak her zaman doğru olan bir WHERE koşulu eksik sayılır; dolayısıyla WHERE 1 = 1, WHERE true ve id = 1 OR 1 = 1 reddedilir. Kontrol statik ve elinden geleni yapan türdendir; bu yüzden bir kolon ya da fonksiyon gibi değerlendiremediği bir işlenen asla doğru sayılmaz.
- QueryProxy birden fazla ifade için neden transaction ister?
- Bir istekteki iki çıplak ifade reddedilir, çünkü yolun ortasında bir hata olursa ilki uygulanmış kalırdı. BEGIN ve COMMIT ile sarıldığında işçi (worker) bunları gerçek bir transaction içinde çalıştırır ve herhangi bir ifade başarısız olursa her şeyi geri alır.
- Yanlışlıkla çalıştırılmış bir UPDATE'i nasıl geri alırım?
- Bu bir önleme değil, kurtarma sorusudur. Yedekten geri yükleyin. PostgreSQL 18.6, temel yedek alındığından bu yana herhangi bir andaki duruma dönmeyi sağlayan point-in-time recovery'yi belgeler; yeter ki WAL arşivleme önceden kurulmuş olsun.