---
title: "SQL Server'da Veritabanları Arası Veri Güncelleme: Cross-Database UPDATE Rehberi"
description: "Master-Slave ERP kurulumlarında şubeler arası veri nasıl senkronize edilir? SQL Server'da Cross-Database UPDATE, Batch Processing ve Linked Server..."
date: 2026-04-14
category: mikro-erp
tags: ["sql-server", "mikro-erp", "cross-database", "update", "senkronizasyon", "multi-database", "astaflow"]
url: https://mikroerp.dev/blog/sql-server-cross-database-update-senkronizasyon/
---

## İş Problemi: "Merkezde Değişen Ünvan Adana'ya Neden Gitmedi?"

Özellikle inşaat, perakende veya grup şirket yapıları kullanan büyük çaplı Mikro ERP kurguları genellikle Tek Veritabanı (Single DB) yerine "Multi-Tenant / Multi-Database" tercih eder. (Örn: `MikroDB_Holding`, `MikroDB_A_Sirketi`, `MikroDB_B_Sirketi` vb.)
Ancak bu mimarinin **karanlık bir yüzü** vardır: Veri Uyumsuzluğu.

Muhasebe veya satınalma departmanı Master (Ana) şirkette bir Cari Ünvanı'nı (`cari_unvan1`) değiştirir, Vergi Dairesi bilgisini günceller. Fakat bu veri alt şubeye otomatik olarak gitmez. Bunun sonucunda, Adana şubesi fatura kesmeye çalıştığında, e-Fatura entegratöründe VKN/Ünvan uymaz ve e-Fatura iptal veya red yer. Şirket itibar zedeleyici bir sürece girer.

**Neden Geleneksel Çözümler Batırır?**
Kullanıcılar genellikle DB üzerine bir TRIGGER yazar. "Şu veritabanında UPDATE oldu mu diğerine de at" sistemi, SQL sunucusunun IO (Input/Output) performansını tüketir ve bir şube DB'sinde kilitlenme (Deadlock) yaşandığında ana üretim hattını da kilitler!

## Çözüm: Asenkron Toplu (Batch) Senkronizasyon Algoritması

Bizim AstaFlow tarzı Multi-DB yapılarında tavsiye ettiğimiz olay, "Transaction Riskini Minimize Eden Programlanmış Çapraz Güncelleme" mimarisidir. Bunu SQL Server Agent içerisine konulan periyodik bir "Sync Job" (Örn: Her 15 dakikada bir) ile yaparsanız sıfır hata ve kesintisizlik elde edersiniz.

Aşağıda veritabanını felç etmeden (Batch bloklarıyla) güncelleme yapan bir Kurumsal "Cross-DB Sync" yordamını görebilirsiniz:

```sql
-- GÜVENLİ CROSS-DB SENKRONİZASYON STORED YORDAMI
SET NOCOUNT ON;

DECLARE @KaynakDB NVARCHAR(128) = 'MikroDB_Merkez';
DECLARE @HedefDB NVARCHAR(128) = 'MikroDB_Adana';

-- Hangi tablonun hangi sütunları denetlenecek?
-- (Örnekte Müşteri Sicil Kartları-CARI_HESAPLAR Master alınıyor)

DECLARE @SQL_SENKRON NVARCHAR(MAX) = N'
-- TRANSACT-SQL ERROR HANDLING AÇILIYOR
BEGIN TRY
    BEGIN TRANSACTION;
    
    -- ADIM 1: Sadece "Farklı" olan kayıtları hedefleyip performansı artırıyoruz
    -- Hedef tablodaki Ünvan veya VKN, Ana tablodaki ile aynı DEĞİLSE tetiklenir.
    UPDATE Hedef
    SET 
        Hedef.cari_unvan1 = Kaynak.cari_unvan1,
        Hedef.cari_vdaire_no = Kaynak.cari_vdaire_no
    FROM [' + @HedefDB + N'].dbo.CARI_HESAPLAR Hedef
    INNER JOIN [' + @KaynakDB + N'].dbo.CARI_HESAPLAR Kaynak 
        ON Hedef.cari_kod = Kaynak.cari_kod
    WHERE 
        ISNULL(Hedef.cari_unvan1, '''') <> ISNULL(Kaynak.cari_unvan1, '''')
        OR 
        ISNULL(Hedef.cari_vdaire_no, '''') <> ISNULL(Kaynak.cari_vdaire_no, '''');
        
    -- Eğer etkilenen satır yoksa işlem şeffafça devam eder.
    DECLARE @RowAffected INT = @@ROWCOUNT;

    COMMIT TRANSACTION;
    PRINT ''✅ Senkronizasyon BAŞARILI. Güncellenen Kayıt: '' + CAST(@RowAffected AS NVARCHAR);
    
END TRY
BEGIN CATCH
    IF @@TRANCOUNT > 0
        ROLLBACK TRANSACTION;
        
    -- Hatayı Log tablonuza yazın veya SysAdmin''e alert çıkartın
    PRINT ''❌ KRİTİK SYNC HATASI'';
    PRINT ''Error Message: '' + ERROR_MESSAGE();
END CATCH
';

EXEC sp_executesql @SQL_SENKRON;
```

## Performans / Ölçekleme (Lock ve Timeout Sorunsalı)

Eğer Cari Hesaplar tablonuzda 300.000 kayıt varsa ve siz yukarıdaki gibi salt `UPDATE` atarsanız, Database Engine tüm hedef tabloya **Exclusive Lock (X)** uygular. Başka bir memur o saniyede Adana şubesine fatura kaydedemez, SQL `Timeout` yer.

**Nasıl Çözülür (Batch Update Senaryosu):** Yüz binlerce satırlık farklarda, 5000 satırlık bloklara ayırıp `WAITFOR DELAY` (nefes alma) kurgusu eklenerek tablo lock baypas edilebilir:

```sql
-- DÖNGÜSEL BATCH UPDATE (Özet Mantık)
WHILE (1=1)
BEGIN
   UPDATE TOP (5000) Hedef SET Hedef.Unvan = Kaynak.Unvan ...
   IF @@ROWCOUNT = 0 BREAK;
   WAITFOR DELAY '00:00:01'; -- 1 Saniye Sunucunun nefes almasına izin ver!
END
```

## Edge Cases (İstisnai Durumlar) ve Mimari Tehlikeler

1. **Farklı Sunucularda Olma Durumu (Linked Servers):** Eğer Merkez İstanbul'da ayrı bir Cloud makinesinde, Adana şubesi kendi binasındaki bir sunucuda ise `[MikroDB_Merkez].dbo.Cari` şeklinde direkt bağlanılamaz! SQL Server'da `SP_ADDLINKEDSERVER` ile ağ geçidi tanımlanmalıdır. Ancak Linked Server üzerinden Cross-DB UPDATE yapmak ağ gecikmesi (*Latency*) nedeniyle son derece risklidir; işlem koptuğunda veri yarı yolda kalabilir. Bunun yerine "Veri Aktarımını Yapan API" (Microservice) tercih edilmelidir.
2. **Kayıt "Yoksa" (INSERT) Olasılığı:** Yukardaki senaryo `INNER JOIN` tabanlı bir Edit (`UPDATE`) mantığıdır. Merkezde açılan yeni bayi henüz şubede hiç açılmadıysa? O zaman `MERGE INTO` SQL komutuyla "Bulursan Update et, Bulamazsan Arkasına Insert at" mantığı devreye alınmalıdır.
3. **Collation (Dil Karakter Seti) Sorunları:** Eğer Merkez şube veritabanı `Turkish_CI_AS` ile açılmış, Şube DB `Latin1_General_CI_AS` ile kurulmuşsa (kurulum hatası), Cross-DB Join attığınız esnada "Cannot resolve collation conflict" SQL patlaması yaşarsınız. Join bloklarına `COLLATE DATABASE_DEFAULT` eklemeniz hayat kurtarır.

## Bu Bilgiyi Nereden Biliyoruz? (Kaynaklar)

*   **AstaFlow Case Study:** [Asta Stoka Yansıyan Ana Şube Veri Senkronizasyonu](/case-study/)
*   **İlgili Çözüm:** [SQL Server'ı Cloudflare Arkası Web'e Açma Reçetesi](/blog/mikro-erp-web-baglanti-cloudflare-tunnel/)