Java mühendisi mülakatı 1000 soru 146-Spring veritabanı işlem yayılma özellikleri ve yalıtım düzeyi

146. Spring tarafından desteklenen veritabanı işlem yayılma özelliklerini ve izolasyon seviyelerini kısaca tanıtın.

Spring'in desteklediği işlem ve yayılma özelliklerini tanıtmadan önce, bu konuyla hiçbir ilgisi olmayan, sadece basit bir kayıt olan SpringBean'in kapsamını anlayalım.

İlkbaharda şunları yapabilirsiniz: < fasulye > Çekirdeğin kapsamı, çekirdeğin tek eşgörünümlü mü yoksa çoklu eşgörünümlü mü olduğunu belirlemek için öğenin kapsam özniteliğinde ayarlanır. Varsayılan olarak, Spring yalnızca IOC kapsayıcısında bildirilen her çekirdek için benzersiz bir örnek oluşturur ve tüm IOC kapsayıcısı içinde paylaşılabilir; sonraki tüm getBean () çağrıları ve fasulye referansları bu benzersiz fasulye örneğini döndürür , Kapsama singleton denir, o tüm fasulyelerin varsayılan kapsamıdır.

  • singleton: SpringIOC kapsayıcısında yalnızca bir bean örneği vardır ve fasulye tek bir örnek olarak mevcuttur
  • prototip: getBean () her çağrıldığında yeni bir örnek döndürülür
  • istek: Her HTTP isteği yeni bir Bean oluşturur. Bu kapsam yalnızca WebApplicationContext ortamı için geçerlidir.
  • Oturum: Aynı HTTP Oturumu bir Bean'i paylaşır ve farklı HTTP Oturumları farklı Beans kullanır. Bu kapsam yalnızca WebApplicationContext ortamı için geçerlidir.
  • Spring Bean kapsamını tanıttıktan sonra konuya girmeye başlayalım - Spring'in desteklediği veritabanı işlem yayılma özellikleri ve izolasyon seviyesi

    1. İşlemin yayılma özellikleri

    Öncelikle, bir işlemin yayılma özelliğinin (yayılma davranışı) ne olduğunu anlayalım: Bir işlem yöntemi başka bir işlem yöntemi tarafından çağrıldığında, işlemin nasıl yayılması gerektiğini belirtmelisiniz. Örneğin: yöntem mevcut bir işlemde çalışmaya devam edebilir veya yeni bir işlem başlatıp kendi işleminde çalışabilir.

    İşlemin yayılma davranışı, yayılma özniteliğiyle belirtilir.

    Yayılma: İşlemin yayılma davranışını ayarlamak için kullanılır: Bir yöntem bir işlemi açan bir yöntemde çalıştığında, mevcut yöntemin orijinal işlemi kullanması veya yeni bir işlem açması, işlemin yayılma davranışıdır.

    Örneğin: Propagation.REQUIRED: orijinal işlemi kullanmaya devam etmek anlamına gelen varsayılan değer; Propagation.REQUIRES_NEW: orijinal işlemi askıya alın ve yeni bir işlem başlatın. En yaygın olarak kullanılan işlem yayılma öznitelikleri, aşağıdaki programlamayla test edilen GEREKLİ ve GEREKLİDİR.

    İlk olarak, veritabanında üç tablo oluşturun:

    VERİTABANI OLUŞTURMA / *! 32312 VAR DEĞİLSE * / `location` / *! 40100 VARSAYILAN KARAKTER SETİ utf8 * /; "Konum" KULLANIN; "Hesap" VARSA TABLO DÜŞÜR; TABLE "hesabı" ( `id` int (11) BOŞ DEĞİL AUTO_INCREMENT, `kullanıcı adı` varchar (30) VARSAYILAN NULL, "denge" işaretsiz VARSAYILAN NULL kayar, BİRİNCİL ANAHTAR ("kimlik") ) MOTOR = InnoDB AUTO_INCREMENT = 2 DEFAULT CHARSET = utf8; "hesap" ("id", "kullanıcı adı", "bakiye") değerlerine (1, "HanZong", 100) ekleyin; "Kitap" VARSA TABLOSU BIRAKIN; TABLO OLUŞTUR "kitap" ( `isbn` varchar (20) VARSAYILAN NULL, `isim` varchar (20) VARSAYILAN NULL, "fiyat" float VARSAYILAN NULL ) MOTOR = InnoDB VARSAYILAN KARAKTER = utf8; "kitap" ("isbn", "isim", "fiyat") değerlerine ('1001', 'Bahar', 60), ('1002', 'İlkbaharMVC', 50) ekleyin; TABLO VARSA "book_stock"; TABLO OLUŞTUR "book_stock" ( `isbn` varchar (20) VARSAYILAN NULL, `stock` int (11) VARSAYILAN NULL ) MOTOR = InnoDB VARSAYILAN KARAKTER = utf8; "book_stock" ("isbn", "stok") değerlerine ('1001', 100), ('1002', 100) ekleyin;

    Ardından, Spring geliştirme ortamını oluşturun, özel yapılandırma burada açıklanmayacaktır, bu bilgi noktasının odak noktası değildir. Ardından üç arayüz ve üç uygulama sınıfı oluşturun.

    Kasiyer arayüzü:

    import java.util.List; genel arayüz Kasiyer { // Nasıl kontrol edilir void checkout (int userId, List < Dize > isbns); } Uygulama sınıfı: import com.spring.transaction.BookShopService; import com.spring.transaction.Cashier; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; @Service ("kasiyer") public class CashierImpl, Cashier { @Autowired özel BookShopService bookShopService; @Transactional @Override public void checkout (int userId, List < Dize > isbns) { for (String isbn: isbns) { // BookShopService'de alışveriş yöntemini çağırın bookShopService.purchase (userId, isbn); } } } BookShopService arayüzü: genel arayüz BookShopService { // Bir satın alma yöntemi tanımlayın geçersiz satın alma (int userId, String isbn); }

    Uygulama sınıfı:

    import com.spring.transaction.BookShop Dao; import com.spring.transaction.BookShopService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Hizmet public class BookShopServiceImpl, BookShopService'i uygular { @Autowired özel BookShop Dao bookShop Dao; @Transactional @Override public void satın alma (int userId, String isbn) { // 1. Almak istediğiniz kitabın fiyatını alın double bookPrice = bookShop Dao.getBookPriceByIsbn (isbn); System.out.println (bookPrice); // 2. Kitap envanterini güncelleyin bookShop Dao.updateBookStock (isbn); // 3. Kullanıcının bakiyesini güncelleyin bookShop Dao.updateAccountBalance (userId, bookPrice); double bookPriceByIsbn = bookShop Dao.getBookPriceByIsbn (isbn); System.out.println (bookPriceByIsbn); } }

    Veritabanını çalıştırmak için arayüz:

    genel arayüz BookShop Dao { // Kitap numarasına göre kitabın fiyatını kontrol edin double getBookPriceByIsbn (Dize isbn); // Kitapların envanterini kitap numarasına göre güncelleyin ve bir seferde yalnızca bir kitap satın alın void updateBookStock (String isbn); // Kullanıcının hesap bakiyesini kullanıcı kimliği ve kitabın fiyatına göre güncelleyin void updateAccountBalance (int userId, double bookPrice); }

    Uygulama sınıfı:

    import com.spring.transaction.BookShop Dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.stereotype.Repository; @Repository ("bookShop Dao") public class BookShop DaoImpl, BookShop Dao { @Autowired özel JdbcTemplate jdbcTemplate; @Override public double getBookPriceByIsbn (String isbn) { // sql ifadesi yaz String sql = "isbn =? Olan kitaptan fiyat seçin"; // JdbcTemplate içinde queryForObject yöntemini çağırın Double bookPrice = jdbcTemplate.queryForObject (sql, Double.class, isbn); iade bookPrice; } @Override public void updateBookStock (String isbn) { // sql ifadesi yaz String sql = "book_stock set stoğunu güncelle = stock-1 isbn =?"; // JdbcTemplate'te güncelleme yöntemini çağırın jdbcTemplate.update (sql, isbn); } @Override public void updateAccountBalance (int userId, double bookPrice) { // sql ifadesi yaz String sql = "hesap bakiyesini güncelle = bakiye-? İd =?"; // JdbcTemplate'te güncelleme yöntemini çağırın jdbcTemplate.update (sql, bookPrice, userId); } }

    Yukarıdaki arayüzü ve uygulama sınıflarını tanıtın. BookShopService arayüzünde bir satın alma () yöntemi, Cashier'de bir checkout () yöntemi, bir ödeme yöntemi, checkout () yönteminin işlevi, checkout'u elde etmek için satın alma () yöntemini çağırması gerekir Bildirim temelli işlem açıklaması @ İşlem, () yöntemine eklenir ve bildirim temelli işlem açıklaması @ İşlem açıklaması da buy () yöntemine eklenir. Checkout () yöntemi, satın alma () yöntemini çağırır ve her iki yöntem de işlemleri kullanır. Şu anda, çalışırken, satın alma () kendi işlemini veya checkout () kullanan işlemi kullanıyor mu? Bu, işlerin yayılması!

    İşlemin yayılma davranışı, @Transactional ek açıklamasında bir yayılma özelliği kullanılarak ayarlanabilir. Yayılma için aşağıdaki 7 öznitelik değeri ayarlanabilir.

    Bir göz atalım. Purchase () yöntemi checkout () yönteminde çalışır. Springin varsayılan işlem yayma özniteliğine göre GEREKLİDİR, daha sonra satın alma () yöntemi checkout () yöntemini kullanmalıdır. Checkout () yönteminde bir tane vardır. For döngüsü, satın alma yöntemini birden çok kez çağırabilir İşlemin atomikliğine göre, satın alma () yönteminin birden çok yürütülmesi ya başarılı ya da başarısız olacaktır. Bir test yöntemi yazıyoruz:

    public class TestTX { // IOC kapsayıcı nesnesi oluştur ApplicationContext ioc = new ClassPathXmlApplicationContext ("applicationContext.xml"); @Ölçek public void testCashier () { Kasiyer kasiyer = (Kasiyer) ioc.getBean ("kasiyer"); // Liste Oluştur Liste < Dize > isbns = new ArrayList < > (); isbns.add ("1001"); isbns.add ("1002"); // Ödemeye git cashier.checkout (1, isbns); } }

    Test programında bir ArrayList oluşturup biri 1001 diğeri ise satın alacağımız kitabı temsil eden 1002 olmak üzere iki kitap ID'si ekliyoruz.Kitabın fiyatı veri tabanındaki kitap tablosunda saklanıyor. 1001 fiyatı 60.1002. Fiyat 50'dir. Diğer tablo book_store kitap envanterini saklar, 1001 envanter 100 kitap, 1002 envanter 100 kitap, son tablo kullanıcı tablosu hesabıdır, sadece bir kullanıcı vardır, kullanıcı bakiyesi 100 yuan, bu bakiye yapım aşamasındadır Tablo işaretsiz olarak ayarlanmalıdır ve negatif bir sayı olamaz, aksi takdirde test edilemez.

    Artık hesap bakiyesi sadece 100 yuan olduğuna göre, aynı anda 1001 ve 1002'nin iki kopyasını satın almam gerekiyor, bu da 10 yuan gibi önemli bir fark. Şimdi bir nüsha alamayacağımızı ya da satın alabileceğimizi test edelim. İşlem yayılma davranışına göre ayar yoksa varsayılan değeri temsil eder Varsayılan değer GEREKLİDİR: Çalışan bir işlem varsa mevcut yöntem bu işlemde çalışır, aksi takdirde yeni bir işlem açılır ve kendi işleminde çalıştırılır. Diğer bir deyişle, 1001 satın almak ve 1002 almak aynı işlem içindedir.İşlemin atomikliğine göre ikisi de tamamlanır ya da tamamlanmaz.Şimdi bakiyem 100'dür. 1001'i başarıyla satın alabilirim ama 1002'yi satamıyorum. Sonuç nedir? Test programını çalıştıralım. Bir istisna bildirildi:

    Nedeni: com.mysql.jdbc.MysqlDataTruncation: Veri kesme: 1. satırdaki 'denge' sütunu için aralık dışı değer

    Bu cümle anormaldir çünkü tablo oluşturulurken bakiye işaretsiz olarak ayarlanmıştır, böylece negatif bir sayı olamaz. Bu bizim umursadığımız şey değil, bizim önemsediğimiz şey, veri tabanındaki envanter ve hesap bakiyesinin değişip değişmediği. Veritabanı tablosunu yeniledik ve bakiyenin değişmediğini ve iki kitabın da başarıyla satın alınmadığını gördük. Bu neden böyle? Tekrar analiz edelim. İşlemin yayılma davranışı varsayılan değer ise, yani bunu @ İşlem ek açıklamasında ayarlamadıysak, varsayılan değer GEREKLİDİR, bu da satın alma işlemine () işlemi de eklememize rağmen checkout () yönteminin orijinal işleminin kullanılacağı anlamına gelir. , Ancak işlemin yayılma davranışı varsayılan değer olduğundan, işlemin checkout () yöntemini kullanacaktır. İşlemin checkout () yöntemini kullanırsanız, ArrayList'te iki kitap olduğunu ve iki kitabın çağrıldığını görürüz. Aynı satın alma () yöntemi, iki çağrı aynı işlemdedir, ancak 1001 satın aldıktan sonra tekrar 1002 satın alın ve başarısız olur. İşlemin atomikliğine göre, hepsi tamamlanır veya tamamlanmaz, bu nedenle İşlemi geri almak, nihayet yukarıdaki sonucu verdi.

    Öyleyse, başarılı bir tane yapabilir miyiz? Evet, satın alma () yönteminin işlem yayılma davranışını yalnızca REQUIRES_NEW olarak değiştirmeniz gerekir.

    @Transactional (yayılma = Yayılma.REQUIRES_NEW)

    Test programını da aynı şekilde çalıştırın ve yine de "Veri kesme: 1. satırdaki" denge "sütunu için aralık dışı değeri" rapor eder. Ondan bağımsız olarak, veritabanını yeniler ve hesap bakiyesini gözlemleriz ve 40 olduğunu buluruz, ardından envantere, 1001 envantere bakarız. 99.1002 olan envanter değişmeden kalır ve 100 olarak kalır. Bu, bir kopyasını başarıyla satın aldığımızı gösterir. Purchase () yönteminin işlem yayma davranışını REQUIRES_NEW olarak değiştirdiğimizden, her çağrıldığında yeni bir şey açılıyor. Checkout () işlemi de ayarlasa da, sizinkini kullanmıyorum, her seferinde kendiminkini kullanıyorum. Bu Birbiri üzerinde etkisi olmayan işlemler arasındaki izolasyondur, bu yüzden 1001 ve 1002 satın aldığımızda aynı işlem kullanılmaz. 1002'nin alınmaması 1001'in satın alınmasının başarısız olmasına neden olmaz. Yani nihai sonuç, 1001'in başarıyla satın alındığı ve 1002'nin başarıyla satın alınamadığıdır.

    Küçük özet:

    • GEREKLİ yayılma davranışı: bookService'in satın alma () yöntemi başka bir işlem yöntemi checkout () tarafından çağrıldığında, varsayılan olarak mevcut işlemde çalışacaktır. Bu nedenle, checkout () yönteminin başında ve sonunda yalnızca bir işlem vardır Bu işlem yalnızca checkout () yöntem çağrısının sonunda gerçekleştirilecek ve kullanıcının bir kopya satın alamamasına neden olacaktır.

    • REQUIRES_NEW yayılma davranışı: Yöntemin yeni bir işlem başlatması ve kendi işleminde çalışması gerektiğini belirtir.Zaten çalışıyorsa, önce askıya alın.

    2. İşlemin izolasyon seviyesi

    İşlemlerin izolasyon seviyesinden bahsetmeden önce, ilk olarak veritabanı işlem eşzamanlılığı sorununa bakalım:

    İki işlem olduğunu varsayalım: İşlem01 ve İşlem02 eşzamanlı olarak yürütülür.

    Kirli okuma: Mevcut işlem diğer işlem güncellemelerini okur, ancak Henüz gönderilmedi Değer (diğer işlemler geri alınmaz, ancak okuduğunuz geri alınan diğer işlemler geçersiz bir değerdir).

  • Transaction01 bir kaydın AEG değerini 20'den 30'a değiştirir
  • Transaction02, İşlemin güncellenmiş değerini okur01: 30
  • Transaction01 işlemi geri alır ve AEG'nin değeri 20'ye geri yüklenir
  • Transaction02 tarafından okunan 30 geçersiz bir değerdir
  • Tekrarlanamayan okuma:

  • Transaction01, AEG'nin değerini 20 olarak okur
  • Transaction02, AEG'nin değerini 30 olarak değiştirdi
  • Transaction01, ilk okuma sonucu ile tutarsız olan 30 AEG değerini tekrar okuyor
  • Phantom okuma:

  • İşlem01 ÖĞRENCİ tablosundaki verilerin bir kısmını oku
  • İşlem02, ÖĞRENCİ tablosuna yeni bir satır ekledi
  • İşlemin izolasyon seviyesi: Veritabanı sistemi, çeşitli işlemleri eşzamanlı olarak izole etme ve çalıştırma yeteneğine sahip olmalıdır, böylece birbirlerini etkilemeyecek ve çeşitli eşzamanlılık sorunlarını önleyecektir. Bir işlemin diğer işlemlerden yalıtılma derecesi, işlemin yalıtım düzeyi haline gelir. SQL standardı, çeşitli işlem izolasyon seviyelerini belirtir ve farklı izolasyon seviyeleri, farklı enterferans seviyelerine karşılık gelir.İzolasyon seviyesi ne kadar yüksekse, veri tutarlılığı o kadar iyidir, ancak eşzamanlılık o kadar zayıftır.

    1. Taahhüt edilmemiş okuma: TAHMİN EDİLMEYİ OKUYUN, Transaction01'in Transaction02'nin taahhüt edilmeyen değişikliklerini okumasına izin verin. (Kirli okuma, tekrarlanamayan okuma ve hayali okuma mümkündür)

    2. Gönderilen okuma: TAMAMLANDI OKUYUN, İşlem01'in yalnızca İşlem02'nin gönderdiği değişiklikleri okumasını gerektirir. (Kirli okumalardan kaçınılabilir)

    3. Tekrarlanabilir okuma: TEKRARLANABİLİR OKUMA, İşlem01'in bir alandan aynı değeri birden çok kez okuyabilmesini sağlar, yani İşlem01'in yürütülmesi sırasında, diğer işlemlerin bu alanın güncellenmesi yasaktır. (Kirli okumalar ve tekrarlanamayan okumalar görünmeyecek)

    4. Serileştirme: SERİLEŞTİRİLEBİLİR, İşlem01'in bir tablodan aynı satırı birden çok kez okuyabilmesini sağlamak için İşlem01'in yürütülmesi sırasında, diğer işlemlerin bu tabloya işlem eklenmesi, güncellenmesi ve silinmesi yasaktır. Tüm eşzamanlılık sorunları önlenebilir, ancak performans en düşüktür. (Kirli okuma, tekrarlanamayan okuma ve hayali okuma imkansızdır)

    İşlem izolasyon seviyesi için her bir veritabanı ürününün destek derecesi:

    Porsche Cenevre Otomobil Fuarı serisi, Panamera Seyahat Sürümü vb.
    önceki
    Korkunç orta şerit Luna! Editör okuduktan sonra gerçekten şaşkına döndü
    Sonraki
    "Duman Bombası" nın "Dürüstlük" endişesi izleyiciler tarafından çok beğenildi. Yönetmen Mak Siu-fai, "yükselen duruş" filminin ayrıntılarını yorumladı
    Sabah Okuması Pakistan Dışişleri Bakanı, Pakistan ve Hindistan'daki durumu bildirmek için gece geç saatlerde Wang Yi'yi acilen aradı
    AI Etki Faktörü Ağustos incelemesi: Tencent AI Lab yine listenin başında
    MADNESS üçüncü yıl dönümü için hatırlatıcıyı açmaya devam ediyor, bu sefer ilk ikisinden birini satın alabilirsiniz!
    Sorun bele zarar vermesidir. Yolda test sürüşü Chevrolet Camaro
    Suning, Akıllı Bir Ev Ekosferini Oluşturmak için Health Expo'da Çarpıcı Bir Görünüm Yaratmak İçin Siyah Teknolojisini Getiriyor
    Hafta sonları çiçeklerin tadını çıkarmaya gittim ve cep telefonumla Chongqing Bulut Çiçek Fuarı'nı izledim
    Daji ve Xiao Qiao arasındaki düello, yüksek patlama ve tüketim kimden hoşlanırsın
    Bugün Google yirmi yaşında: kendini, interneti ve dünyayı nasıl değiştirdi?
    Nissan Juke'nin yerel casus fotoğrafları ortaya çıktı Küçük bir SUV / veya tanıtım?
    Bu cep telefonu fotoğrafçılığı ipuçlarından yararlanın, Apple Fotoğraf Yarışması'nı kazanmak hayal değil!
    Film incelemesi, ekranı kaydıran bu "küçük kırık top" ne kadar iyi?
    To Top