Veritabanındaki her satır değişikliğinin kaydı genellikle nasıl saklanır?


10

Üzerinde çalıştığım bir projede , veritabanının bazı tablolarındaki satırlarda yapılan her değişiklik, daha fazla denetim veya geri alma için izlenmelidir . Satırı kimin, hangi IP adresinin ne zaman ve ne zaman değiştirdiğini bulmak ve önceki sürümü geri yükleyebilmek kolay olmalıdır.

Benzer bir şey, örneğin Stack Exchange tarafından kullanılır. Başka birinin sorusunu değiştirdiğimde, değiştirdiğimi bulmak ve değişiklikleri geri almak mümkündür.

Geçerli şemamın ortalama bir işletme uygulamasıyla aynı özelliklere (aşağıda) sahip olması nedeniyle, bir nesnede yapılan her değişikliği bir veritabanında depolamak için kullanılan genel teknik nedir ?

  • Bazı olabilir: nesneler nispeten küçük boyuta sahip nvarchar(1000), örneğin ancak ikili verilerin büyük lekeler, bu bir doğrudan ve direkt olarak diskte depolanır ve erişilen değil değil , Microsoft SQL arasında filestream,
  • Veritabanı yükü oldukça düşük ve tüm veritabanı sunucudaki bir sanal makine tarafından işleniyor,
  • Önceki sürümlere erişimin en son sürüme erişim kadar hızlı olması gerekmez, ancak yine de güncel olması gerekir¹ ve çok yavaş değildir².

<Tl-dr>

Aşağıdaki vakaları düşündüm, ancak bu tür senaryolarla ilgili gerçek bir deneyimim yok, bu yüzden başkalarının fikirlerini duyacağım:

  1. Satırları kimlik ve sürüme göre ayırarak her şeyi aynı tabloda saklayın. IMO, ciddi bir şekilde aptalca ve performans düzeyinde yakında veya daha sonra incinecek. Bu yaklaşımla, en son öğelere ve sürüm izlemesine farklı bir güvenlik düzeyi ayarlamak da imkansızdır. Son olarak, her sorgunun yazılması daha karmaşık olacaktır. Aslında, güncel verilere erişmek için her şeyi kimliğe göre gruplamak ve her grupta son sürümü almak zorunda kalırdım.

  2. En son sürümü bir tabloda saklayın ve her değişiklikte eski sürümü başka bir şemadaki başka bir tabloya kopyalayın. Kusur şu ki, her seferinde, değişmemiş olsa bile her değeri saklıyoruz. nullDeğerin ne zaman nullveya olarak değiştirildiğini de izlemem gerektiğinden, değişmeyen değerleri olarak ayarlamak bir çözüm değildir null.

  3. En son sürümü bir tabloda ve değiştirilen özellikler listesini önceki değerleri ile başka bir tabloda depolayın. Bu iki kusura sahip gibi görünüyor: en önemlisi, aynı sütundaki heterojen önceki değer türlerini sıralamanın tek yolunun a binary(max). İkincisi, bence, önceki sürümleri kullanıcıya görüntülerken bu yapıyı kullanmak daha zor olurdu.

  4. Önceki iki noktayla aynı işlemi yapın, ancak sürümleri ayrı bir veritabanında saklayın. Performans açısından, aynı veritabanında önceki sürümlere sahip olarak en son sürümlere erişimi yavaşlatmaktan kaçınmak ilginç olabilir; Yine de, bunun erken bir optimizasyon olduğuna ve yalnızca aynı veritabanında eski ve en son sürümlere sahip olmanın bir darboğaz olduğuna dair bir kanıt varsa yapılması gerektiğine inanıyorum.

</ Tl-dr>


¹ Örneğin, HTTP günlükleri için yapıldığı gibi değişikliklerin bir günlük dosyasına kaydedilmesi ve sunucu yükünün en düşük olduğu gece verileri günlükten veritabanına akıtmak kabul edilemez. Farklı sürümler hakkındaki bilgiler derhal ya da hemen erişilebilir olmalıdır; birkaç saniye gecikme kabul edilebilir.

² Bilgiye çok sık erişilemez ve sadece belirli bir grup kullanıcı tarafından erişilebilir, ancak yine de sürüm listesinin görüntülenmesi için 30 saniye beklemeye zorlanması kabul edilemez. Yine, birkaç saniye gecikme kabul edilebilir.


3
İlgili: SQL Server Veri Yakalama Değişikliği .
Nick Chammas

Yanıtlar:


8

Bu tür denetim günlüğü tutmanın normal yolu, bir gölge tablosu ve denetlediğiniz temel tabloda tetikleyicilerle günlük değişiklikleri yapmaktır. Performans için buna gerek duymanız halinde diğer tablolar farklı bir fiziksel diske yerleştirilebilir ve verilerin hızlı bir şekilde alınmasını desteklemeniz gerekiyorsa bunlara dizinler koyabilirsiniz.

Tablolar, orijinal tablolarınızla kabaca aynı yapıya sahip olacak, ancak değişikliğin ne zaman yapıldığı için bir datetime sütunu ve satırın eklenmiş, değiştirilmiş veya silinmiş olup olmadığına dair bir işaretçi olacaktır. Sürümlerin sıralanması zaman damgası ile yapılabilir.

Değişiklik tarihi varsayılan tarih olan getdate () ile datetime sütunu null değil olarak yapılabilir; bir denetim kullanıcısı sütunu, kullanıcıyı Suser_Sname () varsayılan olarak boş olmayan bir sütuna sahip olarak yakalar. Gerçek kullanıcının oturumda kimliğine büründüğü varsayılarak bu, değişikliği yapan kullanıcının kimliğini yakalayacaktır.

Veritabanının bir web sunucusuna bağlanan IP adresinden haberdar olmasının bir yolu yoktur. Uygulama IP adresini işlemle açıkça yakalamalı ve günlüğe kaydetmelidir.

Denetlemek istediğiniz çok sayıda tablonuz varsa, tetikleyicileri programlı olarak oluşturmak için sistem veri sözlüğündeki meta verileri kullanabilirsiniz.

Bu çözüm birkaç nedenden dolayı en iyisidir:

  • Yalnızca uygulama tarafından yapılanları değil, tablodaki değişiklikleri de yakalar.

  • Denetim tabloları, birincil tablolarınızdaki G / Ç yükünü azaltmak için farklı disklere yerleştirilebilir.

  • Geçerli sürüm de dahil olmak üzere tüm geçmişi gösteren tablo ve denetim günlüğü tablosunun birleşimini temel alan bir görünüm kullanabilirsiniz.

  • Denetim günlüğü tablolarını, denetim kullanıcılarının bunları hızlı bir şekilde sorgulayabilmeleri için gerektiği şekilde dizine ekleyebilirsiniz. Her zamanki gibi, dizin seçimi, sorgu performansı ile güncelleme yükü arasında bir dengedir.


Eğer herhangi bir değişiklik için günlük korumak gerekir 1000 tablo varsa söylemeye çalışın sonra 1000 gölge tablo ha oluşturmak zorunda? ve değişikliği yakalamak için 1000 tetikleyici? evet ise o zaman sahte bir fikir ... biz değiştirilen verileri yakalamak ve günlüğe kaydetmek için tek bir geçmiş tablosu ve tek bir tetikleyici oluşturabilir. biz eski ve yeni satır verileri bu tabloda bir xml olarak saklayabilirsiniz .... bu birçok insanın yaptığı .... açık mıyım !!
Thomas

1
1000 tablo için, sistem veri sözlüğünden tanımları okuyan ve tetikleyicileri ve tablo tanımlarını üreten bir yardımcı program yazarsınız. 560 tablolu bir sistem üzerinde yaptım ve gayet iyi çalışıyor.
ConcernedOfTunbridgeWells

0

Verilerin tüm sürümlerini depolamak için tek bir tablo kullanan birçok CMS sistemini (Wordpress dahil) biliyorum. Ama yine de, bunu sadece blog gönderilerinin bulunduğu tablo için yapmak zorundalar. Wordpress veritabanı yapısına bakın .

Ayrıca, her satırdaki kayıt sayısı ve revizyon sayısı kararınızda önemli bir rol oynayacaktır.


0

CMS sürüm oluşturma hakkında; drupal için eski değeri depolayan varlığın her alanı için özel bir tablo oluşturur; böyle bir kavram size verilerinizi ince bir manipülasyon alllows ama pahalı olduğunu düşünüyorum, benim kendi çözüm xml formatına dönüştürmek ve diğer alanları ile dize olarak saklamak (changetime, id ...)

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.