JDBC'de açık taahhütleri devre dışı bırakın, SQL'de tespit edin veya veritabanını salt okunur bir duruma getirin


12

Arka plan : http://sqlfiddle.com (sitem) üzerinde çalışıyorum ve orada olası bir kötüye kullanım yolunu önlemeye çalışıyorum. Şu anda ele aldığım bir soruyu sorarak umarım potansiyel kötüye kullanımı daha da kötüleştirmiyorum, ama ne yapabilirsiniz? Sana güveniyorum millet.

Herhangi bir kullanıcının belirli bir işlem bloğu içinde açık 'taahhüt' çağrıları yapmasını önlemek istiyorum. SQL Fiddle bağlamından işlem bloğu, sağ taraftaki panelde yürütülen koddur. Temel olarak, döngü ve bir düz metin SQL komutları listesi yürütüyorum ve yaptıkları tüm değişikliklerin toplu işlemin sonunda geri alınmasını sağlamak istiyorum. Normalde, değişiklikleri geri alınır, ancak bazen metin içinde açık bir 'kesin' ifadesi vardır ve bu nedenle geri dönmem işe yaramaz. Bu açık işlem büyük olasılıkla SQL Fiddle'daki şemayı kırmaya çalışan bir kullanıcıdan büyük olasılıkla, üzerinde çalışan diğer insanlar hataları görecektir.

Ana İstenen Sonuç : Mümkünse JDBC düzeyinde açık taahhütleri devre dışı bırakmak istiyorum. Bunun nedeni, birden çok veritabanı arka uç satıcısını desteklemem gerektiğidir ve elbette her birinin düşük düzeyde tuhaflıkları vardır.

Yedek seçenek : JDBC'yi açık taahhütleri devre dışı bırakacak şekilde yapılandırmak mümkün değilse, şu arka uçların her biri için bir toplu işlemi işlerken açık taahhütleri tespit etmek için çözümlere açık olurum: SQL Server, Oracle, MySQL ve PostgreSQL.

SQL Server için, bu çözüm düşündüm: Ben çalıştırmadan önce ifade için XML sorgu planı ayrıştırmak ve bu XPath eşleşen bir giriş olup olmadığını kontrol edin:

//*[@StatementType="COMMIT TRANSACTION"]

Bu SQL Server için oldukça iyi çalışacağını düşünüyorum. Ancak, bu yaklaşım diğer DB türleri için geçerli değildir. Oracle'ın açık taahhütler için XML yürütme planı çıktısı, bir taahhüt ifadesi çalıştırdığınıza (ancak bunun yerine yürüttüğü sorgulardan yürütme planı çıktısını tekrarladığına) gönderme yapmaz. PostgreSQL ve MySQL, açık taahhütler için hiçbir yürütme planı çıktısı (XML veya başka türlü) sağlamaz.

Bu beni "taahhüt" kelimesinin gerçek ifadesini kontrol etmeme bırakıyor. Mümkün olan her türlü varyasyon olabilmesi dışında bu işe yarar:

declare @sql varchar(50)
set @sql = 'com' + 'mit'
exec(@sql);

Yukarıdaki SQL Server (ki ben etrafında çalışabilir) için bir örnektir, ancak Oracle, MySQL ve PostgreSQL için benzer şeyler mümkün olacağını tahmin ediyorum. Bu varsayımda yanlış mıyım? Belki "dinamik" taahhüt ifadelerine izin vermezlerdi? Oracle, MySQL ve PostgreSQL'de benzer bir şey yapıp yapamayacağınızı görmek için SQL Fiddle'ı (tercihen örnek şema veya başka birinin üzerinde çalışması muhtemel değildir) kullanmaktan çekinmeyin. Değilse, belki basit dize algılama bunlar için işe yarayabilir.

Yine başka bir olasılık

Başka bir seçenek bana geldi - bu veritabanlarından herhangi birini salt okunur bir moda ayarlamanın bir yolunu biliyorsanız, bu modda hiçbir şey yapılamaz, bu da işe yarayabilir. Ben hala bu modda hiçbir şey taahhüt edilebilir sürece işlemleri başlatmak ve kod içinde çalışmasına izin gerekir. Mümkün mü?

Güncelleme

Son zamanlarda öğrendiklerim - bu aslında PostgreSQL ile ilgili bir sorun değil. Görünüşe göre bir işlem bloğu içinde verilen taahhütler, aynı blok sonunda geri alınırsa (Postgres'te) uygulanmaz. Postgres için Yaşasın!

Phil'in SO yazısına bağlantısı sayesinde, Oracle'ın sonradan ne olduğumu başarmak için DEFERRABLE INITIALLY DEFERRED hackini kullanabileceğimi düşünüyorum (bir taahhüt verildiyse bir hata atılacak, ancak bunun etrafında çalışabilirim). Bu Oracle'a yönelik olmalıdır. (Bir an için iç içe geçmiş işlemlerin burada işe yarayabileceğini düşündüm, ancak Oracle iç içe geçmiş işlemleri desteklemiyor gibi görünüyor mu? Her neyse, bu şekilde çalışan hiçbir şey bulamadım).

MySQL için henüz bir çözümünüz yok. Yuvalanmış işlemler kullanılarak denendi, ancak bu işe yaramıyor. Ciddi MySQL için bir şey izin vermiyor gibi sağ tarafında SELECTs veya bırakarak / DB her sorgu sonra yeniden oluşturma gibi daha sert yaklaşımlar düşünüyorum. İkisi de kulağa hoş gelmiyor.

çözüm

Şimdi, SQL Server ve Oracle için açıklanan çözümleri uyguladım ve bahsettiğim gibi, bu aslında PostgreSQL için bir sorun değil. MySQL için, sorgu panelini yalnızca ifadeleri seçmekle kısıtlamanın biraz talihsiz bir adımını attım. MySQL için DDL ve DML'nin şema paneline (sol taraf) girilmesi yeterlidir. Umarım bu çok fazla eski işi bozmaz, ancak veri tutarlılığını sağlamak için yapılması gereken şey olduğunu düşünüyorum. Teşekkürler!


Bahsetmeye değer - Ben de "ön-taahhüt" tetikleyicileri bakarak bir çok araştırma yaptım. Görünüşe göre bunlar mevcut değil, maalesef bu da bir seçenek değil.
Jake Feasel

2
Oracle için bu, COMMIT'leri yakalamak için iyi bir sinsi yol gibi görünüyor: stackoverflow.com/a/6463800/790702 Bahsetmediği, 2. durumu durdurmak için kodunuzdaki kısıtlama ihlallerini de yakalayabilmeniz gerektiğidir. meydana gelen.
Philᵀᴹ

@Phil orada tek sorun tabloların her biri (sol panelde tanımlanmıştır) tanımı üzerinde kontrol yok (ve gerçekten istemiyorum) olmasıdır. Böylece, ERTELENEBİLİR BAŞLANGIÇLA ERTELENEN yan tümcesi orada olmazdı (bunu tüm tablolar için otomatik olarak yapmanın bir yolu yoksa - tablo ifadeleri oluşturmak için yanıt veren bir sistem tetikleyicisi aracılığıyla söyleyin? Ugh)
Jake Feasel

1
@NickChammas Şemayı (sol panelde tanımlandığı gibi) sabit bir durumda tutabilmem için taahhütleri devre dışı bırakmam gerekiyor. Aynı sorunu çözmeye çalışan aynı şemaya göre sorgu yazan çok sayıda kişi olabilir. Birbirlerine müdahale etmelerini önlemek için, yapının ve verilerin değişmesini engellediğimden emin olmalıyım. Bu geri alma işlemleri ile gerçekleştirilir, ancak sağ taraf kodu işlenirse bu gerçekleşmez.
Jake Feasel

2
@RickJames DDL, MySQL ve Oracle'da örtülü taahhütler oluşturur, ancak PostgreSQL veya SQL Server'da oluşturmaz. Bu yazıdan sonra uyguladığım mekanizmalar bu endişeyi ele alıyor. Keyfi SQL girmek kadar - bütün mesele bu!
Jake Feasel

Yanıtlar:


3

Oracle için bu, KOMİTELER'i yakalamanın iyi bir gizli yolu gibi görünüyor:

/programming//a/6463800/790702

Bahsetmediği şey, meydana gelen 2. durumu durdurmak için kodunuzdaki kısıtlama ihlallerini de yakalayabilmenizdir.


Harika, tekrar teşekkürler Phil. Oracle için bu tekniği iyi kullanabildim. Diğer veritabanlarının ertelenmiş kısıtlamaları desteklemesini ister.
Jake Feasel

Telaşa gerek yok. Sohbete bırakın ve merhaba deyin :)
Philᵀᴹ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.