Salt okunur işlemler için neden Hazırda Bekletme'de İşlem'e ihtiyacım var?


107

Salt okunur işlemler için neden Hazırda Bekletme'de İşlem'e ihtiyacım var?

Aşağıdaki işlem DB'ye bir kilit koyuyor mu?

DB'den alınacak örnek kod:

Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction?
//readonly operation here

tx.commit() // why tx.commit? I don't want to write anything

session.close() Bunun yerine kullanabilir miyim tx.commit()?


9
İşlem, DB'nin kendisi tarafından gereklidir. Autocommit modu hakkında buradan okuyabilirsiniz: community.jboss.org/wiki/…
Bhesh Gurung

@BheshGurung Sanırım sadece yazma işlemi için işlemlere ihtiyacımız var
user93796

4
Bağlantıdaki "Otomatik işleme mitlerini çürütme" bölümünü okudunuz mu?
Bhesh Gurung

Yanıtlar:


131

İşlemleri salt okunur olarak işaretlemek için aslında nedenleriniz olabilir.

  1. Okuma işlemleri gerçekten tuhaf görünebilir ve bu durumda çoğu zaman insanlar işlemlere yönelik yöntemleri işaretlemez. Ancak JDBC yine de işlem yaratacak, sadece autocommit=truefarklı seçenek açıkça ayarlanmadıysa çalışacak .
  2. Ancak yönteminizin veritabanına yazmayacağının garantisi yoktur. Yöntemi olarak işaretlerseniz @Transactional(readonly=true), Spring JDBC işlemini salt okunur moda ayarlayacaktır, böylece bu işlem kapsamında DB'ye yazmanın gerçekten mümkün olup olmadığını belirleyeceksiniz . Mimariniz hantalsa ve bazı ekip üyeleri değişiklik sorgusunu beklenmeyen bir yere koymayı seçebilir, bu bayrak sizi sorunlu yere yönlendirecektir.
  3. Ayrıca salt okunur işlemler DB'ler tarafından optimize edilebilir, ancak bu tabii ki DB'ye özgüdür. Örneğin MySQL, 5.6.4 sürümünden itibaren yalnızca InnoDB'de bunun için destek ekledi.
  4. Doğrudan JDBC'yi değil, bir ORM'yi kullanıyorsanız, bu sorunlu olabilir. Örneğin, Hibernate topluluğu, işlem dışında çalışmanın öngörülemeyen davranışlara neden olabileceğini söylüyor. Bunun nedeni, Hibernate'in işlemi açacağı ancak kendi kendine kapatmayacağı için bağlantı, işlem yapılmadan Bağlantı Havuzuna geri dönecektir. O zaman ne olacak? JDBC sessizliği korur, dolayısıyla bu uygulamaya özgüdür (MySQL işlemi geri alır, Oracle bunu taahhüt eder). Bu aynı zamanda Bağlantı Havuzu seviyesinde de yapılandırılabilir (örneğin, C3P0 size böyle bir seçenek sunar, varsayılan olarak geri alma).
  5. Hazırda bekletme söz konusu olduğunda başka bir şey de Spring, salt okunur işlemlerde FlushMode'u MANUAL olarak ayarlar, bu da kirli kontrollere gerek olmadığı gibi başka optimizasyonlara yol açar.
  6. İşlem yalıtım düzeyini geçersiz kılmak veya açıkça ayarlamak isteyebilirsiniz. Bu, taahhüt edilmeyen değişiklikleri okuduğunuz veya istemediğiniz için, hayali okumalara maruz kalacağınız için okuma işlemlerini de etkiler.

Özetlemek gerekirse - her iki tarafa da gidebilirsiniz, ancak sonuçlarını anlamanız gerekir.


Yanıt verdiğiniz için teşekkürler. Hazırda bekletme kullanıyorum (jpa değil, hazırda bekletme). Ancak hazırda bekletme beni herhangi bir db işlemi yapmadan önce bir transcation başlatmaya zorluyor. evet ise nasıl?
user93796

Salt okunur bayrağı işlemin kendisi için değil aslında bağlantı için ayarlanmıştır ve bu şekilde Hazırda Bekletme aracılığıyla ona erişemezsiniz. Spring Transaction desteğini kullanmanız ve ek açıklamalar veya XML tabanlı işlem yapılandırması kullanmanız gerekir. Bunu yaparak Spring, Hibernate yerine bağlantı ve işlem yönetiminin sahipliğini üstlenir.
Stanislav Bashkyrtsev

1
Çok iyi açıkladı! Mark Richards'ın başka bir makalesi, İşlem ek açıklamasında salt okunur bayrağın tuzaklarını oldukça iyi açıklıyor - ibm.com/developerworks/java/library/j-ts1/index.html .
Mahesh

48

Tüm veritabanı ifadeleri, işlem sınırlarını açıkça belirtmediğimizde bile (BEGIN / COMMIT / ROLLBACK) fiziksel bir işlem bağlamında yürütülür .

İşlem sınırlarını açıkça belirtmezseniz, her bir ifadenin ayrı bir işlemde ( autocommitmod) yürütülmesi gerekecektir . Ortamınız iş parçacığı başına bağlantıyla başa çıkamıyorsa, bu durum ifade başına bir bağlantının açılıp kapanmasına bile yol açabilir.

Bir hizmetin @Transactional, tüm işlem süresi boyunca size tek bir bağlantı sağlayacağını ve tüm ifadelerin bu tek izolasyon bağlantısını kullanacağını bildirirsiniz. Bu, ilk etapta açık işlemleri kullanmamaktan çok daha iyidir.

Büyük uygulamalarda, çok sayıda eşzamanlı isteğiniz olabilir ve veritabanı bağlantısı edinme isteği oranını düşürmek , genel uygulama performansınızı kesinlikle artıracaktır.

JPA, okuma işlemlerinde işlemleri zorunlu kılmaz. İşlem bağlamını başlatmayı unutmanız durumunda, yalnızca yazma işlemleri işlem gerektiren bir istisna atar. Bununla birlikte, salt okunur işlemler için bile işlem sınırlarını beyan etmek her zaman daha iyidir ( @TransactionalBahar'da, büyük bir performans avantajı sağlayan salt okunur işlemleri işaretlemenize izin verir).


1
"... daha sonra her ifadenin ayrı bir işlemde yürütülmesi gerekecek". Konteyner, Toplu İşleme'yi otomatik olarak yapmıyor mu?
Arash

Toplu işlem veri okumak için değil, değişiklikler içindir. Ve yine de, JDBC toplu işlemi , JPA ve Hazırda Bekletme kullanılırken varsayılan olarak etkinleştirilmez.
Vlad Mihalcea

1
Teşekkürler Vlad. Bazı makalelerinizi okudum. Gerçekten faydalıdırlar.
Arash

Bu stackoverflow.com/q/34797480/179850 , salt okunur işlemlerin büyük performans avantajı sağladığına dair onayınızla biraz çelişiyor gibi görünüyor. En azından, hazırda bekletme bağlamında durum böyle görünmüyor.
nimai

Hayır değil. Bu salt okunur ayarı yapmakla ilgili, benimki ise otomatik tamamlamayı önlemekle ilgili.
Vlad Mihalcea

18

İşlemler gerçekten de veritabanına kilitler koyar - iyi veritabanı motorları eşzamanlı kilitleri mantıklı bir şekilde ele alır - ve salt okunur kullanımda, başka hiçbir işlemin görünümünüzü tutarsız hale getiren veriler eklememesini sağlamak için kullanışlıdır . Her zaman bir işlem istiyorsunuz (bazen izolasyon düzeyini ayarlamak mantıklı olsa da, başlamak için bunu yapmamak en iyisidir); İşleminiz sırasında DB'ye asla yazmazsanız, işlemi hem taahhüt etmek hem de geri almak aynı (ve çok ucuz) olacaktır.

Şimdi, eğer şanslıysanız ve DB'ye yönelik sorgularınız ORM'nin onları her zaman tek SQL sorgularıyla eşleştireceği şekildeyse, DB'nin yerleşik otomatik tamamlama davranışına güvenerek açık işlemler olmadan kurtulabilirsiniz , ancak ORM'ler nispeten karmaşık sistemlerdir. bu nedenle, uygulamanın gerçekte ne yaptığını kontrol etmek için çok daha fazla çalışmaya gitmedikçe, bu tür davranışlara güvenmek hiç de güvenli değildir. Açık işlem sınırlarını yazmak doğru yapmak çok daha kolaydır (özellikle bunu AOP veya ORM güdümlü bir teknikle yapabiliyorsanız; Java 7'den itibaren kaynakla deneme de kullanılabilir sanırım).


14

Yalnızca okuyup okumamanız önemli değildir - veritabanı, sonuç kümenizi yine de takip etmelidir, çünkü diğer veritabanı istemcileri sonuç kümenizi değiştirecek veriler yazmak isteyebilir.

Devasa veritabanı sistemlerini öldüren hatalı programlar gördüm, çünkü sadece verileri okuyorlar, ancak asla taahhüt etmiyorlar, işlem günlüğünü büyümeye zorluyorlar, çünkü DB işlem verilerini COMMIT veya ROLLBACK'ten önce, istemci hiçbir şey yapmasa bile serbest bırakamıyor. saatlerce.

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.