İki farklı veritabanı arasında veri senkronize etmenin en iyi yolu


24

Tamamen farklı yapılara sahip iki büyük veritabanı arasında veri senkronizasyonu uygulamak zorundayım. Temel olarak, ilk veri tabanındaki farklı tablolardaki ürünlerle ilgili bazı verileri toplayıp, ikinci veri tabanındaki diğer tablolar için bunları yeniden düzenlemem gerekiyor.

Ürünlerimi ilk kez yaratmak çok karmaşık değil. Ancak her ürünle ilgili belirli verileri (tüm verileri değil) güncellemenin bir yolunu arıyorum.

Açıkçası, bunu zorlaştıran birkaç sorun var.

  • Seçme sorguları dışında kaynak veritabanında hiçbir şey yapmama izin verilmiyor.
  • Hedef veritabanında olağan sorguları yapabilirim (seç, güncelle, ekle, oluştur) ancak mevcut yapı / tabloları değiştiremiyorum.
  • Hedef ve kaynak db tamamen farklı yapılara sahip, tablolar hiç aynı değil, bu nedenle verilerin gerçekten yeniden düzenlenmesi gerekiyor - karşılaştırma tabloları çalışmaz.
  • Hedef veritabanı bir MySQL sunucusu kullanıyor - kaynak DB2 olabilir.
  • Hiçbir yerde "güncellenmiş zaman" alanı yok.

Bu yüzden, tüm işlem tek bir Python (ideal olarak) komut dosyasında yapılmalıdır.

Hedef veritabanında güncellenecek alanlara bağlı olarak her ürün için bir karma oluşturmayı düşünüyorum: md5 (kod + açıklama + tedarikçi + yaklaşık 10 diğer alan). Aynı veriye dayalı yeni bir karma, kaynak veritabanından günlük olarak oluşturulacaktır. Performansları için tüm karmaları tek bir tabloda (kalem kodu, current_hash, old_hash) saklayacağım. Ardından, yeni karma eskisinden farklıysa, ürünü karşılaştırın ve güncelleyin.

Yaklaşık 500.000 ürün var, bu yüzden performansları hakkında biraz endişeliyim.

Gitmek için iyi bir yol mu?


2
Senin de gözü kapalı olmanı mı istiyorlar? Şu andaki sorunum bu ...
Captain Hypertext

1
@Neow, Nasıl geçti? Şimdi önerebileceğiniz herhangi bir tavsiye var mı?
Edwin Evans,

4
@EdwinEvans temelde ilk fikrimle kaldım, ancak özellikle sahip olduğum kısıtlamalar nedeniyle. Komut dosyası, tüm öğeler için anahtar verilere dayalı md5 karmaları oluşturur. Sonra önceki hash'lerle karşılaştırırım. Karma değerler farklıysa, öğeye ilişkin tüm verileri yükler ve her şeyi günceller. Bunun en iyi yol olup olmadığından emin değilim, ancak geceleri çalışıyor ve gösteriler iyi.
Neow

Yanıtlar:


9

Bu benim yaptığım ya da son birkaç yıldır yaşayan bir şeydi ve içgüdülerim kaynak veritabanından 500.000 maddeyi okuma ve varış yerindeki eşitleme zamanının sanıldığı kadar uzun sürmeyeceği yönünde. "anahtar" alanlarını okumak için harcanan zaman, MD5 karmasını hesaplayın ve değişmemiş öğelerin senkronize edilmesini önlemek için masanızla çapraz kontrol edin, çok fazla zaman kazanmaz ve daha uzun sürebilir. Sadece hepsini okuyup güncellerdim. Bu, çok uzun bir çalışma süresine neden olursa, ETL'yi muti iş parçacıklı hale getirerek çalışma zamanını sıkıştırabilirim, her iş parçacığı yalnızca tablonun bir bölümünde çalışır, ancak paralel çalışır.

Hedef veritabanınızın birincil anahtar endeksine veya benzersiz bir dizine sahip olmasını sağlamak önemli olacaktır. Aksi takdirde, güncellemelerinizden / eklerinizden her biri tüm tabloyu kilitleyebilir. Çok iş parçacıklı yaklaşımı kullanıyorsanız, bu kötü olacaktır, ancak işiniz hedef DB tablosunu kilitleyebileceği ve bu DB'nin üzerinde süren uygulamaya müdahale edebileceği için tek iş parçacıklı kalırsanız bile önemlidir.

DB kaynağının "DB2 olabileceğini" söylüyorsunuz. "Olabilir" derken, DB hala tasarlanmakta / planlanmakta mıdır? DB2 9 veya üzeri, en son güncelleme zamanının yerleşik izlemesine ve yalnızca bir zamandan beri değişen öğeleri sorgulama ve geri alma özelliğine sahiptir. Belki de bu yüzden DB son güncelleme zamanını gösteren bir sütuna sahip olmamak üzere tasarlandı, örneğin:

SELECT * FROM T1 WHERE ROW CHANGE TIMESTAMP FOR TAB t1 > current timestamp - 1 hours;

Yukarıdaki sorgu için zaman damgası kesmesi, senkronizasyonunuzun koştuğu son zaman damgası olur.

Bu durumda sorununuzu çözmeniz gerekir. Ancak, çözümünüz DB2'ye çok sıkı bir şekilde bağlı kalmakla sonuçlanacak ve gelecekte başka bir DB platformuna geçmeyi ve senkronizasyon işinizin tekrar ziyaret edilmesine gerek kalmamasını bekleyebilirler. Bu nedenle, tüm doğru kişilerin, ürününüzün DB2’de kalmaya bağlı olacağını veya göç etmeyi planlıyorsa, geçişin DB’yi “son değiştirilen zaman damgası” sütununa sahip olacak şekilde yeniden yapılandırmayı içereceğini bilmesini sağlamak ve ne olursa olsun yapmak önemlidir. Bu alanı doldurmak için uygulama düzeyinde gerekli değişiklikleri yapın.


MySQL için de benzer bir çözüm var mı?
Fardin Behboudi

5

Bir çeşit delta tanımlayıcısı veya bayrağı temelinde yapılabiliyorsa, veri senkronizasyonu çok daha iyi ve daha hızlı olacaktır. Temel olarak, hedef db veri satırlarını yalnızca kaynak db ile senkronize olmadığı zaman güncellemelisiniz.

SQL server db'de delta tabanlı tanımlayıcıyı oluşturmak için Checksum fn'nin yardımını alabilirsiniz .

Bu sql mantığını tetiklemek için gece veya gündüz belirli bir saatte çağrılmak için SQL tabanlı bir iş geliştirmelisiniz . Db kullanımı çok düşük olduğunda, gecelik bir SQL işi olarak çalıştırmak daha iyidir. Kaynağın ve hedef db kayıtlarının deltası eşleşmiyorsa, yalnızca bu kayıtları çekin. Ancak olumsuz, her seferinde kaynak veri satırlarının sağlama toplamını hesaplamak ve sonra onu hedef verilerle karşılaştırmak olacaktır.

Kaynak db tablolarında "LastModifiedDate" gibi bir sütununuz varsa, sağlama toplamı yaklaşımını atlayabilirsiniz. Bu şekilde, değerlendirmeniz tarih esaslı sütunda gerçekleştirilir ve sağlama toplamı yaklaşımına kıyasla daha az zaman alır.


Teşekkürler ama çözümünüzün işe yarayacağından emin değilim - düzenlemelerimi "sorunlar" bölümünde görün.
Neow

Kaynak veritabanında güncellenmiş zaman alanı olmadığından, sağlama toplamına veya karma değere bağlı olarak nitelikli veri satırlarını çekmeye bıraktık.
Karan

Kaynağınız db2 olduğundan. Verileri ondan nasıl çekmeyi düşünüyorsunuz? bazı web servis veya API aracılığıyla ..
Karan

Bir odbc sürücüsü kullanılarak bir dsn kuruldu. Python için pyodbc kullanarak bağlantı kurabilir ve sorgular yapabilirim.
Neow

Tamam, bu iyidir, çünkü sorguları PyODBC adlı aracı kullanarak uzak DB içine sorgulayabilirsiniz. Bir şey daha yapabilirsin. Ürün verilerini, herhangi bir kontrol veya doğrulama yapmadan, hedef DB'nizdeki yeni "Aşama tablosu" na olduğu gibi aynı biçimde çekebilirsiniz. Bu şekilde canlı veriyi, sahne tablolarının altındaki hedef db'deki tek bir çekimde elde edeceksiniz. Sonra ikinci adımda, sağlama toplamı işlemlerini gerçekleştirebilir ve hedef işlem tablosu verilerini güncelleyebilirsiniz. Bu, gerçek zamanlı olarak kaynak db verileriyle yapılan karma ya da sağlama toplamı değerlendirmesini önler.
Karan

1

Bir karma kullanmak iyi bir fikirdir. Güvenlik bu durumda amaç olmadığından, hızlı olan bir karma işlevi seçin (md5 iyidir).

Karma hesaplamasını birden fazla iş parçacığı / işlemi arasında bölmeyi planlamadığınız sürece, geçerli karma değerini veritabanında saklamanız gerekmez. İşleminiz tek bir komut dosyasıysa, mevcut karma değeri bellekte olacak ve yeni veritabanındaki verileri güncelledikten sonra bunu eski karma olarak veritabanına yazacaksınız.


-1

istediğiniz zaman bazı belirli zamanlarda çalışacak ve kaynak veritabanınızdaki değişiklikleri bulacak ve bu değişiklikleri hedef veritabanınıza ekleyecek bir windows servisi yaratmış olmalısınız.


-1 (gerçekten aşağı oy vermedi, ancak;) yalnızca öneri için. Yazılım geliştirirken belirli bir mimariye güvenmeyelim, bu sadece birkaç kişinin eşyalarını kullanabileceği anlamına gelir. tek sabit değişimdir ve bu nedenle, kendiniz ve kullanıcılar için bakımı kolaylaştıracak ölçüde herhangi bir platforma güvenmemek daha iyidir
pythonian29033

1
@manish kumar bölümü "kaynak veritabanınızdaki değişiklikleri bulacak" bölümünde en zor olanı!
Narvalex
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.