SQL Server'da iki veritabanını senkronize etme


16

İki SQL Server veritabanım var. Biri istemci (Windows uygulaması) ve ikincisi sunucuda. Bu iki veritabanını sık sık eşitlemek istiyorum (örneğin her 2 dakikada bir!).

Çoğaltma, zaman damgası, tetikleyicileri kullanarak günlük tabloları, Microsoft Sync Framework ve benzeri gibi eşitlemenin farklı yollarını okudum.

Aslında onları güncellemek ve sunucu ile senkronize ederken SQL Server belirli tabloları engellenmesini istemiyorum çünkü bir kara kutu (çoğaltma gibi) olabilir bir senkronizasyon yöntemi kullanmak istemiyorum.

  1. bu durumda hangi yöntemi kullanmam gerektiğini düşünüyorsun? Her birkaç dakikada bir, istemciden sunucuya birkaç tablo değişikliği göndermem ve sunucudan iki tablo değişikliği almam gerektiğini unutmayın.

  2. Garip ama yeni bir yöntem buldum. İstemcide yürütülen tüm (belirli tercih edilen) saklı yordamları günlüğe kaydedip bunları bir .sqldosyadaki parametreleriyle sunucuya göndermem ve orada yürütmem mümkün mü? Aynı şey sunucuda gerçekleşecek ve istemciye gönderilecektir. Bunun basit ama kullanışlı bir yöntem olduğunu düşünüyor musunuz?

  3. lütfen eğer varsa bana herhangi bir yararlı yaklaşım önerin. Çok teşekkür ederim.

EDIT: Bunun gerçek zamanlı bir senkronizasyon olduğunu ve bunu özel kıldığını unutmayın. İstemci kullanıcı tabloyu kullanırken, sunucu ile senkronizasyon işleminin birkaç dakikada bir gerçekleşmesi gerektiği için tabloların hiçbirinin kilitlenmemesi gerektiği anlamına gelir.


1
Bu "kara kutular" ın nasıl çalıştıklarına, bakımlarının nasıl yapılacağına ve izleneceğine ve bunları ortak (ve çok da yaygın olmayan) başarısızlık senaryolarında düzeltmek için neler yapabileceğinize ilişkin nispeten iyi belgelendiğini unutmayın. Kendi senkronizasyon yöntemimi yuvarlamayı ve "kara kutular" ın uzun zaman önce ele aldığı ve yalnızca uygulamaya özel ihtiyaçları (kısmi senkronizasyon veya kullanıcı ihtiyacı) varsa , kenar durumlarıyla ilgili hataları bulup düzeltmek zorunda kalmayı düşünürdüm. etkileşimli çatışma çözümü vb.).
David Spillett

@DavidSpillett: Gerçek zamanlı bir senkronizasyon projesinde çoğaltmayı başarıyla kullandınız mı? Temel kaygım, gerçek zamanlı senkronizasyon ve "kilitleme ve engelleme".
Emad Farrokhi

Yanıtlar:


14

Anlamayabilirim, ama cevaplamaya çalışıyorum.

Sık çalışan (minimum 2 dakikada bir) yüksek performanslı bir çözüme ihtiyacınız olduğunu ve kilitlemeden hızlı olması gereken iyi bir yaklaşıma ihtiyacınız olduğunu söylediniz. Ama bir kara kutu sistemi istemiyorsun.

Milyonlarca kurulumda iyi sonuçlarla kullanılan bir kara kutu sistemi yerine, tekerleği tekrar icat etmeye ve kendi çözümünüzü oluşturmaya çalışıyorsunuz? Hm, biraz garip geliyor.

Aslında bunlar benim önerilerim.

  1. Kullanmayacağınızı söylemiş olsanız bile çoğaltma . Bunun için kullanabileceğiniz en kolay ve en iyi çözüm. Çoğaltma kurulumu kolaydır, hızlı çoğaltma yapar ve tekerleği tekrar icat etmenize gerek yoktur. Kilitleme hakkında garip sen, belirlediğiniz çalışabilir ISOLATION LEVELiçin READ_COMMITTED_SNAPSHOT. Burada daha fazla bilgi edinebilirsiniz . Bu tempdb'nizin bir bölümünü kullanır, ancak tablonuz her zaman okunabilir ve yazılabilir ve çoğaltma arka planda çalışabilir.

Aşağıdaki örneğe bakın:

ALTER DATABASE yourDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE yourDatabase SET READ_COMMITTED_SNAPSHOT ON
  1. CDC (Veri Yakalamayı Değiştir) de bir çözüm olabilir. Ama bu şekilde neredeyse her şeyi kendi başınıza inşa etmeniz gerekiyor. Ve CDCbazı durumlarda kırılgan bir şey olabilecek deneyimi yaptım . CDCizlenen bir tablodaki tüm verileri yakalar (izlenen her tabloyu manuel olarak belirtmeniz gerekir). Ardından bir sonraki önce değer ve değer elde edersiniz INSERT, UPDATEya da DELETE. CDCbu bilgileri bir süre saklar (kendiniz belirtebilirsiniz). Yaklaşım, CDCbu değişiklikleri izlemeniz ve diğer veritabanına el ile çoğaltmanız gereken belirli tablolarda kullanmak olabilir . Bu arada, CDCbaşlık altında SQL Server Çoğaltma'yı da kullanır. ;-) Burada daha fazla bilgi edinebilirsiniz .

Uyarı: -değişikliklerin CDCfarkında DDLolmayacak. Bu, bir tabloyu değiştirir ve yeni bir sütun eklerseniz CDC, tabloyu izleyecek, ancak yeni sütundaki tüm değişiklikleri yok sayacak demektir. Aslında sadece NULLönce değer ve sonra değer olarak kaydeder . DDLİzlenen bir tablodan sonra -Değiştirildikten sonra yeniden başlatmanız gerekir .

  1. Yukarıda tarif ettiğiniz yol, SQL Server Profiler kullanarak bir iş yükünü yakalamak ve bazı karşılaştırmalar için başka bir veritabanında tekrar çalıştırmak gibi bir şeydir. Workţe yarayabilir. Ancak çok fazla yan etkinin olması benim için biraz fazla ağır. İstemcinizde bir prosedür çağrısı yakalarsanız ne yaparsınız? Daha sonra prensip veritabanınızda senkronize olmadığı için aynı komutu çalıştırıyor musunuz? Yordam çalıştırılabilir, ancak istemcinizde bulunmayan satırları silebilir / güncelleyebilir / ekleyebilir. Veya birden fazla istemciyi tek bir ilke ile nasıl ele alırsınız? Bence bu çok zor. En kötü durumda, muhtemelen bütünlüğünüzü yok edersiniz.
  2. Başka bir fikir, uygulamaya dayalı veya bir tetikleyici kullanmak olabilir. Senkronize etmek istediğiniz tablo sayısına bağlı olarak. Tüm değişiklikleri ayrı bir aşamalandırma tablosuna yazabilir ve aşamalandırma tablosundaki bu satırları ana verilerinizle eşitlemek için bir SQL Server Agent Job all x Minutes çalıştırabilirsiniz. Ancak, 150 tabloyu senkronize etmeye çalışırsanız (örn.) Bu biraz ağır olabilir. Büyük bir yükünüz olurdu.

Bunlar benim 2 sentim. Umarım iyi bir genel bakışa sahip olabilirsiniz ve belki de sizin için çalışan bir çözüm buldunuz.


9

Bazı seçenekleri, onları algıladıkça avantajları ve dezavantajları ile numaralandırmaya çalışacağım:

  1. SQL Server Çoğaltma - bu, bu görev için en iyi ve en optimize edilmiş yerel SQL Server aracıdır. Ancak birkaç sorun var: a. tüm istemcileriniz için, SQL Express veritabanları olsun veya olmasın, SQL Server CAL lisansına ihtiyacınız olacaktır. İşlemci başına lisanslama kullanılarak bu önlenebilir. b. SQL CE istemcisini burada olduğu gibi senkronize edemezsiniz. c. SQL Express veya LocalDB bir yayıncı veya dağıtıcı işlevi göremez, bu nedenle çoğaltma işlemi üzerinde istemci üzerinde daha az denetime sahip olursunuz.
  2. Microsoft Sync Framework - bana daha küçük mobil uygulama veritabanlarına daha uygun görünüyor. Veritabanınıza oldukça fazla tablo ekler ve çoğaltma kadar verimli değildir. Bileşen olarak SQL Server dışında uygulandığından, yapılandırılması daha zor olacaktır. Onunla hiçbir deneyimim yok, sadece denedim ve kullanmamaya karar verdim.

  3. Veritabanı değişiklik takibi . Ekler, güncellemeler ve siler dahil izleme değiştirmenizi sağlayan yerleşik bir SQL Server işlevidir. Değişiklik gönderme ve uygulama, uyuşmazlıkları çözme vb. Gibi diğer her şeyi kendiniz kodlamanız gerekecektir.

  4. Rowversion (zaman damgası) sütunları Tüm silme işlemlerine izin vermezseniz ( silinen kayıtların senkronizasyonu olmaz) - kendi çözümünüzü yalnızca rowversion bilgilerine dayalı olarak uygulayabilirsiniz. Rowversion sütunları SQL Server Çoğaltma tarafından da kullanılır, bu nedenle bunları yine de eklemeniz gerekir.
  5. Ionic'in cevabında belirtildiği gibi CDC - Bununla ilgili hiçbir deneyimim yok, çünkü yalnızca Enterprise veya Developer sürümlerinde mevcut.

  6. Kayıtlı yordamları günlüğe kaydetme ile kendi hile kullanmak - veritabanı uygulamanızın doğasına çok bağlıdır. Ancak prosedürler biraz farklılaştığında, verilerde büyük bir karışıklık yaşayabilirsiniz. Ve çatışmalarla nasıl başa çıkardınız?

Sorunuzdan, tüm büyük veritabanlarını değil, yalnızca birkaç tabloyu senkronize etmeniz gerekiyor gibi görünüyor. Bu amaçla, ihtiyaçlarınızı soruda belirttiğinizden daha ayrıntılı olarak analiz etmelisiniz, örneğin:

  • Silme işlemleri gerçekleşebilir ve sonra ne olur?
  • Çatışmalar olabilir, nasıl önlenir ve nasıl çözülür?
  • Tablo yapısı değişiklikleriyle nasıl başa çıkacağım?
  • ...

Sonunda, silme ve çakışmaların sizin probleminiz olmadığını ve yapınızın çok fazla değişmeyeceğini öğrenirseniz, kendi mantığınızı yazmayı düşünebilirsiniz, ancak 1000 satırlık kodlara kolayca büyüyebilirsiniz.


2

Geri bildiriminiz için hepinize teşekkürler.

Senkronizasyon işlemini, yürütülmüş saklı yordamları bir grup olarak değil, benim durumumda harika çalışan tek tek yakalayarak başarıyla çözdüm. Bütünlük ve her şey dikkatle ele alındığından, sistem şimdiye kadar gerçek zamanlı olarak çalışmaktadır.


Harika, ancak ne yaptığınızı daha ayrıntılı olarak açıklayabilirsiniz. Yürütülen saklı yordamların çağrıları günlüğe kaydeder ve bunları geçici tablo / komut dosyasında depolar ve bu komut dosyasını çalıştırıp bir alan (bir bit alanı veya TÜM bunlar için söylediğiniz bir datetime alanı gibi) ayarlar mı İşlenmemiş kayıtlar onları işlemek ve bit alanını güncellemek?
JonH

0

Geç cevap, ancak ziyaretçileri dizmek yararlı olabilir

Farklı sunucular arasında veri dağıtmaya çalışırken benzer bir zorluk yaşadım ve üçüncü taraf araçları ( şema değişiklikleri için Diff ve veri değişiklikleri senkronizasyonu için DataDiff ) ve işlemi otomatikleştirmek için gerekli PowerShell betiği kullanarak çözdüm:

#check for the existence of the Outputs folder
function CheckAndCreateFolder($rootFolder, [switch]$Outputs)
{
$location = $rootFolder

#setting up location 
if($Outputs -eq $true)
{
    $location += "\Outputs"
}

#if the folder doesn't exist it will be created
if(-not (Test-Path $location))
{ mkdir $location -Force:$true -Confirm:$false | Out-Null }

return $location
}

#root folder for the schema sync process
$rootFolder = "SchemaSync"

#schema output summaries location 
$outsLoc = CheckAndCreateFolder $rootFolder -Outputs

#ApexSQL Diff location, date stamp variable is defined, along with tools parameters 
$diffLoc   = "ApexSQLDiff"
$stamp = (Get-Date -Format "MMddyyyy_HHMMss") 
$Params = "/pr:""MyProject.axds""    /out:""$outsLoc\SchemaOutput_$stamp.txt"" /sync /v /f" 
$returnCode = $LASTEXITCODE

#initiate the schema comparison and synchronization process
(Invoke-Expression ("& `"" + $diffLoc +"`" " +$Params))

#write output to file
"$outsLoc\SchemaOutput_$dateStamp.txt"

#schema changes are detected
if($returnCode -eq 0)
{
"`r`n $returnCode - Schema changes were successfully synchronized" >> 

}
else
{
#there are no schema changes
if($returnCode -eq 102)
{
"`r`n $returnCode - There are no schema changes. Job aborted" >> 
}
#an error is encountered
else
{
"`r`n $returnCode - An error is encountered" >> 

#output file is opened when an error is encountered
Invoke-Item "$outsLoc\SchemaOutput_$stamp.txt"
}

}

Bu yöntem, iki veritabanı arasındaki karşılaştırmayı zamanlar ve bulunan değişiklikleri gerçek zamanlı olarak senkronize eder. İşte adım adım talimatlar sunan bazı makaleler:

https://solutioncenter.apexsql.com/automatically-compare-and-synchronize-sql-server-data/ https://solutioncenter.apexsql.com/how-to-automatically-keep-two-sql-server-database- şemalar--sync /

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.