İşlemsel çoğaltma için kimlik aralıklarıyla başa çıkmak


9

Bir işlem çoğaltması ayarladığınızda, SQL Server'ın kimlik aralığı yönetimini el ile olarak ayarlayacağını fark ettim. Bunun anlamı, abonelik veritabanımda, PK bir kimlik sütunu olan bir tabloya yeni bir kayıt eklemeye çalıştığımda, bana bir hata verecek ve "1", "2'lik bir PK eklemeye çalıştığını söyleyecek "," 3 "vb. Bunun nedeni, abone üzerindeki tüm kimlik sütunlarının geçerli kimlik değerinin, yayıncıda olduğu gibi kalmak yerine tohum değerine (genellikle 1) sıfırlanmasıdır.

SQL Server'ın bunu neden yaptığını anlıyorum - abone tablosunu salt okunur olarak bırakmanız gerekiyor. Ancak, senaryom biraz alışılmışın dışında - Abonemi zaman zaman çoğaltma yoluyla güncelliyor, bu DB'nin anında bir yedeğini alıyorum, daha sonra aboneye yayıncıya geri gönderilmeyecek bazı güncellemeler yapmak istiyorum, sonra Aboneyi tekrar güncellemeye gittiğimde, veritabanını önceki yedeklemeden geri yükler ve en son güncellemeleri alırım. Aboneye bu güncellemeler arasında güncellemeler yapmak istediğim için (eğer yapacaksanız 'geçici deltalar'), çoğaltıldığında 1'e sıfırlanmaması için kimlik sütununa ihtiyacım var.

Yayımı oluştururken otomatik kimlik aralığı yönetimini açmayı denedim, ancak yayına bir tablo eklemeye çalıştığımda bu sadece bana aşağıdaki hatayı veriyor:

Msg 21231, Seviye 16, Durum 1, Prosedür sp_MSrepl_addarticle, Line 2243
Otomatik kimlik aralığı desteği yalnızca abonelerin güncellenmesine izin veren yayınlar için kullanışlıdır.

Bu sorunu çözmenin bir yolu var mı? Bu çoğaltmayı SQL Server'a abone sonunda salt okunur olarak sunmak istiyorum, çünkü yayıncıya geri gönderilecek güncelleştirmeler yapmayı planlamıyorum , ancak geçici güncelleştirmeler yapmak istiyorum sonraki çoğaltma işleminden önce silinecektir.

Ayrıca anlık görüntü çoğaltma benim kullanım deseni için işlem çoğaltma daha uygun bir yöntem olabilir, ama sorun anlık görüntü çoğaltma her darn DB her güncelleştirme gönderme gerektirir olmasıdır ; Ben en son çoğaltma sonra DB hemen bir yedek almayı planlıyorum çünkü, her zaman tüm transfer yapmak gerekmez; sadece son zamandan bu yana yapılan değişiklikler.


Hangi SQL Server sürümünü kullanıyorsunuz? Tabloyu yeniden tanımlayabilir misiniz?

2008 r2. Tabloyu yeniden tanımlamanın bu sorunu nasıl çözeceğini göremiyorum ...
Jez

SEQUENCE kullanarak bir çözüm düşünüyordum, ama bu sadece SQL 2012 için.

2
Is there any way I can get round this problem?Sql server 2005 ve sonraki sürümler için sys.sp_identitycolumnforreplication kullanarak kimlik sütununu REPLICATION için DEĞİL olarak ayarlamanız gerekir . Kimlik sütununu çoğaltma için değil olarak değiştirdiğinizde makalelerinizi yeniden görüntülemeniz bile gerekmez. GUI kullanarak yapmayın.
Kin Shah

Zaten çoğaltma için değil olarak işaretlendi. Temelde sorun bu - SQL Server kimlik bilgilerini kopyalamıyor, bu yüzden
abonede

Yanıtlar:


3

Yayıncınızın 1 ile başlayan bir int kimliği kullandığını varsayarsak, abonede yayınlayabilirsiniz DBCC CHECKIDENT('dbo.mytable', RESEED, -2147483648) . Daha sonra "geçici deltalarınızı" tutmak için -2147483648 ile 0 arasındaki aralığı kullanabilirsiniz.


Bu geldiğim çözüm, ancak yine de kodumun yayıncıya ve aboneye bağlandığı ve kimlikleri manuel olarak senkronize ettiği anlamına geliyor. Bunu yapmanın daha otomatik bir yolu olduğunu umuyordum.
Jez

Kimlikleri neden manuel olarak senkronize etmeniz gerekiyor? Geçici deltaları depoladığınız her tablo için denetleyici çalıştıran aboneye depolanmış bir yordam yazmanız ve anlık görüntünün uygulanmasını bitirdikten sonra çalıştırmanız yeterlidir. Dağıtım aracısı, değişiklikleri "gerçek" kimlik aralığında gerçekleştikçe ekleyecek ve doğrudan aboneye yapılan değişiklikler negatif aralıkta olacaktır.
Liam Confrey

1

Yaptığım şey, çekme tabanlı bir işlem çoğaltmasıyla uğraşmaktı ve programımın abone kimlik değerlerini senkronizasyondan hemen sonra yayın veritabanındakilerle aynı olacak şekilde güncellemesini sağlamaktı (dağıtım ajanının kendi isteğiyle yapmasını diliyorum ). Sahte kodda şöyle görünüyordu:

synchronize databases with TransSynchronizationAgent

equivalentTablesNotFound is a list of strings
for each table in publisher tables:
    try:
        check table identity value (this is via functionality provided by .NET's Microsoft.SqlServer.Management.Smo.Server class)
        parse identity value as integer to newIdentity
        if the table's identity value was NULL, skip to next loop iteration
        (HACK) increment newIdentity value by 1
        if there is no subscriber table with the same name as this one:
            record its name in equivalentTablesNotFound and skip to next loop iteration
        set subscriber table with same name's identity value to newIdentity using TSQL: DBCC CHECKIDENT ("tableName", newIdentity)
    catch:
        if exception shows that the error was because the table doesn't have an identity column, drop the exception

if equivalentTablesNotFound has more than zero entries, warn about tables on publisher without an equivalent name on subscriber

Tamam görünüyor. HACK biti, varsayılan olarak ve tüm tablolarımda kimlik değerinin birer birer artmasına rağmen, farklı bir şekilde yapılandırılabileceğinden, teknik olarak burada yayıncı tablosundaki kimlik değerinin nasıl arttığını ve onu artırdığını aynı şekilde.


0

Bunu ele almak için tercih ettiğim yöntem aşağıdakileri yapmaktır:

a. İlk önce çoğaltma aracısını durdurun (böylece abone DB'nize yeni veri alamazsınız)

b. İkinci olarak mevcut tablonuzu yeniden adlandırın

exec sp_rename '[CurrentTable]', '[BackupTableName]'

c. IDENTITY kümesiyle masanızı yeniden oluşturun

CREATE TABLE [CurrentTable]
(
   ID INT NOT NULL IDENTITY(1,1), 
   OtherField VARCHAR(10) NULL,
   ....
)

d. Tablonuzu ([BackupTableName] 'tan) SET IDENTITY_INSERT ile doldurun

SET IDENTITY_INSERT [CurrentTable] ON
INSERT INTO [CurrentTable] (ID, OtherField, ...)
SELECT ID, OtherField, ....
FROM [BackupTableName]
SET IDENTITY_INSERT [CurrentTable] OFF

DB'nizde IDENTITY kısıtlamasına sahip olduğunuzda, özel çoğaltma yapabilirsiniz (yani: insert repc proc'unuzu SET IDENTITY_INSERT [TableName] ON olarak değiştirebilirsiniz veya tablodaki REPLICATION DEĞİL bayrağını (SQL sunucusuna bağlanan kullanıcı çoğaltma aracısıysa, IDENTITY değerinin sağlanmasını bekler) ( Bana daha fazla esneklik sağladığı için özel çoğaltma yaklaşımını tercih ederim )

e. Ekleme çoğaltması saklı yordamınızı (genellikle sp_MSins_CurrentTable olarak adlandırılır) kullanarakSET IDENTITY INSERT

ALTER procedure [dbo].[sp_MSins_CurrentTable]
    @c1 int, @c2 varchar(50), ...
as
begin
    /* allow replication to insert values for IDENTITY */
    SET IDENTITY_INSERT [CurrentTable] ON
    insert into [CurrentTable]
        ([ID], [OtherField], ...)
    values
        (@c1, @c2, ...)
    /* now turn off Identity insert */
    SET IDENTITY_INSERT [CurrentTable] OFF
end

f. Şimdi çoğaltma aracısını yeniden başlatabilirsiniz.


1
lol, kullanmaya kıyasla DBCC CHECKIDENT, bu yöntem büyük miktarda çalışmadır.
Jez

@ Jez DBCC CHECKIDENT çalıştırmak için tabloyu (IDENTITY ile) yeniden oluşturmanız gerekir ... Çoğaltma bir anlık görüntü IDENTITY kısıtlaması ile tablo oluşturur (q dayalı DBCC CHECKIDENT kazandığını söyleyebilirim 't work)
Andrew Bickerton

FYI işe yaradı ve çoğaltma KİMLİK kısıtlaması ile tablo oluşturuyor ...
Jez

@Jez ne tür çoğaltma kurdunuz? (gerçekleşecek MERGE olarak ayarladıysanız, İŞLEM için genellikle GUI kullanmıyorsanız çoğaltma oldukça özelleştirilebilir olsa da)
Andrew Bickerton

İşlem. Dediğim gibi KİMLİK orada, ancak mevcut kimlik değeri tohum değerine (1) sıfırlandı.
Jez
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.