Oracle’da Güvenilir Benzersiz Anahtar Olmadan Güvenli Satır Güncelleme

Oracle’da Güvenilir Benzersiz Anahtar Olmadan Güvenli Satır Güncelleme

Primary key veya güvenilir unique constraint bulunmayan, yinelenen iş anahtarları içeren eski Oracle tablolarında deterministik satır seçimi, ROWID, kilitleme ve güncelleme sınırları.

Eski bir veri tabanında en zor sorunlardan biri, tablonun iş açısından bir kayıt kimliğine sahip görünmesine rağmen bu değerin fiziksel olarak benzersiz olmamasıdır. CC_ID, kayıt numarası veya zaman damgası gibi bir sütun uygulama tarafından anahtar gibi kullanılabilir; fakat veri tabanında bunu güvence altına alan PRIMARY KEY veya UNIQUE constraint yoksa aynı değer birden fazla satırda bulunabilir. Bu durumda WHERE id = :id biçimindeki bir güncelleme tek satır güncelleme niyetini ifade etmez; eşleşen bütün satırlar değişebilir.

İş anahtarı ile fiziksel satır kimliğini ayırmak

Bir business key, uygulamanın kaydı nasıl adlandırdığını gösterir. Fiziksel satır kimliği ise o anda hangi tablo satırının değiştirileceğini belirler. Legacy şemada bu ikisini aynı şey kabul etmek güvenli değildir.

Oracle ROWID, heap-organized bir tablodaki satırın konumunu çok düşük maliyetle adresleyebilir. Bu nedenle benzersizliği garanti edilmeyen iş anahtarından aday satırları bulduktan sonra seçilen fiziksel satırı güncellemek için yararlı olabilir. Ancak ROWID kalıcı business key değildir; taşıma, yeniden oluşturma, export/import gibi işlemlerden sonra değişebilir. Uygulama kimliği olarak saklanmamalı, aynı işlem akışında seçilen satırı hedeflemek için kullanılmalıdır.

Deterministik seçim

“En yeni kayıt” kuralı tek başına yeterli değildir. İki satırın tarih değeri eşitse sonuç yine belirsizdir. Sıralama eşitlikleri kıracak kadar tam olmalıdır:

SELECT rid
FROM (
    SELECT ROWID rid,
           ROW_NUMBER() OVER (
               ORDER BY islem_tarihi DESC, ROWID DESC
           ) rn
    FROM legacy_table
    WHERE business_id = :businessId
)
WHERE rn = 1;

Buradaki ROWID ikinci sıralama ölçütü olarak iş anlamı taşımaz; yalnızca aynı tarihli adaylar arasında kararlı bir fiziksel seçim sağlar. Eğer veri modelinde daha anlamlı ve benzersiz bir ikincil ölçüt varsa o tercih edilmelidir.

Seçim ile güncelleme arasındaki yarış

Satırı seçmek ve daha sonra ayrı bir adımda güncellemek, iki işlem arasındaki zaman aralığında başka bir transaction'ın aynı veri üzerinde çalışmasına izin verir. Güncelleme gerçekten tek fiziksel satıra uygulanacaksa seçim ve kilitleme aynı transaction sınırında ele alınmalıdır. Uygun tablolarda SELECT ... FOR UPDATE veya ORM tarafında pessimistic locking bu amaçla kullanılabilir.

Bununla birlikte her view kilitlenebilir değildir. DISTINCT, GROUP BY, aggregate veya bazı birleşim biçimleri içeren view'larda FOR UPDATE uygulanabilirliği ve key-preserved table kuralları ayrıca değerlendirilmelidir. Karmaşık bir view üzerinde kilidi zorlamak yerine güncellenecek temel tablonun fiziksel satırını güvenilir biçimde belirlemek daha açık bir tasarımdır.

ORM kimliğiyle veri gerçeğinin çatışması

JPA/Hibernate entity modeli tekil kimlik varsayar. Veri kaynağı bu varsayımı sağlamıyorsa yalnız annotation eklemek veriyi benzersiz hale getirmez. Aynı business identifier'a sahip iki fiziksel satırı tek entity kimliği altında göstermek cache, dirty checking ve update hedefi açısından hatalı davranışlara yol açabilir. Şema değiştirilemiyorsa okuma modeli ile güncelleme modeli farklılaştırılmalı; yazma işlemi sonunda fiziksel satıra yönelmelidir.

Sınırlar

Bu yaklaşım bozuk veri modelini düzeltmez. Şema üzerinde değişiklik yapılabiliyorsa gerçek çözüm, iş kurallarına uygun bir primary key veya unique constraint oluşturmaktır. ROWID burada legacy kısıt altında kontrollü bir adresleme aracıdır.

Ayrıca “en yeni satır kazanır” yalnız teknik bir sıralama değildir; iş kuralıdır. Hangi zaman sütununun otorite sayıldığı, NULL değerlerin nasıl ele alındığı ve eşitlikte hangi satırın seçileceği açıkça tanımlanmalıdır.

İlişkili konular: Oracle Veritabanı ve PL/SQL: Mimari, SQL ve Performans, ROWID, Pessimistic Locking, Consistent Read.

Kaynaklar

  • Oracle Database 19c SQL Language Reference — ROWID Pseudocolumn
  • Oracle Database 19c Concepts — Data Concurrency and Consistency
Bu sayfanın QR kodu