QueryProxy

Üretimde WHERE'siz UPDATE ve DELETE nasıl engellenir

Üretimde WHERE'siz UPDATE ve DELETE ifadeleri nasıl engellenir; MySQL safe updates'ten parse etmeye, onaya ve veritabanı yetkilerine kadar.

3 dk okuma

Ü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 LIMIT onu tatmin eder. DELETE FROM orders LIMIT 100000 kuralı geçer ve yine de yüz bin satırı siler.
  • Kılavuz, WHERE koş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 UPDATE ifadesi reddedilir. BEGIN … COMMIT iç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, NOT ve parantezleri değerlendirir. Bir kolon ya da fonksiyon gibi değerlendiremediği bir işlenen asla doğru sayılmaz. PostgreSQL DO blokları 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.
Paylaş

İlgili yazılar

Gezinmek için ok tuşları, açmak için Enter.